Statistics
| Branch: | Revision:

napa-baselibs / ml / ml.c @ 612e856d

History | View | Annotate | Download (63.1 KB)

1
/*
2
 *          Policy Management
3
 *
4
 *          NEC Europe Ltd. PROPRIETARY INFORMATION
5
 *
6
 * This software is supplied under the terms of a license agreement
7
 * or nondisclosure agreement with NEC Europe Ltd. and may not be
8
 * copied or disclosed except in accordance with the terms of that
9
 * agreement.
10
 *
11
 *      Copyright (c) 2009 NEC Europe Ltd. All Rights Reserved.
12
 *
13
 * Authors: Kristian Beckers  <beckers@nw.neclab.eu>
14
 *          Sebastian Kiesel  <kiesel@nw.neclab.eu>
15
 *          
16
 *
17
 * NEC Europe Ltd. DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED,
18
 * INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY
19
 * AND FITNESS FOR A PARTICULAR PURPOSE AND THE WARRANTY AGAINST LATENT
20
 * DEFECTS, WITH RESPECT TO THE PROGRAM AND THE ACCOMPANYING
21
 * DOCUMENTATION.
22
 *
23
 * No Liability For Consequential Damages IN NO EVENT SHALL NEC Europe
24
 * Ltd., NEC Corporation OR ANY OF ITS SUBSIDIARIES BE LIABLE FOR ANY
25
 * DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS
26
 * OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF INFORMATION, OR
27
 * OTHER PECUNIARY LOSS AND INDIRECT, CONSEQUENTIAL, INCIDENTAL,
28
 * ECONOMIC OR PUNITIVE DAMAGES) ARISING OUT OF THE USE OF OR INABILITY
29
 * TO USE THIS PROGRAM, EVEN IF NEC Europe Ltd. HAS BEEN ADVISED OF THE
30
 * POSSIBILITY OF SUCH DAMAGES.
31
 *
32
 *     THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
33
 */
34

    
35
#include <stdlib.h>
36
#include <unistd.h>
37
#include <stdio.h>
38
#include <stddef.h>
39
#include <stdint.h>
40
#include <string.h>
41
#include <sys/types.h>
42
#include <time.h>
43
#include <math.h>
44
#include <assert.h>
45
#include <errno.h>
46

    
47
#ifndef WIN32
48
#include <arpa/inet.h>
49
#include <netdb.h>
50
#include <netinet/in.h>
51
#include <sys/socket.h>
52
#include <fcntl.h>
53
#else
54

    
55
#include <winsock2.h>
56
#include <ws2tcpip.h>
57
#endif
58

    
59
#include "util/udpSocket.h"
60
#include "util/stun.h"
61
#include "transmissionHandler.h"
62
#include "util/rateLimiter.h"
63
#include "util/queueManagement.h"
64

    
65
#define LOG_MODULE "[ml] "
66
#include "ml_log.h"
67

    
68
/**************************** START OF INTERNALS ***********************/
69

    
70

    
71
/*
72
 * reserved message type for internal puposes
73
 */
74
#define MSG_TYPE_ML_KEEPALIVE 0x126        //TODO: check that it is really interpreted as internal
75

    
76
/*
77
 * a pointer to a libevent instance
78
 */
79
struct event_base *base;
80

    
81
/*
82
 * define the nr of connections the messaging layer can handle
83
 */
84
#define CONNECTBUFSIZE 10000
85
/*
86
 * define the nr of data that can be received parallel
87
 */
88
#define RECVDATABUFSIZE 10000
89
/*
90
 * define an array for message multiplexing
91
 */
92
#define MSGMULTIPLEXSIZE 127
93

    
94

    
95
/*
96
 * timeout before thinking that the STUN server can't be connected
97
 */
98
#define NAT_TRAVERSAL_TIMEOUT { 1, 0 }
99

    
100
/*
101
 * timeout before thinking of an mtu problem (check MAX_TRIALS as well)
102
 */
103
#define PMTU_TIMEOUT { 0, 500000 }
104

    
105
/*
106
 * retry sending connection messages this many times before reducing pmtu
107
 */
108
#define MAX_TRIALS 3
109

    
110
/*
111
 * default timeout value between the first and the last received packet of a message
112
 */
113
#define RECV_TIMEOUT_DEFAULT { 2, 0 }
114

    
115
/*
116
 * global variables
117
 */
118
/*
119
 * define a buffer of pointers to connect structures
120
 */
121
connect_data *connectbuf[CONNECTBUFSIZE];
122

    
123
/*
124
 * define a pointer buffer with pointers to recv_data structures
125
 */
126
recvdata *recvdatabuf[RECVDATABUFSIZE];
127

    
128
/*
129
 * define a pointer buffer for message multiplexing
130
 */
131
receive_data_cb recvcbbuf[MSGMULTIPLEXSIZE];
132

    
133
/*
134
 * stun server address
135
 */
136
struct sockaddr_in stun_server;
137

    
138
/*
139
 * receive timeout
140
 */
141
static struct timeval recv_timeout = RECV_TIMEOUT_DEFAULT;
142

    
143
/*
144
 * boolean NAT traversal successful if true
145
 */
146
boolean NAT_traversal;
147

    
148
/*
149
 * file descriptor for local socket
150
 */
151
evutil_socket_t socketfd;
152

    
153
/*
154
 * local socketID
155
 */
156
socket_ID local_socketID;
157

    
158
socketID_handle loc_socketID = &local_socketID;
159

    
160
/*
161
 * callback function pointers
162
 */
163
/*
164
 * monitoring module callbacks
165
 */
166
get_recv_pkt_inf_cb get_Recv_pkt_inf_cb = NULL;
167
get_send_pkt_inf_cb get_Send_pkt_inf_cb = NULL;
168
set_monitoring_header_pkt_cb set_Monitoring_header_pkt_cb = NULL;
169
get_recv_data_inf_cb get_Recv_data_inf_cb = NULL;
170
get_send_data_inf_cb get_Send_data_inf_cb = NULL;
171
set_monitoring_header_data_cb set_Monitoring_header_data_cb = NULL;
172
/*
173
 * connection callbacks
174
 */
175
receive_connection_cb receive_Connection_cb = NULL;
176
connection_failed_cb failed_Connection_cb = NULL;
177
/*
178
 * local socketID callback
179
 */
180
receive_localsocketID_cb receive_SocketID_cb;
181

    
182
/*
183
 * boolean that defines if received data is transmitted to the upper layer
184
 * via callback or via upper layer polling
185
 */
186
boolean recv_data_callback;
187

    
188
/*
189
 * helper function to get rid of a warning
190
 */
191
#ifndef WIN32
192
int min(int a, int b) {
193
        if (a > b) return b;
194
        return a;
195
}
196
#endif
197

    
198
/*
199
 * convert a socketID to a string. It uses a static buffer, so either strdup is needed, or the string will get lost!
200
 */
