Statistics
| Branch: | Revision:

grapes / src / net_helper-udp.c @ f872ab6f

History | View | Annotate | Download (9 KB)

1
/*
2
 *  Copyright (c) 2010 Luca Abeni
3
 *  Copyright (c) 2010 Csaba Kiraly
4
 *  Copyright (c) 2010 Alessandro Russo
5
 *
6
 *  This is free software; see lgpl-2.1.txt
7
 */
8

    
9
#include <sys/types.h>
10
#include <unistd.h>
11
#include <errno.h>
12
#include <stdlib.h>
13
#include <stdint.h>
14
#include <stdio.h>
15
#include <string.h>
16

    
17
#ifndef _WIN32
18
#include <sys/socket.h>
19
#include <netinet/in.h>
20
#include <netdb.h>
21
#include <arpa/inet.h>
22
#else
23
#define _WIN32_WINNT 0x0501 /* WINNT>=0x501 (WindowsXP) for supporting getaddrinfo/freeaddrinfo.*/
24
#include "win32-net.h"
25
#endif
26

    
27
#include "net_helper.h"
28

    
29
#define MAX_MSG_SIZE 1024 * 60
30
enum L3PROTOCOL {IPv4, IPv6} l3 = IPv4;
31

    
32
struct nodeID {
33
  struct sockaddr_storage addr;
34
  int fd;
35
};
36

    
37
int wait4data(const struct nodeID *s, struct timeval *tout, int *user_fds)
38
/* returns 0 if timeout expires 
39
 * returns -1 in case of error of the select function
40
 * retruns 1 if the nodeID file descriptor is ready to be read
41
 *                                         (i.e., some data is ready from the network socket)
42
 * returns 2 if some of the user_fds file descriptors is ready
43
 */
