Statistics
| Branch: | Revision:

ml / ml.c @ 9f09d1ae

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

    
57
#define LOG_MODULE "[ml] "
58
#include "ml_log.h"
59

    
60
/**************************** START OF INTERNALS ***********************/
61

    
62
/*
63
 * a pointer to a libevent instance
64
 */
65
struct event_base *base;
66

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

    
80

    
81
/*
82
 * timeout before thinking that the STUN server can't be connected
83
 */
84
#define NAT_TRAVERSAL_TIMEOUT { 1, 0 }
85

    
86
/*
87
 * timeout before thinking of an mtu problem (check MAX_TRIALS as well)
88
 */
89
#define PMTU_TIMEOUT { 0, 250000 }
90

    
91
/*
92
 * retry sending connection messages this many times before reducing pmtu
93
 */
94
#define MAX_TRIALS 3
95

    
96
/*
97
 * default timeout value between the first and the last received packet of a message
98
 */
99
#define RECV_TIMEOUT_DEFAULT { 2, 0 }
100

    
101
/*
102
 * global variables
103
 */
104
/*
105
 * define a buffer of pointers to connect structures
106
 */
107
connect_data *connectbuf[CONNECTBUFSIZE];
108

    
109
/*
110
 * define a pointer buffer with pointers to recv_data structures
111
 */
112
recvdata *recvdatabuf[RECVDATABUFSIZE];
113

    
114
/*
115
 * define a pointer buffer for message multiplexing
116
 */
117
receive_data_cb recvcbbuf[MSGMULTIPLEXSIZE];
118

    
119
/*
120
 * stun server address
121
 */
122
struct sockaddr_in stun_server;
123

    
124
/*
125
 * receive timeout
126
 */
127
static struct timeval recv_timeout = RECV_TIMEOUT_DEFAULT;
128

    
129
/*
130
 * boolean NAT traversal successful if true
131
 */
132
boolean NAT_traversal;
133

    
134
/*
135
 * file descriptor for local socket
136
 */
137
evutil_socket_t socketfd;
138

    
139
/*
140
 * local socketID
141
 */
142
socket_ID local_socketID;
143

    
144
socketID_handle loc_socketID = &local_socketID;
145

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

    
168
/*
169
 * boolean that defines if received data is transmitted to the upper layer
170
 * via callback or via upper layer polling
171
 */
172
boolean recv_data_callback;
173

    
174
/*
175
 * helper function to get rid of a warning
176
 */
177
int min(int a, int b) {
178
        if (a > b) return b;
179
        return a;
180
}
181

    
182
void register_recv_localsocketID_cb(receive_localsocketID_cb local_socketID_cb)
183
{
184
        if (local_socketID_cb == NULL)
185
                error("ML : Register receive_localsocketID_cb: NULL ptr \n");
186
        else
187
        receive_SocketID_cb = local_socketID_cb;
188
}
189

    
190

    
191
//void keep_connection_alive(const int connectionID)
192
//{
193
//
194
//    // to be done with the NAT traversal
195
//    // send a message over the wire
196
//    printf("\n");
197
//
198
//}
199

    
200
void unsetStunServer()
201
{
202
        stun_server.sin_addr.s_addr = 0;
203
}
204

    
205
bool isStunDefined()
206
{
207
        return stun_server.sin_addr.s_addr;
208
}
209

    
210
void send_msg(int con_id, int msg_type, char* msg, int msg_len, bool truncable, send_params * sParams) {
211
        socketaddrgen udpgen;
212
        bool retry;
213
        int pkt_len, offset;
214
        struct iovec iov[4];
215

    
216
        char h_pkt[MON_HEADER_SPACE];
217
        char h_data[MON_HEADER_SPACE];
218

    
219
        struct msg_header msg_h;
220

    
221
        char str[1000];
222
        mlSocketIDToString(&connectbuf[con_id]->external_socketID,str,999);
223
        debug("ML: send_msg to conID:%d extID:%d, %s\n",con_id,connectbuf[con_id]->external_connectionID,str);
224

    
225
        iov[0].iov_base = &msg_h;
226
        iov[0].iov_len = MSG_HEADER_SIZE;
227

    
228
        msg_h.local_con_id = con_id;
229
        msg_h.remote_con_id = connectbuf[con_id]->external_connectionID;
230
        msg_h.msg_type = msg_type;
231
        msg_h.msg_seq_num = connectbuf[con_id]->seqnr++;
232

    
233

    
234
        iov[1].iov_len = iov[2].iov_len = 0;
235
        iov[1].iov_base = h_pkt;
236
        iov[2].iov_base = h_data;
237

    
238

    
239
        if (connectbuf[con_id]->internal_connect)
240
                udpgen = connectbuf[con_id]->external_socketID.internal_addr;
241
        else
242
                udpgen = connectbuf[con_id]->external_socketID.external_addr;
243

    
244
        do{
245
                offset = 0;
246
                retry = false;
247
                // Monitoring layer hook
248
                if(set_Monitoring_header_data_cb != NULL) {
249
                        iov[2].iov_len = ((set_Monitoring_header_data_cb) (&(connectbuf[con_id]->external_socketID), msg_type));
250
                }
251
                msg_h.len_mon_data_hdr = iov[2].iov_len;
252

    
253
                if(get_Send_data_inf_cb != NULL && iov[2].iov_len != 0) {
254
                        mon_data_inf sd_data_inf;
255

    
256
                        sd_data_inf.remote_socketID = &(connectbuf[con_id]->external_socketID);
257
                        sd_data_inf.buffer = msg;
258
                        sd_data_inf.bufSize = msg_len;
259
                        sd_data_inf.msgtype = msg_type;
260
                        sd_data_inf.monitoringDataHeader = iov[2].iov_base;
261
                        sd_data_inf.monitoringDataHeaderLen = iov[2].iov_len;
262
                        sd_data_inf.priority = sParams->priority;
263
                        sd_data_inf.padding = sParams->padding;
264
                        sd_data_inf.confirmation = sParams->confirmation;
265
                        sd_data_inf.reliable = sParams->reliable;
266
                        memset(&sd_data_inf.arrival_time, 0, sizeof(struct timeval));
267

    
268
                        (get_Send_data_inf_cb) ((void *) &sd_data_inf);
269
                }
270

    
271
                do {
272
                        if(set_Monitoring_header_pkt_cb != NULL) {
273
                                iov[1].iov_len = (set_Monitoring_header_pkt_cb) (&(connectbuf[con_id]->external_socketID), msg_type);
274
                        }
275
                        pkt_len = min(connectbuf[con_id]->pmtusize - iov[2].iov_len - iov[1].iov_len - iov[0].iov_len, msg_len - offset) ;
276

    
277
                        iov[3].iov_len = pkt_len;
278
                        iov[3].iov_base = msg + offset;
279

    
280
                        //fill header
281
                        msg_h.len_mon_packet_hdr = iov[1].iov_len;
282
                        msg_h.offset = offset;
283
                        msg_h.msg_length = truncable ? pkt_len : msg_len;
284

    
285
                        //monitoring layer hook
286
                        if(get_Send_pkt_inf_cb != NULL && iov[1].iov_len) {
287
                                mon_pkt_inf pkt_info;
288

    
289
                                pkt_info.remote_socketID = &(connectbuf[con_id]->external_socketID);
290
                                pkt_info.buffer = msg + offset;
291
                                pkt_info.bufSize = pkt_len;
292
                                pkt_info.msgtype = msg_type;
293
                                pkt_info.dataID = connectbuf[con_id]->seqnr;
294
                                pkt_info.offset = offset;
295
                                pkt_info.datasize = msg_len;
296
                                pkt_info.monitoringHeaderLen = iov[1].iov_len;
297
                                pkt_info.monitoringHeader = iov[1].iov_base;
298
                                pkt_info.ttl = -1;
299
                                memset(&(pkt_info.arrival_time),0,sizeof(struct timeval));
300

    
301
                                (get_Send_pkt_inf_cb) ((void *) &pkt_info);
302
                        }
303

    
304
                        debug("ML: sending packet with rconID:%d lconID:%d\n",msg_h.remote_con_id,msg_h.local_con_id);
305
                        switch(sendPacket(socketfd, iov, 4, &udpgen.udpaddr)) {
306
                                case MSGLEN:
307
                                        info("ML: sending message failed, reducing MTU from %d to %d (conID:%d lconID:%d msgsize:%d offset:%d)\n", connectbuf[con_id]->pmtusize, pmtu_decrement(connectbuf[con_id]->pmtusize), msg_h.remote_con_id, msg_h.local_con_id, msg_len, offset);
308
                                        // TODO: pmtu decremented here, but not in the "truncable" packet. That is currently resent without changing the claimed pmtu. Might need to be changed.
309
                                        connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
310
                                        if (connectbuf[con_id]->pmtusize > 0) {
311
                                                connectbuf[con_id]->delay = true;
312
                                                retry = true;
313
                                        }
314
                                        offset = msg_len + msg_h.len_mon_data_hdr; // exit the while
315
                                        break;
316
                                case FAILURE:
317
                                        info("ML: sending message failed (conID:%d lconID:%d msgsize:%d offset:%d)\n", msg_h.remote_con_id, msg_h.local_con_id, msg_len, offset);
318
                                        offset = msg_len + msg_h.len_mon_data_hdr; // exit the while
319
                                        break;
320
                                case OK:
321
                                        //update
322
                                        offset += pkt_len + iov[2].iov_len;
323
                                        //transmit data header only in the first packet
324
                                        iov[2].iov_len = 0;
325
                                        break;
326
                        }
327
                } while(offset != msg_len + msg_h.len_mon_data_hdr && !truncable);
328
        } while(retry);
329
}
330

    
331
void pmtu_timeout_cb(int fd, short event, void *arg);
332

    
333
void reschedule_conn_msg(int con_id)
334
{
335
        if (connectbuf[con_id]->timeout_event) {
336
                /* delete old timout */        
337
                event_del(connectbuf[con_id]->timeout_event);
338
                event_free(connectbuf[con_id]->timeout_event);
339
        }
340
        connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
341
        evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
342
}
343

    
344
void send_conn_msg(int con_id, int buf_size, int command_type)
345
{
346
        if (buf_size < sizeof(struct conn_msg)) {
347
                error("ML: requested connection message size is too small\n");
348
                return;
349
        }
350

    
351
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
352
                connectbuf[con_id]->ctrl_msg_buf = malloc(buf_size);
353
                memset(connectbuf[con_id]->ctrl_msg_buf, 0, buf_size);
354
        }