201
const char *conid_to_string(int con_id)
202
{
203
        static char s[INET_ADDRSTRLEN+1+5+1+INET_ADDRSTRLEN+1+5+1];
204
        mlSocketIDToString(&connectbuf[con_id]->external_socketID, s, sizeof(s));
205
        return s;
206
}
207

    
208
void register_recv_localsocketID_cb(receive_localsocketID_cb local_socketID_cb)
209
{
210
        if (local_socketID_cb == NULL) {
211
                error("ML : Register receive_localsocketID_cb: NULL ptr \n");
212
        } else {
213
                receive_SocketID_cb = local_socketID_cb;
214
        }
215
}
216

    
217

    
218
//void keep_connection_alive(const int connectionID)
219
//{
220
//
221
//    // to be done with the NAT traversal
222
//    // send a message over the wire
223
//    printf("\n");
224
//
225
//}
226

    
227
void unsetStunServer()
228
{
229
        stun_server.sin_addr.s_addr = INADDR_NONE;
230
}
231

    
232
bool isStunDefined()
233
{
234
        return stun_server.sin_addr.s_addr != INADDR_NONE;
235
}
236

    
237
void send_msg(int con_id, int msg_type, char* msg, int msg_len, bool truncable, send_params * sParams) {
238
        socketaddrgen udpgen;
239
        bool retry;
240
        int pkt_len, offset;
241
        struct iovec iov[4];
242

    
243
        char h_pkt[MON_PKT_HEADER_SPACE];
244
        char h_data[MON_DATA_HEADER_SPACE];
245

    
246
        struct msg_header msg_h;
247

    
248
        debug("ML: send_msg to %s conID:%d extID:%d\n", conid_to_string(con_id), con_id, connectbuf[con_id]->external_connectionID);
249

    
250
        iov[0].iov_base = &msg_h;
251
        iov[0].iov_len = MSG_HEADER_SIZE;
252

    
253
        msg_h.local_con_id = htonl(con_id);
254
        msg_h.remote_con_id = htonl(connectbuf[con_id]->external_connectionID);
255
        msg_h.msg_type = msg_type;
256
        msg_h.msg_seq_num = htonl(connectbuf[con_id]->seqnr++);
257

    
258

    
259
        iov[1].iov_len = iov[2].iov_len = 0;
260
        iov[1].iov_base = h_pkt;
261
        iov[2].iov_base = h_data;
262

    
263

    
264
        if (connectbuf[con_id]->internal_connect)
265
                udpgen = connectbuf[con_id]->external_socketID.internal_addr;
266
        else
267
                udpgen = connectbuf[con_id]->external_socketID.external_addr;
268

    
269
        do{
270
                offset = 0;
271
                retry = false;
272
                // Monitoring layer hook
273
                if(set_Monitoring_header_data_cb != NULL) {
274
                        iov[2].iov_len = ((set_Monitoring_header_data_cb) (&(connectbuf[con_id]->external_socketID), msg_type));
275
                }
276
                msg_h.len_mon_data_hdr = iov[2].iov_len;
277

    
278
                if(get_Send_data_inf_cb != NULL && iov[2].iov_len != 0) {
279
                        mon_data_inf sd_data_inf;
280

    
281
                        memset(h_data, 0, MON_DATA_HEADER_SPACE);
282

    
283
                        sd_data_inf.remote_socketID = &(connectbuf[con_id]->external_socketID);
284
                        sd_data_inf.buffer = msg;
285
                        sd_data_inf.bufSize = msg_len;
286
                        sd_data_inf.msgtype = msg_type;
287
                        sd_data_inf.monitoringDataHeader = iov[2].iov_base;
288
                        sd_data_inf.monitoringDataHeaderLen = iov[2].iov_len;
289
                        sd_data_inf.priority = sParams->priority;
290
                        sd_data_inf.padding = sParams->padding;
291
                        sd_data_inf.confirmation = sParams->confirmation;
292
                        sd_data_inf.reliable = sParams->reliable;
293
                        memset(&sd_data_inf.arrival_time, 0, sizeof(struct timeval));
294

    
295
                        (get_Send_data_inf_cb) ((void *) &sd_data_inf);
296
                }
297

    
298
                do {
299
                        if(set_Monitoring_header_pkt_cb != NULL) {
300
                                iov[1].iov_len = (set_Monitoring_header_pkt_cb) (&(connectbuf[con_id]->external_socketID), msg_type);
301
                        }
302
                        pkt_len = min(connectbuf[con_id]->pmtusize - iov[2].iov_len - iov[1].iov_len - iov[0].iov_len, msg_len - offset) ;
303

    
304
                        iov[3].iov_len = pkt_len;
305
                        iov[3].iov_base = msg + offset;
306

    
307
                        //fill header
308
                        msg_h.len_mon_packet_hdr = iov[1].iov_len;
309
                        msg_h.offset = htonl(offset);
310
                        msg_h.msg_length = htonl(truncable ? pkt_len : msg_len);
311

    
312
                        //monitoring layer hook
313
                        if(get_Send_pkt_inf_cb != NULL && iov[1].iov_len) {
314
                                mon_pkt_inf pkt_info;
315

    
316
                                memset(h_pkt,0,MON_PKT_HEADER_SPACE);
317

    
318
                                pkt_info.remote_socketID = &(connectbuf[con_id]->external_socketID);
319
                                pkt_info.buffer = msg + offset;
320
                                pkt_info.bufSize = pkt_len;
321
                                pkt_info.msgtype = msg_type;
322
                                pkt_info.dataID = connectbuf[con_id]->seqnr;
323
                                pkt_info.offset = offset;
324
                                pkt_info.datasize = msg_len;
325
                                pkt_info.monitoringHeaderLen = iov[1].iov_len;
326
                                pkt_info.monitoringHeader = iov[1].iov_base;
327
                                pkt_info.ttl = -1;
328
                                memset(&(pkt_info.arrival_time),0,sizeof(struct timeval));
329

    
330
                                (get_Send_pkt_inf_cb) ((void *) &pkt_info);
331
                        }
332

    
333
                        debug("ML: sending packet to %s with rconID:%d lconID:%d\n", conid_to_string(con_id), ntohl(msg_h.remote_con_id), ntohl(msg_h.local_con_id));
334
                        int priority = 0; 
335
                        if (msg_type == ML_CON_MSG) priority = HP;
336
                        switch(queueOrSendPacket(socketfd, iov, 4, &udpgen.udpaddr,priority)) {
337
                                case MSGLEN:
338
                                        info("ML: sending message failed, reducing MTU from %d to %d (to:%s conID:%d lconID:%d msgsize:%d offset:%d)\n", connectbuf[con_id]->pmtusize, pmtu_decrement(connectbuf[con_id]->pmtusize), conid_to_string(con_id), ntohl(msg_h.remote_con_id), ntohl(msg_h.local_con_id), msg_len, offset);
339
                                        // TODO: pmtu decremented here, but not in the "truncable" packet. That is currently resent without changing the claimed pmtu. Might need to be changed.
340
                                        connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
341
                                        if (connectbuf[con_id]->pmtusize > 0) {
342
                                                connectbuf[con_id]->delay = true;
343
                                                retry = true;
344
                                        }
345
                                        offset = msg_len; // exit the while
346
                                        break;
347
                                case FAILURE:
348
                                        info("ML: sending message failed (to:%s conID:%d lconID:%d msgsize:%d offset:%d)\n", conid_to_string(con_id), ntohl(msg_h.remote_con_id), ntohl(msg_h.local_con_id), msg_len, offset);
349
                                        offset = msg_len; // exit the while
350
                                        break;
351
                                case THROTTLE:
352
                                    //    debug("THROTTLE on output"); 
353
                                        offset = msg_len; // exit the while
354
                                        break;
355
                                case OK:
356
                                        //update
357
                                        offset += pkt_len;
358
                                        //transmit data header only in the first packet
359
                                        iov[2].iov_len = 0;
360
                                        break;
361
                        }
362
                } while(offset != msg_len && !truncable);
363
        } while(retry);
364
}
365

    
366
void pmtu_timeout_cb(int fd, short event, void *arg);
367

    
368
void reschedule_conn_msg(int con_id)
369
{
370
        if (connectbuf[con_id]->timeout_event) {
371
                /* delete old timout */        
372
                event_del(connectbuf[con_id]->timeout_event);
373
                event_free(connectbuf[con_id]->timeout_event);
374
        }
375
        connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
376
        evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
377
}
378

    
379
void send_conn_msg(int con_id, int buf_size, int command_type)
380
{
381
        if (buf_size < sizeof(struct conn_msg)) {
382
                error("ML: requested connection message size is too small\n");
383
                return;
384
        }
385

    
386
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
387
                connectbuf[con_id]->ctrl_msg_buf = malloc(buf_size);
388
                memset(connectbuf[con_id]->ctrl_msg_buf, 0, buf_size);
389
        }
390

    
391
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
392
                error("ML: can not allocate memory for connection message\n");
393
                return;
394
        }
395

    
396
        struct conn_msg *msg_header = (struct conn_msg*) connectbuf[con_id]->ctrl_msg_buf;
397

    
398
        msg_header->comand_type = command_type;
399
        msg_header->pmtu_size = connectbuf[con_id]->pmtusize;
400

    
401
        memcpy(&(msg_header->sock_id), loc_socketID, sizeof(socket_ID));
402
  {
403
                        char buf[SOCKETID_STRING_SIZE];
404
                        mlSocketIDToString(&((struct conn_msg*)connectbuf[con_id]->ctrl_msg_buf)->sock_id,buf,sizeof(buf));
405
                        debug("Local socket_address sent in INVITE: %s, sizeof msg %ld\n", buf, sizeof(struct conn_msg));
406
   }
407
        send_msg(con_id, ML_CON_MSG, connectbuf[con_id]->ctrl_msg_buf, buf_size, true, &(connectbuf[con_id]->defaultSendParams));
408
}
409

    
410
void send_conn_msg_with_pmtu_discovery(int con_id, int buf_size, int command_type)
411
{
412
        struct timeval tout = PMTU_TIMEOUT;
413
        connectbuf[con_id]->timeout_value = tout;
414
        connectbuf[con_id]->trials = 1;
415
        send_conn_msg(con_id, buf_size, command_type);
416
        reschedule_conn_msg(con_id);
417
}
418

    
419
void resend_conn_msg(int con_id)
420
{
421
        connectbuf[con_id]->trials++;
422
        send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
423
        reschedule_conn_msg(con_id);
424
}
425

    
426
void recv_conn_msg(struct msg_header *msg_h, char *msgbuf, int msg_size, struct sockaddr_in *recv_addr)
427
{
428
        struct conn_msg *con_msg;
429
        int free_con_id, con_id;
430

    
431
        time_t now = time(NULL);
432
        double timediff = 0.0;
433
        char sock_id_str[1000];
434
        
435
        msgbuf += msg_h->len_mon_data_hdr;
436
        msg_size -= msg_h->len_mon_data_hdr;
437
        con_msg = (struct conn_msg *)msgbuf;
438
        
439
        //verify message validity
440
        if (msg_size < sizeof(struct conn_msg)) {
441
                char recv_addr_str[INET_ADDRSTRLEN];
442
                inet_ntop(AF_INET, &(recv_addr->sin_addr.s_addr), recv_addr_str, INET_ADDRSTRLEN);
443
                info("Invalid conn_msg received from %s\n", recv_addr_str);
444
                return;
445
        }
446

    
447
        //decode sock_id for debug messages
448
        mlSocketIDToString(&con_msg->sock_id,sock_id_str,999);
449

    
450
        if (con_msg->sock_id.internal_addr.udpaddr.sin_addr.s_addr != recv_addr->sin_addr.s_addr &&
451
            con_msg->sock_id.external_addr.udpaddr.sin_addr.s_addr != recv_addr->sin_addr.s_addr   ) {
452
                char recv_addr_str[INET_ADDRSTRLEN];
453
                inet_ntop(AF_INET, &(recv_addr->sin_addr.s_addr), recv_addr_str, INET_ADDRSTRLEN);
454
                info("Conn msg received from %s, but claims to be from %s", recv_addr_str, sock_id_str);
455
                return;
456
        }
457

    
458
        // Monitoring layer hook
459
        if(get_Recv_data_inf_cb != NULL) {
460
                // update pointer to the real data
461
                mon_data_inf recv_data_inf;
462
                recv_data_inf.remote_socketID = &(con_msg->sock_id);
463
                recv_data_inf.buffer = msgbuf;
464
                recv_data_inf.bufSize = msg_size;
465
                recv_data_inf.msgtype = msg_h->msg_type;
466
                recv_data_inf.monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
467
                recv_data_inf.monitoringDataHeader = msg_h->len_mon_data_hdr ? msgbuf : NULL;
468
                gettimeofday(&recv_data_inf.arrival_time, NULL);
469
                recv_data_inf.firstPacketArrived = true;
470
                recv_data_inf.recvFragments = 1;
471
                recv_data_inf.priority = false;
472
                recv_data_inf.padding = false;
473
                recv_data_inf.confirmation = false;
474
                recv_data_inf.reliable = false;
475

    
476
                // send data recv callback to monitoring module
477
                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
478
        }
479

    
480
        // check the connection command type
481
        switch (con_msg->comand_type) {
482
                /*
483
                * if INVITE: enter a new socket make new entry in connect array
484
                * send an ok
485
                */
486
                case INVITE:
487
                        info("ML: received INVITE from %s (size:%d)\n", sock_id_str, msg_size);
488
                        /*
489
                        * check if another connection for the external connectionID exist
490
                        * that was established within the last 2 seconds
491
                        */
492
                        free_con_id = -1;
493
                        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
494
                                if (connectbuf[con_id] != NULL) {
495
                                        if (mlCompareSocketIDs(&(connectbuf[con_id]->external_socketID), &(con_msg->sock_id)) == 0) {
496
                                                //timediff = difftime(now, connectbuf[con_id]->starttime);        //TODO: why this timeout? Shouldn't the connection be closed instead if there is a timeout?
497
                                                //if (timediff < 2)
498
                                                //update remote connection ID
499
                                                if (connectbuf[con_id]->external_connectionID != msg_h->local_con_id) {
500
                                                        warn("ML: updating remote connection ID for %s: from %d to %d\n",sock_id_str, connectbuf[con_id]->external_connectionID, msg_h->local_con_id);
501
                                                        connectbuf[con_id]->external_connectionID = msg_h->local_con_id;
502
                                                }
503
                                                break;
504
                                        }
505
                                } else if(free_con_id == -1)
506
                                        free_con_id = con_id;
507
                        }
508

    
509
                        if (con_id == CONNECTBUFSIZE) {
510
                                // create an entry in the connecttrybuf
511
                                if(free_con_id == -1) {
512
                                        error("ML: no new connect_buf available\n");
513
                                        return;
514
                                }
515
                                connectbuf[free_con_id] = (connect_data *) malloc(sizeof(connect_data));
516
                                memset(connectbuf[free_con_id],0,sizeof(connect_data));
517
                                connectbuf[free_con_id]->connection_head = connectbuf[free_con_id]->connection_last = NULL;
518
                                connectbuf[free_con_id]->starttime = time(NULL);
519
                                memcpy(&(connectbuf[free_con_id]->external_socketID), &(con_msg->sock_id), sizeof(socket_ID));
520
                //Workaround to support reuse of socketID
521
                                connectbuf[free_con_id]->external_socketID.internal_addr.udpaddr.sin_family=AF_INET;
522
                                connectbuf[free_con_id]->external_socketID.external_addr.udpaddr.sin_family=AF_INET;
523
                                connectbuf[free_con_id]->pmtusize = con_msg->pmtu_size;        // bootstrap pmtu from the other's size. Not strictly needed, but a good hint
524
                                connectbuf[free_con_id]->timeout_event = NULL;
525
                                connectbuf[free_con_id]->external_connectionID = msg_h->local_con_id;
526
                                connectbuf[free_con_id]->internal_connect =
527
                                        !compare_external_address_socketIDs(&(con_msg->sock_id), loc_socketID);
528
                                con_id = free_con_id;
529
                        }
530

    
531
                        //if(connectbuf[con_id]->status <= CONNECT) { //TODO: anwer anyway. Why the outher would invite otherwise?
532
                                //update status and send back answer
533
                                connectbuf[con_id]->status = CONNECT;
534
                                send_conn_msg_with_pmtu_discovery(con_id, con_msg->pmtu_size, CONNECT);
535
                        //}
536
                        break;
537
                case CONNECT:
538
                        info("ML: received CONNECT from %s (size:%d)\n", sock_id_str, msg_size);
539

    
540
                        if(msg_h->remote_con_id != -1 && connectbuf[msg_h->remote_con_id] == NULL) {
541
                                error("ML: received CONNECT for inexistent connection rconID:%d\n",msg_h->remote_con_id);
542
                                return;
543
                        }
544

    
545
                        /*
546
                        * check if the connection status is not already 1 or 2
547
                        */
548
                        if (connectbuf[msg_h->remote_con_id]->status == INVITE) {
549
                                // set the external connectionID
550
                                connectbuf[msg_h->remote_con_id]->external_connectionID = msg_h->local_con_id;
551
                                // change status con_msg the connection_data
552
                                connectbuf[msg_h->remote_con_id]->status = READY;
553
                                // change pmtusize in the connection_data: not needed. receiving a CONNECT means our INVITE went through. So why change pmtu?
554
                                //connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
555

    
556
                                // send the READY
557
                                send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
558

    
559
                                if (receive_Connection_cb != NULL)
560
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
561

    
562
                                // call all registered callbacks
563
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
564
                                        struct receive_connection_cb_list *temp;
565
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
566
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
567
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
568
                                        free(temp);
569
                                }
570
                                connectbuf[msg_h->remote_con_id]->connection_head =
571
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
572
                        } else {
573
                                // send the READY
574
                                send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
575
                        }
