Statistics
| Branch: | Revision:

ml / ml.c @ 8fed9f23

History | View | Annotate | Download (60.9 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
//void keep_connection_alive(const int connectionID)
206
//{
207
//
208
//    // to be done with the NAT traversal
209
//    // send a message over the wire
210
//    printf("\n");
211
//
212
//}
213

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

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

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

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

    
233
        struct msg_header msg_h;
234

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

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

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

    
245

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

    
250

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

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

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

    
268
                        memset(h_data, 0, MON_DATA_HEADER_SPACE);
269

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

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

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

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

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

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

    
303
                                memset(h_pkt,0,MON_PKT_HEADER_SPACE);
304

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
632

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

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

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

    
664
                        // send data recv callback to monitoring module
665

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

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

    
672
                recv_params rParams;
673

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

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

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

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

    
702
        int recv_id, free_recv_id = -1;
703

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

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

    
719

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

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

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

    
755

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

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

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

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

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

    
792
                                // send data recv callback to monitoring module
793

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

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

    
801
                                recv_params rParams;
802

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
911

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

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

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

    
955
    char *msgbufptr = NULL;
956
    int msgtype;
957
    int connectionID;
958
    pmtu pmtusize;
959
    pmtu new_pmtusize;
960
    int dead = 0;
961

    
962
    // check the packettype
963
    msgbufptr = &msg[0];
964

    
965
    // check the msgtype
966
    msgbufptr = &msg[1];
967
    memcpy(&msgtype, msgbufptr, 4);
968

    
969
    if (msgtype == 0) {
970

    
971
        // get the connectionID
972
        msgbufptr = &msg[5];
973
        memcpy(&connectionID, msgbufptr, 4);
974

    
975
        int msgtype_c = connectbuf[connectionID]->status;
976
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
977

    
978
        if (msgtype_c != msgtype) {
979
            dead = 1;
980
        }
981

    
982

    
983
    } else if (msgtype == 1) {
984

    
985
        // read the connectionID
986
        msgbufptr = &msg[9];
987
        memcpy(&connectionID, msgbufptr, 4);
988

    
989
        int msgtype_c = connectbuf[connectionID]->status;
990
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
991

    
992
        if (msgtype_c != msgtype) {
993
            dead = 1;
994
        }
995

    
996
    }
997
    // decrement the pmtu size
998
    new_pmtusize = pmtu_decrement(pmtusize);
999

    
1000
//    connectbuf[connectionID]->pmtutrysize = new_pmtusize;
1001

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

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

    
1014
    if (msgtype == 0 && dead != 1) {
1015

    
1016
        // stop the timeout event
1017
        // timeout_del(connectbuf[connectionID]->timeout);
1018
        /*
1019
         * libevent2
1020
         */
1021

    
1022
        // event_del(connectbuf[connectionID]->timeout);
1023

    
1024

    
1025
        // create and send a connection message
1026
//         create_conn_msg(new_pmtusize, connectionID,
1027
//                         &local_socketID, INVITE);
1028

    
1029
//        send_conn_msg(connectionID, new_pmtusize);
1030

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

    
1035
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1036

    
1037
        /*
1038
         * libevent2
1039
         */
1040

    
1041
        struct event *ev;
1042
        ev = evtimer_new(base, pmtu_timeout_cb,
1043
                         (void *) connectbuf[connectionID]);
1044

    
1045
        // connectbuf[connectionID]->timeout = ev;
1046

    
1047
        event_add(ev, &connectbuf[connectionID]->timeout_value);
1048

    
1049
    } else if (msgtype == 1 && dead != 1) {
1050

    
1051
        // stop the timeout event
1052
        // timeout_del(connectbuf[connectionID]->timeout);
1053

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

    
1062

    
1063
//         // create and send a connection message
1064
//         create_conn_msg(new_pmtusize,
1065
//                         connectbuf[connectionID]->connectionID,
1066
//                         NULL, CONNECT);
1067

    
1068
        //send_conn_msg(connectionID, new_pmtusize);
1069

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

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

    
1084
    }
1085
}
1086

    
1087
/*
1088
 * what to do once a packet arrived if it is a conn packet send it to
1089
 * recv_conn handler if it is a data packet send it to the recv_data
1090
 * handler
1091
 */
1092

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

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

    
1106
        recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
1107

    
1108

    
1109
        // check if it is not just an ERROR message
1110
        if(recvSize < 0)
1111
                return;
1112

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

    
1122
        msg_h = (struct msg_header *) msgbuf;
1123

    
1124
        //verify minimum size
