Statistics
| Branch: | Revision:

ml / ml.c @ 028bda1f

History | View | Annotate | Download (61.4 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 <arpa/inet.h>
36
#ifndef WIN32
37
#include <netinet/in.h>
38
#include <sys/socket.h>
39
#endif
40
#include <fcntl.h>
41
#include <event2/event.h>
42
#include <stdlib.h>
43
#include <unistd.h>
44
#include <stdio.h>
45
#include <stddef.h>
46
#include <stdint.h>
47
#include <string.h>
48
#include <sys/types.h>
49
#include <arpa/inet.h>
50
#include <netdb.h>
51
#include <errno.h>
52
#include <time.h>
53
#include <math.h>
54
#include <assert.h>
55

    
56
#include "msg_types.h"
57
#include "util/udpSocket.h"
58
#include "util/stun.h"
59
#include "transmissionHandler.h"
60

    
61
#define LOG_MODULE "[ml] "
62
#include "ml_log.h"
63

    
64
/**************************** START OF INTERNALS ***********************/
65

    
66
/*
67
 * a pointer to a libevent instance
68
 */
69
struct event_base *base;
70

    
71
/*
72
 * define the nr of connections the messaging layer can handle
73
 */
74
#define CONNECTBUFSIZE 10000
75
/*
76
 * define the nr of data that can be received parallel
77
 */
78
#define RECVDATABUFSIZE 10000
79
/*
80
 * define an array for message multiplexing
81
 */
82
#define MSGMULTIPLEXSIZE 127
83

    
84

    
85
/*
86
 * timeout before thinking that the STUN server can't be connected
87
 */
88
#define NAT_TRAVERSAL_TIMEOUT { 1, 0 }
89

    
90
/*
91
 * timeout before thinking of an mtu problem (check MAX_TRIALS as well)
92
 */
93
#define PMTU_TIMEOUT { 0, 500000 }
94

    
95
/*
96
 * retry sending connection messages this many times before reducing pmtu
97
 */
98
#define MAX_TRIALS 3
99

    
100
/*
101
 * default timeout value between the first and the last received packet of a message
102
 */
103
#define RECV_TIMEOUT_DEFAULT { 2, 0 }
104

    
105
/*
106
 * global variables
107
 */
108
/*
109
 * define a buffer of pointers to connect structures
110
 */
111
connect_data *connectbuf[CONNECTBUFSIZE];
112

    
113
/*
114
 * define a pointer buffer with pointers to recv_data structures
115
 */
116
recvdata *recvdatabuf[RECVDATABUFSIZE];
117

    
118
/*
119
 * define a pointer buffer for message multiplexing
120
 */
121
receive_data_cb recvcbbuf[MSGMULTIPLEXSIZE];
122

    
123
/*
124
 * stun server address
125
 */
126
struct sockaddr_in stun_server;
127

    
128
/*
129
 * receive timeout
130
 */
131
static struct timeval recv_timeout = RECV_TIMEOUT_DEFAULT;
132

    
133
/*
134
 * boolean NAT traversal successful if true
135
 */
136
boolean NAT_traversal;
137

    
138
/*
139
 * file descriptor for local socket
140
 */
141
evutil_socket_t socketfd;
142

    
143
/*
144
 * local socketID
145
 */
146
socket_ID local_socketID;
147

    
148
socketID_handle loc_socketID = &local_socketID;
149

    
150
/*
151
 * callback function pointers
152
 */
153
/*
154
 * monitoring module callbacks
155
 */
156
get_recv_pkt_inf_cb get_Recv_pkt_inf_cb = NULL;
157
get_send_pkt_inf_cb get_Send_pkt_inf_cb = NULL;
158
set_monitoring_header_pkt_cb set_Monitoring_header_pkt_cb = NULL;
159
get_recv_data_inf_cb get_Recv_data_inf_cb = NULL;
160
get_send_data_inf_cb get_Send_data_inf_cb = NULL;
161
set_monitoring_header_data_cb set_Monitoring_header_data_cb = NULL;
162
/*
163
 * connection callbacks
164
 */
165
receive_connection_cb receive_Connection_cb = NULL;
166
connection_failed_cb failed_Connection_cb = NULL;
167
/*
168
 * local socketID callback
169
 */
170
receive_localsocketID_cb receive_SocketID_cb;
171

    
172
/*
173
 * boolean that defines if received data is transmitted to the upper layer
174
 * via callback or via upper layer polling
175
 */
176
boolean recv_data_callback;
177

    
178
/*
179
 * helper function to get rid of a warning
180
 */
181
int min(int a, int b) {
182
        if (a > b) return b;
183
        return a;
184
}
185

    
186
/*
187
 * convert a socketID to a string. It uses a static buffer, so either strdup is needed, or the string will get lost!
188
 */
189
const char *conid_to_string(int con_id)
190
{
191
        static char s[INET_ADDRSTRLEN+1+5+1+INET_ADDRSTRLEN+1+5+1];
192
        mlSocketIDToString(&connectbuf[con_id]->external_socketID, s, sizeof(s));
193
        return s;
194
}
195

    
196
void register_recv_localsocketID_cb(receive_localsocketID_cb local_socketID_cb)
197
{
198
        if (local_socketID_cb == NULL) {
199
                error("ML : Register receive_localsocketID_cb: NULL ptr \n");
200
        } else {
201
                receive_SocketID_cb = local_socketID_cb;
202
        }
203
}
204

    
205

    
206
//void keep_connection_alive(const int connectionID)
207
//{
208
//
209
//    // to be done with the NAT traversal
210
//    // send a message over the wire
211
//    printf("\n");
212
//
213
//}
214

    
215
void unsetStunServer()
216
{
217
        stun_server.sin_addr.s_addr = INADDR_NONE;
218
}
219

    
220
bool isStunDefined()
221
{
222
        return stun_server.sin_addr.s_addr != INADDR_NONE;
223
}
224

    
225
void send_msg(int con_id, int msg_type, char* msg, int msg_len, bool truncable, send_params * sParams) {
226
        socketaddrgen udpgen;
227
        bool retry;
228
        int pkt_len, offset;
229
        struct iovec iov[4];
230

    
231
        char h_pkt[MON_PKT_HEADER_SPACE];
232
        char h_data[MON_DATA_HEADER_SPACE];
233

    
234
        struct msg_header msg_h;
235

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

    
238
        iov[0].iov_base = &msg_h;
239
        iov[0].iov_len = MSG_HEADER_SIZE;
240

    
241
        msg_h.local_con_id = htonl(con_id);
242
        msg_h.remote_con_id = htonl(connectbuf[con_id]->external_connectionID);
243
        msg_h.msg_type = msg_type;
244
        msg_h.msg_seq_num = htonl(connectbuf[con_id]->seqnr++);
245

    
246

    
247
        iov[1].iov_len = iov[2].iov_len = 0;
248
        iov[1].iov_base = h_pkt;
249
        iov[2].iov_base = h_data;
250

    
251

    
252
        if (connectbuf[con_id]->internal_connect)
253
                udpgen = connectbuf[con_id]->external_socketID.internal_addr;
254
        else
255
                udpgen = connectbuf[con_id]->external_socketID.external_addr;
256

    
257
        do{
258
                offset = 0;
259
                retry = false;
260
                // Monitoring layer hook
261
                if(set_Monitoring_header_data_cb != NULL) {
262
                        iov[2].iov_len = ((set_Monitoring_header_data_cb) (&(connectbuf[con_id]->external_socketID), msg_type));
263
                }
264
                msg_h.len_mon_data_hdr = iov[2].iov_len;
265

    
266
                if(get_Send_data_inf_cb != NULL && iov[2].iov_len != 0) {
267
                        mon_data_inf sd_data_inf;
268

    
269
                        memset(h_data, 0, MON_DATA_HEADER_SPACE);
270

    
271
                        sd_data_inf.remote_socketID = &(connectbuf[con_id]->external_socketID);
272
                        sd_data_inf.buffer = msg;
273
                        sd_data_inf.bufSize = msg_len;
274
                        sd_data_inf.msgtype = msg_type;
275
                        sd_data_inf.monitoringDataHeader = iov[2].iov_base;
276
                        sd_data_inf.monitoringDataHeaderLen = iov[2].iov_len;
277
                        sd_data_inf.priority = sParams->priority;
278
                        sd_data_inf.padding = sParams->padding;
279
                        sd_data_inf.confirmation = sParams->confirmation;
280
                        sd_data_inf.reliable = sParams->reliable;
281
                        memset(&sd_data_inf.arrival_time, 0, sizeof(struct timeval));
282

    
283
                        (get_Send_data_inf_cb) ((void *) &sd_data_inf);
284
                }
285

    
286
                do {
287
                        if(set_Monitoring_header_pkt_cb != NULL) {
288
                                iov[1].iov_len = (set_Monitoring_header_pkt_cb) (&(connectbuf[con_id]->external_socketID), msg_type);
289
                        }
290
                        pkt_len = min(connectbuf[con_id]->pmtusize - iov[2].iov_len - iov[1].iov_len - iov[0].iov_len, msg_len - offset) ;
291

    
292
                        iov[3].iov_len = pkt_len;
293
                        iov[3].iov_base = msg + offset;
294

    
295
                        //fill header
296
                        msg_h.len_mon_packet_hdr = iov[1].iov_len;
297
                        msg_h.offset = htonl(offset);
298
                        msg_h.msg_length = htonl(truncable ? pkt_len : msg_len);
299

    
300
                        //monitoring layer hook
301
                        if(get_Send_pkt_inf_cb != NULL && iov[1].iov_len) {
302
                                mon_pkt_inf pkt_info;
303

    
304
                                memset(h_pkt,0,MON_PKT_HEADER_SPACE);
305

    
306
                                pkt_info.remote_socketID = &(connectbuf[con_id]->external_socketID);
307
                                pkt_info.buffer = msg + offset;
308
                                pkt_info.bufSize = pkt_len;
309
                                pkt_info.msgtype = msg_type;
310
                                pkt_info.dataID = connectbuf[con_id]->seqnr;
311
                                pkt_info.offset = offset;
312
                                pkt_info.datasize = msg_len;
313
                                pkt_info.monitoringHeaderLen = iov[1].iov_len;
314
                                pkt_info.monitoringHeader = iov[1].iov_base;
315
                                pkt_info.ttl = -1;
316
                                memset(&(pkt_info.arrival_time),0,sizeof(struct timeval));
317

    
318
                                (get_Send_pkt_inf_cb) ((void *) &pkt_info);
319
                        }
320

    
321
                        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));
322
                        switch(sendPacket(socketfd, iov, 4, &udpgen.udpaddr)) {
323
                                case MSGLEN:
324
                                        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);
325
                                        // TODO: pmtu decremented here, but not in the "truncable" packet. That is currently resent without changing the claimed pmtu. Might need to be changed.
326
                                        connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
327
                                        if (connectbuf[con_id]->pmtusize > 0) {
328
                                                connectbuf[con_id]->delay = true;
329
                                                retry = true;
330
                                        }
331
                                        offset = msg_len; // exit the while
332
                                        break;
333
                                case FAILURE:
334
                                        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);
335
                                        offset = msg_len; // exit the while
336
                                        break;
337
                                case OK:
338
                                        //update
339
                                        offset += pkt_len;
340
                                        //transmit data header only in the first packet
341
                                        iov[2].iov_len = 0;
342
                                        break;
343
                        }
