Revision e933e753

View differences:

Tests/Makefile
1
BASE = ..
2

  
3
CFLAGS = -Wall
4
CFLAGS += -Wdeclaration-after-statement
5
CFLAGS += -Wno-switch -Wpointer-arith -Wredundant-decls
6
CFLAGS += -Wno-pointer-sign 
7
CFLAGS += -g
8

  
9
CPPFLAGS = -I$(BASE)/include
10

  
11
LDFLAGS = -L../MsgLayer -L../TopologyManager
12
LDLIBS = -lmsglayer -ltopman
13
#LDFLAGS += -static
14

  
15
topology_test: topology_test.o net_helpers.o
16
topology_test: ../MsgLayer/libmsglayer.a
17
topology_test: ../TopologyManager/libtopman.a
18

  
19
../TopologyManager/libtopman.a:
20
	make -C ../TopologyManager
21
../MsgLayer/libmsglayer.a:
22
	make -C ../MsgLayer 
23

  
24
clean:
25
	rm -f topology_test
26
	rm -f *.o
27
allclean: clean
28
	make -C ../TopologyManager clean
29
	make -C ../MsgLayer clean
Tests/net_helpers.c
1
#include <sys/ioctl.h>
2
#include <sys/socket.h>
3
#include <netinet/in.h>
4
#include <arpa/inet.h>
5
#include <net/if.h>     /* For struct ifreq */
6
#include <unistd.h>
7
#include <stdlib.h>
8
#include <stdio.h>
9
#include <string.h>
10

  
11
#include "net_helpers.h"
12

  
13
const char *iface_addr(const char *iface)
14
{
15
    int s, res;
16
    struct ifreq iface_request;
17
    struct sockaddr_in *sin;
18
    char buff[512];
19

  
20
    s = socket(AF_INET, SOCK_DGRAM, 0);
21
    if (s < 0) {
22
        return NULL;
23
    }
24

  
25
    memset(&iface_request, 0, sizeof(struct ifreq));
26
    sin = (struct sockaddr_in *)&iface_request.ifr_addr;
27
    strcpy(iface_request.ifr_name, iface);
28
    /* sin->sin_family = AF_INET); */
29
    res = ioctl(s, SIOCGIFADDR, &iface_request);
30
    if (res < 0) {
31
        perror("ioctl(SIOCGIFADDR)");
32
        close(s);
33

  
34
        return NULL;
35
    }
36
    close(s);
37

  
38
    inet_ntop(AF_INET, &sin->sin_addr, buff, sizeof(buff));
39

  
40
    return strdup(buff);
41
}
42

  
43

  
44

  
Tests/net_helpers.h
1
const char *iface_addr(const char *iface);
2

  
Tests/peers.txt
1
192.168.23.15 1000
2
192.168.23.16 1000
Tests/topology_test.c
1
/*
2
 *  Copyright (c) 2009 Luca Abeni
3
 *
4
 *  This is free software; see GPL.txt
5
 */
6
#include <sys/select.h>
7
#include <stdlib.h>
8
#include <stdint.h>
9
#include <stdio.h>
10
#include <string.h>
11
#include <getopt.h>
12

  
13
#include "msglayer.h"
14
#include "topmanager.h"
15
#include "net_helpers.h"
16

  
17
static const char *my_addr = "127.0.0.1";
18
static int port = 6666;
19
static int srv_port;
20
static const char *srv_ip;
21
static struct timeval tout = {1, 0};
22

  
23
static void cmdline_parse(int argc, char *argv[])
24
{
25
  int o;
26

  
27
  while ((o = getopt(argc, argv, "p:i:P:I:")) != -1) {
28
    switch(o) {
29
      case 'p':
30
        srv_port = atoi(optarg);
31
        break;
32
      case 'i':
33
        srv_ip = strdup(optarg);
34
        break;
35
      case 'P':
36
        port =  atoi(optarg);
37
        break;
38
      case 'I':
39
        my_addr = iface_addr(optarg);
40
        break;
41
      default:
42
        fprintf(stderr, "Error: unknown option %c\n", o);
43

  
44
        exit(-1);
45
    }
46
  }
47
}
48

  
49
static int wait4fd(void)
50
{
51
  struct conn_fd *c;
52
  fd_set fds;
53
  int n, i, res;
54
  int max = -1;
55
  struct timeval tv;
56

  
57
  c = getConnections(&n);
58
  FD_ZERO(&fds);
59
  for (i = 0; i < n; i++) {
60
    if (c[i].fd > max) {
61
      max = c[i].fd;
62
    }
63
    FD_SET(c[i].fd, &fds);
64
  }
65
  tv = tout;
66
  res = select(max + 1, &fds, NULL, NULL, &tv);
67
  for (i = 0; i < n; i++) {
68
    if (FD_ISSET(c[i].fd, &fds)) {
69
      //fprintf(stderr, "Connection %p %d\n", c[i].conn, c[i].fd);
70
      return c[i].fd;
71
    }
72
  }
73

  
74
  return -1;
75
}
76

  
77
static struct connectionID *fd2conn(int fd)
78
{
79
  struct conn_fd *c;
80
  int n, i;
81

  
82
  c = getConnections(&n);
83
  for (i = 0; i < n; i++) {
84
    if (c[i].fd == fd) {
85
      return c[i].conn;
86
    }
87
  }
88

  
89
  return NULL;
90
}
91

  
92
static void init(void)
93
{
94
  struct socketID *myID;
95

  
96
  myID = create_socket(my_addr, port);
97
  if (myID == NULL) {
98
    fprintf(stderr, "Error creating my socket (%s:%d)!\n", my_addr, port);
99
  }
100
  topInit(myID);
101
}
102

  
103
static void loop(void)
104
{
105
  int done = 0;
106
#define BUFFSIZE 1024
107
  static uint8_t buff[BUFFSIZE];
108
  int cnt = 0;
109
  
110
  topParseData(NULL, NULL, 0);
111
  while (!done) {
112
    int len;
113
    int fd;
114

  
115
    fd = wait4fd();
116
    if (fd > 0) {
117
      struct connectionID *conn;
118

  
119
      conn = fd2conn(fd);
120
      len = recv_data(conn, buff, BUFFSIZE);
121
      topParseData(conn, buff, len);
122
    } else {
123
      topParseData(NULL, NULL, 0);
124
      if (cnt++ % 10 == 0) {
125
        const struct socketID** neighbourhoods;
126
        int n, i;
127

  
128
        neighbourhoods = topGetNeighbourhood(&n);
129
        printf("I have %d neighbourhoods:\n", n);
130
        for (i = 0; i < n; i++) {
131
          printf("\t%d: %s\n", i, socket_addr(neighbourhoods[i]));
132
        }
133
      }
134
    }
135
  }
136
}
137

  
138
int main(int argc, char *argv[])
139
{
140
  cmdline_parse(argc, argv);
141

  
142
  init();
143
  if (srv_port != 0) {
144
    struct socketID *srv;
145

  
146
    srv = create_socket(srv_ip, srv_port);
147
    topAddNeighbour(srv);
148
  }
149

  
150
  loop();
151

  
152
  return 0;
153
}
TopologyManager/Makefile
1
BASE = ..
2

  
3
CFLAGS = -Wall
4
CFLAGS += -Wdeclaration-after-statement
5
CFLAGS += -Wno-switch -Wpointer-arith -Wredundant-decls
6
CFLAGS += -Wno-pointer-sign 
7
CFLAGS += -g
8

  
9
CPPFLAGS = -I$(BASE)/include
10

  
11
OBJS = ncast.o ncast_proto.o nccache.o
12

  
13
all: libtopman.a
14

  
15
%.a: $(OBJS)
16
	ar rcs $@ $^