355

    
356
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
357
                error("ML: can not allocate memory for connection message\n");
358
                return;
359
        }
360

    
361
        struct conn_msg *msg_header = (struct conn_msg*) connectbuf[con_id]->ctrl_msg_buf;
362

    
363
        msg_header->comand_type = command_type;
364
        msg_header->pmtu_size = connectbuf[con_id]->pmtusize;
365

    
366
        memcpy(&(msg_header->sock_id), loc_socketID, sizeof(socket_ID));
367

    
368
        send_msg(con_id, ML_CON_MSG, connectbuf[con_id]->ctrl_msg_buf, buf_size, true, &(connectbuf[con_id]->defaultSendParams));
369
}
370

    
371
void send_conn_msg_with_pmtu_discovery(int con_id, int buf_size, int command_type)
372
{
373
        struct timeval tout = PMTU_TIMEOUT;
374
        connectbuf[con_id]->timeout_value = tout;
375
        connectbuf[con_id]->trials = 1;
376
        send_conn_msg(con_id, buf_size, command_type);
377
        reschedule_conn_msg(con_id);
378
}
379

    
380
void resend_conn_msg(int con_id)
381
{
382
        connectbuf[con_id]->trials++;
383
        send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
384
        reschedule_conn_msg(con_id);
385
}
386

    
387
void
388
recv_conn_msg(struct msg_header *msg_h, char *msgbuf, int msg_size)
389
{
390
        struct conn_msg *con_msg;
391
        int free_con_id, con_id;
392

    
393
        time_t now = time(NULL);
394
        double timediff = 0.0;
395
        char str[1000];
396

    
397
        // Monitoring layer hook
398
        if(get_Recv_data_inf_cb != NULL && msg_h->len_mon_data_hdr != 0) {
399
                // update pointer to the real data
400
                msgbuf += msg_h->len_mon_data_hdr;
401
                msg_size -= msg_h->len_mon_data_hdr;
402
                con_msg = (struct conn_msg *)msgbuf;
403

    
404
                mon_data_inf recv_data_inf;
405
                recv_data_inf.remote_socketID = &(con_msg->sock_id);
406
                recv_data_inf.buffer = msgbuf;
407
                recv_data_inf.bufSize = msg_size;
408
                recv_data_inf.msgtype = msg_h->msg_type;
409
                recv_data_inf.monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
410
                recv_data_inf.monitoringDataHeader = msg_h->len_mon_data_hdr ? msgbuf : NULL;
411
                gettimeofday(&recv_data_inf.arrival_time, NULL);
412
                recv_data_inf.firstPacketArrived = true;
413
                recv_data_inf.recvFragments = 1;
414
                recv_data_inf.priority = false;
415
                recv_data_inf.padding = false;
416
                recv_data_inf.confirmation = false;
417
                recv_data_inf.reliable = false;
418

    
419
                // send data recv callback to monitoring module
420
                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
421
        } else {
422
                con_msg = (struct conn_msg *) msgbuf;
423
        }
424

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

    
428
        // check the connection command type
429
        switch (con_msg->comand_type) {
430
                /*
431
                * if INVITE: enter a new socket make new entry in connect array
432
                * send an ok
433
                */
434
                case INVITE:
435
                        info("ML: received INVITE from %s (size:%d)\n", str, msg_size);
436
                        /*
437
                        * check if another connection for the external connectionID exist
438
                        * that was established within the last 2 seconds
439
                        */
440
                        free_con_id = -1;
441
                        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
442
                                if (connectbuf[con_id] != NULL) {
443
                                        if (mlCompareSocketIDs(&(connectbuf[con_id]->external_socketID), &(con_msg->sock_id)) == 0) {
444
                                                //timediff = difftime(now, connectbuf[con_id]->starttime);        //TODO: why this timeout? Shouldn't the connection be closed instead if there is a timeout?
445
                                                //if (timediff < 2)
446
                                                //update remote connection ID
447
                                                if (connectbuf[con_id]->external_connectionID != msg_h->local_con_id) {
448
                                                        warn("ML: updating remote connection ID for %s: from %d to %d\n",str, connectbuf[con_id]->external_connectionID, msg_h->local_con_id);
449
                                                        connectbuf[con_id]->external_connectionID = msg_h->local_con_id;
450
                                                }
451
                                                break;
452
                                        }
453
                                } else if(free_con_id == -1)
454
                                        free_con_id = con_id;
455
                        }
456

    
457
                        if (con_id == CONNECTBUFSIZE) {
458
                                // create an entry in the connecttrybuf
459
                                if(free_con_id == -1) {
460
                                        error("ML: no new connect_buf available\n");
461
                                        return;
462
                                }
463
                                connectbuf[free_con_id] = (connect_data *) malloc(sizeof(connect_data));
464
                                memset(connectbuf[free_con_id],0,sizeof(connect_data));
465
                                connectbuf[free_con_id]->connection_head = connectbuf[free_con_id]->connection_last = NULL;
466
                                connectbuf[free_con_id]->starttime = time(NULL);
467
                                memcpy(&(connectbuf[free_con_id]->external_socketID), &(con_msg->sock_id), sizeof(socket_ID));
468
                                connectbuf[free_con_id]->pmtusize = con_msg->pmtu_size;        // bootstrap pmtu from the other's size. Not strictly needed, but a good hint
469
                                connectbuf[free_con_id]->timeout_event = NULL;
470
                                connectbuf[free_con_id]->external_connectionID = msg_h->local_con_id;
471
                                connectbuf[free_con_id]->internal_connect =
472
                                        !compare_external_address_socketIDs(&(con_msg->sock_id), loc_socketID);
473
                                con_id = free_con_id;
474
                        }
475

    
476
                        //if(connectbuf[con_id]->status <= CONNECT) { //TODO: anwer anyway. Why the outher would invite otherwise?
477
                                //update status and send back answer
478
                                connectbuf[con_id]->status = CONNECT;
479
                                send_conn_msg_with_pmtu_discovery(con_id, con_msg->pmtu_size, CONNECT);
480
                        //}
481
                        break;
482
                case CONNECT:
483
                        info("ML: received CONNECT from %s (size:%d)\n", str, msg_size);
484

    
485
                        if(msg_h->remote_con_id != -1 && connectbuf[msg_h->remote_con_id] == NULL) {
486
                                error("ML: received CONNECT for inexistent connection rconID:%d\n",msg_h->remote_con_id);
487
                                return;
488
                        }
489

    
490
                        /*
491
                        * check if the connection status is not already 1 or 2
492
                        */
493
                        if (connectbuf[msg_h->remote_con_id]->status == INVITE) {
494
                                // set the external connectionID
495
                                connectbuf[msg_h->remote_con_id]->external_connectionID = msg_h->local_con_id;
496
                                // change status con_msg the connection_data
497
                                connectbuf[msg_h->remote_con_id]->status = READY;
498
                                // change pmtusize in the connection_data: not needed. receiving a CONNECT means our INVITE went through. So why change pmtu?
499
                                //connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
500

    
501
                                // send the READY
502
                                send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
503

    
504
                                if (receive_Connection_cb != NULL)
505
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
506

    
507
                                // call all registered callbacks
508
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
509
                                        struct receive_connection_cb_list *temp;
510
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
511
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
512
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
513
                                        free(temp);
514
                                }
515
                                connectbuf[msg_h->remote_con_id]->connection_head =
516
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
517
                        } else {
518
                                // send the READY
519
                                send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
520
                        }
521

    
522
                        debug("ML: active connection established\n");
523
                        break;
524

    
525
                        /*
526
                        * if READY: find the entry in the connection array set the
527
                        * connection active change the pmtu size
528
                        */