1125
        if (recvSize < sizeof(struct msg_header)) {
1126
          info("UDP packet too small, can't be an ML packet");
1127
          return;
1128
        }
1129

    
1130
        //TODO add more verifications
1131

    
1132
        bufptr += MSG_HEADER_SIZE + msg_h->len_mon_packet_hdr;
1133
        msg_size = recvSize - MSG_HEADER_SIZE - msg_h->len_mon_packet_hdr;
1134

    
1135
        //verify more fields
1136
        if (msg_size < 0) {
1137
          info("Corrupted UDP packet received");
1138
          return;
1139
        }
1140

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

    
1166

    
1167
        switch(msg_h->msg_type) {
1168
                case ML_CON_MSG:
1169
                        debug("ML: received conn pkg\n");
1170
                        recv_conn_msg(msg_h, bufptr, msg_size, &recv_addr);
1171
                        break;
1172
                default:
1173
                        if(msg_h->msg_type < 127) {
1174
                                debug("ML: received data pkg\n");
1175
                                recv_data_msg(msg_h, bufptr, msg_size);
1176
                                break;
1177
                        }
1178
                        debug("ML: unrecognised msg_type\n");
1179
                        break;
1180
        }
1181
}
1182

    
1183
/*
1184
 * compare the external IP address of two socketIDs
1185
 */
1186
int
1187
compare_external_address_socketIDs(socketID_handle sock1, socketID_handle sock2)
1188
{
1189
        if( sock1->external_addr.udpaddr.sin_addr.s_addr == sock2->external_addr.udpaddr.sin_addr.s_addr)
1190
                return 0;
1191
        return 1;
1192
}
1193

    
1194
void try_stun();
1195

    
1196
/*
1197
 * the timeout of the NAT traversal
1198
 */
1199
void nat_traversal_timeout(int fd, short event, void *arg)
1200
{
1201
        if (NAT_traversal == false) {
1202
                debug("ML: NAT traversal request re-send\n");
1203
                if(receive_SocketID_cb)
1204
                        (receive_SocketID_cb) (&local_socketID, 2);
1205
                try_stun();
1206
        }
1207
}
1208

    
1209
//return IP address, or INADDR_NONE if can't resolve
1210
unsigned long resolve(const char *ipaddr)
1211
{
1212
        struct hostent *h = gethostbyname(ipaddr);
1213
        if (!h) {
1214
                error("ML: Unable to resolve host name %s\n", ipaddr);
1215
                return INADDR_NONE;
1216
        }
1217
        unsigned long *addr = (unsigned long *) (h->h_addr);
1218
        return *addr;
1219
}
1220

    
1221

    
1222
/*
1223
 * returns the file descriptor, or <0 on error. The ipaddr can be a null
1224
 * pointer. Then all available ipaddr on the machine are choosen.
1225
 */
1226
int create_socket(const int port, const char *ipaddr)
1227
{
1228
        struct sockaddr_in udpaddr = {0};
1229
        udpaddr.sin_family = AF_INET;
1230
        if (ipaddr == NULL) {
1231
                /*
1232
                * try to guess the local IP address
1233
                */
1234
                const char *ipaddr_iface = mlAutodetectIPAddress();
1235
                if (ipaddr_iface) {
1236
                        udpaddr.sin_addr.s_addr = inet_addr(ipaddr_iface);
1237
                } else {
1238
                        udpaddr.sin_addr.s_addr = INADDR_ANY;
1239
                }
1240
        } else {
1241
                udpaddr.sin_addr.s_addr = inet_addr(ipaddr);
1242
        }
1243
        udpaddr.sin_port = htons(port);
1244

    
1245
        socketaddrgen udpgen;
1246
        memset(&udpgen,0,sizeof(socketaddrgen));        //this will be sent over the net, so set it to 0
1247
        udpgen.udpaddr = udpaddr;
1248
        local_socketID.internal_addr = udpgen;
1249

    
1250
        socketfd = createSocket(port, ipaddr);
1251
        if (socketfd < 0){
1252
                return socketfd;
1253
        }
1254

    
1255
        struct event *ev;
1256
        ev = event_new(base, socketfd, EV_READ | EV_PERSIST, recv_pkg, NULL);
1257

    
1258
        event_add(ev, NULL);
1259

    
1260
        try_stun();
1261

    
1262
        return socketfd;
1263
}
1264

    
1265
/*
1266
 * try to figure out external IP using STUN, if defined
1267
 */
1268
void try_stun()
1269
{
1270
        if (isStunDefined()) {
1271
                /*
1272
                * send the NAT traversal STUN request
1273
                */
1274
                 send_stun_request(socketfd, &stun_server);
1275

    
1276
                /*
1277
                * enter a NAT traversal timeout that takes care of retransmission
1278
                */
1279
                struct event *ev1;
1280
                struct timeval timeout_value_NAT_traversal = NAT_TRAVERSAL_TIMEOUT;
1281
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1282
                event_add(ev1, &timeout_value_NAT_traversal);
1283

    
1284
                NAT_traversal = false;
1285
        } else {
1286
                /*
1287
                * Assume we have accessibility and copy internal address to external one
1288
                */
1289
                local_socketID.external_addr = local_socketID.internal_addr;
1290
                NAT_traversal = true; // @TODO: this is not really NAT traversal, but a flag that init is over
1291
                // callback to the upper layer indicating that the socketID is now
1292
                // ready to use
1293
                if(receive_SocketID_cb)
1294
                        (receive_SocketID_cb) (&local_socketID, 0); //success
1295
        }
1296
}
1297

    
1298
/**************************** END OF INTERNAL ***********************/
1299

    
1300
/**************************** MONL functions *************************/
1301

    
1302
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){
1303

    
1304
        base = (struct event_base *) arg;
1305
        recv_data_callback = recv_data_cb;
1306
        mlSetRecvTimeout(timeout_value);
1307
        if (stun_ipaddr) {
1308
                 mlSetStunServer(stun_port, stun_ipaddr);
1309
        } else {
1310

    
1311
        }
1312
        register_recv_localsocketID_cb(local_socketID_cb);
1313
        return create_socket(port, ipaddr);
1314
}
1315

    
1316
/* register callbacks  */
1317
void mlRegisterGetRecvPktInf(get_recv_pkt_inf_cb recv_pkt_inf_cb){
1318

    
1319
        if (recv_pkt_inf_cb == NULL)
1320
                error("ML: Register get_recv_pkt_inf_cb failed: NULL ptr  \n");
1321
        else
1322
                get_Recv_pkt_inf_cb = recv_pkt_inf_cb;
1323

    
1324
}
1325

    
1326
void mlRegisterGetSendPktInf(get_send_pkt_inf_cb  send_pkt_inf_cb){
1327

    
1328
        if (send_pkt_inf_cb == NULL)
1329
                error("ML: Register get_send_pkt_inf_cb: NULL ptr  \n");
1330
        else
1331
                get_Send_pkt_inf_cb = send_pkt_inf_cb;
1332

    
1333
}
1334

    
1335

    
1336
void mlRegisterSetMonitoringHeaderPktCb(set_monitoring_header_pkt_cb monitoring_header_pkt_cb ){
1337

    
1338
        if (monitoring_header_pkt_cb == NULL)
1339
                error("ML: Register set_monitoring_header_pkt_cb: NULL ptr  \n");
1340
        else
1341
                set_Monitoring_header_pkt_cb = monitoring_header_pkt_cb;
1342

    
1343
}
1344

    
1345
void mlRegisterGetRecvDataInf(get_recv_data_inf_cb recv_data_inf_cb){
1346

    
1347
        if (recv_data_inf_cb == NULL)
1348
                error("ML: Register get_recv_data_inf_cb: NULL ptr  \n");
1349
        else
1350
                get_Recv_data_inf_cb = recv_data_inf_cb;
1351

    
1352
}
1353

    
1354
void mlRegisterGetSendDataInf(get_send_data_inf_cb  send_data_inf_cb){
1355

    
1356
        if (send_data_inf_cb == NULL)
1357
                error("ML: Register get_send_data_inf_cb: NULL ptr  \n");
1358
        else
1359
                get_Send_data_inf_cb = send_data_inf_cb;
1360

    
1361
}
1362

    
1363
void mlRegisterSetMonitoringHeaderDataCb(set_monitoring_header_data_cb monitoring_header_data_cb){
1364

    
1365
        if (monitoring_header_data_cb == NULL)
1366
                error("ML: Register set_monitoring_header_data_cb : NULL ptr  \n");
1367
        else
1368
        set_Monitoring_header_data_cb = monitoring_header_data_cb;
1369

    
1370
}
1371

    
1372
void mlSetRecvTimeout(struct timeval timeout_value){
1373

    
1374
        recv_timeout = timeout_value;
1375

    
1376
}
1377

    
1378
int mlGetStandardTTL(socketID_handle socketID,uint8_t *ttl){
1379

    
1380
        return getTTL(socketfd, ttl);
1381

    
1382
}
1383

    
1384
socketID_handle mlGetLocalSocketID(int *errorstatus){
1385

    
1386
        if (NAT_traversal == false) {
1387
                *errorstatus = 2;
1388
                return NULL;
1389
        }
1390

    
1391
        *errorstatus = 0;
1392
        return &local_socketID;
1393

    
1394
}
1395

    
1396

    
1397
/**************************** END of MONL functions *************************/
1398

    
1399
/**************************** GENERAL functions *************************/
1400

    
1401
void mlRegisterRecvConnectionCb(receive_connection_cb recv_conn_cb){
1402

    
1403
        if (recv_conn_cb == NULL)
1404
                error("ML: Register receive_connection_cb: NULL ptr  \n");
1405
        else
1406
                receive_Connection_cb = recv_conn_cb;
1407

    
1408
}
1409

    
1410
void mlRegisterErrorConnectionCb(connection_failed_cb conn_failed){
1411

    
1412
        if (conn_failed == NULL)
1413
                error("ML: Register connection_failed_cb: NULL ptr  \n");
1414
        else
1415
        failed_Connection_cb = conn_failed;
1416

    
1417
}
1418

    
1419
void mlRegisterRecvDataCb(receive_data_cb data_cb,unsigned char msgtype){
1420

    
1421
    if (msgtype > 126) {
1422

    
1423
            error
1424
            ("ML: Could not register recv_data callback. Msgtype is greater then 126 \n");
1425

    
1426
    }
1427

    
1428
    if (data_cb == NULL) {
1429

    
1430
            error("ML: Register receive data callback: NUll ptr \n ");
1431

    
1432
    } else {
1433

    
1434
        recvcbbuf[msgtype] = data_cb;
1435

    
1436
    }
1437

    
1438
}
1439

    
1440
void mlCloseSocket(socketID_handle socketID){
1441

    
1442
        free(socketID);
1443

    
1444
}
1445

    
1446
void keepalive_fn(evutil_socket_t fd, short what, void *arg) {
1447
        socketID_handle peer = arg;
1448

    
1449
        int con_id = mlConnectionExist(peer, false);
1450
        if (con_id < 0 || connectbuf[con_id]->defaultSendParams.keepalive <= 0) {
1451
                /* Connection fell from under us or keepalive was disabled */
1452
                free(arg);
1453
                return;
1454
        }
1455

    
1456
        /* do what we gotta do */
1457
        if ( connectbuf[con_id]->status == READY) {
1458
                char keepaliveMsg[32] = "";
1459
                sprintf(keepaliveMsg, "KEEPALIVE %d", connectbuf[con_id]->keepalive_seq++);
1460
                send_msg(con_id, MSG_TYPE_ML_KEEPALIVE, keepaliveMsg, 1 + strlen(keepaliveMsg), false, 
1461
                        &(connectbuf[con_id]->defaultSendParams));
1462
        }
1463

    
1464
        /* re-schedule */
1465
        struct timeval t = { 0,0 };
1466
        t.tv_sec = connectbuf[con_id]->defaultSendParams.keepalive;
1467
        if (connectbuf[con_id]->defaultSendParams.keepalive) 
1468
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1469
}
1470

    
1471
void setupKeepalive(int conn_id) {
1472
        /* Save the peer's address for us */
1473
        socketID_handle peer = malloc(sizeof(socket_ID));
1474
        memcpy(peer, &connectbuf[conn_id]->external_socketID, sizeof(socket_ID));
1475

    
1476
        struct timeval t = { 0,0 };
1477
        t.tv_sec = connectbuf[conn_id]->defaultSendParams.keepalive;
1478

    
1479
        if (connectbuf[conn_id]->defaultSendParams.keepalive) 
1480
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1481
}
1482

    
1483
/* connection functions */
1484
int mlOpenConnection(socketID_handle external_socketID,receive_connection_cb connection_cb,void *arg, const send_params defaultSendParams){
1485

    
1486
        int con_id;
1487
        if (external_socketID == NULL) {
1488
                error("ML: cannot open connection: one of the socketIDs is NULL\n");
1489
                return -1;
1490
        }
1491
        if (NAT_traversal == false) {
1492
                error("ML: cannot open connection: NAT traversal for socketID still in progress\n");
1493
                return -1;
1494
        }
1495
        if (connection_cb == NULL) {
1496
                error("ML: cannot open connection: connection_cb is NULL\n");
1497
                return -1;
1498
        }
1499

    
1500
        // check if that connection already exist
1501

    
1502
        con_id = mlConnectionExist(external_socketID, false);
1503
        if (con_id >= 0) {
1504
                // overwrite defaultSendParams
1505
                bool newKeepalive = 
1506
                        connectbuf[con_id]->defaultSendParams.keepalive == 0 && defaultSendParams.keepalive != 0;
1507
                connectbuf[con_id]->defaultSendParams = defaultSendParams;
1508
                if (newKeepalive) setupKeepalive(con_id);
1509
                // if so check if it is ready to use
1510
                if (connectbuf[con_id]->status == READY) {
1511
                                // if so use the callback immediately
1512
                                (connection_cb) (con_id, arg);
1513

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

    
1544
                        connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
1545
                        connectbuf[con_id]->connection_last->next = NULL;
1546
                        connectbuf[con_id]->connection_last->connection_cb = connection_cb;
1547
                        connectbuf[con_id]->connection_last->arg = arg;
1548
                        connectbuf[con_id]->external_connectionID = -1;
1549

    
1550
                        connectbuf[con_id]->defaultSendParams = defaultSendParams;
1551
                        if (defaultSendParams.keepalive) setupKeepalive(con_id);
1552
                        break;
1553
                }
1554
        } //end of for
1555

    
1556
        if (con_id == CONNECTBUFSIZE) {
1557
                error("ML: Could not open connection: connection buffer full\n");
1558
                return -1;
1559
        }
1560

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

    
1565
        return con_id;
1566

    
1567
}
1568

    
1569
void mlCloseConnection(const int connectionID){
1570

    
1571
        // remove it from the connection array
1572
        if(connectbuf[connectionID]) {
1573
                if(connectbuf[connectionID]->ctrl_msg_buf) {
1574
                        free(connectbuf[connectionID]->ctrl_msg_buf);
1575
                }
1576
                // remove related events
1577
                if (connectbuf[connectionID]->timeout_event) {
1578
                        event_del(connectbuf[connectionID]->timeout_event);
1579
                        event_free(connectbuf[connectionID]->timeout_event);
1580
                        connectbuf[connectionID]->timeout_event = NULL;
1581
                }
1582
                free(connectbuf[connectionID]);
1583
                connectbuf[connectionID] = NULL;
1584
        }
1585

    
1586
}
1587

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

    
1590
        if (connectionID < 0) {
1591
                error("ML: send data failed: connectionID does not exist\n");
1592
                return;
1593
        }
1594

    
1595
        if (connectbuf[connectionID] == NULL) {
1596
                error("ML: send data failed: connectionID does not exist\n");
1597
                return;
1598
        }
1599
        if (connectbuf[connectionID]->status != READY) {
1600
            error("ML: send data failed: connection is not active\n");
1601
            return;
1602
        }
1603

    
1604
        if (sParams == NULL) {
1605
                sParams = &(connectbuf[connectionID]->defaultSendParams);
1606
        }
1607

    
1608
        send_msg(connectionID, msgtype, sendbuf, bufsize, false, sParams);
1609

    
1610
}
1611

    
1612
/* transmit data functions  */
1613
int mlSendAllData(const int connectionID,send_all_data_container *container,int nr_entries,unsigned char msgtype,send_params *sParams){
1614

    
1615
    if (nr_entries < 1 || nr_entries > 5) {
1616

    
1617
        error
1618
            ("ML : sendALlData : nr_enties is not between 1 and 5 \n ");
1619
        return 0;
1620

    
1621
    } else {
1622

    
1623
        if (nr_entries == 1) {
1624

    
1625
                mlSendData(connectionID, container->buffer_1,
1626
                      container->length_1, msgtype, sParams);
1627

    
1628
            return 1;
1629

    
1630
        } else if (nr_entries == 2) {
1631

    
1632
            int buflen = container->length_1 + container->length_2;
1633
            char buf[buflen];
1634
            memcpy(buf, container->buffer_1, container->length_1);
1635
            memcpy(&buf[container->length_1], container->buffer_2,
1636
                   container->length_2);
1637
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1638

    
1639
            return 1;
1640

    
1641
        } else if (nr_entries == 3) {
1642

    
1643
            int buflen =
1644
                container->length_1 + container->length_2 +
1645
                container->length_3;
1646
            char buf[buflen];
1647
            memcpy(buf, container->buffer_1, container->length_1);
1648
            memcpy(&buf[container->length_1], container->buffer_2,
1649
                   container->length_2);
1650
            memcpy(&buf[container->length_2], container->buffer_3,
1651
                   container->length_3);
1652
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1653

    
1654

    
1655
            return 1;
1656

    
1657
        } else if (nr_entries == 4) {
1658

    
1659
            int buflen =
1660
                container->length_1 + container->length_2 +
1661
                container->length_3 + container->length_4;
1662
            char buf[buflen];
1663
            memcpy(buf, container->buffer_1, container->length_1);
1664
            memcpy(&buf[container->length_1], container->buffer_2,
1665
                   container->length_2);
1666
            memcpy(&buf[container->length_2], container->buffer_3,
1667
                   container->length_3);
1668
            memcpy(&buf[container->length_3], container->buffer_4,
1669
                   container->length_4);
1670
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1671

    
1672
            return 1;
1673

    
1674
        } else {
1675

    
1676
            int buflen =
1677
                container->length_1 + container->length_2 +
1678
                container->length_3 + container->length_4 +
1679
                container->length_5;
1680
            char buf[buflen];
1681
            memcpy(buf, container->buffer_1, container->length_1);
1682
            memcpy(&buf[container->length_1], container->buffer_2,
1683
                   container->length_2);
1684
            memcpy(&buf[container->length_2], container->buffer_3,
1685
                   container->length_3);
1686
            memcpy(&buf[container->length_3], container->buffer_4,
1687
                   container->length_4);
1688
            memcpy(&buf[container->length_4], container->buffer_5,
1689
                   container->length_5);
1690
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1691

    
1692
            return 1;
1693
        }
1694

    
1695
    }
1696

    
1697
}
1698

    
1699
int mlRecvData(const int connectionID,char *recvbuf,int *bufsize,recv_params *rParams){
1700

    
1701
        //TODO yet to be converted
1702
        return 0;
1703
#if 0
1704
        if (rParams == NULL) {
1705
                error("ML: recv_data failed: recv_params is a NULL ptr\n");
1706
                return 0;
1707
    } else {
1708

1709
        info("ML: recv data called \n");
1710

1711
        int i = 0;
1712
        int returnValue = 0;
1713
        double timeout = (double) recv_timeout.tv_sec;
1714
        time_t endtime = time(NULL);
1715

1716
        for (i = 0; i < RECVDATABUFSIZE; i++) {
1717

1718
            if (recvdatabuf[i] != NULL) {
1719

1720
                if (recvdatabuf[i]->connectionID == connectionID) {
1721

1722
                    info("ML: recv data has entry  \n");
1723

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

1726
                    // check if the specified connection has data and it
1727
                    // is complete
1728
                    // check the data seqnr
1729
                    // if(connectionID == recvdatabuf[i]->connectionID &&
1730
                    // 1 == recvdatabuf[i]->status){
1731

1732
                    if (1 == recvdatabuf[i]->status) {
1733

1734
                        // info("transmissionHandler: recv_data set is
1735
                        // complete \n" );
1736

1737
                        // debug("debud \n");
1738

1739
                        // exchange the pointers
1740
                        int buffersize = 0;
1741
                        buffersize = recvdatabuf[i]->bufsize;
1742
                        *bufsize = buffersize;
1743
                        // recvbuf = recvdatabuf[i]->recvbuf;
1744

1745
                        // info("buffersize %d \n",buffersize);
1746
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1747
                               buffersize);
1748
                        // debug(" recvbuf %s \n",recvbuf );
1749

1750
//                         double nrMissFrags =
1751
//                             (double) recvdatabuf[i]->nrFragments /
1752
//                             (double) recvdatabuf[i]->recvFragments;
1753
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
1754

1755
//                        rParams->nrMissingFragments = nrMissingFragments;
1756
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
1757
                        rParams->msgtype = recvdatabuf[i]->msgtype;
1758
                        rParams->connectionID =
1759
                            recvdatabuf[i]->connectionID;
1760

1761
                        // break from the loop
1762
                        // debug(" recvbuf %s \n ",recvbuf);
1763

1764
                        // double nrMissFrags =
1765
                        // (double)recvdatabuf[i]->nrFragments /
1766
                        // (double)recvdatabuf[i]->recvFragments;
1767
                        // int nrMissingFragments =
1768
                        // (int)ceil(nrMissFrags);
1769

1770
                        if(get_Recv_data_inf_cb != NULL) {
1771
                                mon_data_inf recv_data_inf;
1772

1773
                                recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1774
                                recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1775
                                recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1776
                                recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1777
//                                 recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1778
//                                 recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1779
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
1780
                                recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1781
                                recv_data_inf.nrMissingFragments = nrMissingFragments;
1782
                                recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1783
                                recv_data_inf.priority = false;
1784
                                recv_data_inf.padding = false;
1785
                                recv_data_inf.confirmation = false;
1786
                                recv_data_inf.reliable = false;
1787

1788
                                // send data recv callback to monitoring module
1789

1790
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1791
                        }
1792

1793

1794
                        // free the allocated memory
1795
                        free(recvdatabuf[i]);
1796
                        recvdatabuf[i] = NULL;
1797

1798
                        returnValue = 1;
1799
                        break;
1800

1801
                    }
1802

1803
                    if (recvdatabuf[i] != NULL) {
1804

1805
                        if (timepass > timeout) {
1806

1807
                            info("ML: recv_data timeout called  \n");
1808

1809
                            // some data about the missing chunks should
1810
                            // be added here
1811
                            // exchange the pointers
1812
                            int buffersize = 0;
1813
                            buffersize = recvdatabuf[i]->bufsize;
1814
                            *bufsize = buffersize;
1815
                            // recvbuf = recvdatabuf[i]->recvbuf;
1816

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

1823
                            // debug(" recvbuf %s \n",recvbuf );
1824

1825
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1826
                                   buffersize);
1827

1828
                            rParams->nrMissingFragments =
1829
                                nrMissingFragments;
1830
                            rParams->nrFragments =
1831
                                recvdatabuf[i]->nrFragments;
1832
                            rParams->msgtype = recvdatabuf[i]->msgtype;
1833
                            rParams->connectionID =
1834
                                recvdatabuf[i]->connectionID;
1835

1836
                                if(get_Recv_data_inf_cb != NULL) {
1837
                                        mon_data_inf recv_data_inf;
1838

1839
                                        recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1840
                                        recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1841
                                        recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1842
                                        recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1843
                                        recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1844
                                        recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1845
                                        gettimeofday(&recv_data_inf.arrival_time, NULL);
1846
                                        recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1847
                                        recv_data_inf.nrMissingFragments = nrMissingFragments;
1848
                                        recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1849
                                        recv_data_inf.priority = false;
1850
                                        recv_data_inf.padding = false;
1851
                                        recv_data_inf.confirmation = false;
1852
                                        recv_data_inf.reliable = false;
1853

1854
                                        // send data recv callback to monitoring module
1855

1856
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1857
                                }
1858

1859
                            // free the allocated memory
1860
                            free(recvdatabuf[i]);
1861
                            recvdatabuf[i] = NULL;
1862

1863
                            returnValue = 1;
1864
                            break;
1865

1866
                        }
1867
                    }
1868

1869
                }
1870

1871
            }
1872
            // debug("2 recvbuf %s \n ",recvbuf);
1873
        }
1874
        return returnValue;
1875
    }
1876
#endif
1877

    
1878
}
1879

    
1880
int mlSocketIDToString(socketID_handle socketID,char* socketID_string, size_t len){
1881

    
1882
        char internal_addr[INET_ADDRSTRLEN];
1883
        char external_addr[INET_ADDRSTRLEN];
1884

    
1885
        assert(socketID);
1886

    
1887
        inet_ntop(AF_INET, &(socketID->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1888
        inet_ntop(AF_INET, &(socketID->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1889

    
1890
        snprintf(socketID_string,len,"%s:%d-%s:%d", internal_addr, ntohs(socketID->internal_addr.udpaddr.sin_port),
1891
                external_addr,        ntohs(socketID->external_addr.udpaddr.sin_port));
1892
        return 0;
1893

    
1894
}
1895

    
1896
int mlStringToSocketID(const char* socketID_string, socketID_handle socketID){
1897

    
1898
        //@TODO add checks against malformed string
1899
        char external_addr[INET_ADDRSTRLEN];
1900
        int external_port;
1901
        char internal_addr[INET_ADDRSTRLEN];
1902
        int internal_port;
1903

    
1904
        char *pch;
1905
        char *s = strdup(socketID_string);
1906

    
1907
        //replace ':' with a blank
1908
        pch=strchr(s,':');
1909
        while (pch!=NULL){
1910
                                *pch = ' ';
1911
                pch=strchr(pch+1,':');
1912
        }
1913
        pch=strchr(s,'-');
1914
        if(pch) *pch = ' ';
1915

    
1916
        sscanf(s,"%s %d %s %d", internal_addr, &internal_port,
1917
                external_addr, &external_port);
1918

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

    
1922
        if(inet_pton(AF_INET, internal_addr, &(socketID->internal_addr.udpaddr.sin_addr)) == 0)
1923
                return EINVAL;
1924
        socketID->internal_addr.udpaddr.sin_family = AF_INET;
1925
        socketID->internal_addr.udpaddr.sin_port = htons(internal_port);
1926

    
1927

    
1928
        if(inet_pton(AF_INET, external_addr, &(socketID->external_addr.udpaddr.sin_addr)) ==0)
1929
                return EINVAL;
1930
        socketID->external_addr.udpaddr.sin_family = AF_INET;
1931
        socketID->external_addr.udpaddr.sin_port = htons(external_port);
1932

    
1933
        free(s);
1934
        return 0;
1935

    
1936
}
1937

    
1938
int mlGetConnectionStatus(int connectionID){
1939

    
1940
        if(connectbuf[connectionID])
1941
                return connectbuf[connectionID]->status == READY;
1942
        return -1;
1943
    
1944
}
1945

    
1946

    
1947
int mlConnectionExist(socketID_handle socketID, bool ready){
1948

    
1949
    /*
1950
     * check if another connection for the external connectionID exist
1951
     * that was established \ within the last 2 seconds
1952
     */
1953
        int i;
1954
        for (i = 0; i < CONNECTBUFSIZE; i++)
1955
                if (connectbuf[i] != NULL)
1956
                        if (mlCompareSocketIDs(&(connectbuf[i]->external_socketID), socketID) == 0) {
1957
                                if (ready) return (connectbuf[i]->status == READY ? i : -1);;
1958
                                return i;
1959
                                }
1960

    
1961
    return -1;
1962

    
1963
}
1964

    
1965
//Added by Robert Birke as comodity functions
1966

    
1967
//int mlPrintSocketID(socketID_handle socketID) {
1968
//        char str[SOCKETID_STRING_SIZE];
1969
//        mlSocketIDToString(socketID, str, sizeof(str));
1970
//        printf(stderr,"int->%s<-ext\n",str);
1971
//}
1972

    
1973
/*
1974
 * hash code of a socketID
1975
 * TODO might think of a better way
1976
 */
1977
int mlHashSocketID(socketID_handle sock) {
1978
    return sock->internal_addr.udpaddr.sin_port +
1979
                          sock->external_addr.udpaddr.sin_port;
1980
}
1981

    
1982
int mlCompareSocketIDs(socketID_handle sock1, socketID_handle sock2) {
1983

    
1984
        assert(sock1 && sock2);
1985

    
1986
        /*
1987
        * compare internal addr
1988
        */
1989
        if(sock1 == NULL || sock2 == NULL)
1990
                return 1;
1991

    
1992
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr !=
1993
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
1994
                        return 1;
1995

    
1996
        if (sock1->internal_addr.udpaddr.sin_port !=
1997
                 sock2->internal_addr.udpaddr.sin_port)
1998
                        return 1;
1999

    
2000
        /*
2001
        * compare external addr
2002
        */
2003
        if (sock1->external_addr.udpaddr.sin_addr.s_addr !=
2004
            sock2->external_addr.udpaddr.sin_addr.s_addr)
2005
                        return 1;
2006

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

    
2011
        return 0;
2012
}
2013

    
2014
int mlCompareSocketIDsByPort(socketID_handle sock1, socketID_handle sock2)
2015
{
2016
        if(sock1 == NULL || sock2 == NULL)
2017
                return 1;
2018
 
2019
        if (sock1->internal_addr.udpaddr.sin_port !=
2020
                 sock2->internal_addr.udpaddr.sin_port)
2021
                        return 1;
2022

    
2023
        if (sock1->external_addr.udpaddr.sin_port !=
2024
                 sock2->external_addr.udpaddr.sin_port)
2025
                        return 1;
2026
        return 0;
2027
}
2028

    
2029
int mlGetPathMTU(int ConnectionId) {
2030
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
2031
                return -1;
2032
        if (connectbuf[ConnectionId] != NULL)
2033
                return connectbuf[ConnectionId]->pmtusize;
2034
        return -1;
2035
}
2036

    
2037
/**************************** END of GENERAL functions *************************/
2038

    
2039
/**************************** NAT functions *************************/
2040

    
2041
/* setter  */
2042
void mlSetStunServer(const int port,const char *ipaddr){
2043

    
2044
        stun_server.sin_family = AF_INET;
2045
        if (ipaddr == NULL)
2046
                stun_server.sin_addr.s_addr = htonl(INADDR_NONE);
2047
        else
2048
                stun_server.sin_addr.s_addr = resolve(ipaddr);
2049
        stun_server.sin_port = htons(port);
2050

    
2051
}
2052

    
2053
int mlGetExternalIP(char* external_addr){
2054

    
2055
        socketaddrgen udpgen;
2056
        struct sockaddr_in udpaddr;
2057

    
2058
        udpgen = local_socketID.external_addr;
2059
        udpaddr = udpgen.udpaddr;
2060

    
2061
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
2062
                        INET_ADDRSTRLEN);
2063

    
2064
        if (external_addr == NULL) {
2065

    
2066
        return -1;
2067

    
2068
        } else {
2069

    
2070
        return 0;
2071

    
2072
        }
2073

    
2074
}
2075

    
2076
/**************************** END of NAT functions *************************/