576

    
577
                        debug("ML: active connection established\n");
578
                        break;
579

    
580
                        /*
581
                        * if READY: find the entry in the connection array set the
582
                        * connection active change the pmtu size
583
                        */
584
                case READY:
585
                        info("ML: received READY from %s (size:%d)\n", sock_id_str, msg_size);
586
                        if(connectbuf[msg_h->remote_con_id] == NULL) {
587
                                error("ML: received READY for inexistent connection\n");
588
                                return;
589
                        }
590
                        /*
591
                        * checks if the connection is not already established
592
                        */
593
                        if (connectbuf[msg_h->remote_con_id]->status == CONNECT) {
594
                                // change status of the connection
595
                                connectbuf[msg_h->remote_con_id]->status = READY;
596
                                // change pmtusize: not needed. pmtu doesn't have to be symmetric
597
                                //connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
598

    
599
                                if (receive_Connection_cb != NULL)
600
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
601

    
602
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
603
                                        struct receive_connection_cb_list *temp;
604
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
605
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
606
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
607
                                        free(temp);
608
                                }
609
                                connectbuf[msg_h->remote_con_id]->connection_head =
610
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
611
                                debug("ML: passive connection established\n");
612
                        }
613
                        break;
614
        }
615
}
616

    
617
void recv_stun_msg(char *msgbuf, int recvSize)
618
{
619
        /*
620
        * create empty stun message struct
621
        */
622
        StunMessage resp;
623
        memset(&resp, 0, sizeof(StunMessage));
624
        /*
625
        * parse the message
626
        */
627
        int returnValue = 0;
628
        returnValue = recv_stun_message(msgbuf, recvSize, &resp);
629

    
630
        if (returnValue == 0) {
631
                /*
632
                * read the reflexive Address into the local_socketID
633
                */
634
                struct sockaddr_in reflexiveAddr = {0};
635
                reflexiveAddr.sin_family = AF_INET;
636
                reflexiveAddr.sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
637
                reflexiveAddr.sin_port = htons(resp.mappedAddress.ipv4.port);
638
                socketaddrgen reflexiveAddres = {0};
639
                reflexiveAddres.udpaddr = reflexiveAddr;
640
                local_socketID.external_addr = reflexiveAddres;
641
                NAT_traversal = true;
642
                // callback to the upper layer indicating that the socketID is now
643
                // ready to use
644
                {
645
                        char buf[SOCKETID_STRING_SIZE];
646
                        mlSocketIDToString(&local_socketID,buf,sizeof(buf));
647
                         debug("received local socket_address: %s\n", buf);
648
                }
649
                (receive_SocketID_cb) (&local_socketID, 0);
650
        }
651
}
652

    
653
//done
654
void recv_timeout_cb(int fd, short event, void *arg)
655
{
656
        int recv_id = (long) arg;
657
        debug("ML: recv_timeout_cb called. Timeout for id:%d\n",recv_id);
658

    
659
        if (recvdatabuf[recv_id] == NULL) {
660
                return;
661
        }
662

    
663

    
664
/*        if(recvdatabuf[recv_id]->status == ACTIVE) {
665
                //TODO make timeout at least a DEFINE
666
                struct timeval timeout = { 4, 0 };
667
                recvdatabuf[recv_id]->status = INACTIVE;
668
                event_base_once(base, -1, EV_TIMEOUT, recv_timeout_cb,
669
                        arg, &timeout);
670
                return;
671
        }
672
*/
673

    
674
        if(recvdatabuf[recv_id]->status == ACTIVE) {
675
                // Monitoring layer hook
676
                if(get_Recv_data_inf_cb != NULL) {
677
                        mon_data_inf recv_data_inf;
678

    
679
                        recv_data_inf.remote_socketID =
680
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
681
                        recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
682
                        recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
683
                        recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
684
                        recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
685
                        recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
686
                                recvdatabuf[recv_id]->recvbuf : NULL;
687
                        gettimeofday(&recv_data_inf.arrival_time, NULL);
688
                        recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
689
                        recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
690
                        recv_data_inf.priority = false;
691
                        recv_data_inf.padding = false;
692
                        recv_data_inf.confirmation = false;
693
                        recv_data_inf.reliable = false;
694

    
695
                        // send data recv callback to monitoring module
696

    
697
//                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
698
                }
699

    
700
                // Get the right callback
701
                receive_data_cb receive_data_callback = recvcbbuf[recvdatabuf[recv_id]->msgtype];
702

    
703
                recv_params rParams;
704

    
705
                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
706
                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
707
                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
708
                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
709
                rParams.remote_socketID =
710
                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
711
                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
712

    
713
//                 (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
714
//                         recvdatabuf[recv_id]->msgtype, &rParams);
715

    
716
                //clean up
717
                if (recvdatabuf[recv_id]->timeout_event) {
718
                        event_del(recvdatabuf[recv_id]->timeout_event);
719
                        event_free(recvdatabuf[recv_id]->timeout_event);
720
                        recvdatabuf[recv_id]->timeout_event = NULL;
721
                }
722
                free(recvdatabuf[recv_id]->recvbuf);
723
                free(recvdatabuf[recv_id]);
724
                recvdatabuf[recv_id] = NULL;
725
        }
726
}
727

    
728
// process a single recv data message
729
void recv_data_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
730
{
731
        debug("ML: received packet of size %d with rconID:%d lconID:%d type:%d offset:%d\n",bufsize,msg_h->remote_con_id,msg_h->local_con_id,msg_h->msg_type,msg_h->offset);
732

    
733
        int recv_id, free_recv_id = -1;
734

    
735
        if(connectbuf[msg_h->remote_con_id] == NULL) {
736
                debug("ML: Received a message not related to any opened connection!\n");
737
                return;
738
        }
739

    
740
        // check if a recv_data exist and enter data
741
        for (recv_id = 0; recv_id < RECVDATABUFSIZE; recv_id++)
742
                if (recvdatabuf[recv_id] != NULL) {
743
                        if (msg_h->remote_con_id == recvdatabuf[recv_id]->connectionID &&
744
                                        msg_h->msg_seq_num == recvdatabuf[recv_id]->seqnr)
745
                                                break;
746
                } else
747
                        if(free_recv_id == -1)
748
                                free_recv_id = recv_id;
749

    
750

    
751
        if(recv_id == RECVDATABUFSIZE) {
752
                //no recv_data found: create one
753
                recv_id = free_recv_id;
754
                recvdatabuf[recv_id] = (recvdata *) malloc(sizeof(recvdata));
755
                memset(recvdatabuf[recv_id], 0, sizeof(recvdata));
756
                recvdatabuf[recv_id]->connectionID = msg_h->remote_con_id;
757
                recvdatabuf[recv_id]->seqnr = msg_h->msg_seq_num;
758
                recvdatabuf[recv_id]->monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
759
                recvdatabuf[recv_id]->bufsize = msg_h->msg_length + msg_h->len_mon_data_hdr;
760
                recvdatabuf[recv_id]->recvbuf = (char *) malloc(recvdatabuf[recv_id]->bufsize);
761
                recvdatabuf[recv_id]->arrivedBytes = 0;        //count this without the Mon headers
762
                /*
763
                * read the timeout data and set it
764
                */
765
                recvdatabuf[recv_id]->timeout_value = recv_timeout;
766
                recvdatabuf[recv_id]->timeout_event = NULL;
767
                recvdatabuf[recv_id]->recvID = recv_id;
768
                recvdatabuf[recv_id]->starttime = time(NULL);
769
                recvdatabuf[recv_id]->msgtype = msg_h->msg_type;
770

    
771
                // fill the buffer with zeros
772
                memset(recvdatabuf[recv_id]->recvbuf, 0, recvdatabuf[recv_id]->bufsize);
773
                debug(" new @ id:%d\n",recv_id);
774
        } else {        //message structure already exists, no need to create new
775
                debug(" found @ id:%d (arrived before this packet: bytes:%d fragments%d\n",recv_id, recvdatabuf[recv_id]->arrivedBytes, recvdatabuf[recv_id]->recvFragments);
776
        }
777

    
778
        //if first packet extract mon data header and advance pointer
779
        if (msg_h->offset == 0) {
780
                memcpy(recvdatabuf[recv_id]->recvbuf, msgbuf, msg_h->len_mon_data_hdr);
781
                msgbuf += msg_h->len_mon_data_hdr;
782
                bufsize -= msg_h->len_mon_data_hdr;
783
                recvdatabuf[recv_id]->firstPacketArrived = 1;
784
        }
785

    
786

    
787
        // increment fragmentnr
788
        recvdatabuf[recv_id]->recvFragments++;
789
        // increment the arrivedBytes
790
        recvdatabuf[recv_id]->arrivedBytes += bufsize;
791

    
792
        // enter the data into the buffer
793
        memcpy(recvdatabuf[recv_id]->recvbuf + msg_h->len_mon_data_hdr + msg_h->offset, msgbuf, bufsize);
794

    
795
        //TODO very basic checkif all fragments arrived: has to be reviewed
796
        if(recvdatabuf[recv_id]->arrivedBytes == recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen)
797
                recvdatabuf[recv_id]->status = COMPLETE; //buffer full -> msg completly arrived
798
        else
799
                recvdatabuf[recv_id]->status = ACTIVE;
800

    
801
        if (recv_data_callback) {
802
                if(recvdatabuf[recv_id]->status == COMPLETE) {
803
                        // Monitoring layer hook
804
                        if(get_Recv_data_inf_cb != NULL) {
805
                                mon_data_inf recv_data_inf;
806

    
807
                                recv_data_inf.remote_socketID =
808
                                         &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
809
                                recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
810
                                recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
811
                                recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
812
                                recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
813
                                recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
814
                                        recvdatabuf[recv_id]->recvbuf : NULL;
815
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
816
                                recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
817
                                recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
818
                                recv_data_inf.priority = false;
819
                                recv_data_inf.padding = false;
820
                                recv_data_inf.confirmation = false;
821
                                recv_data_inf.reliable = false;
822

    
823
                                // send data recv callback to monitoring module
824

    
825
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
826
                        }
827

    
828
                        // Get the right callback
829
                        receive_data_cb receive_data_callback = recvcbbuf[msg_h->msg_type];
830
                        if (receive_data_callback) {
831

    
832
                                recv_params rParams;
833

    
834
                                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen - recvdatabuf[recv_id]->arrivedBytes;
835
                                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
836
                                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
837
                                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
838
                                rParams.remote_socketID =
839
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
840

    
841
                                char str[1000];
842
                                mlSocketIDToString(rParams.remote_socketID,str,999);
843
                                debug("ML: received message from conID:%d, %s\n",recvdatabuf[recv_id]->connectionID,str);
844
                                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
845

    
846
                                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
847
                                        recvdatabuf[recv_id]->msgtype, (void *) &rParams);
848
                        } else {
849
                            warn("ML: callback not initialized for this message type: %d!\n",msg_h->msg_type);
850
                        }
851

    
852
                        //clean up
853
                        if (recvdatabuf[recv_id]->timeout_event) {
854
                                debug("ML: freeing timeout for %d\n",recv_id);
855
                                event_del(recvdatabuf[recv_id]->timeout_event);
856
                                event_free(recvdatabuf[recv_id]->timeout_event);
857
                                recvdatabuf[recv_id]->timeout_event = NULL;
858
                        } else {
859
                                debug("ML: received in 1 packet\n",recv_id);
860
                        }
861
                        free(recvdatabuf[recv_id]->recvbuf);
862
                        free(recvdatabuf[recv_id]);
863
                        recvdatabuf[recv_id] = NULL;
864
                } else { // not COMPLETE
865
                        if (!recvdatabuf[recv_id]->timeout_event) {
866
                                //start time out
867
                                //TODO make timeout at least a DEFINE
868
                                recvdatabuf[recv_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &recv_timeout_cb, (void *) (long)recv_id);
869
                                evtimer_add(recvdatabuf[recv_id]->timeout_event, &recv_timeout);
870
                        }
871
                }
872
        }