17

  
18
clean:
19
	rm -f *.a
20
	rm -f *.o
TopologyManager/dummy.c
1
#include <stdint.h>
2
#include <stdio.h>
3

  
4
#include "msglayer.h"
5
#include "topmanager.h"
6

  
7
#define MAX_PEERS 5000
8
static struct socketID *table[MAX_PEERS];
9

  
10
int topInit(struct socketID *myID)
11
{
12
  FILE *f;
13
  int i = 0;
14

  
15
  f = fopen("peers.txt", "r");
16
  while(!feof(f)) {
17
    int res;
18
    char addr[32];
19
    int port;
20

  
21
    res = fscanf(f, "%s %d\n", addr, &port);
22
    if ((res == 2) && (i < MAX_PEERS - 1)) {
23
fprintf(stderr, "Creating table[%d]\n", i);
24
      table[i++] = create_socket(addr, port);
25
    }
26
  }
27
  table[i] = NULL;
28

  
29
  return i;
30
}
31

  
32
int topAddNeighbour(struct socketID *neighbour)
33
{
34
  int i;
35

  
36
  for (i = 0; table[i] != NULL; i++);
37
  table[i++] = neighbour;
38
  table[i] = NULL;
39

  
40
  return i;
41
}
42

  
43
int topParseData(const struct connectionID *conn, const uint8_t *buff, int len)
44
{
45
  /* FAKE! */
46
  return 0;
47
}
48

  
49
const struct socketID **topGetNeighbourhood(int *n)
50
{
51
  for (*n = 0; table[*n] != NULL; (*n)++) {
52
fprintf(stderr, "Checking table[%d]\n", *n);
53
  }
54
  return (const struct socketID **)table;
55
}
TopologyManager/ncast.c
1
#include <sys/time.h>
2
#include <time.h>
3
#include <stdlib.h>
4
#include <stdint.h>
5
#include <stdio.h>
6
#include <string.h>
7

  
8
#include "msglayer.h"
9
#include "topmanager.h"
10
#include "nccache.h"
11
#include "ncast_proto.h"
12
#include "proto.h"
13

  
14
#define MAX_PEERS 30
15

  
16
static uint64_t currtime;
17
static int cache_size = MAX_PEERS;
18
static struct cache_entry *local_cache;
19
static int period = 10000000;
20

  
21
static uint64_t gettime(void)
22
{
23
  struct timeval tv;
24

  
25
  gettimeofday(&tv, NULL);
26

  
27
  return tv.tv_usec + tv.tv_sec * 1000000ull;
28
}
29

  
30
static int time_to_send(void)
31
{
32
  if (gettime() - currtime > period) {
33
    currtime += period;
34

  
35
    return 1;
36
  }
37

  
38
  return 0;
39
}
40

  
41
/*
42
 * Public Functions!
43
 */