344
                } while(offset != msg_len && !truncable);
345
        } while(retry);
346
}
347

    
348
void pmtu_timeout_cb(int fd, short event, void *arg);
349

    
350
void reschedule_conn_msg(int con_id)
351
{
352
        if (connectbuf[con_id]->timeout_event) {
353
                /* delete old timout */        
354
                event_del(connectbuf[con_id]->timeout_event);
355
                event_free(connectbuf[con_id]->timeout_event);
356
        }
357
        connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
358
        evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
359
}
360

    
361
void send_conn_msg(int con_id, int buf_size, int command_type)
362
{
363
        if (buf_size < sizeof(struct conn_msg)) {
364
                error("ML: requested connection message size is too small\n");
365
                return;
366
        }
367

    
368
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
369
                connectbuf[con_id]->ctrl_msg_buf = malloc(buf_size);
370
                memset(connectbuf[con_id]->ctrl_msg_buf, 0, buf_size);
371
        }
372

    
373
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
374
                error("ML: can not allocate memory for connection message\n");
375
                return;
376
        }
377

    
378
        struct conn_msg *msg_header = (struct conn_msg*) connectbuf[con_id]->ctrl_msg_buf;
379

    
380
        msg_header->comand_type = command_type;
381
        msg_header->pmtu_size = connectbuf[con_id]->pmtusize;
382

    
383
        memcpy(&(msg_header->sock_id), loc_socketID, sizeof(socket_ID));
384

    
385
        send_msg(con_id, ML_CON_MSG, connectbuf[con_id]->ctrl_msg_buf, buf_size, true, &(connectbuf[con_id]->defaultSendParams));
386
}
387

    
388
void send_conn_msg_with_pmtu_discovery(int con_id, int buf_size, int command_type)
389
{
390
        struct timeval tout = PMTU_TIMEOUT;
391
        connectbuf[con_id]->timeout_value = tout;
392
        connectbuf[con_id]->trials = 1;
393
        send_conn_msg(con_id, buf_size, command_type);
394
        reschedule_conn_msg(con_id);
395
}
396

    
397
void resend_conn_msg(int con_id)
398
{
399
        connectbuf[con_id]->trials++;
400
        send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
401
        reschedule_conn_msg(con_id);
402
}
403

    
404
void recv_conn_msg(struct msg_header *msg_h, char *msgbuf, int msg_size, struct sockaddr_in *recv_addr)
405
{
406
        struct conn_msg *con_msg;
407
        int free_con_id, con_id;
408

    
409
        time_t now = time(NULL);
410
        double timediff = 0.0;
411
        char sock_id_str[1000];
412
        
413
        msgbuf += msg_h->len_mon_data_hdr;
414
        msg_size -= msg_h->len_mon_data_hdr;
415
        con_msg = (struct conn_msg *)msgbuf;
416
        
417
        //verify message validity
418
        if (msg_size < sizeof(struct conn_msg)) {
419
                char recv_addr_str[INET_ADDRSTRLEN];
420
                inet_ntop(AF_INET, &(recv_addr->sin_addr.s_addr), recv_addr_str, INET_ADDRSTRLEN);
421
                info("Invalid conn_msg received from %s\n", recv_addr_str);
422
                return;
423
        }
424

    
425
        //decode sock_id for debug messages
426
        mlSocketIDToString(&con_msg->sock_id,sock_id_str,999);
427

    
428
        if (con_msg->sock_id.internal_addr.udpaddr.sin_addr.s_addr != recv_addr->sin_addr.s_addr &&
429
            con_msg->sock_id.external_addr.udpaddr.sin_addr.s_addr != recv_addr->sin_addr.s_addr   ) {
430
                char recv_addr_str[INET_ADDRSTRLEN];
431
                inet_ntop(AF_INET, &(recv_addr->sin_addr.s_addr), recv_addr_str, INET_ADDRSTRLEN);
432
                info("Conn msg received from %s, but claims to be from %s", recv_addr_str, sock_id_str);
433
                return;
434
        }
435

    
436
        // Monitoring layer hook
437
        if(get_Recv_data_inf_cb != NULL) {
438
                // update pointer to the real data
439
                mon_data_inf recv_data_inf;
440
                recv_data_inf.remote_socketID = &(con_msg->sock_id);
441
                recv_data_inf.buffer = msgbuf;
442
                recv_data_inf.bufSize = msg_size;
443
                recv_data_inf.msgtype = msg_h->msg_type;
444
                recv_data_inf.monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
445
                recv_data_inf.monitoringDataHeader = msg_h->len_mon_data_hdr ? msgbuf : NULL;
446
                gettimeofday(&recv_data_inf.arrival_time, NULL);
447
                recv_data_inf.firstPacketArrived = true;
448
                recv_data_inf.recvFragments = 1;
449
                recv_data_inf.priority = false;
450
                recv_data_inf.padding = false;
451
                recv_data_inf.confirmation = false;
452
                recv_data_inf.reliable = false;
453

    
454
                // send data recv callback to monitoring module
455
                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
456
        }
457

    
458
        // check the connection command type
459
        switch (con_msg->comand_type) {
460
                /*
461
                * if INVITE: enter a new socket make new entry in connect array
462
                * send an ok
463
                */
464
                case INVITE:
465
                        info("ML: received INVITE from %s (size:%d)\n", sock_id_str, msg_size);
466
                        /*
467
                        * check if another connection for the external connectionID exist
468
                        * that was established within the last 2 seconds
469
                        */
470
                        free_con_id = -1;
471
                        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
472
                                if (connectbuf[con_id] != NULL) {
473
                                        if (mlCompareSocketIDs(&(connectbuf[con_id]->external_socketID), &(con_msg->sock_id)) == 0) {
474
                                                //timediff = difftime(now, connectbuf[con_id]->starttime);        //TODO: why this timeout? Shouldn't the connection be closed instead if there is a timeout?
475
                                                //if (timediff < 2)
476
                                                //update remote connection ID
477
                                                if (connectbuf[con_id]->external_connectionID != msg_h->local_con_id) {
478
                                                        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);
479
                                                        connectbuf[con_id]->external_connectionID = msg_h->local_con_id;
480
                                                }
481
                                                break;
482
                                        }
483
                                } else if(free_con_id == -1)
484
                                        free_con_id = con_id;
485
                        }
486

    
487
                        if (con_id == CONNECTBUFSIZE) {
488
                                // create an entry in the connecttrybuf
489
                                if(free_con_id == -1) {
490
                                        error("ML: no new connect_buf available\n");
491
                                        return;
492
                                }
493
                                connectbuf[free_con_id] = (connect_data *) malloc(sizeof(connect_data));
494
                                memset(connectbuf[free_con_id],0,sizeof(connect_data));
495
                                connectbuf[free_con_id]->connection_head = connectbuf[free_con_id]->connection_last = NULL;
496
                                connectbuf[free_con_id]->starttime = time(NULL);
497
                                memcpy(&(connectbuf[free_con_id]->external_socketID), &(con_msg->sock_id), sizeof(socket_ID));
498
                                connectbuf[free_con_id]->pmtusize = con_msg->pmtu_size;        // bootstrap pmtu from the other's size. Not strictly needed, but a good hint
499
                                connectbuf[free_con_id]->timeout_event = NULL;
500
                                connectbuf[free_con_id]->external_connectionID = msg_h->local_con_id;
501
                                connectbuf[free_con_id]->internal_connect =
502
                                        !compare_external_address_socketIDs(&(con_msg->sock_id), loc_socketID);
503
                                con_id = free_con_id;
504
                        }
505

    
506
                        //if(connectbuf[con_id]->status <= CONNECT) { //TODO: anwer anyway. Why the outher would invite otherwise?
507
                                //update status and send back answer
508
                                connectbuf[con_id]->status = CONNECT;
509
                                send_conn_msg_with_pmtu_discovery(con_id, con_msg->pmtu_size, CONNECT);
510
                        //}
511
                        break;
512
                case CONNECT:
513
                        info("ML: received CONNECT from %s (size:%d)\n", sock_id_str, msg_size);