529
                case READY:
530
                        info("ML: received READY from %s (size:%d)\n", str, msg_size);
531
                        if(connectbuf[msg_h->remote_con_id] == NULL) {
532
                                error("ML: received READY for inexistent connection\n");
533
                                return;
534
                        }
535
                        /*
536
                        * checks if the connection is not already established
537
                        */
538
                        if (connectbuf[msg_h->remote_con_id]->status == CONNECT) {
539
                                // change status of the connection
540
                                connectbuf[msg_h->remote_con_id]->status = READY;
541
                                // change pmtusize: not needed. pmtu doesn't have to be symmetric
542
                                //connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
543

    
544
                                if (receive_Connection_cb != NULL)
545
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
546

    
547
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
548
                                        struct receive_connection_cb_list *temp;
549
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
550
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
551
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
552
                                        free(temp);
553
                                }
554
                                connectbuf[msg_h->remote_con_id]->connection_head =
555
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
556
                                debug("ML: passive connection established\n");
557
                        }
558
                        break;
559
        }
560
}
561

    
562
void recv_stun_msg(char *msgbuf, int recvSize)
563
{
564
        /*
565
        * create empty stun message struct
566
        */
567
        StunMessage resp;
568
        memset(&resp, 0, sizeof(StunMessage));
569
        /*
570
        * parse the message
571
        */
572
        int returnValue = 0;
573
        returnValue = recv_stun_message(msgbuf, recvSize, &resp);
574

    
575
        if (returnValue == 0) {
576
                /*
577
                * read the reflexive Address into the local_socketID
578
                */
579
                struct sockaddr_in reflexiveAddr;
580
                reflexiveAddr.sin_family = AF_INET;
581
                reflexiveAddr.sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
582
                reflexiveAddr.sin_port = htons(resp.mappedAddress.ipv4.port);
583
                socketaddrgen reflexiveAddres;
584
                reflexiveAddres.udpaddr = reflexiveAddr;
585
                local_socketID.external_addr = reflexiveAddres;
586
                NAT_traversal = true;
587
                // callback to the upper layer indicating that the socketID is now
588
                // ready to use
589
                (receive_SocketID_cb) (&local_socketID, 0);
590
        }
591
}
592

    
593
//done
594
void recv_timeout_cb(int fd, short event, void *arg)
595
{
596
        int recv_id = (long) arg;
597
        debug("ML: recv_timeout_cb called. Timeout for id:%d\n",recv_id);
598

    
599
        if (recvdatabuf[recv_id] == NULL) {
600
                return;
601
        }
602

    
603

    
604
/*        if(recvdatabuf[recv_id]->status == ACTIVE) {
605
                //TODO make timeout at least a DEFINE
606
                struct timeval timeout = { 4, 0 };
607
                recvdatabuf[recv_id]->status = INACTIVE;
608
                event_base_once(base, -1, EV_TIMEOUT, recv_timeout_cb,
609
                        arg, &timeout);
610
                return;
611
        }
612
*/
613

    
614
        if(recvdatabuf[recv_id]->status == ACTIVE) {
615
                // Monitoring layer hook
616
                if(get_Recv_data_inf_cb != NULL) {
617
                        mon_data_inf recv_data_inf;
618

    
619
                        recv_data_inf.remote_socketID =
620
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
621
                        recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
622
                        recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
623
                        recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
624
                        recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
625
                        recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
626
                                recvdatabuf[recv_id]->recvbuf : NULL;
627
                        gettimeofday(&recv_data_inf.arrival_time, NULL);
628
                        recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
629
                        recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
630
                        recv_data_inf.priority = false;
631
                        recv_data_inf.padding = false;
632
                        recv_data_inf.confirmation = false;
633
                        recv_data_inf.reliable = false;
634

    
635
                        // send data recv callback to monitoring module
636

    
637
                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
638
                }
639

    
640
                // Get the right callback
641
                receive_data_cb receive_data_callback = recvcbbuf[recvdatabuf[recv_id]->msgtype];
642

    
643
                recv_params rParams;
644

    
645
                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
646
                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
647
                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
648
                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
649
                rParams.remote_socketID =
650
                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
651
                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
652

    
653
                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
654
                        recvdatabuf[recv_id]->msgtype, &rParams);
655

    
656
                //clean up
657
                free(recvdatabuf[recv_id]->recvbuf);
658
                free(recvdatabuf[recv_id]);
659
                recvdatabuf[recv_id] = NULL;
660
        }
661
}
662

    
663
// process a single recv data message
664
void recv_data_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
665
{
666
        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);
667

    
668
        int recv_id, free_recv_id = -1;
669

    
670
        if(connectbuf[msg_h->remote_con_id] == NULL) {
671
                debug("ML: Received a message not related to any opened connection!\n");
672
                return;
673
        }
674

    
675
        // check if a recv_data exist and enter data
676
        for (recv_id = 0; recv_id < RECVDATABUFSIZE; recv_id++)
677
                if (recvdatabuf[recv_id] != NULL) {
678
                        if (msg_h->remote_con_id == recvdatabuf[recv_id]->connectionID &&
679
                                        msg_h->msg_seq_num == recvdatabuf[recv_id]->seqnr)
680
                                                break;
681
                } else
682
                        if(free_recv_id == -1)
683
                                free_recv_id = recv_id;
684

    
685

    
686
        if(recv_id == RECVDATABUFSIZE) {
687
                //no recv_data found: create one
688
                recv_id = free_recv_id;
689
                recvdatabuf[recv_id] = (recvdata *) malloc(sizeof(recvdata));
690
                memset(recvdatabuf[recv_id], 0, sizeof(recvdata));
691
                recvdatabuf[recv_id]->connectionID = msg_h->remote_con_id;
692
                recvdatabuf[recv_id]->seqnr = msg_h->msg_seq_num;
693
                recvdatabuf[recv_id]->monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
694
                recvdatabuf[recv_id]->bufsize = msg_h->msg_length + msg_h->len_mon_data_hdr;
695
                recvdatabuf[recv_id]->recvbuf = (char *) malloc(recvdatabuf[recv_id]->bufsize);
696
                /*
697
                * read the timeout data and set it
698
                */
699
                recvdatabuf[recv_id]->timeout_value = recv_timeout;
700
                recvdatabuf[recv_id]->timeout_event = NULL;
701
                recvdatabuf[recv_id]->recvID = recv_id;
702
                recvdatabuf[recv_id]->starttime = time(NULL);
703
                recvdatabuf[recv_id]->msgtype = msg_h->msg_type;
704

    
705
                // fill the buffer with zeros
706
                memset(recvdatabuf[recv_id]->recvbuf, 0, msg_h->msg_length);
707
                debug(" new @ id:%d\n",recv_id);
708
        } else {        //message structure already exists, no need to create new
709
                debug(" found @ id:%d (arrived before this packet: bytes:%d fragments%d\n",recv_id, recvdatabuf[recv_id]->arrivedBytes, recvdatabuf[recv_id]->recvFragments);
710
        }
711

    
712
        if (msg_h->offset == 0)
713
                recvdatabuf[recv_id]->firstPacketArrived = 1;
714

    
715

    
716
        // increment fragmentnr
717
        recvdatabuf[recv_id]->recvFragments++;
718
        // increment the arrivedBytes
719
        recvdatabuf[recv_id]->arrivedBytes += bufsize;
720

    
721
        // enter the data into the buffer
722
        memcpy(recvdatabuf[recv_id]->recvbuf + msg_h->offset, msgbuf, bufsize);
723

    
724
        //TODO very basic checkif all fragments arrived: has to be reviewed
725
        if(recvdatabuf[recv_id]->arrivedBytes == recvdatabuf[recv_id]->bufsize)
726
                recvdatabuf[recv_id]->status = COMPLETE; //buffer full -> msg completly arrived
727
        else
728
                recvdatabuf[recv_id]->status = ACTIVE;