44
int topInit(struct socketID *myID)
45
{
46
  local_cache = cache_init(cache_size);
47
  if (local_cache == NULL) {
48
    return -1;
49
  }
50
  ncast_proto_init(myID);
51
  currtime = gettime();
52

  
53
  return 1;
54
}
55

  
56
int topAddNeighbour(struct socketID *neighbour)
57
{
58
  cache_add(local_cache, neighbour);
59
  return ncast_query_peer(local_cache, neighbour);
60
}
61

  
62
int topParseData(const struct connectionID *conn, const uint8_t *buff, int len)
63
{
64
  if (len) {
65
    struct ncast_header *h = (struct ncast_header *)buff;
66
    struct cache_entry *new, *remote_cache;
67

  
68
    if (h->protocol != PROTO_NCAST) {
69
      fprintf(stderr, "NCAST: Wrong protocol!\n");
70

  
71
      return -1;
72
    }
73

  
74
    if (h->type == NCAST_QUERY) {
75
      ncast_reply(conn, buff + sizeof(struct ncast_header), len - sizeof(struct ncast_header), local_cache);
76
    }
77
    remote_cache = entries_undump(buff + sizeof(struct ncast_header), len - sizeof(struct ncast_header));
78
    new = merge_caches(local_cache, remote_cache, cache_size);
79
    free(remote_cache);
80
    if (new != NULL) {
81
      free(local_cache);
82
      local_cache = new;
83
    } else {
84
      close_connection(conn);
85
    }
86
  }
87

  
88
  if (time_to_send()) {
89
    cache_update(local_cache);
90
    ncast_query(local_cache);
91
  }
92

  
93
  return 0;
94
}
95

  
96
const struct socketID **topGetNeighbourhood(int *n)
97
{
98
  static struct socketID *r[MAX_PEERS];
99

  
100
  for (*n = 0; nodeid(local_cache, *n); (*n)++) {
101
    r[*n] = nodeid(local_cache, *n);
102
    //fprintf(stderr, "Checking table[%d]\n", *n);
103
  }
104
  return (const struct socketID **)r;
105
}
106

  
107
int topGrowNeighbourhood(int n)
108
{
109
  cache_size += n;
110

  
111
  return cache_size;
112
}
113

  
114
int topShrinkNeighbourhood(int n)
115
{
116
  if (cache_size < n) {
117
    return -1;
118
  }
119
  cache_size -= n;
120

  
121
  return cache_size;
122
}
123

  
124
int topRemoveNeighbour(struct socketID *neighbour)
125
{
126
  return cache_del(local_cache, neighbour);
127
}
128

  
TopologyManager/ncast_proto.c
1
#include <stdint.h>
2
#include <stdlib.h>
3
#include <stdio.h>
4

  
5
#include "msglayer.h"
6
#include "nccache.h"
7
#include "proto.h"
8
#include "ncast_proto.h"
9

  
10
static struct cache_entry *myEntry;
11

  
12
int ncast_payload_fill(uint8_t *payload, int size, struct cache_entry *c, struct socketID *snot)
13
{
14
  int i;
15
  uint8_t *p = payload;
16

  
17
  p += entry_dump(p, myEntry, 0);
18
  for (i = 0; nodeid(c, i); i++) {
19
    if (!sockid_equal(nodeid(c, i), snot)) {
20
      if (p - payload > size - 32 /* FIXME */) {
21
        fprintf(stderr, "too many entries!\n");
22
        return -1;
23
      }
24
      p += entry_dump(p, c, i);
25
    }
26
  }
27

  
28
  return p - payload;
29
}
30

  
31
int ncast_reply(const struct connectionID *conn, const uint8_t *payload, int psize, struct cache_entry *local_cache)
32
{
33
  uint8_t pkt[1500];
34
  struct ncast_header *h = (struct ncast_header *)pkt;
35
  const struct cache_entry *c = entries_undump(payload, psize);
36
  int len;
37
  struct socketID *dst;
38

  
39
#if 0
40
  n = psize / sizeof(struct cache_entry);
41
  if (n * sizeof(struct cache_entry) != psize) {
42
    fprintf(stderr, "Wrong number of elems %d (%d / %d)!!!\n", n, psize, sizeof(struct cache_entry));
43
    return -1;
44
  }
45
#endif
46
  dst = nodeid(c, 0);
47
  h->protocol = PROTO_NCAST;
48
  h->type = NCAST_REPLY;
49
  len = ncast_payload_fill(pkt + sizeof(struct ncast_header), 1500 - sizeof(struct ncast_header), local_cache, dst);
50
  free((void *)c);
51

  
52
  return send_data(conn, pkt, sizeof(struct ncast_header) + len);
53
}
54

  
55
int ncast_query_peer(struct cache_entry *local_cache, struct socketID *dst)
56
{
57
  uint8_t pkt[1500];
58
  struct ncast_header *h = (struct ncast_header *)pkt;
59
  struct connectionID *conn;
60
  int len;
61

  
62
  h->protocol = PROTO_NCAST;
63
  h->type = NCAST_QUERY;
64
  conn = open_connection(nodeid(myEntry, 0), dst, 0);
65
  len = ncast_payload_fill(pkt + sizeof(struct ncast_header), 1500 - sizeof(struct ncast_header), local_cache, dst);
66
  return send_data(conn, pkt, sizeof(struct ncast_header) + len);
67
}
68

  
69
int ncast_query(struct cache_entry *local_cache)
70
{
71
  struct socketID *dst;
72

  
73
  dst = rand_peer(local_cache);
74
  if (dst == NULL) {
75
    return 0;
76
  }
77
  return ncast_query_peer(local_cache, dst);
78
}
79

  
80
int ncast_proto_init(struct socketID *s)
81
{
82
  myEntry = cache_init(2);
83
  cache_add(myEntry, s);
84

  
85
  return 0;
86
}
TopologyManager/ncast_proto.h
1
int ncast_payload_fill(uint8_t *payload, int size, struct cache_entry *c, struct socketID *snot);
2
int ncast_reply(const struct connectionID *conn, const uint8_t *payload, int psize, struct cache_entry *local_cache);
3
int ncast_query_peer(struct cache_entry *local_cache, struct socketID *dst);
4
int ncast_query(struct cache_entry *local_cache);
5
int ncast_proto_init(struct socketID *s);
TopologyManager/nccache.c
1
#include <stdint.h>
2
#include <stdlib.h>
3
#include <string.h>
4

  
5
#include <stdio.h>
6

  
7
#include "msglayer.h"
8
#include "nccache.h"
9

  
10
#define MAX_PEERS 50
11
struct cache_entry {
12
  struct socketID *id;
13
  uint64_t timestamp;
14
};
15

  
16
struct socketID *nodeid(const struct cache_entry *c, int i)
17
{
18
  if (c[i].timestamp == 0) {
19
    return NULL;
20
  }
21

  
22
  //fprintf(stderr, "Returning ID for TS=%lld: %p\n", c[i].timestamp, c[i].id);
23

  
24
  return c[i].id;
25
}
26

  
27
int cache_add(struct cache_entry *c, struct socketID *neighbour)
28
{
29
  int i;
30

  
31
  for (i = 0; c->timestamp != 0; i++);
32
  c[i].id = sockid_dup(neighbour);
33
  c[i++].timestamp = 1;
34
  c[i].timestamp = 0;
35
  
36
  return i;
37
}
38

  
39
int cache_del(struct cache_entry *c, struct socketID *neighbour)
40
{
41
  int i;
42
  int found = 0;
43

  
44
  for (i = 0; c->timestamp != 0; i++) {
45
    if (sockid_equal(c[i].id, neighbour)) {
46
      found = 1;
47
    }
48
    if (found) {
49
      c[i] = c[i+1];
50
    }
51
  }
52

  
53
  return i;
54
}
55

  
56
void cache_update(struct cache_entry *c)
57
{
58
  int i;
59
  
60
  for (i = 0; c[i].timestamp != 0; i++) {
61
      c[i].timestamp++;
62
  }
63
}
64

  
65
struct cache_entry *cache_init(int n)
66
{
67
  struct cache_entry *res;
68

  
69
  res = malloc(sizeof(struct cache_entry) * n);
70
  if (res) {
71
    memset(res, 0, sizeof(struct cache_entry) * n);
72
  }
73

  
74
  return res;
75
}
76

  
77
int fill_cache_entry(struct cache_entry *c, const struct socketID *s)
78
{
79
  c->id = sockid_dup(s);
80
  c->timestamp = 1;
81
#warning Timestamps are probably wrong...
82
  return 1;
83
}
84

  
85
int in_cache(const struct cache_entry *c, const struct cache_entry *elem)
86
{
87
  int i;
88

  
89
  for (i = 0; c[i].timestamp != 0; i++) {
90
    if (sockid_equal(c[i].id, elem->id)) {
91
      return 1;
92
    }
93
  }
94

  
95
  return 0;
96
}
97

  
98
struct socketID *rand_peer(struct cache_entry *c)
99
{
100
  int i, j;
101

  
102
  for (i = 0; c[i].timestamp != 0; i++);
103
  if (i == 0) {
104
    return NULL;
105
  }
106
  j = ((double)rand() / (double)RAND_MAX) * i;
107

  
108
  return c[j].id;
109
}
110

  
111
struct cache_entry *entries_undump(const uint8_t *buff, int size)
112
{
113
  struct cache_entry *res;
114
  int i = 0;
115
  const uint8_t *p = buff;
116
  
117
  res = malloc(sizeof(struct cache_entry) * MAX_PEERS);
118
  memset(res, 0, sizeof(struct cache_entry) * MAX_PEERS);
119
  while (p - buff < size) {
120
    int len;
121

  
122
    memcpy(&res[i].timestamp, p, sizeof(uint64_t));
123
    p += sizeof(uint64_t);
124
    res[i++].id = sockid_undump(p, &len);
125
    p += len;
126
  }
127
if (p - buff != size) { fprintf(stderr, "Waz!! %d != %d\n", p - buff, size); exit(-1);}
128

  
129
  return res;
130
}
131

  
132
int entry_dump(uint8_t *b, struct cache_entry *e, int i)
133
{
134
  int res;
135
  
136
  res = sizeof(uint64_t);
137
  memcpy(b, &e[i].timestamp, sizeof(uint64_t));
138
  res += sockid_dump(b + res, e[i].id);
139

  
140
  return res;
141
}
142

  
143
struct cache_entry *merge_caches(const struct cache_entry *c1, const struct cache_entry *c2, int cache_size)
144
{
145
  int i, n1, n2;
146
  struct cache_entry *new_cache;
147

  
148
  new_cache = malloc(sizeof(struct cache_entry) * cache_size);
149
  if (new_cache == NULL) {
150
    return NULL;
151
  }
152
  memset(new_cache, 0, sizeof(struct cache_entry) * cache_size);
153

  
154
  for (i = 0, n1 = 0, n2 = 0; i < cache_size;) {
155
    if ((c1[n1].timestamp == 0) && (c2[n2].timestamp == 0)) {
156
      return new_cache;
157
    }
158
    if (c1[n1].timestamp == 0) {
159
      if (!in_cache(new_cache, &c2[n2])) {
160
        new_cache[i++] = c2[n2];
161
      } else {
162
        free(c2[n2].id);
163
      }
164
      n2++;
165
    } else if (c2[n2].timestamp == 0) {
166
      if (!in_cache(new_cache, &c1[n1])) {
167
        new_cache[i++] = c1[n1];
168
      } else {
169
        free(c1[n1].id);
170
      }
171
      n1++;
172
    } else {
173
      if (c2[n2].timestamp > c1[n1].timestamp) {
174
        if (!in_cache(new_cache, &c1[n1])) {
175
          new_cache[i++] = c1[n1];
176
        } else {
177
          free(c1[n1].id);
178
        }
179
        n1++;
180
      } else {
181
        if (!in_cache(new_cache, &c2[n2])) {
182
          new_cache[i++] = c2[n2];
183
        } else {
184
          free(c2[n2].id);
185
        }
186
        n2++;
187
      }
188
    }
189
  }
190

  
191
  while (c1[n1].timestamp != 0) {
192
    free(c1[n1++].id);
193
  }
194
  while (c2[n2].timestamp != 0) {
195
    free(c2[n2++].id);
196
  }
197

  
198
  return new_cache;
199
}
TopologyManager/nccache.h
1
struct cache_entry;
2

  
3
struct socketID *nodeid(const struct cache_entry *c, int i);
4
int cache_add(struct cache_entry *c, struct socketID *neighbour);
5
int cache_del(struct cache_entry *c, struct socketID *neighbour);
6
struct cache_entry *cache_init(int n);
7
int fill_cache_entry(struct cache_entry *c, const struct socketID *s);
8
int in_cache(const struct cache_entry *c, const struct cache_entry *elem);
9
struct socketID *rand_peer(struct cache_entry *c);
10
struct cache_entry *entries_undump(const uint8_t *buff, int size);
11
int entry_dump(uint8_t *b, struct cache_entry *e, int i);
12
struct cache_entry *merge_caches(const struct cache_entry *c1, const struct cache_entry *c2, int cache_size);
13
void cache_update(struct cache_entry *c);
14
int empty(struct cache_entry *c);
15

  
TopologyManager/proto.h
1
struct ncast_header {
2
  uint8_t protocol;
3
  uint8_t type;
4
} __attribute__((packed));
5

  
6
#define PROTO_NCAST 0x10
7
#define NCAST_QUERY 0x01
8
#define NCAST_REPLY 0x02
som/Tests/Makefile
1
BASE = ..
2

  
3
CFLAGS = -Wall
4
CFLAGS += -Wdeclaration-after-statement
5
CFLAGS += -Wno-switch -Wpointer-arith -Wredundant-decls
6
CFLAGS += -Wno-pointer-sign 
7
CFLAGS += -g
8

  
9
CPPFLAGS = -I$(BASE)/include
10

  
11
LDFLAGS = -L../MsgLayer -L../TopologyManager
12
LDLIBS = -lmsglayer -ltopman
13
#LDFLAGS += -static
14

  
15
topology_test: topology_test.o net_helpers.o
16
topology_test: ../MsgLayer/libmsglayer.a
17
topology_test: ../TopologyManager/libtopman.a
18

  
19
../TopologyManager/libtopman.a:
20
	make -C ../TopologyManager