514

    
515
                        if(msg_h->remote_con_id != -1 && connectbuf[msg_h->remote_con_id] == NULL) {
516
                                error("ML: received CONNECT for inexistent connection rconID:%d\n",msg_h->remote_con_id);
517
                                return;
518
                        }
519

    
520
                        /*
521
                        * check if the connection status is not already 1 or 2
522
                        */
523
                        if (connectbuf[msg_h->remote_con_id]->status == INVITE) {
524
                                // set the external connectionID
525
                                connectbuf[msg_h->remote_con_id]->external_connectionID = msg_h->local_con_id;
526
                                // change status con_msg the connection_data
527
                                connectbuf[msg_h->remote_con_id]->status = READY;
528
                                // change pmtusize in the connection_data: not needed. receiving a CONNECT means our INVITE went through. So why change pmtu?
529
                                //connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
530

    
531
                                // send the READY
532
                                send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
533

    
534
                                if (receive_Connection_cb != NULL)
535
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
536

    
537
                                // call all registered callbacks
538
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
539
                                        struct receive_connection_cb_list *temp;
540
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
541
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
542
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
543
                                        free(temp);
544
                                }
545
                                connectbuf[msg_h->remote_con_id]->connection_head =
546
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
547
                        } else {
548
                                // send the READY
549
                                send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
550
                        }
551

    
552
                        debug("ML: active connection established\n");
553
                        break;
554

    
555
                        /*
556
                        * if READY: find the entry in the connection array set the
557
                        * connection active change the pmtu size
558
                        */
559
                case READY:
560
                        info("ML: received READY from %s (size:%d)\n", sock_id_str, msg_size);
561
                        if(connectbuf[msg_h->remote_con_id] == NULL) {
562
                                error("ML: received READY for inexistent connection\n");
563
                                return;
564
                        }
565
                        /*
566
                        * checks if the connection is not already established
567
                        */
568
                        if (connectbuf[msg_h->remote_con_id]->status == CONNECT) {
569
                                // change status of the connection
570
                                connectbuf[msg_h->remote_con_id]->status = READY;
571
                                // change pmtusize: not needed. pmtu doesn't have to be symmetric
572
                                //connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
573

    
574
                                if (receive_Connection_cb != NULL)
575
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
576

    
577
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
578
                                        struct receive_connection_cb_list *temp;
579
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
580
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
581
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
582
                                        free(temp);
583
                                }
584
                                connectbuf[msg_h->remote_con_id]->connection_head =
585
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
586
                                debug("ML: passive connection established\n");
587
                        }
588
                        break;
589
        }
590
}
591

    
592
void recv_stun_msg(char *msgbuf, int recvSize)
593
{
594
        /*
595
        * create empty stun message struct
596
        */
597
        StunMessage resp;
598
        memset(&resp, 0, sizeof(StunMessage));
599
        /*
600
        * parse the message
601
        */
602
        int returnValue = 0;
603
        returnValue = recv_stun_message(msgbuf, recvSize, &resp);
604

    
605
        if (returnValue == 0) {
606
                /*
607
                * read the reflexive Address into the local_socketID
608
                */
609
                struct sockaddr_in reflexiveAddr = {0};
610
                reflexiveAddr.sin_family = AF_INET;
611
                reflexiveAddr.sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
612
                reflexiveAddr.sin_port = htons(resp.mappedAddress.ipv4.port);
613
                socketaddrgen reflexiveAddres = {0};
614
                reflexiveAddres.udpaddr = reflexiveAddr;
615
                local_socketID.external_addr = reflexiveAddres;
616
                NAT_traversal = true;
617
                // callback to the upper layer indicating that the socketID is now
618
                // ready to use
619
                (receive_SocketID_cb) (&local_socketID, 0);
620
        }
621
}
622

    
623
//done
624
void recv_timeout_cb(int fd, short event, void *arg)
625
{
626
        int recv_id = (long) arg;
627
        debug("ML: recv_timeout_cb called. Timeout for id:%d\n",recv_id);
628

    
629
        if (recvdatabuf[recv_id] == NULL) {
630
                return;
631
        }
632

    
633

    
634
/*        if(recvdatabuf[recv_id]->status == ACTIVE) {
635
                //TODO make timeout at least a DEFINE
636
                struct timeval timeout = { 4, 0 };
637
                recvdatabuf[recv_id]->status = INACTIVE;
638
                event_base_once(base, -1, EV_TIMEOUT, recv_timeout_cb,
639
                        arg, &timeout);
640
                return;
641
        }
642
*/
643

    
644
        if(recvdatabuf[recv_id]->status == ACTIVE) {
645
                // Monitoring layer hook
646
                if(get_Recv_data_inf_cb != NULL) {
647
                        mon_data_inf recv_data_inf;
648

    
649
                        recv_data_inf.remote_socketID =
650
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
651
                        recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
652
                        recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
653
                        recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
654
                        recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
655
                        recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
656
                                recvdatabuf[recv_id]->recvbuf : NULL;
657
                        gettimeofday(&recv_data_inf.arrival_time, NULL);
658
                        recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
659
                        recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
660
                        recv_data_inf.priority = false;
661
                        recv_data_inf.padding = false;
662
                        recv_data_inf.confirmation = false;
663
                        recv_data_inf.reliable = false;
664

    
665
                        // send data recv callback to monitoring module
666

    
667
                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
668
                }
669

    
670
                // Get the right callback
671
                receive_data_cb receive_data_callback = recvcbbuf[recvdatabuf[recv_id]->msgtype];
672

    
673
                recv_params rParams;
674

    
675
                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
676
                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
677
                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
678
                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
679
                rParams.remote_socketID =
680
                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
681
                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
682

    
683
                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
684
                        recvdatabuf[recv_id]->msgtype, &rParams);
685

    
686
                //clean up
687
                if (recvdatabuf[recv_id]->timeout_event) {
688
                        event_del(recvdatabuf[recv_id]->timeout_event);
689
                        event_free(recvdatabuf[recv_id]->timeout_event);
690
                        recvdatabuf[recv_id]->timeout_event = NULL;
691
                }
692
                free(recvdatabuf[recv_id]->recvbuf);
693
                free(recvdatabuf[recv_id]);
694
                recvdatabuf[recv_id] = NULL;
695
        }
696
}
697

    
698
// process a single recv data message
699
void recv_data_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
700
{
701
        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);
702

    
703
        int recv_id, free_recv_id = -1;
704

    
705
        if(connectbuf[msg_h->remote_con_id] == NULL) {
706
                debug("ML: Received a message not related to any opened connection!\n");
707
                return;
708
        }
709

    
710
        // check if a recv_data exist and enter data
711
        for (recv_id = 0; recv_id < RECVDATABUFSIZE; recv_id++)
712
                if (recvdatabuf[recv_id] != NULL) {
713
                        if (msg_h->remote_con_id == recvdatabuf[recv_id]->connectionID &&
714
                                        msg_h->msg_seq_num == recvdatabuf[recv_id]->seqnr)
715
                                                break;
716
                } else
717
                        if(free_recv_id == -1)
718
                                free_recv_id = recv_id;
719

    
720

    
721
        if(recv_id == RECVDATABUFSIZE) {
722
                //no recv_data found: create one
723
                recv_id = free_recv_id;
724
                recvdatabuf[recv_id] = (recvdata *) malloc(sizeof(recvdata));
725
                memset(recvdatabuf[recv_id], 0, sizeof(recvdata));
726
                recvdatabuf[recv_id]->connectionID = msg_h->remote_con_id;
727
                recvdatabuf[recv_id]->seqnr = msg_h->msg_seq_num;
728
                recvdatabuf[recv_id]->monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
729
                recvdatabuf[recv_id]->bufsize = msg_h->msg_length + msg_h->len_mon_data_hdr;
730
                recvdatabuf[recv_id]->recvbuf = (char *) malloc(recvdatabuf[recv_id]->bufsize);
731
                recvdatabuf[recv_id]->arrivedBytes = 0;        //count this without the Mon headers
732
                /*
733
                * read the timeout data and set it
734
                */
735
                recvdatabuf[recv_id]->timeout_value = recv_timeout;
736
                recvdatabuf[recv_id]->timeout_event = NULL;
737
                recvdatabuf[recv_id]->recvID = recv_id;
738
                recvdatabuf[recv_id]->starttime = time(NULL);
739
                recvdatabuf[recv_id]->msgtype = msg_h->msg_type;
740

    
741
                // fill the buffer with zeros
742
                memset(recvdatabuf[recv_id]->recvbuf, 0, recvdatabuf[recv_id]->bufsize);
743
                debug(" new @ id:%d\n",recv_id);
744
        } else {        //message structure already exists, no need to create new
745
                debug(" found @ id:%d (arrived before this packet: bytes:%d fragments%d\n",recv_id, recvdatabuf[recv_id]->arrivedBytes, recvdatabuf[recv_id]->recvFragments);
746
        }
747

    
748
        //if first packet extract mon data header and advance pointer
749
        if (msg_h->offset == 0) {
750
                memcpy(recvdatabuf[recv_id]->recvbuf, msgbuf, msg_h->len_mon_data_hdr);
751
                msgbuf += msg_h->len_mon_data_hdr;
752
                bufsize -= msg_h->len_mon_data_hdr;
753
                recvdatabuf[recv_id]->firstPacketArrived = 1;
754
        }
755

    
756

    
757
        // increment fragmentnr
758
        recvdatabuf[recv_id]->recvFragments++;
759
        // increment the arrivedBytes
760
        recvdatabuf[recv_id]->arrivedBytes += bufsize;
761

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

    
765
        //TODO very basic checkif all fragments arrived: has to be reviewed
766
        if(recvdatabuf[recv_id]->arrivedBytes == recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen)
767
                recvdatabuf[recv_id]->status = COMPLETE; //buffer full -> msg completly arrived
768
        else