44
{
45
  fd_set fds;
46
  int i, res, max_fd;
47

    
48
  FD_ZERO(&fds);
49
  if (s) {
50
    max_fd = s->fd;
51
    FD_SET(s->fd, &fds);
52
  } else {
53
    max_fd = -1;
54
  }
55
  if (user_fds) {
56
    for (i = 0; user_fds[i] != -1; i++) {
57
      FD_SET(user_fds[i], &fds);
58
      if (user_fds[i] > max_fd) {
59
        max_fd = user_fds[i];
60
      }
61
    }
62
  }
63
  res = select(max_fd + 1, &fds, NULL, NULL, tout);
64
  if (res <= 0) {
65
    return res;
66
  }
67
  if (s && FD_ISSET(s->fd, &fds)) {
68
    return 1;
69
  }
70

    
71
  /* If execution arrives here, user_fds cannot be 0
72
     (an FD is ready, and it's not s->fd) */
73
  for (i = 0; user_fds[i] != -1; i++) {
74
    if (!FD_ISSET(user_fds[i], &fds)) {
75
      user_fds[i] = -2;
76
    }
77
  }
78

    
79
  return 2;
80
}
81

    
82
struct nodeID *create_node(const char *IPaddr, int port)
83
{
84
  struct nodeID *s;
85
  int res;
86
  struct addrinfo hints, *result;
87

    
88
  memset(&hints, 0, sizeof(hints));
89
  hints.ai_family = AF_UNSPEC;
90
  hints.ai_flags = AI_NUMERICHOST;
91

    
92
  s = malloc(sizeof(struct nodeID));
93
  memset(s, 0, sizeof(struct nodeID));
94

    
95
  if ((res = getaddrinfo(IPaddr, NULL, &hints, &result)))
96
  {
97
    fprintf(stderr, "Cannot resolve hostname '%s'\n", IPaddr);
98
    return NULL;
99
  }
100
  s->addr.ss_family = result->ai_family;
101
  switch (result->ai_family)
102
  {
103
    case (AF_INET):
104
      ((struct sockaddr_in *)&s->addr)->sin_port = htons(port);
105
      res = inet_pton (result->ai_family, IPaddr, &((struct sockaddr_in *)&s->addr)->sin_addr);
106
    break;
107
    case (AF_INET6):
108
      ((struct sockaddr_in6 *)&s->addr)->sin6_port = htons(port);
109
      res = inet_pton (result->ai_family, IPaddr, &(((struct sockaddr_in6 *) &s->addr)->sin6_addr));
110
    break;
111
    default:
112
      fprintf(stderr, "Cannot resolve address family %d for '%s'\n", result->ai_family, IPaddr);
113
      res = 0;
114
      break;
115
  }
116
  freeaddrinfo(result);
117
  if (res != 1)
118
  {
119
    fprintf(stderr, "Could not convert address '%s'\n", IPaddr);
120
    free(s);
121

    
122
    return NULL;
123
  }
124

    
125
  s->fd = -1;
126

    
127
  return s;
128
}
129

    
130
struct nodeID *net_helper_init(const char *my_addr, int port, const char *config)
131
{
132
  int res;
133
  struct nodeID *myself;
134

    
135
  myself = create_node(my_addr, port);
136
  if (myself == NULL) {
137
    fprintf(stderr, "Error creating my socket (%s:%d)!\n", my_addr, port);
138

    
139
    return NULL;
140
  }
141
  myself->fd =  socket(myself->addr.ss_family, SOCK_DGRAM, 0);
142
  if (myself->fd < 0) {
143
    free(myself);
144

    
145
    return NULL;
146
  }
147
//  TODO:
148
//  if (addr->sa_family == AF_INET6) {
149
//      r = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
150
//  }
151

    
152
  fprintf(stderr, "My sock: %d\n", myself->fd);
153

    
154
  switch (myself->addr.ss_family)
155
  {
156
    case (AF_INET):
157
        res = bind(myself->fd, (struct sockaddr *)&myself->addr, sizeof(struct sockaddr_in));
158
    break;
159
    case (AF_INET6):
160
        res = bind(myself->fd, (struct sockaddr *)&myself->addr, sizeof(struct sockaddr_in6));
161
    break;
162
    default:
163
      fprintf(stderr, "Cannot resolve address family %d in bind\n", myself->addr.ss_family);
164
      res = 0;
165
    break;
166
  }
167

    
168
  if (res < 0) {
169
    /* bind failed: not a local address... Just close the socket! */
170
    close(myself->fd);
171
    free(myself);
172

    
173
    return NULL;
174
  }
175

    
176
  return myself;
177
}
178

    
179
void bind_msg_type (uint8_t msgtype)
180
{
181
}
182

    
183
struct my_hdr_t {
184
  uint8_t m_seq;
185
  uint8_t frag_seq;
186
  uint8_t frags;
187
} __attribute__((packed));
188

    
189
int send_to_peer(const struct nodeID *from,const  struct nodeID *to, const uint8_t *buffer_ptr, int buffer_size)
190
{
191
  struct msghdr msg = {0};
192
  static struct my_hdr_t my_hdr;
193
  struct iovec iov[2];
194
  int res;
195

    
196
  iov[0].iov_base = &my_hdr;
197
  iov[0].iov_len = sizeof(struct my_hdr_t);
198
  msg.msg_name = &to->addr;
199
  msg.msg_namelen = sizeof(struct sockaddr_storage);
200
  msg.msg_iovlen = 2;
201
  msg.msg_iov = iov;
202

    
203
  my_hdr.m_seq++;
204
  my_hdr.frags = (buffer_size / (MAX_MSG_SIZE)) + 1;
205
  my_hdr.frag_seq = 0;
206

    
207
  do {
208
    iov[1].iov_base = buffer_ptr;
209
    if (buffer_size > MAX_MSG_SIZE) {
210
      iov[1].iov_len = MAX_MSG_SIZE;
211
    } else {
212
      iov[1].iov_len = buffer_size;
213
    }
214
    my_hdr.frag_seq++;
215

    
216
    buffer_size -= iov[1].iov_len;
217
    buffer_ptr += iov[1].iov_len;
218
    res = sendmsg(from->fd, &msg, 0);
219

    
220
    if (res  < 0){
221
      int error = errno;
222
      fprintf(stderr,"net-helper: sendmsg failed errno %d: %s\n", error, strerror(error));
223
    }
224
  } while (buffer_size > 0);
225

    
226
  return res;
227
}
228

    
229
int recv_from_peer(const struct nodeID *local, struct nodeID **remote, uint8_t *buffer_ptr, int buffer_size)
230
{
231
  int res, recv, m_seq, frag_seq;
232
  struct sockaddr_storage raddr;
233
  struct msghdr msg = {0};
234
  static struct my_hdr_t my_hdr;
235
  struct iovec iov[2];
236

    
237
  iov[0].iov_base = &my_hdr;
238
  iov[0].iov_len = sizeof(struct my_hdr_t);
239
  msg.msg_name = &raddr;
240
  msg.msg_namelen = sizeof(struct sockaddr_storage);
241
  msg.msg_iovlen = 2;
242
  msg.msg_iov = iov;
243

    
244
  *remote = malloc(sizeof(struct nodeID));
245
  if (*remote == NULL) {
246
    return -1;
247
  }
248

    
249
  recv = 0;
250
  m_seq = -1;
251
  frag_seq = 0;
252
  do {
253
    iov[1].iov_base = buffer_ptr;
254
    if (buffer_size > MAX_MSG_SIZE) {
255
      iov[1].iov_len = MAX_MSG_SIZE;
256
    } else {
257
      iov[1].iov_len = buffer_size;
258
    }
259
    buffer_size -= iov[1].iov_len;
260
    buffer_ptr += iov[1].iov_len;
261
    res = recvmsg(local->fd, &msg, 0);
262
    recv += (res - sizeof(struct my_hdr_t));
263
    if (m_seq != -1 && my_hdr.m_seq != m_seq) {
264
      return -1;
265
    } else {
266
      m_seq = my_hdr.m_seq;
267
    }
268
    if (my_hdr.frag_seq != frag_seq + 1) {
269
      return -1;
270
    } else {
271
     frag_seq++;
272
    }
273
  } while ((my_hdr.frag_seq < my_hdr.frags) && (buffer_size > 0));
274
  memcpy(&(*remote)->addr, &raddr, msg.msg_namelen);
275
  (*remote)->fd = -1;
276

    
277
  return recv;
278
}
279

    
280
int node_addr(const struct nodeID *s, char *addr, int len)
281
{
282
  int n;
283

    
284
        if (s && node_ip(s, addr, len)>=0)
285
        {
286
                n = snprintf(addr + strlen(addr), len - strlen(addr) - 1, ":%d", node_port(s));
287
        } else
288
                n = snprintf(addr, len , "None");
289

    
290
  return n;
291
}
292

    
293
struct nodeID *nodeid_dup(const struct nodeID *s)
294
{
295
  struct nodeID *res;
296

    
297
  res = malloc(sizeof(struct nodeID));
298
  if (res != NULL) {
299
    memcpy(res, s, sizeof(struct nodeID));
300
  }
301

    
302
  return res;
303
}
304

    
305
int nodeid_equal(const struct nodeID *s1, const struct nodeID *s2)
306
{
307
        return (nodeid_cmp(s1,s2) == 0);
308
//  return (memcmp(&s1->addr, &s2->addr, sizeof(struct sockaddr_storage)) == 0);
309
}
310

    
311
int nodeid_cmp(const struct nodeID *s1, const struct nodeID *s2)
312
{
313
        char ip1[80], ip2[80];
314
        int port1,port2,res;
315

    
316
        port1=node_port(s1);
317
        port2=node_port(s2);
318
        node_ip(s1,ip1,80);
319
        node_ip(s2,ip2,80);
320

    
321
//        int res = (port1^port2)|strcmp(ip1,ip2);
322
//        fprintf(stderr,"Comparing %s:%d and %s:%d\n",ip1,port1,ip2,port2);
323
//        fprintf(stderr,"Result: %d\n",res);
324
        res  = strcmp(ip1,ip2);
325
        if (res!=0)
326
                return res;
327
        else
328
                return port1-port2;
329
//                return port1 == port2 ? 0 : 1;
330

    
331
//  return memcmp(&s1->addr, &s2->addr, sizeof(struct sockaddr_storage));
332
}
333

    
334
int nodeid_dump(uint8_t *b, const struct nodeID *s, size_t max_write_size)
335
{
336
  if (max_write_size < sizeof(struct sockaddr_storage)) return -1;
337

    
338
  memcpy(b, &s->addr, sizeof(struct sockaddr_storage));
339

    
340
  return sizeof(struct sockaddr_storage);
341
}
342

    
343
struct nodeID *nodeid_undump(const uint8_t *b, int *len)
344
{
345
  struct nodeID *res;
346
  res = malloc(sizeof(struct nodeID));
347
  if (res != NULL) {
348
    memcpy(&res->addr, b, sizeof(struct sockaddr_storage));
349
    res->fd = -1;
350
  }
351
  *len = sizeof(struct sockaddr_storage);
352

    
353
  return res;
354
}
355

    
356
void nodeid_free(struct nodeID *s)
357
{
358
  free(s);
359
}
360

    
361
int node_ip(const struct nodeID *s, char *ip, int len)
362
{
363
        int res = 0;
364
  switch (s->addr.ss_family)
365
  {
366
    case AF_INET:
367
      inet_ntop(s->addr.ss_family, &((const struct sockaddr_in *)&s->addr)->sin_addr, ip, len);
368
      break;
369
    case AF_INET6:
370
      inet_ntop(s->addr.ss_family, &((const struct sockaddr_in6 *)&s->addr)->sin6_addr, ip, len);
371
      break;
372
    default:
373
                        res = -1;
374
      break;
375
  }
376
  if (!ip) {
377
          perror("inet_ntop");
378
                res = -1;
379
  }
380
  if (ip && res <0 && len)
381
    ip[0] = '\0';
382
  return res;
383
}
384

    
385
int node_port(const struct nodeID *s)
386
{
387
  int res;
388
  switch (s->addr.ss_family)
389
  {
390
    case AF_INET:
391
      res = ntohs(((const struct sockaddr_in *) &s->addr)->sin_port);
392
      break;
393
    case AF_INET6:
394
      res = ntohs(((const struct sockaddr_in6 *)&s->addr)->sin6_port);
395
      break;
396
    default:
397
      res = -1;
398
      break;
399
  }
400
  return res;
401
}