21
../MsgLayer/libmsglayer.a:
22
	make -C ../MsgLayer 
23

  
24
clean:
25
	rm -f topology_test
26
	rm -f *.o
27
allclean: clean
28
	make -C ../TopologyManager clean
29
	make -C ../MsgLayer clean
som/Tests/net_helpers.c
1
#include <sys/ioctl.h>
2
#include <sys/socket.h>
3
#include <netinet/in.h>
4
#include <arpa/inet.h>
5
#include <net/if.h>     /* For struct ifreq */
6
#include <unistd.h>
7
#include <stdlib.h>
8
#include <stdio.h>
9
#include <string.h>
10

  
11
#include "net_helpers.h"
12

  
13
const char *iface_addr(const char *iface)
14
{
15
    int s, res;
16
    struct ifreq iface_request;
17
    struct sockaddr_in *sin;
18
    char buff[512];
19

  
20
    s = socket(AF_INET, SOCK_DGRAM, 0);
21
    if (s < 0) {
22
        return NULL;
23
    }
24

  
25
    memset(&iface_request, 0, sizeof(struct ifreq));
26
    sin = (struct sockaddr_in *)&iface_request.ifr_addr;
27
    strcpy(iface_request.ifr_name, iface);
28
    /* sin->sin_family = AF_INET); */
29
    res = ioctl(s, SIOCGIFADDR, &iface_request);
30
    if (res < 0) {
31
        perror("ioctl(SIOCGIFADDR)");
32
        close(s);
33

  
34
        return NULL;
35
    }
36
    close(s);
37

  
38
    inet_ntop(AF_INET, &sin->sin_addr, buff, sizeof(buff));
39

  
40
    return strdup(buff);
41
}
42

  
43

  
44

  
som/Tests/net_helpers.h
1
const char *iface_addr(const char *iface);
2

  
som/Tests/peers.txt
1
192.168.23.15 1000
2
192.168.23.16 1000
som/Tests/topology_test.c
1
/*
2
 *  Copyright (c) 2009 Luca Abeni
3
 *
4
 *  This is free software; see GPL.txt
5
 */