769
                recvdatabuf[recv_id]->status = ACTIVE;
770

    
771
        if (recv_data_callback) {
772
                if(recvdatabuf[recv_id]->status == COMPLETE) {
773
                        // Monitoring layer hook
774
                        if(get_Recv_data_inf_cb != NULL) {
775
                                mon_data_inf recv_data_inf;
776

    
777
                                recv_data_inf.remote_socketID =
778
                                         &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
779
                                recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
780
                                recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
781
                                recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
782
                                recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
783
                                recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
784
                                        recvdatabuf[recv_id]->recvbuf : NULL;
785
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
786
                                recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
787
                                recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
788
                                recv_data_inf.priority = false;
789
                                recv_data_inf.padding = false;
790
                                recv_data_inf.confirmation = false;
791
                                recv_data_inf.reliable = false;
792

    
793
                                // send data recv callback to monitoring module
794

    
795
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
796
                        }
797

    
798
                        // Get the right callback
799
                        receive_data_cb receive_data_callback = recvcbbuf[msg_h->msg_type];
800
                        if (receive_data_callback) {
801

    
802
                                recv_params rParams;
803

    
804
                                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen - recvdatabuf[recv_id]->arrivedBytes;
805
                                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
806
                                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
807
                                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
808
                                rParams.remote_socketID =
809
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
810

    
811
                                char str[1000];
812
                                mlSocketIDToString(rParams.remote_socketID,str,999);
813
                                debug("ML: received message from conID:%d, %s\n",recvdatabuf[recv_id]->connectionID,str);
814
                                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
815

    
816
                                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
817
                                        recvdatabuf[recv_id]->msgtype, (void *) &rParams);
818
                        } else {
819
                            warn("ML: callback not initialized for this message type: %d!\n",msg_h->msg_type);
820
                        }
821

    
822
                        //clean up
823
                        if (recvdatabuf[recv_id]->timeout_event) {
824
                                debug("ML: freeing timeout for %d",recv_id);
825
                                event_del(recvdatabuf[recv_id]->timeout_event);
826
                                event_free(recvdatabuf[recv_id]->timeout_event);
827
                                recvdatabuf[recv_id]->timeout_event = NULL;
828
                        } else {
829
                                debug("ML: received in 1 packet\n",recv_id);
830
                        }
831
                        free(recvdatabuf[recv_id]->recvbuf);
832
                        free(recvdatabuf[recv_id]);
833
                        recvdatabuf[recv_id] = NULL;
834
                } else { // not COMPLETE
835
                        if (!recvdatabuf[recv_id]->timeout_event) {
836
                                //start time out
837
                                //TODO make timeout at least a DEFINE
838
                                recvdatabuf[recv_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &recv_timeout_cb, (void *) (long)recv_id);
839
                                evtimer_add(recvdatabuf[recv_id]->timeout_event, &recv_timeout);
840
                        }
841
                }
842
        }
843
}
844

    
845
//done
846
void pmtu_timeout_cb(int fd, short event, void *arg)
847
{
848

    
849
        int con_id = (long) arg;
850
        pmtu new_pmtusize;
851

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

    
854
        if(connectbuf[con_id] == NULL) {
855
                error("ML: pmtu timeout called on non existing con_id\n");
856
                return;
857
        }
858

    
859
        if(connectbuf[con_id]->status == READY) {
860
                // nothing to do anymore
861
                event_del(connectbuf[con_id]->timeout_event);
862
                event_free(connectbuf[con_id]->timeout_event);
863
                connectbuf[con_id]->timeout_event = NULL;
864
                return;
865
        }
866

    
867
        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);
868

    
869
        if(connectbuf[con_id]->delay || connectbuf[con_id]->trials == MAX_TRIALS - 1) {
870
                double delay = connectbuf[con_id]->timeout_value.tv_sec + connectbuf[con_id]->timeout_value.tv_usec / 1000000.0;
871
                delay = delay * 2;
872
                info("\tML: increasing pmtu timeout to %f sec\n", delay);
873
                connectbuf[con_id]->timeout_value.tv_sec = floor(delay);
874
                connectbuf[con_id]->timeout_value.tv_usec = fmod(delay, 1.0) * 1000000.0;
875
                if(connectbuf[con_id]->delay) {
876
                        connectbuf[con_id]->delay = false;
877
                        reschedule_conn_msg(con_id);
878
                }
879
        }
880

    
881
        if(connectbuf[con_id]->trials == MAX_TRIALS) {
882
                // decrement the pmtu size
883
                struct timeval tout = PMTU_TIMEOUT;
884
                info("\tML: decreasing pmtu estimate from %d to %d\n", connectbuf[con_id]->pmtusize, pmtu_decrement(connectbuf[con_id]->pmtusize));
885
                connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
886
                connectbuf[con_id]->timeout_value = tout; 
887
                connectbuf[con_id]->trials = 0;
888
        }
889

    
890
        //error in PMTU discovery?
891
        if (connectbuf[con_id]->pmtusize == ERROR) {
892
                if (connectbuf[con_id]->internal_connect == true) {
893
                        //as of now we tried directly connecting, now let's try trough the NAT
894
                        connectbuf[con_id]->internal_connect = false;
895
                        connectbuf[con_id]->pmtusize = DSLSLIM;
896
                } else {
897
                        //nothing to do we have to give up
898
                        error("ML: Could not create connection with connectionID %i!\n",con_id);
899
                        // envoke the callback for failed connection establishment
900
                        if(failed_Connection_cb != NULL)
901
                                (failed_Connection_cb) (con_id, NULL);
902
                        // delete the connection entry
903
                        mlCloseConnection(con_id);
904
                        return;
905
                }
906
        }
907

    
908
        //retry
909
        resend_conn_msg(con_id);
910
}
911

    
912

    
913
int schedule_pmtu_timeout(int con_id)
914
{
915
        if (! connectbuf[con_id]->timeout_event) {
916
                struct timeval tout = PMTU_TIMEOUT;
917
                connectbuf[con_id]->timeout_value = tout;
918
                connectbuf[con_id]->trials = 1;
919
                connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
920
                evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
921
        }
922
}
923

    
924
/*
925
 * decrements the mtu size
926
 */
927
pmtu pmtu_decrement(pmtu pmtusize)
928
{
929
        pmtu pmtu_return_size;
930
        switch(pmtusize) {
931
        case MAX:
932
                //return DSL;
933
                return DSLSLIM;        //shortcut to use less vales
934
        case DSL:
935
                return DSLMEDIUM;
936
        case DSLMEDIUM:
937
                return DSLSLIM;
938
        case DSLSLIM:
939
                //return BELOWDSL;
940
                return MIN;        //shortcut to use less vales
941
        case BELOWDSL:
942
                return MIN;
943
        case MIN:
944
                return ERROR;
945
        default:
946
                warn("ML: strange pmtu size encountered:%d, changing to some safe value:%d\n", pmtusize, MIN);
947
                return MIN;
948
        }
949
}
950

    
951
// called when an ICMP pmtu error message (type 3, code 4) is received
952
void pmtu_error_cb_th(char *msg, int msglen)
953
{
954
        debug("ML: pmtu_error callback called msg_size: %d\n",msglen);
955
        //TODO debug
956
        return;
957

    
958
    char *msgbufptr = NULL;
959
    int msgtype;
960
    int connectionID;
961
    pmtu pmtusize;
962
    pmtu new_pmtusize;
963
    int dead = 0;
964

    
965
    // check the packettype
966
    msgbufptr = &msg[0];
967

    
968
    // check the msgtype
969
    msgbufptr = &msg[1];
970
    memcpy(&msgtype, msgbufptr, 4);
971

    
972
    if (msgtype == 0) {
973

    
974
        // get the connectionID
975
        msgbufptr = &msg[5];
976
        memcpy(&connectionID, msgbufptr, 4);
977

    
978
        int msgtype_c = connectbuf[connectionID]->status;
979
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
980

    
981
        if (msgtype_c != msgtype) {
982
            dead = 1;
983
        }
984

    
985

    
986
    } else if (msgtype == 1) {
987

    
988
        // read the connectionID
989
        msgbufptr = &msg[9];
990
        memcpy(&connectionID, msgbufptr, 4);
991

    
992
        int msgtype_c = connectbuf[connectionID]->status;
993
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
994

    
995
        if (msgtype_c != msgtype) {
996
            dead = 1;
997
        }
998

    
999
    }
1000
    // decrement the pmtu size
1001
    new_pmtusize = pmtu_decrement(pmtusize);
1002

    
1003
//    connectbuf[connectionID]->pmtutrysize = new_pmtusize;
1004

    
1005
    if (new_pmtusize == ERROR) {
1006
                error("ML:  Could not create connection with connectionID %i !\n",
1007
                        connectionID);
1008

    
1009
                if(failed_Connection_cb != NULL)
1010
                        (failed_Connection_cb) (connectionID, NULL);
1011
                // set the message type to a non existent message
1012
                msgtype = 2;
1013
                // delete the connection entry
1014
                 mlCloseConnection(connectionID);
1015
        }
1016

    
1017
    if (msgtype == 0 && dead != 1) {
1018

    
1019
        // stop the timeout event
1020
        // timeout_del(connectbuf[connectionID]->timeout);
1021
        /*
1022
         * libevent2
1023
         */
1024

    
1025
        // event_del(connectbuf[connectionID]->timeout);
1026

    
1027

    
1028
        // create and send a connection message
1029
//         create_conn_msg(new_pmtusize, connectionID,
1030
//                         &local_socketID, INVITE);
1031

    
1032
//        send_conn_msg(connectionID, new_pmtusize);
1033

    
1034
        // set a timeout event for the pmtu discovery
1035
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
1036
        // *)&connectionID);
1037

    
1038
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1039

    
1040
        /*
1041
         * libevent2
1042
         */
1043

    
1044
        struct event *ev;
1045
        ev = evtimer_new(base, pmtu_timeout_cb,
1046
                         (void *) connectbuf[connectionID]);
1047

    
1048
        // connectbuf[connectionID]->timeout = ev;
1049

    
1050
        event_add(ev, &connectbuf[connectionID]->timeout_value);
1051

    
1052
    } else if (msgtype == 1 && dead != 1) {
1053

    
1054
        // stop the timeout event
1055
        // timeout_del(connectbuf[connectionID]->timeout);
1056

    
1057
        /*
1058
         * libevent2
1059
         */
1060
        // info("still here 11 \n");
1061
        // printf("ev %d \n",connectbuf[connectionID]->timeout);
1062
        // event_del(connectbuf[connectionID]->timeout );
1063
        // evtimer_del(connectbuf[connectionID]->timeout );
1064

    
1065

    
1066
//         // create and send a connection message
1067
//         create_conn_msg(new_pmtusize,
1068
//                         connectbuf[connectionID]->connectionID,
1069
//                         NULL, CONNECT);
1070

    
1071
        //send_conn_msg(connectionID, new_pmtusize);
1072

    
1073
        // set a timeout event for the pmtu discovery
1074
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
1075
        // *)&connectionID);
1076
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1077

    
1078
        /*
1079
         * libevent2
1080
         */
1081
        // struct event *ev;
1082
        // ev = evtimer_new(base,pmtu_timeout_cb, (void
1083
        // *)connectbuf[connectionID]);
1084
        // connectbuf[connectionID]->timeout = ev;
1085
        // event_add(ev,&connectbuf[connectionID]->timeout_value);
1086

    
1087
    }
1088
}
1089

    
1090
/*
1091
 * what to do once a packet arrived if it is a conn packet send it to
1092
 * recv_conn handler if it is a data packet send it to the recv_data
1093
 * handler
1094
 */
1095

    
1096
//done --
1097
void recv_pkg(int fd, short event, void *arg)
1098
{
1099
        debug("ML: recv_pkg called\n");
1100

    
1101
        struct msg_header *msg_h;
1102
        char msgbuf[MAX];
1103
        pmtu recvSize = MAX;
1104
        char *bufptr = msgbuf;
1105
        int ttl;
1106
        struct sockaddr_in recv_addr;
1107
        int msg_size;
1108

    
1109
        recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
1110

    
1111

    
1112
        // check if it is not just an ERROR message
1113
        if(recvSize < 0)
1114
                return;
1115

    
1116
        // @TODO check if this simplistic STUN message recognition really always works, probably not
1117
        unsigned short stun_bind_response = 0x0101;
1118
        unsigned short * msgspot = (unsigned short *) msgbuf;
1119
        if (*msgspot == stun_bind_response) {
1120
                debug("ML: recv_pkg: parse stun message called\n");
1121
                recv_stun_msg(msgbuf, recvSize);
1122
                return;
1123
        }
1124

    
1125
        msg_h = (struct msg_header *) msgbuf;
1126

    
1127
        /* convert header from network to host order */
1128
        msg_h->offset = ntohl(msg_h->offset);
1129
        msg_h->msg_length = ntohl(msg_h->msg_length);
1130
        msg_h->local_con_id = ntohl(msg_h->local_con_id);
1131
        msg_h->remote_con_id = ntohl(msg_h->remote_con_id);
1132
        msg_h->msg_seq_num = ntohl(msg_h->msg_seq_num);
1133

    
1134
        //verify minimum size
1135
        if (recvSize < sizeof(struct msg_header)) {
1136
          info("UDP packet too small, can't be an ML packet");
1137
          return;
1138
        }
1139

    
1140
        //TODO add more verifications
1141

    
1142
        bufptr += MSG_HEADER_SIZE + msg_h->len_mon_packet_hdr;
1143
        msg_size = recvSize - MSG_HEADER_SIZE - msg_h->len_mon_packet_hdr;
1144

    
1145
        //verify more fields
1146
        if (msg_size < 0) {
1147
          info("Corrupted UDP packet received");
1148
          return;
1149
        }
1150

    
1151
        if(get_Recv_pkt_inf_cb != NULL) {
1152
                mon_pkt_inf msginfNow;
1153
                msginfNow.monitoringHeaderLen = msg_h->len_mon_packet_hdr;
1154
                msginfNow.monitoringHeader = msg_h->len_mon_packet_hdr ? &msgbuf[0] + MSG_HEADER_SIZE : NULL;
1155
                //TODO rethink this ...
1156
                if(msg_h->msg_type == ML_CON_MSG) {
1157
                        struct conn_msg *c_msg = (struct conn_msg *) bufptr;
1158
                        msginfNow.remote_socketID = &(c_msg->sock_id);
1159
                }
1160
                else if(connectbuf[msg_h->remote_con_id] == NULL) {
1161
                        error("ML: received pkg called with non existent connection\n");
1162
                        return;
1163
                } else
1164
                        msginfNow.remote_socketID = &(connectbuf[msg_h->remote_con_id]->external_socketID);
1165
                msginfNow.buffer = bufptr;
1166
                msginfNow.bufSize = recvSize;
1167
                msginfNow.msgtype = msg_h->msg_type;
1168
                msginfNow.ttl = ttl;
1169
                msginfNow.dataID = msg_h->msg_seq_num;
1170
                msginfNow.offset = msg_h->offset;
1171
                msginfNow.datasize = msg_h->msg_length;
1172
                gettimeofday(&msginfNow.arrival_time, NULL);
1173
                (get_Recv_pkt_inf_cb) ((void *) &msginfNow);
1174
        }
1175

    
1176

    
1177
        switch(msg_h->msg_type) {
1178
                case ML_CON_MSG:
1179
                        debug("ML: received conn pkg\n");
1180
                        recv_conn_msg(msg_h, bufptr, msg_size, &recv_addr);
1181
                        break;
1182
                default:
1183
                        if(msg_h->msg_type < 127) {
1184
                                debug("ML: received data pkg\n");
1185
                                recv_data_msg(msg_h, bufptr, msg_size);
1186
                                break;
1187
                        }
1188
                        debug("ML: unrecognised msg_type\n");
1189
                        break;
1190
        }
1191
}
1192

    
1193
/*
1194
 * compare the external IP address of two socketIDs
1195
 */
1196
int
1197
compare_external_address_socketIDs(socketID_handle sock1, socketID_handle sock2)
1198
{
1199
        if( sock1->external_addr.udpaddr.sin_addr.s_addr == sock2->external_addr.udpaddr.sin_addr.s_addr)
1200
                return 0;
1201
        return 1;
1202
}
1203

    
1204
void try_stun();
1205

    
1206
/*
1207
 * the timeout of the NAT traversal
1208
 */
1209
void nat_traversal_timeout(int fd, short event, void *arg)
1210
{
1211
        if (NAT_traversal == false) {
1212
                debug("ML: NAT traversal request re-send\n");
1213
                if(receive_SocketID_cb)
1214
                        (receive_SocketID_cb) (&local_socketID, 2);
1215
                try_stun();
1216
        }
1217
}
1218

    
1219
//return IP address, or INADDR_NONE if can't resolve
1220
unsigned long resolve(const char *ipaddr)
1221
{
1222
        struct hostent *h = gethostbyname(ipaddr);
1223
        if (!h) {
1224
                error("ML: Unable to resolve host name %s\n", ipaddr);
1225
                return INADDR_NONE;
1226
        }
1227
        unsigned long *addr = (unsigned long *) (h->h_addr);
1228
        return *addr;
1229
}
1230

    
1231

    
1232
/*
1233
 * returns the file descriptor, or <0 on error. The ipaddr can be a null
1234
 * pointer. Then all available ipaddr on the machine are choosen.
1235
 */
1236
int create_socket(const int port, const char *ipaddr)
1237
{
1238
        struct sockaddr_in udpaddr = {0};
1239
        udpaddr.sin_family = AF_INET;
1240
        if (ipaddr == NULL) {
1241
                /*
1242
                * try to guess the local IP address
1243
                */
1244
                const char *ipaddr_iface = mlAutodetectIPAddress();
1245
                if (ipaddr_iface) {
1246
                        udpaddr.sin_addr.s_addr = inet_addr(ipaddr_iface);
1247
                } else {
1248
                        udpaddr.sin_addr.s_addr = INADDR_ANY;
1249
                }
1250
        } else {
1251
                udpaddr.sin_addr.s_addr = inet_addr(ipaddr);
1252
        }
1253
        udpaddr.sin_port = htons(port);
1254

    
1255
        socketaddrgen udpgen;
1256
        memset(&udpgen,0,sizeof(socketaddrgen));        //this will be sent over the net, so set it to 0
1257
        udpgen.udpaddr = udpaddr;
1258
        local_socketID.internal_addr = udpgen;
1259

    
1260
        socketfd = createSocket(port, ipaddr);
1261
        if (socketfd < 0){
1262
                return socketfd;
1263
        }
1264

    
1265
        struct event *ev;
1266
        ev = event_new(base, socketfd, EV_READ | EV_PERSIST, recv_pkg, NULL);
1267

    
1268
        event_add(ev, NULL);
1269

    
1270
        try_stun();
1271

    
1272
        return socketfd;
1273
}
1274

    
1275
/*
1276
 * try to figure out external IP using STUN, if defined
1277
 */