729

    
730
        if (recv_data_callback) {
731
                if(recvdatabuf[recv_id]->status == COMPLETE) {
732
                        // Monitoring layer hook
733
                        if(get_Recv_data_inf_cb != NULL) {
734
                                mon_data_inf recv_data_inf;
735

    
736
                                recv_data_inf.remote_socketID =
737
                                         &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
738
                                recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
739
                                recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
740
                                recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
741
                                recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
742
                                recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
743
                                        recvdatabuf[recv_id]->recvbuf : NULL;
744
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
745
                                recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
746
                                recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
747
                                recv_data_inf.priority = false;
748
                                recv_data_inf.padding = false;
749
                                recv_data_inf.confirmation = false;
750
                                recv_data_inf.reliable = false;
751

    
752
                                // send data recv callback to monitoring module
753

    
754
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
755
                        }
756

    
757
                        // Get the right callback
758
                        receive_data_cb receive_data_callback = recvcbbuf[msg_h->msg_type];
759
                        if (receive_data_callback) {
760

    
761
                                recv_params rParams;
762

    
763
                                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
764
                                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
765
                                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
766
                                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
767
                                rParams.remote_socketID =
768
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
769

    
770
                                char str[1000];
771
                                mlSocketIDToString(rParams.remote_socketID,str,999);
772
                                debug("ML: received message from conID:%d, %s\n",recvdatabuf[recv_id]->connectionID,str);
773
                                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
774

    
775
                                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
776
                                        recvdatabuf[recv_id]->msgtype, (void *) &rParams);
777
                        } else {
778
                            warn("ML: callback not initialized for this message type: %d!\n",msg_h->msg_type);
779
                        }
780

    
781
                        //clean up
782
                        if (recvdatabuf[recv_id]->timeout_event) {
783
                                int ret;
784
                                debug("ML: freeing timeout for %d",recv_id);
785
                                ret = event_del(recvdatabuf[recv_id]->timeout_event);
786
                                event_free(recvdatabuf[recv_id]->timeout_event);
787
                                recvdatabuf[recv_id]->timeout_event = NULL;
788
                                debug(" ret: %d\n",ret);
789
                        } else {
790
                                debug("ML: received in 1 packet\n",recv_id);
791
                        }
792
                        free(recvdatabuf[recv_id]->recvbuf);
793
                        free(recvdatabuf[recv_id]);
794
                        recvdatabuf[recv_id] = NULL;
795
                } else { // not COMPLETE
796
                        if (!recvdatabuf[recv_id]->timeout_event) {
797
                                //start time out
798
                                //TODO make timeout at least a DEFINE
799
                                recvdatabuf[recv_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &recv_timeout_cb, (void *) (long)recv_id);
800
                                evtimer_add(recvdatabuf[recv_id]->timeout_event, &recv_timeout);
801
                        }
802
                }
803
        }
804
}
805

    
806
//done
807
void pmtu_timeout_cb(int fd, short event, void *arg)
808
{
809

    
810
        int con_id = (long) arg;
811
        pmtu new_pmtusize;
812
        struct timeval timeout;
813

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

    
816
        if(connectbuf[con_id] == NULL) {
817
                error("ML: pmtu timeout called on non existing con_id\n");
818
                return;
819
        }
820

    
821
        if(connectbuf[con_id]->status == READY) {
822
                // nothing to do anymore
823
                event_del(connectbuf[con_id]->timeout_event);
824
                event_free(connectbuf[con_id]->timeout_event);
825
                connectbuf[con_id]->timeout_event = NULL;
826
                return;
827
        }
828

    
829
        info("ML: pmtu timeout while connecting(lcon:%d status:%d)\n",con_id, connectbuf[con_id]->status);
830

    
831
        timeout = connectbuf[con_id]->timeout_value;
832

    
833
        if(connectbuf[con_id]->delay || connectbuf[con_id]->trials == MAX_TRIALS - 1) {
834
                double delay = timeout.tv_sec + timeout.tv_usec / 1000000.0;
835
                delay = delay * 2;
836
                info("\tML: increasing pmtu timeout to %f sec\n", delay);
837
                timeout.tv_sec = floor(delay);
838
                timeout.tv_usec = fmod(delay, 1.0) * 1000000.0;
839
                if(connectbuf[con_id]->delay) {
840
                        connectbuf[con_id]->delay = false;
841
                        reschedule_conn_msg(con_id);
842
                }
843
        }
844

    
845
        if(connectbuf[con_id]->trials == MAX_TRIALS) {
846
                // decrement the pmtu size
847
                struct timeval tout = PMTU_TIMEOUT;
848
                info("\tML: decreasing pmtu timeout from %d to %d\n", connectbuf[con_id]->pmtusize, pmtu_decrement(connectbuf[con_id]->pmtusize));
849
                connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
850
                connectbuf[con_id]->timeout_value = tout; 
851
                connectbuf[con_id]->trials = 0;
852
        }
853

    
854
        //error in PMTU discovery?
855
        if (connectbuf[con_id]->pmtusize == ERROR) {
856
                if (connectbuf[con_id]->internal_connect == true) {
857
                        //as of now we tried directly connecting, now let's try trough the NAT
858
                        connectbuf[con_id]->internal_connect = false;
859
                        connectbuf[con_id]->pmtusize = MAX;
860
                } else {
861
                        //nothing to do we have to give up
862
                        error("ML: Could not create connection with connectionID %i!\n",con_id);
863
                        // envoke the callback for failed connection establishment
864
                        if(failed_Connection_cb != NULL)
865
                                (failed_Connection_cb) (con_id, NULL);
866
                        // delete the connection entry
867
                        mlCloseConnection(con_id);
868
                        return;
869
                }
870
        }
871

    
872
        //retry with new pmtu size
873
        connectbuf[con_id]->trials++;
874
        resend_conn_msg(con_id);
875
}
876

    
877

    
878
int schedule_pmtu_timeout(int con_id)
879
{
880
        if (! connectbuf[con_id]->timeout_event) {
881
                struct timeval tout = PMTU_TIMEOUT;
882
                connectbuf[con_id]->timeout_value = tout;
883
                connectbuf[con_id]->trials = 1;
884
                connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
885
                evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
886
        }
887
}
888

    
889
/*
890
 * decrements the mtu size
891
 */
892
pmtu pmtu_decrement(pmtu pmtusize)
893
{
894
        pmtu pmtu_return_size;
895
        switch(pmtusize) {
896
        case MAX:
897
                return DSL;
898
        case DSL:
899
                return DSLMEDIUM;
900
        case DSLMEDIUM:
901
                return DSLSLIM;
902
        case DSLSLIM:
903
                return BELOWDSL;
904
        case BELOWDSL:
905
                return MIN;
906
        case MIN:
907
                return ERROR;
908
        default:
909
                warn("ML: strange pmtu size encountered:%d, changing to some safe value:%d\n", pmtusize, MIN);
910
                return MIN;
911
        }
912
}
913

    
914
// called when an ICMP pmtu error message (type 3, code 4) is received
915
void pmtu_error_cb_th(char *msg, int msglen)
916
{
917
        debug("ML: pmtu_error callback called msg_size: %d\n",msglen);
918
        //TODO debug
919
        return;
920

    
921
    char *msgbufptr = NULL;
922
    int msgtype;
923
    int connectionID;
924
    pmtu pmtusize;
925
    pmtu new_pmtusize;
926
    int dead = 0;
927

    
928
    // check the packettype
929
    msgbufptr = &msg[0];
930

    
931
    // check the msgtype
932
    msgbufptr = &msg[1];
933
    memcpy(&msgtype, msgbufptr, 4);
934

    
935
    if (msgtype == 0) {
936

    
937
        // get the connectionID
938
        msgbufptr = &msg[5];
939
        memcpy(&connectionID, msgbufptr, 4);
940

    
941
        int msgtype_c = connectbuf[connectionID]->status;
942
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
943

    
944
        if (msgtype_c != msgtype) {
945
            dead = 1;
946
        }
947

    
948

    
949
    } else if (msgtype == 1) {
950

    
951
        // read the connectionID
952
        msgbufptr = &msg[9];
953
        memcpy(&connectionID, msgbufptr, 4);
954

    
955
        int msgtype_c = connectbuf[connectionID]->status;
956
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
957

    
958
        if (msgtype_c != msgtype) {
959
            dead = 1;
960
        }
961

    
962
    }
963
    // decrement the pmtu size
964
    new_pmtusize = pmtu_decrement(pmtusize);
965

    
966
//    connectbuf[connectionID]->pmtutrysize = new_pmtusize;
967

    
968
    if (new_pmtusize == ERROR) {
969
                error("ML:  Could not create connection with connectionID %i !\n",
970
                        connectionID);
971

    
972
                if(failed_Connection_cb != NULL)
973
                        (failed_Connection_cb) (connectionID, NULL);
974
                // set the message type to a non existent message
975
                msgtype = 2;
976
                // delete the connection entry
977
                 mlCloseConnection(connectionID);
978
        }
979

    
980
    if (msgtype == 0 && dead != 1) {
981

    
982
        // stop the timeout event
983
        // timeout_del(connectbuf[connectionID]->timeout);
984
        /*
985
         * libevent2
986
         */
987

    
988
        // event_del(connectbuf[connectionID]->timeout);
989

    
990

    
991
        // create and send a connection message
992
//         create_conn_msg(new_pmtusize, connectionID,
993
//                         &local_socketID, INVITE);
994

    
995
//        send_conn_msg(connectionID, new_pmtusize);
996

    
997
        // set a timeout event for the pmtu discovery
998
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
999
        // *)&connectionID);
1000

    
1001
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1002

    
1003
        /*
1004
         * libevent2
1005
         */
1006

    
1007
        struct event *ev;
1008
        ev = evtimer_new(base, pmtu_timeout_cb,
1009
                         (void *) connectbuf[connectionID]);
1010

    
1011
        // connectbuf[connectionID]->timeout = ev;
1012

    
1013
        event_add(ev, &connectbuf[connectionID]->timeout_value);
1014

    
1015
    } else if (msgtype == 1 && dead != 1) {
1016

    
1017
        // stop the timeout event
1018
        // timeout_del(connectbuf[connectionID]->timeout);
1019

    
1020
        /*
1021
         * libevent2
1022
         */
1023
        // info("still here 11 \n");
1024
        // printf("ev %d \n",connectbuf[connectionID]->timeout);
1025
        // event_del(connectbuf[connectionID]->timeout );
1026
        // evtimer_del(connectbuf[connectionID]->timeout );
1027

    
1028

    
1029
//         // create and send a connection message
1030
//         create_conn_msg(new_pmtusize,
1031
//                         connectbuf[connectionID]->connectionID,
1032
//                         NULL, CONNECT);
1033

    
1034
        //send_conn_msg(connectionID, new_pmtusize);
1035

    
1036
        // set a timeout event for the pmtu discovery
1037
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
1038
        // *)&connectionID);
1039
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1040

    
1041
        /*
1042
         * libevent2
1043
         */
1044
        // struct event *ev;
1045
        // ev = evtimer_new(base,pmtu_timeout_cb, (void
1046
        // *)connectbuf[connectionID]);
1047
        // connectbuf[connectionID]->timeout = ev;
1048
        // event_add(ev,&connectbuf[connectionID]->timeout_value);
1049

    
1050
    }
1051
}
1052

    
1053
/*
1054
 * what to do once a packet arrived if it is a conn packet send it to
1055
 * recv_conn handler if it is a data packet send it to the recv_data
1056
 * handler
1057
 */