6
#include <sys/select.h>
7
#include <stdlib.h>
8
#include <stdint.h>
9
#include <stdio.h>
10
#include <string.h>
11
#include <getopt.h>
12

  
13
#include "msglayer.h"
14
#include "topmanager.h"
15
#include "net_helpers.h"
16

  
17
static const char *my_addr = "127.0.0.1";
18
static int port = 6666;
19
static int srv_port;
20
static const char *srv_ip;
21
static struct timeval tout = {1, 0};
22

  
23
static void cmdline_parse(int argc, char *argv[])
24
{
25
  int o;
26

  
27
  while ((o = getopt(argc, argv, "p:i:P:I:")) != -1) {
28
    switch(o) {
29
      case 'p':
30
        srv_port = atoi(optarg);
31
        break;
32
      case 'i':
33
        srv_ip = strdup(optarg);
34
        break;
35
      case 'P':
36
        port =  atoi(optarg);
37
        break;
38
      case 'I':
39
        my_addr = iface_addr(optarg);
40
        break;
41
      default:
42
        fprintf(stderr, "Error: unknown option %c\n", o);
43

  
44
        exit(-1);
45
    }
46
  }
47
}
48

  
49
static int wait4fd(void)
50
{
51
  struct conn_fd *c;
52
  fd_set fds;
53
  int n, i, res;
54
  int max = -1;
55
  struct timeval tv;
56

  
57
  c = getConnections(&n);
58
  FD_ZERO(&fds);
59
  for (i = 0; i < n; i++) {
60
    if (c[i].fd > max) {
61
      max = c[i].fd;
62
    }
63
    FD_SET(c[i].fd, &fds);
64
  }
65
  tv = tout;
66
  res = select(max + 1, &fds, NULL, NULL, &tv);
67
  for (i = 0; i < n; i++) {
68
    if (FD_ISSET(c[i].fd, &fds)) {
69
      //fprintf(stderr, "Connection %p %d\n", c[i].conn, c[i].fd);
70
      return c[i].fd;
71
    }
72
  }
73

  
74
  return -1;
75
}
76

  
77
static struct connectionID *fd2conn(int fd)
78
{
79
  struct conn_fd *c;
80
  int n, i;
81

  
82
  c = getConnections(&n);
83
  for (i = 0; i < n; i++) {
84
    if (c[i].fd == fd) {
85
      return c[i].conn;
86
    }
87
  }
88

  
89
  return NULL;
90
}
91

  
92
static void init(void)
93
{
94
  struct socketID *myID;
95

  
96
  myID = create_socket(my_addr, port);
97
  if (myID == NULL) {
98
    fprintf(stderr, "Error creating my socket (%s:%d)!\n", my_addr, port);
99
  }
100
  topInit(myID);
101
}
102

  
103
static void loop(void)
104
{
105
  int done = 0;
106
#define BUFFSIZE 1024
107
  static uint8_t buff[BUFFSIZE];
108
  int cnt = 0;
109
  
110
  topParseData(NULL, NULL, 0);
111
  while (!done) {
112
    int len;
113
    int fd;
114

  
115
    fd = wait4fd();
116
    if (fd > 0) {
117
      struct connectionID *conn;
118

  
119
      conn = fd2conn(fd);
120
      len = recv_data(conn, buff, BUFFSIZE);
121
      topParseData(conn, buff, len);
122
    } else {
123
      topParseData(NULL, NULL, 0);
124
      if (cnt++ % 10 == 0) {
125
        const struct socketID** neighbourhoods;
126
        int n, i;
127

  
128
        neighbourhoods = topGetNeighbourhood(&n);
129
        printf("I have %d neighbourhoods:\n", n);
130
        for (i = 0; i < n; i++) {
131
          printf("\t%d: %s\n", i, socket_addr(neighbourhoods[i]));
132
        }
133
      }
134
    }
135
  }
136
}
137

  
138
int main(int argc, char *argv[])
139
{
140
  cmdline_parse(argc, argv);
141

  
142
  init();
143
  if (srv_port != 0) {
144
    struct socketID *srv;
145

  
146
    srv = create_socket(srv_ip, srv_port);
147
    topAddNeighbour(srv);
148
  }
149

  
150
  loop();
151

  
152
  return 0;
153
}
som/TopologyManager/Makefile
1
BASE = ../..
2

  
3
CFLAGS = -Wall
4
CFLAGS += -Wdeclaration-after-statement
5
CFLAGS += -Wno-switch -Wpointer-arith -Wredundant-decls
6
CFLAGS += -Wno-pointer-sign 
7
CFLAGS += -g
8

  
9
CPPFLAGS = -I$(BASE)/include
10

  
11
OBJS = ncast.o ncast_proto.o nccache.o
12

  
13
all: libtopman.a
14

  
15
%.a: $(OBJS)
16
	ar rcs $@ $^