873
}
874

    
875
//done
876
void pmtu_timeout_cb(int fd, short event, void *arg)
877
{
878

    
879
        int con_id = (long) arg;
880
        pmtu new_pmtusize;
881

    
882
        debug("ML: pmtu timeout called (lcon:%d)\n",con_id);
883

    
884
        if(connectbuf[con_id] == NULL) {
885
                error("ML: pmtu timeout called on non existing con_id\n");
886
                return;
887
        }
888

    
889
        if(connectbuf[con_id]->status == READY) {
890
                // nothing to do anymore
891
                event_del(connectbuf[con_id]->timeout_event);
892
                event_free(connectbuf[con_id]->timeout_event);
893
                connectbuf[con_id]->timeout_event = NULL;
894
                return;
895
        }
896

    
897
        info("ML: pmtu timeout while connecting(to:%s lcon:%d status:%d size:%d trial:%d tout:%ld.%06ld)\n",conid_to_string(con_id), con_id, connectbuf[con_id]->status, connectbuf[con_id]->pmtusize, connectbuf[con_id]->trials, connectbuf[con_id]->timeout_value.tv_sec, connectbuf[con_id]->timeout_value.tv_usec);
898

    
899
        if(connectbuf[con_id]->delay || connectbuf[con_id]->trials == MAX_TRIALS - 1) {
900
                double delay = connectbuf[con_id]->timeout_value.tv_sec + connectbuf[con_id]->timeout_value.tv_usec / 1000000.0;
901
                delay = delay * 2;
902
                info("\tML: increasing pmtu timeout to %f sec\n", delay);
903
                connectbuf[con_id]->timeout_value.tv_sec = floor(delay);
904
                connectbuf[con_id]->timeout_value.tv_usec = fmod(delay, 1.0) * 1000000.0;
905
                if(connectbuf[con_id]->delay) {
906
                        connectbuf[con_id]->delay = false;
907
                        reschedule_conn_msg(con_id);
908
                }
909
        }
910

    
911
        if(connectbuf[con_id]->trials == MAX_TRIALS) {
912
                // decrement the pmtu size
913
                struct timeval tout = PMTU_TIMEOUT;
914
                info("\tML: decreasing pmtu estimate from %d to %d\n", connectbuf[con_id]->pmtusize, pmtu_decrement(connectbuf[con_id]->pmtusize));
915
                connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
916
                connectbuf[con_id]->timeout_value = tout; 
917
                connectbuf[con_id]->trials = 0;
918
        }
919

    
920
        //error in PMTU discovery?
921
        if (connectbuf[con_id]->pmtusize == P_ERROR) {
922
                if (connectbuf[con_id]->internal_connect == true) {
923
                        //as of now we tried directly connecting, now let's try trough the NAT
924
                        connectbuf[con_id]->internal_connect = false;
925
                        connectbuf[con_id]->pmtusize = DSLSLIM;
926
                } else {
927
                        //nothing to do we have to give up
928
                        error("ML: Could not create connection with connectionID %i!\n",con_id);
929
                        // envoke the callback for failed connection establishment
930
                        if(failed_Connection_cb != NULL)
931
                                (failed_Connection_cb) (con_id, NULL);
932
                        // delete the connection entry
933
                        mlCloseConnection(con_id);
934
                        return;
935
                }
936
        }
937

    
938
        //retry
939
        resend_conn_msg(con_id);
940
}
941

    
942

    
943
int schedule_pmtu_timeout(int con_id)
944
{
945
        if (! connectbuf[con_id]->timeout_event) {
946
                struct timeval tout = PMTU_TIMEOUT;
947
                connectbuf[con_id]->timeout_value = tout;
948
                connectbuf[con_id]->trials = 1;
949
                connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
950
                evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
951
        }
952
}
953

    
954
/*
955
 * decrements the mtu size
956
 */