1058

    
1059
//done --
1060
void recv_pkg(int fd, short event, void *arg)
1061
{
1062
        debug("ML: recv_pkg called\n");
1063

    
1064
        struct msg_header *msg_h;
1065
        char msgbuf[MAX];
1066
        pmtu recvSize = MAX;
1067
        char *bufptr = msgbuf;
1068
        int ttl;
1069
        struct sockaddr_in recv_addr;
1070
        int msg_size;
1071

    
1072
        recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
1073

    
1074

    
1075
        // check if it is not just an ERROR message
1076
        if(recvSize < 0)
1077
                return;
1078

    
1079
        // @TODO check if this simplistic STUN message recognition really always works, probably not
1080
        unsigned short stun_bind_response = 0x0101;
1081
        unsigned short * msgspot = (unsigned short *) msgbuf;
1082
        if (*msgspot == stun_bind_response) {
1083
                debug("ML: recv_pkg: parse stun message called\n");
1084
                recv_stun_msg(msgbuf, recvSize);
1085
                return;
1086
        }
1087

    
1088
        msg_h = (struct msg_header *) msgbuf;
1089
        bufptr += MSG_HEADER_SIZE + msg_h->len_mon_packet_hdr;
1090
        msg_size = recvSize - MSG_HEADER_SIZE - msg_h->len_mon_packet_hdr;
1091

    
1092

    
1093
        if(get_Recv_pkt_inf_cb != NULL && msg_h->len_mon_packet_hdr != 0) {
1094
                mon_pkt_inf msginfNow;
1095
                msginfNow.monitoringHeaderLen = msg_h->len_mon_packet_hdr;
1096
                msginfNow.monitoringHeader = msg_h->len_mon_packet_hdr ? &msgbuf[0] + MSG_HEADER_SIZE : NULL;
1097
                //TODO rethink this ...
1098
                if(msg_h->msg_type == ML_CON_MSG) {
1099
                        struct conn_msg *c_msg = (struct conn_msg *) bufptr;
1100
                        msginfNow.remote_socketID = &(c_msg->sock_id);
1101
                }
1102
                else if(connectbuf[msg_h->remote_con_id] == NULL) {
1103
                        error("ML: received pkg called with non existent connection\n");
1104
                        return;
1105
                } else
1106
                        msginfNow.remote_socketID = &(connectbuf[msg_h->remote_con_id]->external_socketID);
1107
                msginfNow.buffer = bufptr;
1108
                msginfNow.bufSize = recvSize;
1109
                msginfNow.msgtype = msg_h->msg_type;
1110
                msginfNow.ttl = ttl;
1111
                msginfNow.dataID = msg_h->msg_seq_num;
1112
                msginfNow.offset = msg_h->offset;
1113
                msginfNow.datasize = msg_h->msg_length;
1114
                gettimeofday(&msginfNow.arrival_time, NULL);
1115
                (get_Recv_pkt_inf_cb) ((void *) &msginfNow);
1116
        }
1117

    
1118

    
1119
        switch(msg_h->msg_type) {
1120
                case ML_CON_MSG:
1121
                        debug("ML: received conn pkg\n");
1122
                        recv_conn_msg(msg_h, bufptr, msg_size);
1123
                        break;
1124
                default:
1125
                        if(msg_h->msg_type < 127) {
1126
                                debug("ML: received data pkg\n");
1127
                                recv_data_msg(msg_h, bufptr, msg_size);
1128
                                break;
1129
                        }
1130
                        debug("ML: unrecognised msg_type\n");
1131
                        break;
1132
        }
1133
}
1134

    
1135
/*
1136
 * compare the external IP address of two socketIDs
1137
 */
1138
int
1139
compare_external_address_socketIDs(socketID_handle sock1, socketID_handle sock2)
1140
{
1141
        if( sock1->external_addr.udpaddr.sin_addr.s_addr == sock2->external_addr.udpaddr.sin_addr.s_addr)
1142
                return 0;
1143
        return 1;
1144
}
1145

    
1146
void try_stun();
1147

    
1148
/*
1149
 * the timeout of the NAT traversal
1150
 */
1151
void nat_traversal_timeout(int fd, short event, void *arg)
1152
{
1153
        if (NAT_traversal == false) {
1154
                debug("ML: NAT traversal request re-send\n");
1155
                if(receive_SocketID_cb)
1156
                        (receive_SocketID_cb) (&local_socketID, 2);
1157
                try_stun();
1158
        }
1159
}
1160

    
1161
unsigned long resolve(const char *ipaddr)
1162
{
1163
        struct hostent *h = gethostbyname(ipaddr);
1164
        if (!h) {
1165
                error("ML: Unable to resolve host name %s\n", ipaddr);
1166
        exit(-1);
1167
    }
1168
    unsigned long *addr = (unsigned long *) (h->h_addr);
1169
    return *addr;
1170
}
1171

    
1172

    
1173
/*
1174
 * returns a handle to the socketID struct the ipaddr can be a null
1175
 * pointer. Then all available ipaddr on the machine are choosen.
1176
 */
1177
void create_socket(const int port, const char *ipaddr)
1178
{
1179
        struct sockaddr_in udpaddr;
1180
        udpaddr.sin_family = AF_INET;
1181
        if (ipaddr == NULL) {
1182
                /*
1183
                * try to guess the local IP address
1184
                */
1185
                const char *ipaddr_iface = mlAutodetectIPAddress();
1186
                if (ipaddr_iface) {
1187
                        udpaddr.sin_addr.s_addr = inet_addr(ipaddr_iface);
1188
                } else {
1189
                        udpaddr.sin_addr.s_addr = INADDR_ANY;
1190
                }
1191
        } else {
1192
                udpaddr.sin_addr.s_addr = inet_addr(ipaddr);
1193
        }
1194
        udpaddr.sin_port = htons(port);
1195

    
1196
        socketaddrgen udpgen;
1197
        memset(&udpgen,0,sizeof(socketaddrgen));        //this will be sent over the net, so set it to 0
1198
        udpgen.udpaddr = udpaddr;
1199
        local_socketID.internal_addr = udpgen;
1200

    
1201
        socketfd = createSocket(port, ipaddr);
1202

    
1203
        struct event *ev;
1204
        ev = event_new(base, socketfd, EV_READ | EV_PERSIST, recv_pkg, NULL);
1205

    
1206
        event_add(ev, NULL);
1207

    
1208
        try_stun();
1209
}
1210

    
1211
/*
1212
 * try to figure out external IP using STUN, if defined
1213
 */
1214
void try_stun()
1215
{
1216
        if (isStunDefined()) {
1217
                /*
1218
                * send the NAT traversal STUN request
1219
                */
1220
                 send_stun_request(socketfd, &stun_server);
1221

    
1222
                /*
1223
                * enter a NAT traversal timeout that takes care of retransmission
1224
                */
1225
                struct event *ev1;
1226
                struct timeval timeout_value_NAT_traversal = NAT_TRAVERSAL_TIMEOUT;
1227
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1228
                event_add(ev1, &timeout_value_NAT_traversal);
1229

    
1230
                NAT_traversal = false;
1231
        } else {
1232
                /*
1233
                * Assume we have accessibility and copy internal address to external one
1234
                */
1235
                local_socketID.external_addr = local_socketID.internal_addr;
1236
                NAT_traversal = true; // @TODO: this is not really NAT traversal, but a flag that init is over
1237
                // callback to the upper layer indicating that the socketID is now
1238
                // ready to use
1239
                if(receive_SocketID_cb)
1240
                        (receive_SocketID_cb) (&local_socketID, 0); //success
1241
        }
1242
}
1243

    
1244
/**************************** END OF INTERNAL ***********************/
1245

    
1246
/**************************** MONL functions *************************/
1247

    
1248
void 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){
1249

    
1250
        base = (struct event_base *) arg;
1251
        recv_data_callback = recv_data_cb;
1252
        mlSetRecvTimeout(timeout_value);
1253
        if (stun_ipaddr) {
1254
                 mlSetStunServer(stun_port, stun_ipaddr);
1255
        } else {
1256

    
1257
        }
1258
        register_recv_localsocketID_cb(local_socketID_cb);
1259
        create_socket(port, ipaddr);
1260

    
1261
}
1262

    
1263
/* register callbacks  */
1264
void mlRegisterGetRecvPktInf(get_recv_pkt_inf_cb recv_pkt_inf_cb){
1265

    
1266
        if (recv_pkt_inf_cb == NULL)
1267
                error("ML: Register get_recv_pkt_inf_cb failed: NULL ptr  \n");
1268
        else
1269
                get_Recv_pkt_inf_cb = recv_pkt_inf_cb;
1270

    
1271
}
1272

    
1273
void mlRegisterGetSendPktInf(get_send_pkt_inf_cb  send_pkt_inf_cb){
1274

    
1275
        if (send_pkt_inf_cb == NULL)
1276
                error("ML: Register get_send_pkt_inf_cb: NULL ptr  \n");
1277
        else
1278
                get_Send_pkt_inf_cb = send_pkt_inf_cb;
1279

    
1280
}
1281

    
1282

    
1283
void mlRegisterSetMonitoringHeaderPktCb(set_monitoring_header_pkt_cb monitoring_header_pkt_cb ){
1284

    
1285
        if (monitoring_header_pkt_cb == NULL)
1286
                error("ML: Register set_monitoring_header_pkt_cb: NULL ptr  \n");
1287
        else
1288
                set_Monitoring_header_pkt_cb = monitoring_header_pkt_cb;
1289

    
1290
}
1291

    
1292
void mlRegisterGetRecvDataInf(get_recv_data_inf_cb recv_data_inf_cb){
1293

    
1294
        if (recv_data_inf_cb == NULL)
1295
                error("ML: Register get_recv_data_inf_cb: NULL ptr  \n");
1296
        else
1297
                get_Recv_data_inf_cb = recv_data_inf_cb;
1298

    
1299
}
1300

    
1301
void mlRegisterGetSendDataInf(get_send_data_inf_cb  send_data_inf_cb){
1302

    
1303
        if (send_data_inf_cb == NULL)
1304
                error("ML: Register get_send_data_inf_cb: NULL ptr  \n");
1305
        else
1306
                get_Send_data_inf_cb = send_data_inf_cb;
1307

    
1308
}
1309

    
1310
void mlRegisterSetMonitoringHeaderDataCb(set_monitoring_header_data_cb monitoring_header_data_cb){
1311

    
1312
        if (monitoring_header_data_cb == NULL)
1313
                error("ML: Register set_monitoring_header_data_cb : NULL ptr  \n");
1314
        else
1315
        set_Monitoring_header_data_cb = monitoring_header_data_cb;
1316

    
1317
}
1318

    
1319
void mlSetRecvTimeout(struct timeval timeout_value){
1320

    
1321
        recv_timeout = timeout_value;
1322

    
1323
}
1324

    
1325
int mlGetStandardTTL(socketID_handle socketID,uint8_t *ttl){
1326

    
1327
        return getTTL(socketfd, ttl);
1328

    
1329
}
1330

    
1331
socketID_handle mlGetLocalSocketID(int *errorstatus){
1332

    
1333
        if (NAT_traversal == false) {
1334
                *errorstatus = 2;
1335
                return NULL;
1336
        }
1337

    
1338
        *errorstatus = 0;
1339
        return &local_socketID;
1340

    
1341
}
1342

    
1343

    
1344
/**************************** END of MONL functions *************************/
1345

    
1346
/**************************** GENERAL functions *************************/
1347

    
1348
void mlRegisterRecvConnectionCb(receive_connection_cb recv_conn_cb){
1349

    
1350
        if (recv_conn_cb == NULL)
1351
                error("ML: Register receive_connection_cb: NULL ptr  \n");
1352
        else
1353
                receive_Connection_cb = recv_conn_cb;
1354

    
1355
}
1356

    
1357
void mlRegisterErrorConnectionCb(connection_failed_cb conn_failed){
1358

    
1359
        if (conn_failed == NULL)
1360
                error("ML: Register connection_failed_cb: NULL ptr  \n");
1361
        else
1362
        failed_Connection_cb = conn_failed;
1363

    
1364
}
1365

    
1366
void mlRegisterRecvDataCb(receive_data_cb data_cb,unsigned char msgtype){
1367

    
1368
    if (msgtype > 126) {
1369

    
1370
            error
1371
            ("ML: Could not register recv_data callback. Msgtype is greater then 126 \n");
1372

    
1373
    }
1374

    
1375
    if (data_cb == NULL) {
1376

    
1377
            error("ML: Register receive data callback: NUll ptr \n ");
1378

    
1379
    } else {
1380

    
1381
        recvcbbuf[msgtype] = data_cb;
1382

    
1383
    }
1384

    
1385
}
1386

    
1387
void mlCloseSocket(socketID_handle socketID){
1388

    
1389
        free(socketID);
1390

    
1391
}
1392

    
1393
void keepalive_fn(evutil_socket_t fd, short what, void *arg) {
1394
        socketID_handle peer = arg;
1395

    
1396
        int con_id = mlConnectionExist(peer, false);
1397
        if (con_id < 0 || connectbuf[con_id]->defaultSendParams.keepalive <= 0) {
1398
                /* Connection fell from under us or keepalive was disabled */
1399
                free(arg);
1400
                return;
1401
        }
1402

    
1403
        /* do what we gotta do */
1404
        if ( connectbuf[con_id]->status == READY) {
1405
                char keepaliveMsg[32] = "";
1406
                sprintf(keepaliveMsg, "KEEPALIVE %d", connectbuf[con_id]->keepalive_seq++);
1407
                send_msg(con_id, MSG_TYPE_ML_KEEPALIVE, keepaliveMsg, 1 + strlen(keepaliveMsg), false, 
1408
                        &(connectbuf[con_id]->defaultSendParams));
1409
        }
1410

    
1411
        /* re-schedule */
1412
        struct timeval t = { 0,0 };
1413
        t.tv_sec = connectbuf[con_id]->defaultSendParams.keepalive;
1414
        if (connectbuf[con_id]->defaultSendParams.keepalive) 
1415
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1416
}
1417

    
1418
void setupKeepalive(int conn_id) {
1419
        /* Save the peer's address for us */
1420
        socketID_handle peer = malloc(sizeof(socket_ID));
1421
        memcpy(peer, &connectbuf[conn_id]->external_socketID, sizeof(socket_ID));
1422

    
1423
        struct timeval t = { 0,0 };
1424
        t.tv_sec = connectbuf[conn_id]->defaultSendParams.keepalive;
1425

    
1426
        if (connectbuf[conn_id]->defaultSendParams.keepalive) 
1427
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1428
}
1429

    
1430
/* connection functions */
1431
int mlOpenConnection(socketID_handle external_socketID,receive_connection_cb connection_cb,void *arg, const send_params defaultSendParams){
1432

    
1433
        int con_id;
1434
        if (external_socketID == NULL) {
1435
                error("ML: cannot open connection: one of the socketIDs is NULL\n");
1436
                return -1;
1437
        }
1438
        if (NAT_traversal == false) {
1439
                error("ML: cannot open connection: NAT traversal for socketID still in progress\n");
1440
                return -1;
1441
        }
1442
        if (connection_cb == NULL) {
1443
                error("ML: cannot open connection: connection_cb is NULL\n");
1444
                return -1;
1445
        }
1446

    
1447
        // check if that connection already exist
1448

    
1449
        con_id = mlConnectionExist(external_socketID, false);
1450
        if (con_id >= 0) {
1451
                // overwrite defaultSendParams
1452
                bool newKeepalive = 
1453
                        connectbuf[con_id]->defaultSendParams.keepalive == 0 && defaultSendParams.keepalive != 0;
1454
                connectbuf[con_id]->defaultSendParams = defaultSendParams;
1455
                if (newKeepalive) setupKeepalive(con_id);
1456
                // if so check if it is ready to use
1457
                if (connectbuf[con_id]->status == READY) {
1458
                                // if so use the callback immediately
1459
                                (connection_cb) (con_id, arg);
1460

    
1461
                // otherwise just write the connection cb and the arg pointer
1462
                // into the connection struct
1463
                } else {
1464
                        struct receive_connection_cb_list *temp;
1465
                        temp = malloc(sizeof(struct receive_connection_cb_list));
1466
                        temp->next = NULL;
1467
                        temp->connection_cb = connection_cb;
1468
                        temp->arg = arg;
1469
                        if(connectbuf[con_id]->connection_last != NULL) {
1470
                                connectbuf[con_id]->connection_last->next = temp;
1471
                                connectbuf[con_id]->connection_last = temp;
1472
                        } else
1473
                                connectbuf[con_id]->connection_last = connectbuf[con_id]->connection_head = temp;
1474
                }
1475
                return con_id;
1476
        }
1477
        // make entry in connection_establishment array
1478
        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
1479
                if (connectbuf[con_id] == NULL) {
1480
                        connectbuf[con_id] = (connect_data *) malloc(sizeof(connect_data));
1481
                        memset(connectbuf[con_id],0,sizeof(connect_data));
1482
                        connectbuf[con_id]->starttime = time(NULL);
1483
                        memcpy(&connectbuf[con_id]->external_socketID, external_socketID, sizeof(socket_ID));
1484
                        connectbuf[con_id]->pmtusize = DSLSLIM;
1485
                        connectbuf[con_id]->timeout_event = NULL;
1486
                        connectbuf[con_id]->status = INVITE;
1487
                        connectbuf[con_id]->seqnr = 0;
1488
                        connectbuf[con_id]->internal_connect = !compare_external_address_socketIDs(external_socketID, &local_socketID);
1489
                        connectbuf[con_id]->connectionID = con_id;
1490

    
1491
                        connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
1492
                        connectbuf[con_id]->connection_last->next = NULL;
1493
                        connectbuf[con_id]->connection_last->connection_cb = connection_cb;
1494
                        connectbuf[con_id]->connection_last->arg = arg;
1495
                        connectbuf[con_id]->external_connectionID = -1;
1496

    
1497
                        connectbuf[con_id]->defaultSendParams = defaultSendParams;
1498
                        if (defaultSendParams.keepalive) setupKeepalive(con_id);
1499
                        break;
1500
                }
1501
        } //end of for
1502

    
1503
        if (con_id == CONNECTBUFSIZE) {
1504
                error("ML: Could not open connection: connection buffer full\n");
1505
                return -1;
1506
        }
1507

    
1508
        // create and send a connection message
1509
        send_conn_msg_with_pmtu_discovery(con_id, connectbuf[con_id]->pmtusize, INVITE);
1510

    
1511
        return con_id;
1512

    
1513
}
1514

    
1515
void mlCloseConnection(const int connectionID){
1516

    
1517
        // remove it from the connection array
1518
        if(connectbuf[connectionID]) {
1519
                if(connectbuf[connectionID]->ctrl_msg_buf) {
1520
                        free(connectbuf[connectionID]->ctrl_msg_buf);
1521
                }
1522
                // remove related events
1523
                if (connectbuf[connectionID]->timeout_event) {
1524
                        event_del(connectbuf[connectionID]->timeout_event);
1525
                        event_free(connectbuf[connectionID]->timeout_event);
1526
                        connectbuf[connectionID]->timeout_event = NULL;
1527
                }
1528
                free(connectbuf[connectionID]);
1529
                connectbuf[connectionID] = NULL;
1530
        }
1531

    
1532
}
1533

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

    
1536
        if (connectionID < 0) {
1537
                error("ML: send data failed: connectionID does not exist\n");
1538
                return;
1539
        }
1540

    
1541
        if (connectbuf[connectionID] == NULL) {
1542
                error("ML: send data failed: connectionID does not exist\n");
1543
                return;
1544
        }
1545
        if (connectbuf[connectionID]->status != READY) {
1546
            error("ML: send data failed: connection is not active\n");
1547
            return;
1548
        }
1549

    
1550
        if (sParams == NULL) {
1551
                sParams = &(connectbuf[connectionID]->defaultSendParams);
1552
        }
1553

    
1554
        send_msg(connectionID, msgtype, sendbuf, bufsize, false, sParams);
1555

    
1556
}
1557

    
1558
/* transmit data functions  */
1559
int mlSendAllData(const int connectionID,send_all_data_container *container,int nr_entries,unsigned char msgtype,send_params *sParams){
1560

    
1561
    if (nr_entries < 1 || nr_entries > 5) {
1562

    
1563
        error
1564
            ("ML : sendALlData : nr_enties is not between 1 and 5 \n ");
1565
        return 0;
1566

    
1567
    } else {
1568

    
1569
        if (nr_entries == 1) {
1570

    
1571
                mlSendData(connectionID, container->buffer_1,
1572
                      container->length_1, msgtype, sParams);
1573

    
1574
            return 1;
1575

    
1576
        } else if (nr_entries == 2) {
1577

    
1578
            int buflen = container->length_1 + container->length_2;
1579
            char buf[buflen];
1580
            memcpy(buf, container->buffer_1, container->length_1);
1581
            memcpy(&buf[container->length_1], container->buffer_2,
1582
                   container->length_2);
1583
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1584

    
1585
            return 1;
1586

    
1587
        } else if (nr_entries == 3) {
1588

    
1589
            int buflen =
1590
                container->length_1 + container->length_2 +
1591
                container->length_3;
1592
            char buf[buflen];
1593
            memcpy(buf, container->buffer_1, container->length_1);
1594
            memcpy(&buf[container->length_1], container->buffer_2,
1595
                   container->length_2);
1596
            memcpy(&buf[container->length_2], container->buffer_3,
1597
                   container->length_3);
1598
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1599

    
1600

    
1601
            return 1;
1602

    
1603
        } else if (nr_entries == 4) {
1604

    
1605
            int buflen =
1606
                container->length_1 + container->length_2 +
1607
                container->length_3 + container->length_4;
1608
            char buf[buflen];
1609
            memcpy(buf, container->buffer_1, container->length_1);
1610
            memcpy(&buf[container->length_1], container->buffer_2,
1611
                   container->length_2);
1612
            memcpy(&buf[container->length_2], container->buffer_3,
1613
                   container->length_3);
1614
            memcpy(&buf[container->length_3], container->buffer_4,
1615
                   container->length_4);
1616
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1617

    
1618
            return 1;
1619

    
1620
        } else {
1621

    
1622
            int buflen =
1623
                container->length_1 + container->length_2 +
1624
                container->length_3 + container->length_4 +
1625
                container->length_5;
1626
            char buf[buflen];
1627
            memcpy(buf, container->buffer_1, container->length_1);
1628
            memcpy(&buf[container->length_1], container->buffer_2,
1629
                   container->length_2);
1630
            memcpy(&buf[container->length_2], container->buffer_3,
1631
                   container->length_3);
1632
            memcpy(&buf[container->length_3], container->buffer_4,
1633
                   container->length_4);
1634
            memcpy(&buf[container->length_4], container->buffer_5,
1635
                   container->length_5);
1636
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1637

    
1638
            return 1;
1639
        }
1640

    
1641
    }
1642

    
1643
}
1644

    
1645
int mlRecvData(const int connectionID,char *recvbuf,int *bufsize,recv_params *rParams){
1646

    
1647
        //TODO yet to be converted
1648
        return 0;
1649
#if 0
1650
        if (rParams == NULL) {
1651
                error("ML: recv_data failed: recv_params is a NULL ptr\n");
1652
                return 0;
1653
    } else {
1654

1655
        info("ML: recv data called \n");
1656

1657
        int i = 0;
1658
        int returnValue = 0;
1659
        double timeout = (double) recv_timeout.tv_sec;
1660
        time_t endtime = time(NULL);
1661

1662
        for (i = 0; i < RECVDATABUFSIZE; i++) {
1663

1664
            if (recvdatabuf[i] != NULL) {
1665

1666
                if (recvdatabuf[i]->connectionID == connectionID) {
1667

1668
                    info("ML: recv data has entry  \n");
1669

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

1672
                    // check if the specified connection has data and it
1673
                    // is complete
1674
                    // check the data seqnr
1675
                    // if(connectionID == recvdatabuf[i]->connectionID &&
1676
                    // 1 == recvdatabuf[i]->status){
1677

1678
                    if (1 == recvdatabuf[i]->status) {
1679

1680
                        // info("transmissionHandler: recv_data set is
1681
                        // complete \n" );
1682

1683
                        // debug("debud \n");
1684

1685
                        // exchange the pointers
1686
                        int buffersize = 0;
1687
                        buffersize = recvdatabuf[i]->bufsize;
1688
                        *bufsize = buffersize;
1689
                        // recvbuf = recvdatabuf[i]->recvbuf;
1690

1691
                        // info("buffersize %d \n",buffersize);
1692
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1693
                               buffersize);
1694
                        // debug(" recvbuf %s \n",recvbuf );
1695

1696
//                         double nrMissFrags =
1697
//                             (double) recvdatabuf[i]->nrFragments /
1698
//                             (double) recvdatabuf[i]->recvFragments;
1699
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
1700

1701
//                        rParams->nrMissingFragments = nrMissingFragments;
1702
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
1703
                        rParams->msgtype = recvdatabuf[i]->msgtype;
1704
                        rParams->connectionID =
1705
                            recvdatabuf[i]->connectionID;
1706

1707
                        // break from the loop
1708
                        // debug(" recvbuf %s \n ",recvbuf);
1709

1710
                        // double nrMissFrags =
1711
                        // (double)recvdatabuf[i]->nrFragments /
1712
                        // (double)recvdatabuf[i]->recvFragments;
1713
                        // int nrMissingFragments =
1714
                        // (int)ceil(nrMissFrags);
1715

1716
                        if(get_Recv_data_inf_cb != NULL) {
1717
                                mon_data_inf recv_data_inf;
1718

1719
                                recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1720
                                recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1721
                                recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1722
                                recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1723
//                                 recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1724
//                                 recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1725
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
1726
                                recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1727
                                recv_data_inf.nrMissingFragments = nrMissingFragments;
1728
                                recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1729
                                recv_data_inf.priority = false;
1730
                                recv_data_inf.padding = false;
1731
                                recv_data_inf.confirmation = false;
1732
                                recv_data_inf.reliable = false;
1733

1734
                                // send data recv callback to monitoring module
1735

1736
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1737
                        }
1738

1739

1740
                        // free the allocated memory
1741
                        free(recvdatabuf[i]);
1742
                        recvdatabuf[i] = NULL;
1743

1744
                        returnValue = 1;
1745
                        break;
1746

1747
                    }
1748

1749
                    if (recvdatabuf[i] != NULL) {
1750

1751
                        if (timepass > timeout) {
1752

1753
                            info("ML: recv_data timeout called  \n");
1754

1755
                            // some data about the missing chunks should
1756
                            // be added here
1757
                            // exchange the pointers
1758
                            int buffersize = 0;
1759
                            buffersize = recvdatabuf[i]->bufsize;
1760
                            *bufsize = buffersize;
1761
                            // recvbuf = recvdatabuf[i]->recvbuf;
1762

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

1769
                            // debug(" recvbuf %s \n",recvbuf );
1770

1771
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1772
                                   buffersize);
1773

1774
                            rParams->nrMissingFragments =
1775
                                nrMissingFragments;
1776
                            rParams->nrFragments =
1777
                                recvdatabuf[i]->nrFragments;
1778
                            rParams->msgtype = recvdatabuf[i]->msgtype;
1779
                            rParams->connectionID =
1780
                                recvdatabuf[i]->connectionID;
1781

1782
                                if(get_Recv_data_inf_cb != NULL) {
1783
                                        mon_data_inf recv_data_inf;
1784

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

1800
                                        // send data recv callback to monitoring module
1801

1802
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1803
                                }
1804

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

1809
                            returnValue = 1;
1810
                            break;
1811

1812
                        }
1813
                    }
1814

1815
                }
1816

1817
            }
1818
            // debug("2 recvbuf %s \n ",recvbuf);
1819
        }
1820
        return returnValue;
1821
    }
1822
#endif
1823

    
1824
}
1825

    
1826
int mlSocketIDToString(socketID_handle socketID,char* socketID_string, size_t len){
1827

    
1828
        char internal_addr[INET_ADDRSTRLEN];
1829
        char external_addr[INET_ADDRSTRLEN];
1830
        inet_ntop(AF_INET, &(socketID->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1831
        inet_ntop(AF_INET, &(socketID->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1832

    
1833
        snprintf(socketID_string,len,"%s:%d-%s:%d", internal_addr, ntohs(socketID->internal_addr.udpaddr.sin_port),
1834
                external_addr,        ntohs(socketID->external_addr.udpaddr.sin_port));
1835
        return 0;
1836

    
1837
}
1838

    
1839
int mlStringToSocketID(const char* socketID_string, socketID_handle socketID){
1840

    
1841
        //@TODO add checks against malformed string
1842
        char external_addr[INET_ADDRSTRLEN];
1843
        int external_port;
1844
        char internal_addr[INET_ADDRSTRLEN];
1845
        int internal_port;
1846

    
1847
        char *pch;
1848
        char *s = strdup(socketID_string);
1849

    
1850
        //replace ':' with a blank
1851
        pch=strchr(s,':');
1852
        while (pch!=NULL){
1853
                                *pch = ' ';
1854
                pch=strchr(pch+1,':');
1855
        }
1856
        pch=strchr(s,'-');
1857
        if(pch) *pch = ' ';
1858

    
1859
        sscanf(s,"%s %d %s %d", internal_addr, &internal_port,
1860
                external_addr, &external_port);
1861

    
1862
        if(inet_pton(AF_INET, internal_addr, &(socketID->internal_addr.udpaddr.sin_addr)) == 0)
1863
                return EINVAL;
1864
        socketID->internal_addr.udpaddr.sin_family = AF_INET;
1865
        socketID->internal_addr.udpaddr.sin_port = htons(internal_port);
1866

    
1867

    
1868
        if(inet_pton(AF_INET, external_addr, &(socketID->external_addr.udpaddr.sin_addr)) ==0)
1869
                return EINVAL;
1870
        socketID->external_addr.udpaddr.sin_family = AF_INET;
1871
        socketID->external_addr.udpaddr.sin_port = htons(external_port);
1872

    
1873
        free(s);
1874
        return 0;
1875

    
1876
}
1877

    
1878
int mlGetConnectionStatus(int connectionID){
1879

    
1880
        if(connectbuf[connectionID])
1881
                return connectbuf[connectionID]->status == READY;
1882
        return -1;
1883
    
1884
}
1885

    
1886

    
1887
int mlConnectionExist(socketID_handle socketID, bool ready){
1888

    
1889
    /*
1890
     * check if another connection for the external connectionID exist
1891
     * that was established \ within the last 2 seconds
1892
     */
1893
        int i;
1894
        for (i = 0; i < CONNECTBUFSIZE; i++)
1895
                if (connectbuf[i] != NULL)
1896
                        if (mlCompareSocketIDs(&(connectbuf[i]->external_socketID), socketID) == 0) {
1897
                                if (ready) return (connectbuf[i]->status == READY ? i : -1);;
1898
                                return i;
1899
                                }
1900

    
1901
    return -1;
1902

    
1903
}
1904

    
1905
//Added by Robert Birke as comodity functions
1906

    
1907
//int mlPrintSocketID(socketID_handle socketID) {
1908
//        char str[SOCKETID_STRING_SIZE];
1909
//        mlSocketIDToString(socketID, str, sizeof(str));
1910
//        printf(stderr,"int->%s<-ext\n",str);
1911
//}
1912

    
1913
/*
1914
 * hash code of a socketID
1915
 * TODO might think of a better way
1916
 */
1917
int mlHashSocketID(socketID_handle sock) {
1918
    return sock->internal_addr.udpaddr.sin_port +
1919
                          sock->external_addr.udpaddr.sin_port;
1920
}
1921

    
1922
int mlCompareSocketIDs(socketID_handle sock1, socketID_handle sock2) {
1923
        /*
1924
        * compare internal addr
1925
        */
1926
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr !=
1927
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
1928
                        return 1;
1929

    
1930
        if (sock1->internal_addr.udpaddr.sin_port !=
1931
                 sock2->internal_addr.udpaddr.sin_port)
1932
                        return 1;
1933

    
1934
        /*
1935
        * compare external addr
1936
        */
1937
        if (sock1->external_addr.udpaddr.sin_addr.s_addr !=
1938
            sock2->external_addr.udpaddr.sin_addr.s_addr)
1939
                        return 1;
1940

    
1941
        if (sock1->external_addr.udpaddr.sin_port !=
1942
                 sock2->external_addr.udpaddr.sin_port)
1943
                        return 1;
1944

    
1945
        return 0;
1946
}
1947

    
1948
int mlCompareSocketIDsByPort(socketID_handle sock1, socketID_handle sock2)
1949
{ 
1950
        if (sock1->internal_addr.udpaddr.sin_port !=
1951
                 sock2->internal_addr.udpaddr.sin_port)
1952
                        return 1;
1953

    
1954
        if (sock1->external_addr.udpaddr.sin_port !=
1955
                 sock2->external_addr.udpaddr.sin_port)
1956
                        return 1;
1957
        return 0;
1958
}
1959

    
1960
int mlGetPathMTU(int ConnectionId) {
1961
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
1962
                return -1;
1963
        if (connectbuf[ConnectionId] != NULL)
1964
                return connectbuf[ConnectionId]->pmtusize;
1965
        return -1;
1966
}
1967

    
1968
/**************************** END of GENERAL functions *************************/
1969

    
1970
/**************************** NAT functions *************************/
1971

    
1972
/* setter  */
1973
void mlSetStunServer(const int port,const char *ipaddr){
1974

    
1975
        stun_server.sin_family = AF_INET;
1976
        if (ipaddr == NULL)
1977
                stun_server.sin_addr.s_addr = htonl(INADDR_ANY);
1978
        else
1979
                stun_server.sin_addr.s_addr = resolve(ipaddr);
1980
        stun_server.sin_port = htons(port);
1981

    
1982
}
1983

    
1984
int mlGetExternalIP(char* external_addr){
1985

    
1986
        socketaddrgen udpgen;
1987
        struct sockaddr_in udpaddr;
1988

    
1989
        udpgen = local_socketID.external_addr;
1990
        udpaddr = udpgen.udpaddr;
1991

    
1992
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
1993
                        INET_ADDRSTRLEN);
1994

    
1995
        if (external_addr == NULL) {
1996

    
1997
        return -1;
1998

    
1999
        } else {
2000

    
2001
        return 0;
2002

    
2003
        }
2004

    
2005
}
2006

    
2007
/**************************** END of NAT functions *************************/