17

  
18
clean:
19
	rm -f *.a
20
	rm -f *.o
som/TopologyManager/dummy.c
1
#include <stdint.h>
2
#include <stdio.h>
3

  
4
#include "msglayer.h"
5
#include "topmanager.h"
6

  
7
#define MAX_PEERS 5000
8
static struct socketID *table[MAX_PEERS];
9

  
10
int topInit(struct socketID *myID)
11
{
12
  FILE *f;
13
  int i = 0;
14

  
15
  f = fopen("peers.txt", "r");
16
  while(!feof(f)) {
17
    int res;
18
    char addr[32];
19
    int port;
20

  
21
    res = fscanf(f, "%s %d\n", addr, &port);
22
    if ((res == 2) && (i < MAX_PEERS - 1)) {
23
fprintf(stderr, "Creating table[%d]\n", i);
24
      table[i++] = create_socket(addr, port);
25
    }
26
  }
27
  table[i] = NULL;
28

  
29
  return i;
30
}
31

  
32
int topAddNeighbour(struct socketID *neighbour)
33
{
34
  int i;
35

  
36
  for (i = 0; table[i] != NULL; i++);
37
  table[i++] = neighbour;
38
  table[i] = NULL;
39

  
40
  return i;
41
}
42

  
43
int topParseData(const struct connectionID *conn, const uint8_t *buff, int len)
44
{
45
  /* FAKE! */
46
  return 0;
47
}
48

  
49
const struct socketID **topGetNeighbourhood(int *n)
50
{
51
  for (*n = 0; table[*n] != NULL; (*n)++) {
52
fprintf(stderr, "Checking table[%d]\n", *n);
53
  }
54
  return (const struct socketID **)table;
55
}
som/TopologyManager/ncast.c
1
#include <sys/time.h>
2
#include <time.h>
3
#include <stdlib.h>
4
#include <stdint.h>
5
#include <stdio.h>
6
#include <string.h>
7

  
8
#include "msglayer.h"
9
#include "topmanager.h"
10
#include "nccache.h"
11
#include "ncast_proto.h"
12
#include "proto.h"
13

  
14
#define MAX_PEERS 30
15

  
16
static uint64_t currtime;
17
static int cache_size = MAX_PEERS;
18
static struct cache_entry *local_cache;
19
static int period = 10000000;
20

  
21
static uint64_t gettime(void)
22
{
23
  struct timeval tv;
24

  
25
  gettimeofday(&tv, NULL);
26

  
27
  return tv.tv_usec + tv.tv_sec * 1000000ull;
28
}
29

  
30
static int time_to_send(void)
31
{
32
  if (gettime() - currtime > period) {
33
    currtime += period;
34

  
35
    return 1;
36
  }
37

  
38
  return 0;
39
}
40

  
41
/*
42
 * Public Functions!
43
 */