1278
void try_stun()
1279
{
1280
        if (isStunDefined()) {
1281
                /*
1282
                * send the NAT traversal STUN request
1283
                */
1284
                 send_stun_request(socketfd, &stun_server);
1285

    
1286
                /*
1287
                * enter a NAT traversal timeout that takes care of retransmission
1288
                */
1289
                struct event *ev1;
1290
                struct timeval timeout_value_NAT_traversal = NAT_TRAVERSAL_TIMEOUT;
1291
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1292
                event_add(ev1, &timeout_value_NAT_traversal);
1293

    
1294
                NAT_traversal = false;
1295
        } else {
1296
                /*
1297
                * Assume we have accessibility and copy internal address to external one
1298
                */
1299
                local_socketID.external_addr = local_socketID.internal_addr;
1300
                NAT_traversal = true; // @TODO: this is not really NAT traversal, but a flag that init is over
1301
                // callback to the upper layer indicating that the socketID is now
1302
                // ready to use
1303
                if(receive_SocketID_cb)
1304
                        (receive_SocketID_cb) (&local_socketID, 0); //success
1305
        }
1306
}
1307

    
1308
/**************************** END OF INTERNAL ***********************/
1309

    
1310
/**************************** MONL functions *************************/
1311

    
1312
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){
1313

    
1314
        base = (struct event_base *) arg;
1315
        recv_data_callback = recv_data_cb;
1316
        mlSetRecvTimeout(timeout_value);
1317
        if (stun_ipaddr) {
1318
                 mlSetStunServer(stun_port, stun_ipaddr);
1319
        } else {
1320

    
1321
        }
1322
        register_recv_localsocketID_cb(local_socketID_cb);
1323
        return create_socket(port, ipaddr);
1324
}
1325

    
1326
/* register callbacks  */
1327
void mlRegisterGetRecvPktInf(get_recv_pkt_inf_cb recv_pkt_inf_cb){
1328

    
1329
        if (recv_pkt_inf_cb == NULL) {
1330
                error("ML: Register get_recv_pkt_inf_cb failed: NULL ptr  \n");
1331
        } else {
1332
                get_Recv_pkt_inf_cb = recv_pkt_inf_cb;
1333
        }
1334
}
1335

    
1336
void mlRegisterGetSendPktInf(get_send_pkt_inf_cb  send_pkt_inf_cb){
1337

    
1338
        if (send_pkt_inf_cb == NULL) {
1339
                error("ML: Register get_send_pkt_inf_cb: NULL ptr  \n");
1340
        } else {
1341
                get_Send_pkt_inf_cb = send_pkt_inf_cb;
1342
        }
1343
}
1344

    
1345

    
1346
void mlRegisterSetMonitoringHeaderPktCb(set_monitoring_header_pkt_cb monitoring_header_pkt_cb ){
1347

    
1348
        if (monitoring_header_pkt_cb == NULL) {
1349
                error("ML: Register set_monitoring_header_pkt_cb: NULL ptr  \n");
1350
        } else {
1351
                set_Monitoring_header_pkt_cb = monitoring_header_pkt_cb;
1352
        }
1353
}
1354

    
1355
void mlRegisterGetRecvDataInf(get_recv_data_inf_cb recv_data_inf_cb){
1356

    
1357
        if (recv_data_inf_cb == NULL) {
1358
                error("ML: Register get_recv_data_inf_cb: NULL ptr  \n");
1359
        } else {
1360
                get_Recv_data_inf_cb = recv_data_inf_cb;
1361
        }
1362
}
1363

    
1364
void mlRegisterGetSendDataInf(get_send_data_inf_cb  send_data_inf_cb){
1365

    
1366
        if (send_data_inf_cb == NULL) {
1367
                error("ML: Register get_send_data_inf_cb: NULL ptr  \n");
1368
        } else {
1369
                get_Send_data_inf_cb = send_data_inf_cb;
1370
        }
1371
}
1372

    
1373
void mlRegisterSetMonitoringHeaderDataCb(set_monitoring_header_data_cb monitoring_header_data_cb){
1374

    
1375
        if (monitoring_header_data_cb == NULL) {
1376
                error("ML: Register set_monitoring_header_data_cb : NULL ptr  \n");
1377
        } else {
1378
                set_Monitoring_header_data_cb = monitoring_header_data_cb;
1379
        }
1380
}
1381

    
1382
void mlSetRecvTimeout(struct timeval timeout_value){
1383

    
1384
        recv_timeout = timeout_value;
1385

    
1386
}
1387

    
1388
int mlGetStandardTTL(socketID_handle socketID,uint8_t *ttl){
1389

    
1390
        return getTTL(socketfd, ttl);
1391

    
1392
}
1393

    
1394
socketID_handle mlGetLocalSocketID(int *errorstatus){
1395

    
1396
        if (NAT_traversal == false) {
1397
                *errorstatus = 2;
1398
                return NULL;
1399
        }
1400

    
1401
        *errorstatus = 0;
1402
        return &local_socketID;
1403

    
1404
}
1405

    
1406

    
1407
/**************************** END of MONL functions *************************/
1408

    
1409
/**************************** GENERAL functions *************************/
1410

    
1411
void mlRegisterRecvConnectionCb(receive_connection_cb recv_conn_cb){
1412

    
1413
        if (recv_conn_cb == NULL) {
1414
                error("ML: Register receive_connection_cb: NULL ptr  \n");
1415
        }else {
1416
                receive_Connection_cb = recv_conn_cb;
1417
        }
1418
}
1419

    
1420
void mlRegisterErrorConnectionCb(connection_failed_cb conn_failed){
1421

    
1422
        if (conn_failed == NULL) {
1423
                error("ML: Register connection_failed_cb: NULL ptr  \n");
1424
        } else {
1425
                failed_Connection_cb = conn_failed;
1426
        }
1427
}
1428

    
1429
void mlRegisterRecvDataCb(receive_data_cb data_cb,unsigned char msgtype){
1430

    
1431
    if (msgtype > 126) {
1432

    
1433
            error
1434
            ("ML: Could not register recv_data callback. Msgtype is greater then 126 \n");
1435

    
1436
    }
1437

    
1438
    if (data_cb == NULL) {
1439

    
1440
            error("ML: Register receive data callback: NUll ptr \n ");
1441

    
1442
    } else {
1443

    
1444
        recvcbbuf[msgtype] = data_cb;
1445

    
1446
    }
1447

    
1448
}
1449

    
1450
void mlCloseSocket(socketID_handle socketID){
1451

    
1452
        free(socketID);
1453

    
1454
}
1455

    
1456
void keepalive_fn(evutil_socket_t fd, short what, void *arg) {
1457
        socketID_handle peer = arg;
1458

    
1459
        int con_id = mlConnectionExist(peer, false);
1460
        if (con_id < 0 || connectbuf[con_id]->defaultSendParams.keepalive <= 0) {
1461
                /* Connection fell from under us or keepalive was disabled */
1462
                free(arg);
1463
                return;
1464
        }
1465

    
1466
        /* do what we gotta do */
1467
        if ( connectbuf[con_id]->status == READY) {
1468
                char keepaliveMsg[32] = "";
1469
                sprintf(keepaliveMsg, "KEEPALIVE %d", connectbuf[con_id]->keepalive_seq++);
1470
                send_msg(con_id, MSG_TYPE_ML_KEEPALIVE, keepaliveMsg, 1 + strlen(keepaliveMsg), false, 
1471
                        &(connectbuf[con_id]->defaultSendParams));
1472
        }
1473

    
1474
        /* re-schedule */
1475
        struct timeval t = { 0,0 };
1476
        t.tv_sec = connectbuf[con_id]->defaultSendParams.keepalive;
1477
        if (connectbuf[con_id]->defaultSendParams.keepalive) 
1478
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1479
}
1480

    
1481
void setupKeepalive(int conn_id) {
1482
        /* Save the peer's address for us */
1483
        socketID_handle peer = malloc(sizeof(socket_ID));
1484
        memcpy(peer, &connectbuf[conn_id]->external_socketID, sizeof(socket_ID));
1485

    
1486
        struct timeval t = { 0,0 };
1487
        t.tv_sec = connectbuf[conn_id]->defaultSendParams.keepalive;
1488

    
1489
        if (connectbuf[conn_id]->defaultSendParams.keepalive) 
1490
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1491
}
1492

    
1493
/* connection functions */
1494
int mlOpenConnection(socketID_handle external_socketID,receive_connection_cb connection_cb,void *arg, const send_params defaultSendParams){
1495

    
1496
        int con_id;
1497
        if (external_socketID == NULL) {
1498
                error("ML: cannot open connection: one of the socketIDs is NULL\n");
1499
                return -1;
1500
        }
1501
        if (NAT_traversal == false) {
1502
                error("ML: cannot open connection: NAT traversal for socketID still in progress\n");
1503
                return -1;
1504
        }
1505
        if (connection_cb == NULL) {
1506
                error("ML: cannot open connection: connection_cb is NULL\n");
1507
                return -1;
1508
        }
1509

    
1510
        // check if that connection already exist
1511

    
1512
        con_id = mlConnectionExist(external_socketID, false);
1513
        if (con_id >= 0) {
1514
                // overwrite defaultSendParams
1515
                bool newKeepalive = 
1516
                        connectbuf[con_id]->defaultSendParams.keepalive == 0 && defaultSendParams.keepalive != 0;
1517
                connectbuf[con_id]->defaultSendParams = defaultSendParams;
1518
                if (newKeepalive) setupKeepalive(con_id);
1519
                // if so check if it is ready to use
1520
                if (connectbuf[con_id]->status == READY) {
1521
                                // if so use the callback immediately
1522
                                (connection_cb) (con_id, arg);
1523

    
1524
                // otherwise just write the connection cb and the arg pointer
1525
                // into the connection struct
1526
                } else {
1527
                        struct receive_connection_cb_list *temp;
1528
                        temp = malloc(sizeof(struct receive_connection_cb_list));
1529
                        temp->next = NULL;
1530
                        temp->connection_cb = connection_cb;
1531
                        temp->arg = arg;
1532
                        if(connectbuf[con_id]->connection_last != NULL) {
1533
                                connectbuf[con_id]->connection_last->next = temp;
1534
                                connectbuf[con_id]->connection_last = temp;
1535
                        } else
1536
                                connectbuf[con_id]->connection_last = connectbuf[con_id]->connection_head = temp;
1537
                }
1538
                return con_id;
1539
        }
1540
        // make entry in connection_establishment array
1541
        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
1542
                if (connectbuf[con_id] == NULL) {
1543
                        connectbuf[con_id] = (connect_data *) malloc(sizeof(connect_data));
1544
                        memset(connectbuf[con_id],0,sizeof(connect_data));
1545
                        connectbuf[con_id]->starttime = time(NULL);
1546
                        memcpy(&connectbuf[con_id]->external_socketID, external_socketID, sizeof(socket_ID));
1547
                        connectbuf[con_id]->pmtusize = DSLSLIM;
1548
                        connectbuf[con_id]->timeout_event = NULL;
1549
                        connectbuf[con_id]->status = INVITE;
1550
                        connectbuf[con_id]->seqnr = 0;
1551
                        connectbuf[con_id]->internal_connect = !compare_external_address_socketIDs(external_socketID, &local_socketID);
1552
                        connectbuf[con_id]->connectionID = con_id;
1553

    
1554
                        connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
1555
                        connectbuf[con_id]->connection_last->next = NULL;
1556
                        connectbuf[con_id]->connection_last->connection_cb = connection_cb;
1557
                        connectbuf[con_id]->connection_last->arg = arg;
1558
                        connectbuf[con_id]->external_connectionID = -1;
1559

    
1560
                        connectbuf[con_id]->defaultSendParams = defaultSendParams;
1561
                        if (defaultSendParams.keepalive) setupKeepalive(con_id);
1562
                        break;
1563
                }
1564
        } //end of for
1565

    
1566
        if (con_id == CONNECTBUFSIZE) {
1567
                error("ML: Could not open connection: connection buffer full\n");
1568
                return -1;
1569
        }
1570

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

    
1575
        return con_id;
1576

    
1577
}
1578

    
1579
void mlCloseConnection(const int connectionID){
1580

    
1581
        // remove it from the connection array
1582
        if(connectbuf[connectionID]) {
1583
                if(connectbuf[connectionID]->ctrl_msg_buf) {
1584
                        free(connectbuf[connectionID]->ctrl_msg_buf);
1585
                }
1586
                // remove related events
1587
                if (connectbuf[connectionID]->timeout_event) {
1588
                        event_del(connectbuf[connectionID]->timeout_event);
1589
                        event_free(connectbuf[connectionID]->timeout_event);
1590
                        connectbuf[connectionID]->timeout_event = NULL;
1591
                }
1592
                free(connectbuf[connectionID]);
1593
                connectbuf[connectionID] = NULL;
1594
        }
1595

    
1596
}
1597

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

    
1600
        if (connectionID < 0) {
1601
                error("ML: send data failed: connectionID does not exist\n");
1602
                return;
1603
        }
1604

    
1605
        if (connectbuf[connectionID] == NULL) {
1606
                error("ML: send data failed: connectionID does not exist\n");
1607
                return;
1608
        }
1609
        if (connectbuf[connectionID]->status != READY) {
1610
            error("ML: send data failed: connection is not active\n");
1611
            return;
1612
        }
1613

    
1614
        if (sParams == NULL) {
1615
                sParams = &(connectbuf[connectionID]->defaultSendParams);
1616
        }
1617

    
1618
        send_msg(connectionID, msgtype, sendbuf, bufsize, false, sParams);
1619

    
1620
}
1621

    
1622
/* transmit data functions  */
1623
int mlSendAllData(const int connectionID,send_all_data_container *container,int nr_entries,unsigned char msgtype,send_params *sParams){
1624

    
1625
    if (nr_entries < 1 || nr_entries > 5) {
1626

    
1627
        error
1628
            ("ML : sendALlData : nr_enties is not between 1 and 5 \n ");
1629
        return 0;
1630

    
1631
    } else {
1632

    
1633
        if (nr_entries == 1) {
1634

    
1635
                mlSendData(connectionID, container->buffer_1,
1636
                      container->length_1, msgtype, sParams);
1637

    
1638
            return 1;
1639

    
1640
        } else if (nr_entries == 2) {
1641

    
1642
            int buflen = container->length_1 + container->length_2;
1643
            char buf[buflen];
1644
            memcpy(buf, container->buffer_1, container->length_1);
1645
            memcpy(&buf[container->length_1], container->buffer_2,
1646
                   container->length_2);
1647
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1648

    
1649
            return 1;
1650

    
1651
        } else if (nr_entries == 3) {
1652

    
1653
            int buflen =
1654
                container->length_1 + container->length_2 +
1655
                container->length_3;
1656
            char buf[buflen];
1657
            memcpy(buf, container->buffer_1, container->length_1);
1658
            memcpy(&buf[container->length_1], container->buffer_2,
1659
                   container->length_2);
1660
            memcpy(&buf[container->length_2], container->buffer_3,
1661
                   container->length_3);
1662
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1663

    
1664

    
1665
            return 1;
1666

    
1667
        } else if (nr_entries == 4) {
1668

    
1669
            int buflen =
1670
                container->length_1 + container->length_2 +
1671
                container->length_3 + container->length_4;
1672
            char buf[buflen];
1673
            memcpy(buf, container->buffer_1, container->length_1);
1674
            memcpy(&buf[container->length_1], container->buffer_2,
1675
                   container->length_2);
1676
            memcpy(&buf[container->length_2], container->buffer_3,
1677
                   container->length_3);
1678
            memcpy(&buf[container->length_3], container->buffer_4,
1679
                   container->length_4);
1680
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1681

    
1682
            return 1;
1683

    
1684
        } else {
1685

    
1686
            int buflen =
1687
                container->length_1 + container->length_2 +
1688
                container->length_3 + container->length_4 +
1689
                container->length_5;
1690
            char buf[buflen];
1691
            memcpy(buf, container->buffer_1, container->length_1);
1692
            memcpy(&buf[container->length_1], container->buffer_2,
1693
                   container->length_2);
1694
            memcpy(&buf[container->length_2], container->buffer_3,
1695
                   container->length_3);
1696
            memcpy(&buf[container->length_3], container->buffer_4,
1697
                   container->length_4);
1698
            memcpy(&buf[container->length_4], container->buffer_5,
1699
                   container->length_5);
1700
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1701

    
1702
            return 1;
1703
        }
1704

    
1705
    }
1706

    
1707
}
1708

    
1709
int mlRecvData(const int connectionID,char *recvbuf,int *bufsize,recv_params *rParams){
1710

    
1711
        //TODO yet to be converted
1712
        return 0;
1713
#if 0
1714
        if (rParams == NULL) {
1715
                error("ML: recv_data failed: recv_params is a NULL ptr\n");
1716
                return 0;
1717
    } else {
1718

1719
        info("ML: recv data called \n");
1720

1721
        int i = 0;
1722
        int returnValue = 0;
1723
        double timeout = (double) recv_timeout.tv_sec;
1724
        time_t endtime = time(NULL);
1725

1726
        for (i = 0; i < RECVDATABUFSIZE; i++) {
1727

1728
            if (recvdatabuf[i] != NULL) {
1729

1730
                if (recvdatabuf[i]->connectionID == connectionID) {
1731

1732
                    info("ML: recv data has entry  \n");
1733

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

1736
                    // check if the specified connection has data and it
1737
                    // is complete
1738
                    // check the data seqnr
1739
                    // if(connectionID == recvdatabuf[i]->connectionID &&
1740
                    // 1 == recvdatabuf[i]->status){
1741

1742
                    if (1 == recvdatabuf[i]->status) {
1743

1744
                        // info("transmissionHandler: recv_data set is
1745
                        // complete \n" );
1746

1747
                        // debug("debud \n");
1748

1749
                        // exchange the pointers
1750
                        int buffersize = 0;
1751
                        buffersize = recvdatabuf[i]->bufsize;
1752
                        *bufsize = buffersize;
1753
                        // recvbuf = recvdatabuf[i]->recvbuf;
1754

1755
                        // info("buffersize %d \n",buffersize);
1756
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1757
                               buffersize);
1758
                        // debug(" recvbuf %s \n",recvbuf );
1759

1760
//                         double nrMissFrags =
1761
//                             (double) recvdatabuf[i]->nrFragments /
1762
//                             (double) recvdatabuf[i]->recvFragments;
1763
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
1764

1765
//                        rParams->nrMissingFragments = nrMissingFragments;
1766
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
1767
                        rParams->msgtype = recvdatabuf[i]->msgtype;
1768
                        rParams->connectionID =
1769
                            recvdatabuf[i]->connectionID;
1770

1771
                        // break from the loop
1772
                        // debug(" recvbuf %s \n ",recvbuf);
1773

1774
                        // double nrMissFrags =
1775
                        // (double)recvdatabuf[i]->nrFragments /
1776
                        // (double)recvdatabuf[i]->recvFragments;
1777
                        // int nrMissingFragments =
1778
                        // (int)ceil(nrMissFrags);
1779

1780
                        if(get_Recv_data_inf_cb != NULL) {
1781
                                mon_data_inf recv_data_inf;
1782

1783
                                recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1784
                                recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1785
                                recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1786
                                recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1787
//                                 recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1788
//                                 recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1789
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
1790
                                recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1791
                                recv_data_inf.nrMissingFragments = nrMissingFragments;
1792
                                recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1793
                                recv_data_inf.priority = false;
1794
                                recv_data_inf.padding = false;
1795
                                recv_data_inf.confirmation = false;
1796
                                recv_data_inf.reliable = false;
1797

1798
                                // send data recv callback to monitoring module
1799

1800
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1801
                        }
1802

1803

1804
                        // free the allocated memory
1805
                        free(recvdatabuf[i]);
1806
                        recvdatabuf[i] = NULL;
1807

1808
                        returnValue = 1;
1809
                        break;
1810

1811
                    }
1812

1813
                    if (recvdatabuf[i] != NULL) {
1814

1815
                        if (timepass > timeout) {
1816

1817
                            info("ML: recv_data timeout called  \n");
1818

1819
                            // some data about the missing chunks should
1820
                            // be added here
1821
                            // exchange the pointers
1822
                            int buffersize = 0;
1823
                            buffersize = recvdatabuf[i]->bufsize;
1824
                            *bufsize = buffersize;
1825
                            // recvbuf = recvdatabuf[i]->recvbuf;
1826

1827
                            double nrMissFrags =
1828
                                (double) recvdatabuf[i]->nrFragments /
1829
                                (double) recvdatabuf[i]->recvFragments;
1830
                            int nrMissingFragments =
1831
                                (int) ceil(nrMissFrags);
1832

1833
                            // debug(" recvbuf %s \n",recvbuf );
1834

1835
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1836
                                   buffersize);
1837

1838
                            rParams->nrMissingFragments =
1839
                                nrMissingFragments;
1840
                            rParams->nrFragments =
1841
                                recvdatabuf[i]->nrFragments;
1842
                            rParams->msgtype = recvdatabuf[i]->msgtype;
1843
                            rParams->connectionID =
1844
                                recvdatabuf[i]->connectionID;
1845

1846
                                if(get_Recv_data_inf_cb != NULL) {
1847
                                        mon_data_inf recv_data_inf;
1848

1849
                                        recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1850
                                        recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1851
                                        recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1852
                                        recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1853
                                        recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1854
                                        recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1855
                                        gettimeofday(&recv_data_inf.arrival_time, NULL);
1856
                                        recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1857
                                        recv_data_inf.nrMissingFragments = nrMissingFragments;
1858
                                        recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1859
                                        recv_data_inf.priority = false;
1860
                                        recv_data_inf.padding = false;
1861
                                        recv_data_inf.confirmation = false;
1862
                                        recv_data_inf.reliable = false;
1863

1864
                                        // send data recv callback to monitoring module
1865

1866
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1867
                                }
1868

1869
                            // free the allocated memory
1870
                            free(recvdatabuf[i]);
1871
                            recvdatabuf[i] = NULL;
1872

1873
                            returnValue = 1;
1874
                            break;
1875

1876
                        }
1877
                    }
1878

1879
                }
1880

1881
            }
1882
            // debug("2 recvbuf %s \n ",recvbuf);
1883
        }
1884
        return returnValue;
1885
    }
1886
#endif
1887

    
1888
}
1889

    
1890
int mlSocketIDToString(socketID_handle socketID,char* socketID_string, size_t len){
1891

    
1892
        char internal_addr[INET_ADDRSTRLEN];
1893
        char external_addr[INET_ADDRSTRLEN];
1894

    
1895
        assert(socketID);
1896

    
1897
        inet_ntop(AF_INET, &(socketID->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1898
        inet_ntop(AF_INET, &(socketID->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1899

    
1900
        snprintf(socketID_string,len,"%s:%d-%s:%d", internal_addr, ntohs(socketID->internal_addr.udpaddr.sin_port),
1901
                external_addr,        ntohs(socketID->external_addr.udpaddr.sin_port));
1902
        return 0;
1903

    
1904
}
1905

    
1906
int mlStringToSocketID(const char* socketID_string, socketID_handle socketID){
1907

    
1908
        //@TODO add checks against malformed string
1909
        char external_addr[INET_ADDRSTRLEN];
1910
        int external_port;
1911
        char internal_addr[INET_ADDRSTRLEN];
1912
        int internal_port;
1913

    
1914
        char *pch;
1915
        char *s = strdup(socketID_string);
1916

    
1917
        //replace ':' with a blank
1918
        pch=strchr(s,':');
1919
        while (pch!=NULL){
1920
                                *pch = ' ';
1921
                pch=strchr(pch+1,':');
1922
        }
1923
        pch=strchr(s,'-');
1924
        if(pch) *pch = ' ';
1925

    
1926
        sscanf(s,"%s %d %s %d", internal_addr, &internal_port,
1927
                external_addr, &external_port);
1928

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

    
1932
        if(inet_pton(AF_INET, internal_addr, &(socketID->internal_addr.udpaddr.sin_addr)) == 0)
1933
                return EINVAL;
1934
        socketID->internal_addr.udpaddr.sin_family = AF_INET;
1935
        socketID->internal_addr.udpaddr.sin_port = htons(internal_port);
1936

    
1937

    
1938
        if(inet_pton(AF_INET, external_addr, &(socketID->external_addr.udpaddr.sin_addr)) ==0)
1939
                return EINVAL;
1940
        socketID->external_addr.udpaddr.sin_family = AF_INET;
1941
        socketID->external_addr.udpaddr.sin_port = htons(external_port);
1942

    
1943
        free(s);
1944
        return 0;
1945

    
1946
}
1947

    
1948
int mlGetConnectionStatus(int connectionID){
1949

    
1950
        if(connectbuf[connectionID])
1951
                return connectbuf[connectionID]->status == READY;
1952
        return -1;
1953
    
1954
}
1955

    
1956

    
1957
int mlConnectionExist(socketID_handle socketID, bool ready){
1958

    
1959
    /*
1960
     * check if another connection for the external connectionID exist
1961
     * that was established \ within the last 2 seconds
1962
     */
1963
        int i;
1964
        for (i = 0; i < CONNECTBUFSIZE; i++)
1965
                if (connectbuf[i] != NULL)
1966
                        if (mlCompareSocketIDs(&(connectbuf[i]->external_socketID), socketID) == 0) {
1967
                                if (ready) return (connectbuf[i]->status == READY ? i : -1);;
1968
                                return i;
1969
                                }
1970

    
1971
    return -1;
1972

    
1973
}
1974

    
1975
//Added by Robert Birke as comodity functions
1976

    
1977
//int mlPrintSocketID(socketID_handle socketID) {
1978
//        char str[SOCKETID_STRING_SIZE];
1979
//        mlSocketIDToString(socketID, str, sizeof(str));
1980
//        printf(stderr,"int->%s<-ext\n",str);
1981
//}
1982

    
1983
/*
1984
 * hash code of a socketID
1985
 * TODO might think of a better way
1986
 */
1987
int mlHashSocketID(socketID_handle sock) {
1988
    return sock->internal_addr.udpaddr.sin_port +
1989
                          sock->external_addr.udpaddr.sin_port;
1990
}
1991

    
1992
int mlCompareSocketIDs(socketID_handle sock1, socketID_handle sock2) {
1993

    
1994
        assert(sock1 && sock2);
1995

    
1996
        /*
1997
        * compare internal addr
1998
        */
1999
        if(sock1 == NULL || sock2 == NULL)
2000
                return 1;
2001

    
2002
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr !=
2003
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
2004
                        return 1;
2005

    
2006
        if (sock1->internal_addr.udpaddr.sin_port !=
2007
                 sock2->internal_addr.udpaddr.sin_port)
2008
                        return 1;
2009

    
2010
        /*
2011
        * compare external addr
2012
        */
2013
        if (sock1->external_addr.udpaddr.sin_addr.s_addr !=
2014
            sock2->external_addr.udpaddr.sin_addr.s_addr)
2015
                        return 1;
2016

    
2017
        if (sock1->external_addr.udpaddr.sin_port !=
2018
                 sock2->external_addr.udpaddr.sin_port)
2019
                        return 1;
2020

    
2021
        return 0;
2022
}
2023

    
2024
int mlCompareSocketIDsByPort(socketID_handle sock1, socketID_handle sock2)
2025
{
2026
        if(sock1 == NULL || sock2 == NULL)
2027
                return 1;
2028
 
2029
        if (sock1->internal_addr.udpaddr.sin_port !=
2030
                 sock2->internal_addr.udpaddr.sin_port)
2031
                        return 1;
2032

    
2033
        if (sock1->external_addr.udpaddr.sin_port !=
2034
                 sock2->external_addr.udpaddr.sin_port)
2035
                        return 1;
2036
        return 0;
2037
}
2038

    
2039
int mlGetPathMTU(int ConnectionId) {
2040
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
2041
                return -1;
2042
        if (connectbuf[ConnectionId] != NULL)
2043
                return connectbuf[ConnectionId]->pmtusize;
2044
        return -1;
2045
}
2046

    
2047
/**************************** END of GENERAL functions *************************/
2048

    
2049
/**************************** NAT functions *************************/
2050

    
2051
/* setter  */
2052
void mlSetStunServer(const int port,const char *ipaddr){
2053

    
2054
        stun_server.sin_family = AF_INET;
2055
        if (ipaddr == NULL)
2056
                stun_server.sin_addr.s_addr = htonl(INADDR_NONE);
2057
        else
2058
                stun_server.sin_addr.s_addr = resolve(ipaddr);
2059
        stun_server.sin_port = htons(port);
2060

    
2061
}
2062

    
2063
int mlGetExternalIP(char* external_addr){
2064

    
2065
        socketaddrgen udpgen;
2066
        struct sockaddr_in udpaddr;
2067

    
2068
        udpgen = local_socketID.external_addr;
2069
        udpaddr = udpgen.udpaddr;
2070

    
2071
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
2072
                        INET_ADDRSTRLEN);
2073

    
2074
        if (external_addr == NULL) {
2075

    
2076
        return -1;
2077

    
2078
        } else {
2079

    
2080
        return 0;
2081

    
2082
        }
2083

    
2084
}
2085

    
2086
/**************************** END of NAT functions *************************/