957
pmtu pmtu_decrement(pmtu pmtusize)
958
{
959
        pmtu pmtu_return_size;
960
        switch(pmtusize) {
961
        case MAX:
962
                //return DSL;
963
                return DSLSLIM;        //shortcut to use less vales
964
        case DSL:
965
                return DSLMEDIUM;
966
        case DSLMEDIUM:
967
                return DSLSLIM;
968
        case DSLSLIM:
969
                //return BELOWDSL;
970
                return MIN;        //shortcut to use less vales
971
        case BELOWDSL:
972
                return MIN;
973
        case MIN:
974
                return P_ERROR;
975
        default:
976
                warn("ML: strange pmtu size encountered:%d, changing to some safe value:%d\n", pmtusize, MIN);
977
                return MIN;
978
        }
979
}
980

    
981
// called when an ICMP pmtu error message (type 3, code 4) is received
982
void pmtu_error_cb_th(char *msg, int msglen)
983
{
984
        debug("ML: pmtu_error callback called msg_size: %d\n",msglen);
985
        //TODO debug
986
        return;
987

    
988
    char *msgbufptr = NULL;
989
    int msgtype;
990
    int connectionID;
991
    pmtu pmtusize;
992
    pmtu new_pmtusize;
993
    int dead = 0;
994

    
995
    // check the packettype
996
    msgbufptr = &msg[0];
997

    
998
    // check the msgtype
999
    msgbufptr = &msg[1];
1000
    memcpy(&msgtype, msgbufptr, 4);
1001

    
1002
    if (msgtype == 0) {
1003

    
1004
        // get the connectionID
1005
        msgbufptr = &msg[5];
1006
        memcpy(&connectionID, msgbufptr, 4);
1007

    
1008
        int msgtype_c = connectbuf[connectionID]->status;
1009
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
1010

    
1011
        if (msgtype_c != msgtype) {
1012
            dead = 1;
1013
        }
1014

    
1015

    
1016
    } else if (msgtype == 1) {
1017

    
1018
        // read the connectionID
1019
        msgbufptr = &msg[9];
1020
        memcpy(&connectionID, msgbufptr, 4);
1021

    
1022
        int msgtype_c = connectbuf[connectionID]->status;
1023
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
1024

    
1025
        if (msgtype_c != msgtype) {
1026
            dead = 1;
1027
        }
1028

    
1029
    }
1030
    // decrement the pmtu size
1031
    new_pmtusize = pmtu_decrement(pmtusize);
1032

    
1033
//    connectbuf[connectionID]->pmtutrysize = new_pmtusize;
1034

    
1035
    if (new_pmtusize == P_ERROR) {
1036
                error("ML:  Could not create connection with connectionID %i !\n",
1037
                        connectionID);
1038

    
1039
                if(failed_Connection_cb != NULL)
1040
                        (failed_Connection_cb) (connectionID, NULL);
1041
                // set the message type to a non existent message
1042
                msgtype = 2;
1043
                // delete the connection entry
1044
                 mlCloseConnection(connectionID);
1045
        }
1046

    
1047
    if (msgtype == 0 && dead != 1) {
1048

    
1049
        // stop the timeout event
1050
        // timeout_del(connectbuf[connectionID]->timeout);
1051
        /*
1052
         * libevent2
1053
         */
1054

    
1055
        // event_del(connectbuf[connectionID]->timeout);
1056

    
1057

    
1058
        // create and send a connection message
1059
//         create_conn_msg(new_pmtusize, connectionID,
1060
//                         &local_socketID, INVITE);
1061

    
1062
//        send_conn_msg(connectionID, new_pmtusize);
1063

    
1064
        // set a timeout event for the pmtu discovery
1065
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
1066
        // *)&connectionID);
1067

    
1068
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1069

    
1070
        /*
1071
         * libevent2
1072
         */
1073

    
1074
        struct event *ev;
1075
        ev = evtimer_new(base, pmtu_timeout_cb,
1076
                         (void *) connectbuf[connectionID]);
1077

    
1078
        // connectbuf[connectionID]->timeout = ev;
1079

    
1080
        event_add(ev, &connectbuf[connectionID]->timeout_value);
1081

    
1082
    } else if (msgtype == 1 && dead != 1) {
1083

    
1084
        // stop the timeout event
1085
        // timeout_del(connectbuf[connectionID]->timeout);
1086

    
1087
        /*
1088
         * libevent2
1089
         */
1090
        // info("still here 11 \n");
1091
        // printf("ev %d \n",connectbuf[connectionID]->timeout);
1092
        // event_del(connectbuf[connectionID]->timeout );
1093
        // evtimer_del(connectbuf[connectionID]->timeout );
1094

    
1095

    
1096
//         // create and send a connection message
1097
//         create_conn_msg(new_pmtusize,
1098
//                         connectbuf[connectionID]->connectionID,
1099
//                         NULL, CONNECT);
1100

    
1101
        //send_conn_msg(connectionID, new_pmtusize);
1102

    
1103
        // set a timeout event for the pmtu discovery
1104
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
1105
        // *)&connectionID);
1106
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1107

    
1108
        /*
1109
         * libevent2
1110
         */
1111
        // struct event *ev;
1112
        // ev = evtimer_new(base,pmtu_timeout_cb, (void
1113
        // *)connectbuf[connectionID]);
1114
        // connectbuf[connectionID]->timeout = ev;
1115
        // event_add(ev,&connectbuf[connectionID]->timeout_value);
1116

    
1117
    }
1118
}
1119

    
1120
/*
1121
 * what to do once a packet arrived if it is a conn packet send it to
1122
 * recv_conn handler if it is a data packet send it to the recv_data
1123
 * handler
1124
 */
1125

    
1126
//done --
1127
void recv_pkg(int fd, short event, void *arg)
1128
{
1129
        debug("ML: recv_pkg called\n");
1130

    
1131
        struct msg_header *msg_h;
1132
        char msgbuf[MAX];
1133
        pmtu recvSize = MAX;
1134
        char *bufptr = msgbuf;
1135
        int ttl;
1136
        struct sockaddr_in recv_addr;
1137
        int msg_size;
1138

    
1139
        recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
1140

    
1141

    
1142
        // check if it is not just an ERROR message
1143
        if(recvSize < 0)
1144
                return;
1145

    
1146
        // @TODO check if this simplistic STUN message recognition really always works, probably not
1147
        unsigned short stun_bind_response = 0x0101;
1148
        unsigned short * msgspot = (unsigned short *) msgbuf;
1149
        if (*msgspot == stun_bind_response) {
1150
                debug("ML: recv_pkg: parse stun message called on %d bytes\n", recvSize);
1151
                recv_stun_msg(msgbuf, recvSize);
1152
                return;
1153
        }
1154

    
1155
        msg_h = (struct msg_header *) msgbuf;
1156

    
1157
        /* convert header from network to host order */
1158
        msg_h->offset = ntohl(msg_h->offset);
1159
        msg_h->msg_length = ntohl(msg_h->msg_length);
1160
        msg_h->local_con_id = ntohl(msg_h->local_con_id);
1161
        msg_h->remote_con_id = ntohl(msg_h->remote_con_id);
1162
        msg_h->msg_seq_num = ntohl(msg_h->msg_seq_num);
1163

    
1164
        //verify minimum size
1165
        if (recvSize < sizeof(struct msg_header)) {
1166
          info("UDP packet too small, can't be an ML packet");
1167
          return;
1168
        }
1169

    
1170
        //TODO add more verifications
1171

    
1172
        bufptr += MSG_HEADER_SIZE + msg_h->len_mon_packet_hdr;
1173
        msg_size = recvSize - MSG_HEADER_SIZE - msg_h->len_mon_packet_hdr;
1174

    
1175
        //verify more fields
1176
        if (msg_size < 0) {
1177
          info("Corrupted UDP packet received");
1178
          return;
1179
        }
1180

    
1181
        if(get_Recv_pkt_inf_cb != NULL) {
1182
                mon_pkt_inf msginfNow;
1183
                msginfNow.monitoringHeaderLen = msg_h->len_mon_packet_hdr;
1184
                msginfNow.monitoringHeader = msg_h->len_mon_packet_hdr ? &msgbuf[0] + MSG_HEADER_SIZE : NULL;
1185
                //TODO rethink this ...
1186
                if(msg_h->msg_type == ML_CON_MSG) {
1187
                        struct conn_msg *c_msg = (struct conn_msg *) bufptr;
1188
                        msginfNow.remote_socketID = &(c_msg->sock_id);
1189
                }
1190
                else if(connectbuf[msg_h->remote_con_id] == NULL) {
1191
                        error("ML: received pkg called with non existent connection\n");
1192
                        return;
1193
                } else
1194
                        msginfNow.remote_socketID = &(connectbuf[msg_h->remote_con_id]->external_socketID);
1195
                msginfNow.buffer = bufptr;
1196
                msginfNow.bufSize = recvSize;
1197
                msginfNow.msgtype = msg_h->msg_type;
1198
                msginfNow.ttl = ttl;
1199
                msginfNow.dataID = msg_h->msg_seq_num;
1200
                msginfNow.offset = msg_h->offset;
1201
                msginfNow.datasize = msg_h->msg_length;
1202
                gettimeofday(&msginfNow.arrival_time, NULL);
1203
                (get_Recv_pkt_inf_cb) ((void *) &msginfNow);
1204
        }
1205

    
1206

    
1207
        switch(msg_h->msg_type) {
1208
                case ML_CON_MSG:
1209
                        debug("ML: received conn pkg\n");
1210
                        recv_conn_msg(msg_h, bufptr, msg_size, &recv_addr);
1211
                        break;
1212
                default:
1213
                        if(msg_h->msg_type < 127) {
1214
                                debug("ML: received data pkg\n");
1215
                                recv_data_msg(msg_h, bufptr, msg_size);
1216
                                break;
1217
                        }
1218
                        debug("ML: unrecognised msg_type\n");
1219
                        break;
1220
        }
1221
}
1222

    
1223
/*
1224
 * compare the external IP address of two socketIDs
1225
 */
1226
int
1227
compare_external_address_socketIDs(socketID_handle sock1, socketID_handle sock2)
1228
{
1229
        if( sock1->external_addr.udpaddr.sin_addr.s_addr == sock2->external_addr.udpaddr.sin_addr.s_addr)
1230
                return 0;
1231
        return 1;
1232
}
1233

    
1234
void try_stun();
1235

    
1236
/*
1237
 * the timeout of the NAT traversal
1238
 */
1239
void nat_traversal_timeout(int fd, short event, void *arg)
1240
{
1241
debug("X. NatTrTo %d\n", NAT_traversal);
1242
        if (NAT_traversal == false) {
1243
                debug("ML: NAT traversal request re-send\n");
1244
                if(receive_SocketID_cb)
1245
                        (receive_SocketID_cb) (&local_socketID, 2);
1246
                try_stun();
1247
        }
1248
debug("X. NatTrTo\n");
1249
}
1250

    
1251
//return IP address, or INADDR_NONE if can't resolve
1252
unsigned long resolve(const char *ipaddr)
1253
{
1254
        struct hostent *h = gethostbyname(ipaddr);
1255
        if (!h) {
1256
                error("ML: Unable to resolve host name %s\n", ipaddr);
1257
                return INADDR_NONE;
1258
        }
1259
        unsigned long *addr = (unsigned long *) (h->h_addr);
1260
        return *addr;
1261
}
1262

    
1263

    
1264
/*
1265
 * returns the file descriptor, or <0 on error. The ipaddr can be a null
1266
 * pointer. Then all available ipaddr on the machine are choosen.
1267
 */
1268
int create_socket(const int port, const char *ipaddr)
1269
{
1270
        struct sockaddr_in udpaddr = {0};
1271
        udpaddr.sin_family = AF_INET;
1272
        debug("X. create_socket %s, %d\n", ipaddr, port);
1273
        if (ipaddr == NULL) {
1274
                /*
1275
                * try to guess the local IP address
1276
                */
1277
                const char *ipaddr_iface = mlAutodetectIPAddress();
1278
                if (ipaddr_iface) {
1279
                        udpaddr.sin_addr.s_addr = inet_addr(ipaddr_iface);
1280
                } else {
1281
                        udpaddr.sin_addr.s_addr = INADDR_ANY;
1282
                }
1283
        } else {
1284
                udpaddr.sin_addr.s_addr = inet_addr(ipaddr);
1285
        }
1286
        udpaddr.sin_port = htons(port);
1287

    
1288
        socketaddrgen udpgen;
1289
        memset(&udpgen,0,sizeof(socketaddrgen));        //this will be sent over the net, so set it to 0
1290
        udpgen.udpaddr = udpaddr;
1291
        local_socketID.internal_addr = udpgen;
1292

    
1293
        socketfd = createSocket(port, ipaddr);
1294
        if (socketfd < 0){
1295
                return socketfd;
1296
        }
1297

    
1298
        struct event *ev;
1299
        ev = event_new(base, socketfd, EV_READ | EV_PERSIST, recv_pkg, NULL);
1300

    
1301
        event_add(ev, NULL);
1302

    
1303
        try_stun();
1304

    
1305
        return socketfd;
1306
}
1307

    
1308
/*
1309
 * try to figure out external IP using STUN, if defined
1310
 */
1311
void try_stun()
1312
{
1313
        if (isStunDefined()) {
1314
                /*
1315
                * send the NAT traversal STUN request
1316
                */
1317
                 send_stun_request(socketfd, &stun_server);
1318

    
1319
                /*
1320
                * enter a NAT traversal timeout that takes care of retransmission
1321
                */
1322
                struct event *ev1;
1323
                struct timeval timeout_value_NAT_traversal = NAT_TRAVERSAL_TIMEOUT;
1324
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1325
                event_add(ev1, &timeout_value_NAT_traversal);
1326

    
1327
                NAT_traversal = false;
1328
        } else {
1329
                /*
1330
                * Assume we have accessibility and copy internal address to external one
1331
                */
1332
                local_socketID.external_addr = local_socketID.internal_addr;
1333
                NAT_traversal = true; // @TODO: this is not really NAT traversal, but a flag that init is over
1334
                // callback to the upper layer indicating that the socketID is now
1335
                // ready to use
1336
                if(receive_SocketID_cb)
1337
                        (receive_SocketID_cb) (&local_socketID, 0); //success
1338
        }
1339
}
1340

    
1341
/**************************** END OF INTERNAL ***********************/
1342

    
1343
/**************************** MONL functions *************************/
1344

    
1345
int mlInit(bool recv_data_cb,struct timeval timeout_value,const int port,const char *ipaddr,const int stun_port,const char *stun_ipaddr,receive_localsocketID_cb local_socketID_cb,void *arg){
1346

    
1347
/*X*/ //  fprintf(stderr,"MLINIT1 %s, %d, %s, %d\n", ipaddr, port, stun_ipaddr, stun_port);
1348
        base = (struct event_base *) arg;
1349
        recv_data_callback = recv_data_cb;
1350
        mlSetRecvTimeout(timeout_value);
1351
        if (stun_ipaddr) {
1352
                 mlSetStunServer(stun_port, stun_ipaddr);
1353
        } else {
1354

    
1355
        }
1356
        register_recv_localsocketID_cb(local_socketID_cb);
1357
/*X*/ //  fprintf(stderr,"MLINIT1\n");
1358
        return create_socket(port, ipaddr);
1359
}
1360

    
1361
void mlSetRateLimiterParams(int bucketsize, int drainrate, int maxQueueSize, int maxQueueSizeRTX, double maxTimeToHold) {
1362
        setOutputRateParams(bucketsize, drainrate);
1363
        setQueuesParams (maxQueueSize, maxQueueSizeRTX, maxTimeToHold);
1364
}
1365
     
1366
void mlSetVerbosity (int log_level) {
1367
        setLogLevel(log_level);
1368
}
1369

    
1370
/* register callbacks  */
1371
void mlRegisterGetRecvPktInf(get_recv_pkt_inf_cb recv_pkt_inf_cb){
1372

    
1373
        if (recv_pkt_inf_cb == NULL) {
1374
                error("ML: Register get_recv_pkt_inf_cb failed: NULL ptr  \n");
1375
        } else {
1376
                get_Recv_pkt_inf_cb = recv_pkt_inf_cb;
1377
        }
1378
}
1379

    
1380
void mlRegisterGetSendPktInf(get_send_pkt_inf_cb  send_pkt_inf_cb){
1381

    
1382
        if (send_pkt_inf_cb == NULL) {
1383
                error("ML: Register get_send_pkt_inf_cb: NULL ptr  \n");
1384
        } else {
1385
                get_Send_pkt_inf_cb = send_pkt_inf_cb;
1386
        }
1387
}
1388

    
1389

    
1390
void mlRegisterSetMonitoringHeaderPktCb(set_monitoring_header_pkt_cb monitoring_header_pkt_cb ){
1391

    
1392
        if (monitoring_header_pkt_cb == NULL) {
1393
                error("ML: Register set_monitoring_header_pkt_cb: NULL ptr  \n");
1394
        } else {
1395
                set_Monitoring_header_pkt_cb = monitoring_header_pkt_cb;
1396
        }
1397
}
1398

    
1399
void mlRegisterGetRecvDataInf(get_recv_data_inf_cb recv_data_inf_cb){
1400

    
1401
        if (recv_data_inf_cb == NULL) {
1402
                error("ML: Register get_recv_data_inf_cb: NULL ptr  \n");
1403
        } else {
1404
                get_Recv_data_inf_cb = recv_data_inf_cb;
1405
        }
1406
}
1407

    
1408
void mlRegisterGetSendDataInf(get_send_data_inf_cb  send_data_inf_cb){
1409

    
1410
        if (send_data_inf_cb == NULL) {
1411
                error("ML: Register get_send_data_inf_cb: NULL ptr  \n");
1412
        } else {
1413
                get_Send_data_inf_cb = send_data_inf_cb;
1414
        }
1415
}
1416

    
1417
void mlRegisterSetMonitoringHeaderDataCb(set_monitoring_header_data_cb monitoring_header_data_cb){
1418

    
1419
        if (monitoring_header_data_cb == NULL) {
1420
                error("ML: Register set_monitoring_header_data_cb : NULL ptr  \n");
1421
        } else {
1422
                set_Monitoring_header_data_cb = monitoring_header_data_cb;
1423
        }
1424
}
1425

    
1426
void mlSetRecvTimeout(struct timeval timeout_value){
1427

    
1428
        recv_timeout = timeout_value;
1429

    
1430
}
1431

    
1432
int mlGetStandardTTL(socketID_handle socketID,uint8_t *ttl){
1433

    
1434
        return getTTL(socketfd, ttl);
1435

    
1436
}
1437

    
1438
socketID_handle mlGetLocalSocketID(int *errorstatus){
1439

    
1440
        if (NAT_traversal == false) {
1441
                *errorstatus = 2;
1442
                return NULL;
1443
        }
1444

    
1445
        *errorstatus = 0;
1446
        return &local_socketID;
1447

    
1448
}
1449

    
1450

    
1451
/**************************** END of MONL functions *************************/
1452

    
1453
/**************************** GENERAL functions *************************/
1454

    
1455
void mlRegisterRecvConnectionCb(receive_connection_cb recv_conn_cb){
1456

    
1457
        if (recv_conn_cb == NULL) {
1458
                error("ML: Register receive_connection_cb: NULL ptr  \n");
1459
        }else {
1460
                receive_Connection_cb = recv_conn_cb;
1461
        }
1462
}
1463

    
1464
void mlRegisterErrorConnectionCb(connection_failed_cb conn_failed){
1465

    
1466
        if (conn_failed == NULL) {
1467
                error("ML: Register connection_failed_cb: NULL ptr  \n");
1468
        } else {
1469
                failed_Connection_cb = conn_failed;
1470
        }
1471
}
1472

    
1473
void mlRegisterRecvDataCb(receive_data_cb data_cb,unsigned char msgtype){
1474

    
1475
    if (msgtype > 126) {
1476

    
1477
            error
1478
            ("ML: Could not register recv_data callback. Msgtype is greater then 126 \n");
1479

    
1480
    }
1481

    
1482
    if (data_cb == NULL) {
1483

    
1484
            error("ML: Register receive data callback: NUll ptr \n ");
1485

    
1486
    } else {
1487

    
1488
        recvcbbuf[msgtype] = data_cb;
1489

    
1490
    }
1491

    
1492
}
1493

    
1494
void mlCloseSocket(socketID_handle socketID){
1495

    
1496
        free(socketID);
1497

    
1498
}
1499

    
1500
void keepalive_fn(evutil_socket_t fd, short what, void *arg) {
1501
        socketID_handle peer = arg;
1502

    
1503
        int con_id = mlConnectionExist(peer, false);
1504
        if (con_id < 0 || connectbuf[con_id]->defaultSendParams.keepalive <= 0) {
1505
                /* Connection fell from under us or keepalive was disabled */
1506
                free(arg);
1507
                return;
1508
        }
1509

    
1510
        /* do what we gotta do */
1511
        if ( connectbuf[con_id]->status == READY) {
1512
                char keepaliveMsg[32] = "";
1513
                sprintf(keepaliveMsg, "KEEPALIVE %d", connectbuf[con_id]->keepalive_seq++);
1514
                send_msg(con_id, MSG_TYPE_ML_KEEPALIVE, keepaliveMsg, 1 + strlen(keepaliveMsg), false, 
1515
                        &(connectbuf[con_id]->defaultSendParams));
1516
        }
1517

    
1518
        /* re-schedule */
1519
        struct timeval t = { 0,0 };
1520
        t.tv_sec = connectbuf[con_id]->defaultSendParams.keepalive;
1521
        if (connectbuf[con_id]->defaultSendParams.keepalive) 
1522
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1523
}
1524

    
1525
void setupKeepalive(int conn_id) {
1526
        /* Save the peer's address for us */
1527
        socketID_handle peer = malloc(sizeof(socket_ID));
1528
        memcpy(peer, &connectbuf[conn_id]->external_socketID, sizeof(socket_ID));
1529

    
1530
        struct timeval t = { 0,0 };
1531
        t.tv_sec = connectbuf[conn_id]->defaultSendParams.keepalive;
1532

    
1533
        if (connectbuf[conn_id]->defaultSendParams.keepalive) 
1534
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1535
}
1536

    
1537
/* connection functions */
1538
int mlOpenConnection(socketID_handle external_socketID,receive_connection_cb connection_cb,void *arg, const send_params defaultSendParams){
1539

    
1540
        int con_id;
1541
        if (external_socketID == NULL) {
1542
                error("ML: cannot open connection: one of the socketIDs is NULL\n");
1543
                return -1;
1544
        }
1545
        if (NAT_traversal == false) {
1546
                error("ML: cannot open connection: NAT traversal for socketID still in progress\n");
1547
                return -1;
1548
        }
1549
        if (connection_cb == NULL) {
1550
                error("ML: cannot open connection: connection_cb is NULL\n");
1551
                return -1;
1552
        }
1553

    
1554
        // check if that connection already exist
1555

    
1556
        con_id = mlConnectionExist(external_socketID, false);
1557
        if (con_id >= 0) {
1558
                // overwrite defaultSendParams
1559
                bool newKeepalive = 
1560
                        connectbuf[con_id]->defaultSendParams.keepalive == 0 && defaultSendParams.keepalive != 0;
1561
                connectbuf[con_id]->defaultSendParams = defaultSendParams;
1562
                if (newKeepalive) setupKeepalive(con_id);
1563
                // if so check if it is ready to use
1564
                if (connectbuf[con_id]->status == READY) {
1565
                                // if so use the callback immediately
1566
                                (connection_cb) (con_id, arg);
1567

    
1568
                // otherwise just write the connection cb and the arg pointer
1569
                // into the connection struct
1570
                } else {
1571
                        struct receive_connection_cb_list *temp;
1572
                        temp = malloc(sizeof(struct receive_connection_cb_list));
1573
                        temp->next = NULL;
1574
                        temp->connection_cb = connection_cb;
1575
                        temp->arg = arg;
1576
                        if(connectbuf[con_id]->connection_last != NULL) {
1577
                                connectbuf[con_id]->connection_last->next = temp;
1578
                                connectbuf[con_id]->connection_last = temp;
1579
                        } else
1580
                                connectbuf[con_id]->connection_last = connectbuf[con_id]->connection_head = temp;
1581
                }
1582
                return con_id;
1583
        }
1584
        // make entry in connection_establishment array
1585
        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
1586
                if (connectbuf[con_id] == NULL) {
1587
                        connectbuf[con_id] = (connect_data *) malloc(sizeof(connect_data));
1588
                        memset(connectbuf[con_id],0,sizeof(connect_data));
1589
                        connectbuf[con_id]->starttime = time(NULL);
1590
                        memcpy(&connectbuf[con_id]->external_socketID, external_socketID, sizeof(socket_ID));
1591
                        connectbuf[con_id]->pmtusize = DSLSLIM;
1592
                        connectbuf[con_id]->timeout_event = NULL;
1593
                        connectbuf[con_id]->status = INVITE;
1594
                        connectbuf[con_id]->seqnr = 0;
1595
                        connectbuf[con_id]->internal_connect = !compare_external_address_socketIDs(external_socketID, &local_socketID);
1596
                        connectbuf[con_id]->connectionID = con_id;
1597

    
1598
                        connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
1599
                        connectbuf[con_id]->connection_last->next = NULL;
1600
                        connectbuf[con_id]->connection_last->connection_cb = connection_cb;
1601
                        connectbuf[con_id]->connection_last->arg = arg;
1602
                        connectbuf[con_id]->external_connectionID = -1;
1603

    
1604
                        connectbuf[con_id]->defaultSendParams = defaultSendParams;
1605
                        if (defaultSendParams.keepalive) setupKeepalive(con_id);
1606
                        break;
1607
                }
1608
        } //end of for
1609

    
1610
        if (con_id == CONNECTBUFSIZE) {
1611
                error("ML: Could not open connection: connection buffer full\n");
1612
                return -1;
1613
        }
1614

    
1615
        // create and send a connection message
1616
        info("ML:Sending INVITE to %s (lconn:%d)\n",conid_to_string(con_id), con_id);
1617
        send_conn_msg_with_pmtu_discovery(con_id, connectbuf[con_id]->pmtusize, INVITE);
1618

    
1619
        return con_id;
1620

    
1621
}
1622

    
1623
void mlCloseConnection(const int connectionID){
1624

    
1625
        // remove it from the connection array
1626
        if(connectbuf[connectionID]) {
1627
                if(connectbuf[connectionID]->ctrl_msg_buf) {
1628
                        free(connectbuf[connectionID]->ctrl_msg_buf);
1629
                }
1630
                // remove related events
1631
                if (connectbuf[connectionID]->timeout_event) {
1632
                        event_del(connectbuf[connectionID]->timeout_event);
1633
                        event_free(connectbuf[connectionID]->timeout_event);
1634
                        connectbuf[connectionID]->timeout_event = NULL;
1635
                }
1636
                free(connectbuf[connectionID]);
1637
                connectbuf[connectionID] = NULL;
1638
        }
1639

    
1640
}
1641

    
1642
void mlSendData(const int connectionID,char *sendbuf,int bufsize,unsigned char msgtype,send_params *sParams){
1643

    
1644
        if (connectionID < 0) {
1645
                error("ML: send data failed: connectionID does not exist\n");
1646
                return;
1647
        }
1648

    
1649
        if (connectbuf[connectionID] == NULL) {
1650
                error("ML: send data failed: connectionID does not exist\n");
1651
                return;
1652
        }
1653
        if (connectbuf[connectionID]->status != READY) {
1654
            error("ML: send data failed: connection is not active\n");
1655
            return;
1656
        }
1657

    
1658
        if (sParams == NULL) {
1659
                sParams = &(connectbuf[connectionID]->defaultSendParams);
1660
        }
1661

    
1662
        send_msg(connectionID, msgtype, sendbuf, bufsize, false, sParams);
1663

    
1664
}
1665

    
1666
/* transmit data functions  */
1667
int mlSendAllData(const int connectionID,send_all_data_container *container,int nr_entries,unsigned char msgtype,send_params *sParams){
1668

    
1669
    if (nr_entries < 1 || nr_entries > 5) {
1670

    
1671
        error
1672
            ("ML : sendALlData : nr_enties is not between 1 and 5 \n ");
1673
        return 0;
1674

    
1675
    } else {
1676

    
1677
        if (nr_entries == 1) {
1678

    
1679
                mlSendData(connectionID, container->buffer_1,
1680
                      container->length_1, msgtype, sParams);
1681

    
1682
            return 1;
1683

    
1684
        } else if (nr_entries == 2) {
1685

    
1686
            int buflen = container->length_1 + container->length_2;
1687
            char buf[buflen];
1688
            memcpy(buf, container->buffer_1, container->length_1);
1689
            memcpy(&buf[container->length_1], container->buffer_2,
1690
                   container->length_2);
1691
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1692

    
1693
            return 1;
1694

    
1695
        } else if (nr_entries == 3) {
1696

    
1697
            int buflen =
1698
                container->length_1 + container->length_2 +
1699
                container->length_3;
1700
            char buf[buflen];
1701
            memcpy(buf, container->buffer_1, container->length_1);
1702
            memcpy(&buf[container->length_1], container->buffer_2,
1703
                   container->length_2);
1704
            memcpy(&buf[container->length_2], container->buffer_3,
1705
                   container->length_3);
1706
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1707

    
1708

    
1709
            return 1;
1710

    
1711
        } else if (nr_entries == 4) {
1712

    
1713
            int buflen =
1714
                container->length_1 + container->length_2 +
1715
                container->length_3 + container->length_4;
1716
            char buf[buflen];
1717
            memcpy(buf, container->buffer_1, container->length_1);
1718
            memcpy(&buf[container->length_1], container->buffer_2,
1719
                   container->length_2);
1720
            memcpy(&buf[container->length_2], container->buffer_3,
1721
                   container->length_3);
1722
            memcpy(&buf[container->length_3], container->buffer_4,
1723
                   container->length_4);
1724
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1725

    
1726
            return 1;
1727

    
1728
        } else {
1729

    
1730
            int buflen =
1731
                container->length_1 + container->length_2 +
1732
                container->length_3 + container->length_4 +
1733
                container->length_5;
1734
            char buf[buflen];
1735
            memcpy(buf, container->buffer_1, container->length_1);
1736
            memcpy(&buf[container->length_1], container->buffer_2,
1737
                   container->length_2);
1738
            memcpy(&buf[container->length_2], container->buffer_3,
1739
                   container->length_3);
1740
            memcpy(&buf[container->length_3], container->buffer_4,
1741
                   container->length_4);
1742
            memcpy(&buf[container->length_4], container->buffer_5,
1743
                   container->length_5);
1744
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1745

    
1746
            return 1;
1747
        }
1748

    
1749
    }
1750

    
1751
}
1752

    
1753
int mlRecvData(const int connectionID,char *recvbuf,int *bufsize,recv_params *rParams){
1754

    
1755
        //TODO yet to be converted
1756
        return 0;
1757
#if 0
1758
        if (rParams == NULL) {
1759
                error("ML: recv_data failed: recv_params is a NULL ptr\n");
1760
                return 0;
1761
    } else {
1762

1763
        info("ML: recv data called \n");
1764

1765
        int i = 0;
1766
        int returnValue = 0;
1767
        double timeout = (double) recv_timeout.tv_sec;
1768
        time_t endtime = time(NULL);
1769

1770
        for (i = 0; i < RECVDATABUFSIZE; i++) {
1771

1772
            if (recvdatabuf[i] != NULL) {
1773

1774
                if (recvdatabuf[i]->connectionID == connectionID) {
1775

1776
                    info("ML: recv data has entry  \n");
1777

1778
                    double timepass = difftime(endtime, recvdatabuf[i]->starttime);
1779

1780
                    // check if the specified connection has data and it
1781
                    // is complete
1782
                    // check the data seqnr
1783
                    // if(connectionID == recvdatabuf[i]->connectionID &&
1784
                    // 1 == recvdatabuf[i]->status){
1785

1786
                    if (1 == recvdatabuf[i]->status) {
1787

1788
                        // info("transmissionHandler: recv_data set is
1789
                        // complete \n" );
1790

1791
                        // debug("debud \n");
1792

1793
                        // exchange the pointers
1794
                        int buffersize = 0;
1795
                        buffersize = recvdatabuf[i]->bufsize;
1796
                        *bufsize = buffersize;
1797
                        // recvbuf = recvdatabuf[i]->recvbuf;
1798

1799
                        // info("buffersize %d \n",buffersize);
1800
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1801
                               buffersize);
1802
                        // debug(" recvbuf %s \n",recvbuf );
1803

1804
//                         double nrMissFrags =
1805
//                             (double) recvdatabuf[i]->nrFragments /
1806
//                             (double) recvdatabuf[i]->recvFragments;
1807
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
1808

1809
//                        rParams->nrMissingFragments = nrMissingFragments;
1810
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
1811
                        rParams->msgtype = recvdatabuf[i]->msgtype;
1812
                        rParams->connectionID =
1813
                            recvdatabuf[i]->connectionID;
1814

1815
                        // break from the loop
1816
                        // debug(" recvbuf %s \n ",recvbuf);
1817

1818
                        // double nrMissFrags =
1819
                        // (double)recvdatabuf[i]->nrFragments /
1820
                        // (double)recvdatabuf[i]->recvFragments;
1821
                        // int nrMissingFragments =
1822
                        // (int)ceil(nrMissFrags);
1823

1824
                        if(get_Recv_data_inf_cb != NULL) {
1825
                                mon_data_inf recv_data_inf;
1826

1827
                                recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1828
                                recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1829
                                recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1830
                                recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1831
//                                 recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1832
//                                 recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1833
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
1834
                                recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1835
                                recv_data_inf.nrMissingFragments = nrMissingFragments;
1836
                                recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1837
                                recv_data_inf.priority = false;
1838
                                recv_data_inf.padding = false;
1839
                                recv_data_inf.confirmation = false;
1840
                                recv_data_inf.reliable = false;
1841

1842
                                // send data recv callback to monitoring module
1843

1844
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1845
                        }
1846

1847

1848
                        // free the allocated memory
1849
                        free(recvdatabuf[i]);
1850
                        recvdatabuf[i] = NULL;
1851

1852
                        returnValue = 1;
1853
                        break;
1854

1855
                    }
1856

1857
                    if (recvdatabuf[i] != NULL) {
1858

1859
                        if (timepass > timeout) {
1860

1861
                            info("ML: recv_data timeout called  \n");
1862

1863
                            // some data about the missing chunks should
1864
                            // be added here
1865
                            // exchange the pointers
1866
                            int buffersize = 0;
1867
                            buffersize = recvdatabuf[i]->bufsize;
1868
                            *bufsize = buffersize;
1869
                            // recvbuf = recvdatabuf[i]->recvbuf;
1870

1871
                            double nrMissFrags =
1872
                                (double) recvdatabuf[i]->nrFragments /
1873
                                (double) recvdatabuf[i]->recvFragments;
1874
                            int nrMissingFragments =
1875
                                (int) ceil(nrMissFrags);
1876

1877
                            // debug(" recvbuf %s \n",recvbuf );
1878

1879
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1880
                                   buffersize);
1881

1882
                            rParams->nrMissingFragments =
1883
                                nrMissingFragments;
1884
                            rParams->nrFragments =
1885
                                recvdatabuf[i]->nrFragments;
1886
                            rParams->msgtype = recvdatabuf[i]->msgtype;
1887
                            rParams->connectionID =
1888
                                recvdatabuf[i]->connectionID;
1889

1890
                                if(get_Recv_data_inf_cb != NULL) {
1891
                                        mon_data_inf recv_data_inf;
1892

1893
                                        recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1894
                                        recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1895
                                        recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1896
                                        recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1897
                                        recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1898
                                        recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1899
                                        gettimeofday(&recv_data_inf.arrival_time, NULL);
1900
                                        recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1901
                                        recv_data_inf.nrMissingFragments = nrMissingFragments;
1902
                                        recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1903
                                        recv_data_inf.priority = false;
1904
                                        recv_data_inf.padding = false;
1905
                                        recv_data_inf.confirmation = false;
1906
                                        recv_data_inf.reliable = false;
1907

1908
                                        // send data recv callback to monitoring module
1909

1910
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1911
                                }
1912

1913
                            // free the allocated memory
1914
                            free(recvdatabuf[i]);
1915
                            recvdatabuf[i] = NULL;
1916

1917
                            returnValue = 1;
1918
                            break;
1919

1920
                        }
1921
                    }
1922

1923
                }
1924

1925
            }
1926
            // debug("2 recvbuf %s \n ",recvbuf);
1927
        }
1928
        return returnValue;
1929
    }
1930
#endif
1931

    
1932
}
1933

    
1934
int mlSocketIDToString(socketID_handle socketID,char* socketID_string, size_t len){
1935

    
1936
        char internal_addr[INET_ADDRSTRLEN];
1937
        char external_addr[INET_ADDRSTRLEN];
1938

    
1939
        assert(socketID);
1940

    
1941
        inet_ntop(AF_INET, &(socketID->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1942
        inet_ntop(AF_INET, &(socketID->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1943

    
1944
        snprintf(socketID_string,len,"%s:%d-%s:%d", internal_addr, ntohs(socketID->internal_addr.udpaddr.sin_port),
1945
                external_addr,        ntohs(socketID->external_addr.udpaddr.sin_port));
1946
        return 0;
1947

    
1948
}
1949

    
1950
int mlStringToSocketID(const char* socketID_string, socketID_handle socketID){
1951

    
1952
        //@TODO add checks against malformed string
1953
        char external_addr[INET_ADDRSTRLEN];
1954
        int external_port;
1955
        char internal_addr[INET_ADDRSTRLEN];
1956
        int internal_port;
1957

    
1958
        char *pch;
1959
        char *s = strdup(socketID_string);
1960

    
1961
        //replace ':' with a blank
1962
        pch=strchr(s,':');
1963
        while (pch!=NULL){
1964
                                *pch = ' ';
1965
                pch=strchr(pch+1,':');
1966
        }
1967
        pch=strchr(s,'-');
1968
        if(pch) *pch = ' ';
1969

    
1970
        sscanf(s,"%s %d %s %d", internal_addr, &internal_port,
1971
                external_addr, &external_port);
1972

    
1973
        //set structure to 0, we initialize each byte, since it will be sent on the net later
1974
        memset(socketID, 0, sizeof(struct _socket_ID));
1975

    
1976
        if(inet_pton(AF_INET, internal_addr, &(socketID->internal_addr.udpaddr.sin_addr)) == 0)
1977
                return EINVAL;
1978
        socketID->internal_addr.udpaddr.sin_family = AF_INET;
1979
        socketID->internal_addr.udpaddr.sin_port = htons(internal_port);
1980

    
1981

    
1982
        if(inet_pton(AF_INET, external_addr, &(socketID->external_addr.udpaddr.sin_addr)) ==0)
1983
                return EINVAL;
1984
        socketID->external_addr.udpaddr.sin_family = AF_INET;
1985
        socketID->external_addr.udpaddr.sin_port = htons(external_port);
1986

    
1987
        free(s);
1988
        return 0;
1989

    
1990
}
1991

    
1992
int mlGetConnectionStatus(int connectionID){
1993

    
1994
        if(connectbuf[connectionID])
1995
                return connectbuf[connectionID]->status == READY;
1996
        return -1;
1997
    
1998
}
1999

    
2000

    
2001
int mlConnectionExist(socketID_handle socketID, bool ready){
2002

    
2003
    /*
2004
     * check if another connection for the external connectionID exist
2005
     * that was established \ within the last 2 seconds
2006
     */
2007
        int i;
2008
        for (i = 0; i < CONNECTBUFSIZE; i++)
2009
                if (connectbuf[i] != NULL)
2010
                        if (mlCompareSocketIDs(&(connectbuf[i]->external_socketID), socketID) == 0) {
2011
                                if (ready) return (connectbuf[i]->status == READY ? i : -1);;
2012
                                return i;
2013
                                }
2014

    
2015
    return -1;
2016

    
2017
}
2018

    
2019
//Added by Robert Birke as comodity functions
2020

    
2021
//int mlPrintSocketID(socketID_handle socketID) {
2022
//        char str[SOCKETID_STRING_SIZE];
2023
//        mlSocketIDToString(socketID, str, sizeof(str));
2024
//        printf(stderr,"int->%s<-ext\n",str);
2025
//}
2026

    
2027
/*
2028
 * hash code of a socketID
2029
 * TODO might think of a better way
2030
 */
2031
int mlHashSocketID(socketID_handle sock) {
2032
        //assert(sock);
2033
   return sock->internal_addr.udpaddr.sin_port +
2034
                        sock->external_addr.udpaddr.sin_port;
2035
}
2036

    
2037
int mlCompareSocketIDs(socketID_handle sock1, socketID_handle sock2) {
2038

    
2039
        assert(sock1 && sock2);
2040

    
2041
        /*
2042
        * compare internal addr
2043
        */
2044
        if(sock1 == NULL || sock2 == NULL)
2045
                return 1;
2046

    
2047
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr !=
2048
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
2049
                        return 1;
2050

    
2051
        if (sock1->internal_addr.udpaddr.sin_port !=
2052
                 sock2->internal_addr.udpaddr.sin_port)
2053
                        return 1;
2054

    
2055
        /*
2056
        * compare external addr
2057
        */
2058
        if (sock1->external_addr.udpaddr.sin_addr.s_addr !=
2059
            sock2->external_addr.udpaddr.sin_addr.s_addr)
2060
                        return 1;
2061

    
2062
        if (sock1->external_addr.udpaddr.sin_port !=
2063
                 sock2->external_addr.udpaddr.sin_port)
2064
                        return 1;
2065

    
2066
        return 0;
2067
}
2068

    
2069
int mlCompareSocketIDsByPort(socketID_handle sock1, socketID_handle sock2)
2070
{
2071
        if(sock1 == NULL || sock2 == NULL)
2072
                return 1;
2073
 
2074
        if (sock1->internal_addr.udpaddr.sin_port !=
2075
                 sock2->internal_addr.udpaddr.sin_port)
2076
                        return 1;
2077

    
2078
        if (sock1->external_addr.udpaddr.sin_port !=
2079
                 sock2->external_addr.udpaddr.sin_port)
2080
                        return 1;
2081
        return 0;
2082
}
2083

    
2084
int mlGetPathMTU(int ConnectionId) {
2085
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
2086
                return -1;
2087
        if (connectbuf[ConnectionId] != NULL)
2088
                return connectbuf[ConnectionId]->pmtusize;
2089
        return -1;
2090
}
2091

    
2092
/**************************** END of GENERAL functions *************************/
2093

    
2094
/**************************** NAT functions *************************/
2095

    
2096
/* setter  */
2097
void mlSetStunServer(const int port,const char *ipaddr){
2098

    
2099
        stun_server.sin_family = AF_INET;
2100
        if (ipaddr == NULL)
2101
                stun_server.sin_addr.s_addr = htonl(INADDR_NONE);
2102
        else
2103
                stun_server.sin_addr.s_addr = resolve(ipaddr);
2104
        stun_server.sin_port = htons(port);
2105

    
2106
}
2107

    
2108
int mlGetExternalIP(char* external_addr){
2109

    
2110
        socketaddrgen udpgen;
2111
        struct sockaddr_in udpaddr;
2112

    
2113
        udpgen = local_socketID.external_addr;
2114
        udpaddr = udpgen.udpaddr;
2115

    
2116
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
2117
                        INET_ADDRSTRLEN);
2118

    
2119
        if (external_addr == NULL) {
2120

    
2121
        return -1;
2122

    
2123
        } else {
2124

    
2125
        return 0;
2126

    
2127
        }
2128

    
2129
}
2130

    
2131
/**************************** END of NAT functions *************************/