44
int topInit(struct socketID *myID)
45
{
46
  local_cache = cache_init(cache_size);
47
  if (local_cache == NULL) {
48
    return -1;
49
  }
50
  ncast_proto_init(myID);
51
  currtime = gettime();
52

  
53
  return 1;
54
}
55

  
56
int topAddNeighbour(struct socketID *neighbour)
57
{
58
  cache_add(local_cache, neighbour);
59
  return ncast_query_peer(local_cache, neighbour);
60
}
61

  
62
int topParseData(const struct connectionID *conn, const uint8_t *buff, int len)
63
{
64
  if (len) {
65
    struct ncast_header *h = (struct ncast_header *)buff;
66
    struct cache_entry *new, *remote_cache;
67

  
68
    if (h->protocol != PROTO_NCAST) {
69
      fprintf(stderr, "NCAST: Wrong protocol!\n");
70

  
71
      return -1;
72
    }
73

  
74
    if (h->type == NCAST_QUERY) {
75
      ncast_reply(conn, buff + sizeof(struct ncast_header), len - sizeof(struct ncast_header), local_cache);
76
    }
77
    remote_cache = entries_undump(buff + sizeof(struct ncast_header), len - sizeof(struct ncast_header));
78
    new = merge_caches(local_cache, remote_cache, cache_size);
79
    free(remote_cache);
80
    if (new != NULL) {
81
      free(local_cache);
82
      local_cache = new;
83
    } else {
84
      close_connection(conn);
85
    }
86
  }
87

  
88
  if (time_to_send()) {
89
    cache_update(local_cache);
90
    ncast_query(local_cache);
91
  }
92

  
93
  return 0;
94
}
95

  
96
const struct socketID **topGetNeighbourhood(int *n)
97
{
98
  static struct socketID *r[MAX_PEERS];
99

  
100
  for (*n = 0; nodeid(local_cache, *n); (*n)++) {
101
    r[*n] = nodeid(local_cache, *n);
102
    //fprintf(stderr, "Checking table[%d]\n", *n);
103
  }
104
  return (const struct socketID **)r;
105
}
106

  
107
int topGrowNeighbourhood(int n)
108
{
109
  cache_size += n;
110

  
111
  return cache_size;
112
}
113

  
114
int topShrinkNeighbourhood(int n)
115
{
116
  if (cache_size < n) {
117
    return -1;
118
  }
119
  cache_size -= n;
120

  
121
  return cache_size;
122
}
123

  
124
int topRemoveNeighbour(struct socketID *neighbour)
125
{
126
  return cache_del(local_cache, neighbour);
127
}
128

  
som/TopologyManager/ncast_proto.c
1
#include <stdint.h>
2
#include <stdlib.h>
3
#include <stdio.h>
4

  
5
#include "msglayer.h"
6
#include "nccache.h"
7
#include "proto.h"
8
#include "ncast_proto.h"
9

  
10
static struct cache_entry *myEntry;
11

  
12
int ncast_payload_fill(uint8_t *payload, int size, struct cache_entry *c, struct socketID *snot)
13
{
14
  int i;
15
  uint8_t *p = payload;
16

  
17
  p += entry_dump(p, myEntry, 0);
18
  for (i = 0; nodeid(c, i); i++) {
19
    if (!sockid_equal(nodeid(c, i), snot)) {
20
      if (p - payload > size - 32 /* FIXME */) {
21
        fprintf(stderr, "too many entries!\n");
22
        return -1;
23
      }
24
      p += entry_dump(p, c, i);
25
    }
26
  }
27

  
28
  return p - payload;
29
}
30

  
31
int ncast_reply(const struct connectionID *conn, const uint8_t *payload, int psize, struct cache_entry *local_cache)
32
{
33
  uint8_t pkt[1500];
34
  struct ncast_header *h = (struct ncast_header *)pkt;
35
  const struct cache_entry *c = entries_undump(payload, psize);
36
  int len;
37
  struct socketID *dst;
38

  
39
#if 0
40
  n = psize / sizeof(struct cache_entry);
41
  if (n * sizeof(struct cache_entry) != psize) {
42
    fprintf(stderr, "Wrong number of elems %d (%d / %d)!!!\n", n, psize, sizeof(struct cache_entry));
43
    return -1;
44
  }
45
#endif
46
  dst = nodeid(c, 0);
47
  h->protocol = PROTO_NCAST;
48
  h->type = NCAST_REPLY;
49
  len = ncast_payload_fill(pkt + sizeof(struct ncast_header), 1500 - sizeof(struct ncast_header), local_cache, dst);
50
  free((void *)c);
51

  
52
  return send_data(conn, pkt, sizeof(struct ncast_header) + len);
53
}
54

  
55
int ncast_query_peer(struct cache_entry *local_cache, struct socketID *dst)
56
{
57
  uint8_t pkt[1500];
58
  struct ncast_header *h = (struct ncast_header *)pkt;
59
  struct connectionID *conn;
60
  int len;
61

  
62
  h->protocol = PROTO_NCAST;
63
  h->type = NCAST_QUERY;
64
  conn = open_connection(nodeid(myEntry, 0), dst, 0);
65
  len = ncast_payload_fill(pkt + sizeof(struct ncast_header), 1500 - sizeof(struct ncast_header), local_cache, dst);
66
  return send_data(conn, pkt, sizeof(struct ncast_header) + len);
67
}
68

  
69
int ncast_query(struct cache_entry *local_cache)
70
{
71
  struct socketID *dst;
72

  
73
  dst = rand_peer(local_cache);
74
  if (dst == NULL) {
75
    return 0;
76
  }
77
  return ncast_query_peer(local_cache, dst);
78
}
79

  
80
int ncast_proto_init(struct socketID *s)
81
{
82
  myEntry = cache_init(2);
83
  cache_add(myEntry, s);
84

  
85
  return 0;
86
}
som/TopologyManager/ncast_proto.h
1
int ncast_payload_fill(uint8_t *payload, int size, struct cache_entry *c, struct socketID *snot);
2
int ncast_reply(const struct connectionID *conn, const uint8_t *payload, int psize, struct cache_entry *local_cache);
3
int ncast_query_peer(struct cache_entry *local_cache, struct socketID *dst);
4
int ncast_query(struct cache_entry *local_cache);
5
int ncast_proto_init(struct socketID *s);
som/TopologyManager/nccache.c
1
#include <stdint.h>
2
#include <stdlib.h>
3
#include <string.h>
4

  
5
#include <stdio.h>
6

  
7
#include "msglayer.h"
8
#include "nccache.h"
9

  
10
#define MAX_PEERS 50
11
struct cache_entry {
12
  struct socketID *id;
13
  uint64_t timestamp;
14
};
15

  
16
struct socketID *nodeid(const struct cache_entry *c, int i)
17
{
18
  if (c[i].timestamp == 0) {
19
    return NULL;
20
  }
21

  
22
  //fprintf(stderr, "Returning ID for TS=%lld: %p\n", c[i].timestamp, c[i].id);
23

  
24
  return c[i].id;
25
}
26

  
27
int cache_add(struct cache_entry *c, struct socketID *neighbour)
28
{
29
  int i;
30

  
31
  for (i = 0; c->timestamp != 0; i++);
32
  c[i].id = sockid_dup(neighbour);
33
  c[i++].timestamp = 1;
34
  c[i].timestamp = 0;
35
  
36
  return i;
37
}
38

  
39
int cache_del(struct cache_entry *c, struct socketID *neighbour)
40
{
41
  int i;
42
  int found = 0;
43

  
44
  for (i = 0; c->timestamp != 0; i++) {
45
    if (sockid_equal(c[i].id, neighbour)) {
46
      found = 1;
47
    }
48
    if (found) {
49
      c[i] = c[i+1];
50
    }
51
  }
52

  
53
  return i;
54
}
55

  
56
void cache_update(struct cache_entry *c)
57
{
58
  int i;
59
  
60
  for (i = 0; c[i].timestamp != 0; i++) {
61
      c[i].timestamp++;
62
  }
63
}
64

  
65
struct cache_entry *cache_init(int n)
66
{
67
  struct cache_entry *res;
68

  
69
  res = malloc(sizeof(struct cache_entry) * n);
70
  if (res) {
71
    memset(res, 0, sizeof(struct cache_entry) * n);
72
  }
73

  
74
  return res;
75
}
76

  
77
int fill_cache_entry(struct cache_entry *c, const struct socketID *s)
78
{
79
  c->id = sockid_dup(s);
80
  c->timestamp = 1;
81
#warning Timestamps are probably wrong...
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff