Statistics
| Branch: | Revision:

ml / ml.c @ ea1436ee

History | View | Annotate | Download (58.7 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
/*
183
 * convert a socketID to a string. It uses a static buffer, so either strdup is needed, or the string will get lost!
184
 */
185
const char *conid_to_string(int con_id)
186
{
187
        static char s[INET_ADDRSTRLEN+1+5+1+INET_ADDRSTRLEN+1+5+1];
188
        mlSocketIDToString(&connectbuf[con_id]->external_socketID, s, sizeof(s));
189
        return s;
190
}
191

    
192
void register_recv_localsocketID_cb(receive_localsocketID_cb local_socketID_cb)
193
{
194
        if (local_socketID_cb == NULL)
195
                error("ML : Register receive_localsocketID_cb: NULL ptr \n");
196
        else
197
        receive_SocketID_cb = local_socketID_cb;
198
}
199

    
200

    
201
//void keep_connection_alive(const int connectionID)
202
//{
203
//
204
//    // to be done with the NAT traversal
205
//    // send a message over the wire
206
//    printf("\n");
207
//
208
//}
209

    
210
void unsetStunServer()
211
{
212
        stun_server.sin_addr.s_addr = INADDR_NONE;
213
}
214

    
215
bool isStunDefined()
216
{
217
        return stun_server.sin_addr.s_addr != INADDR_NONE;
218
}
219

    
220
void send_msg(int con_id, int msg_type, char* msg, int msg_len, bool truncable, send_params * sParams) {
221
        socketaddrgen udpgen;
222
        bool retry;
223
        int pkt_len, offset;
224
        struct iovec iov[4];
225

    
226
        char h_pkt[MON_HEADER_SPACE];
227
        char h_data[MON_HEADER_SPACE];
228

    
229
        struct msg_header msg_h;
230

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

    
233
        iov[0].iov_base = &msg_h;
234
        iov[0].iov_len = MSG_HEADER_SIZE;
235

    
236
        msg_h.local_con_id = con_id;
237
        msg_h.remote_con_id = connectbuf[con_id]->external_connectionID;
238
        msg_h.msg_type = msg_type;
239
        msg_h.msg_seq_num = connectbuf[con_id]->seqnr++;
240

    
241

    
242
        iov[1].iov_len = iov[2].iov_len = 0;
243
        iov[1].iov_base = h_pkt;
244
        iov[2].iov_base = h_data;
245

    
246

    
247
        if (connectbuf[con_id]->internal_connect)
248
                udpgen = connectbuf[con_id]->external_socketID.internal_addr;
249
        else
250
                udpgen = connectbuf[con_id]->external_socketID.external_addr;
251

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

    
261
                if(get_Send_data_inf_cb != NULL && iov[2].iov_len != 0) {
262
                        mon_data_inf sd_data_inf;
263

    
264
                        sd_data_inf.remote_socketID = &(connectbuf[con_id]->external_socketID);
265
                        sd_data_inf.buffer = msg;
266
                        sd_data_inf.bufSize = msg_len;
267
                        sd_data_inf.msgtype = msg_type;
268
                        sd_data_inf.monitoringDataHeader = iov[2].iov_base;
269
                        sd_data_inf.monitoringDataHeaderLen = iov[2].iov_len;
270
                        sd_data_inf.priority = sParams->priority;
271
                        sd_data_inf.padding = sParams->padding;
272
                        sd_data_inf.confirmation = sParams->confirmation;
273
                        sd_data_inf.reliable = sParams->reliable;
274
                        memset(&sd_data_inf.arrival_time, 0, sizeof(struct timeval));
275

    
276
                        (get_Send_data_inf_cb) ((void *) &sd_data_inf);
277
                }
278

    
279
                do {
280
                        if(set_Monitoring_header_pkt_cb != NULL) {
281
                                iov[1].iov_len = (set_Monitoring_header_pkt_cb) (&(connectbuf[con_id]->external_socketID), msg_type);
282
                        }
283
                        pkt_len = min(connectbuf[con_id]->pmtusize - iov[2].iov_len - iov[1].iov_len - iov[0].iov_len, msg_len - offset) ;
284

    
285
                        iov[3].iov_len = pkt_len;
286
                        iov[3].iov_base = msg + offset;
287

    
288
                        //fill header
289
                        msg_h.len_mon_packet_hdr = iov[1].iov_len;
290
                        msg_h.offset = offset;
291
                        msg_h.msg_length = truncable ? pkt_len : msg_len;
292

    
293
                        //monitoring layer hook
294
                        if(get_Send_pkt_inf_cb != NULL && iov[1].iov_len) {
295
                                mon_pkt_inf pkt_info;
296

    
297
                                pkt_info.remote_socketID = &(connectbuf[con_id]->external_socketID);
298
                                pkt_info.buffer = msg + offset;
299
                                pkt_info.bufSize = pkt_len;
300
                                pkt_info.msgtype = msg_type;
301
                                pkt_info.dataID = connectbuf[con_id]->seqnr;
302
                                pkt_info.offset = offset;
303
                                pkt_info.datasize = msg_len;
304
                                pkt_info.monitoringHeaderLen = iov[1].iov_len;
305
                                pkt_info.monitoringHeader = iov[1].iov_base;
306
                                pkt_info.ttl = -1;
307
                                memset(&(pkt_info.arrival_time),0,sizeof(struct timeval));
308

    
309
                                (get_Send_pkt_inf_cb) ((void *) &pkt_info);
310
                        }
311

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

    
339
void pmtu_timeout_cb(int fd, short event, void *arg);
340

    
341
void reschedule_conn_msg(int con_id)
342
{
343
        if (connectbuf[con_id]->timeout_event) {
344
                /* delete old timout */        
345
                event_del(connectbuf[con_id]->timeout_event);
346
                event_free(connectbuf[con_id]->timeout_event);
347
        }
348
        connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
349
        evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
350
}
351

    
352
void send_conn_msg(int con_id, int buf_size, int command_type)
353
{
354
        if (buf_size < sizeof(struct conn_msg)) {
355
                error("ML: requested connection message size is too small\n");
356
                return;
357
        }
358

    
359
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
360
                connectbuf[con_id]->ctrl_msg_buf = malloc(buf_size);
361
                memset(connectbuf[con_id]->ctrl_msg_buf, 0, buf_size);
362
        }
363

    
364
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
365
                error("ML: can not allocate memory for connection message\n");
366
                return;
367
        }
368

    
369
        struct conn_msg *msg_header = (struct conn_msg*) connectbuf[con_id]->ctrl_msg_buf;
370

    
371
        msg_header->comand_type = command_type;
372
        msg_header->pmtu_size = connectbuf[con_id]->pmtusize;
373

    
374
        memcpy(&(msg_header->sock_id), loc_socketID, sizeof(socket_ID));
375

    
376
        send_msg(con_id, ML_CON_MSG, connectbuf[con_id]->ctrl_msg_buf, buf_size, true, &(connectbuf[con_id]->defaultSendParams));
377
}
378

    
379
void send_conn_msg_with_pmtu_discovery(int con_id, int buf_size, int command_type)
380
{
381
        struct timeval tout = PMTU_TIMEOUT;
382
        connectbuf[con_id]->timeout_value = tout;
383
        connectbuf[con_id]->trials = 1;
384
        send_conn_msg(con_id, buf_size, command_type);
385
        reschedule_conn_msg(con_id);
386
}
387

    
388
void resend_conn_msg(int con_id)
389
{
390
        connectbuf[con_id]->trials++;
391
        send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
392
        reschedule_conn_msg(con_id);
393
}
394

    
395
void
396
recv_conn_msg(struct msg_header *msg_h, char *msgbuf, int msg_size)
397
{
398
        struct conn_msg *con_msg;
399
        int free_con_id, con_id;
400

    
401
        time_t now = time(NULL);
402
        double timediff = 0.0;
403
        char str[1000];
404

    
405
        // Monitoring layer hook
406
        if(get_Recv_data_inf_cb != NULL && msg_h->len_mon_data_hdr != 0) {
407
                // update pointer to the real data
408
                msgbuf += msg_h->len_mon_data_hdr;
409
                msg_size -= msg_h->len_mon_data_hdr;
410
                con_msg = (struct conn_msg *)msgbuf;
411

    
412
                mon_data_inf recv_data_inf;
413
                recv_data_inf.remote_socketID = &(con_msg->sock_id);
414
                recv_data_inf.buffer = msgbuf;
415
                recv_data_inf.bufSize = msg_size;
416
                recv_data_inf.msgtype = msg_h->msg_type;
417
                recv_data_inf.monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
418
                recv_data_inf.monitoringDataHeader = msg_h->len_mon_data_hdr ? msgbuf : NULL;
419
                gettimeofday(&recv_data_inf.arrival_time, NULL);
420
                recv_data_inf.firstPacketArrived = true;
421
                recv_data_inf.recvFragments = 1;
422
                recv_data_inf.priority = false;
423
                recv_data_inf.padding = false;
424
                recv_data_inf.confirmation = false;
425
                recv_data_inf.reliable = false;
426

    
427
                // send data recv callback to monitoring module
428
                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
429
        } else {
430
                con_msg = (struct conn_msg *) msgbuf;
431
        }
432

    
433
        //decode sock_id for debug messages
434
        mlSocketIDToString(&con_msg->sock_id,str,999);
435

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

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

    
484
                        //if(connectbuf[con_id]->status <= CONNECT) { //TODO: anwer anyway. Why the outher would invite otherwise?
485
                                //update status and send back answer
486
                                connectbuf[con_id]->status = CONNECT;
487
                                send_conn_msg_with_pmtu_discovery(con_id, con_msg->pmtu_size, CONNECT);
488
                        //}
489
                        break;
490
                case CONNECT:
491
                        info("ML: received CONNECT from %s (size:%d)\n", str, msg_size);
492

    
493
                        if(msg_h->remote_con_id != -1 && connectbuf[msg_h->remote_con_id] == NULL) {
494
                                error("ML: received CONNECT for inexistent connection rconID:%d\n",msg_h->remote_con_id);
495
                                return;
496
                        }
497

    
498
                        /*
499
                        * check if the connection status is not already 1 or 2
500
                        */
501
                        if (connectbuf[msg_h->remote_con_id]->status == INVITE) {
502
                                // set the external connectionID
503
                                connectbuf[msg_h->remote_con_id]->external_connectionID = msg_h->local_con_id;
504
                                // change status con_msg the connection_data
505
                                connectbuf[msg_h->remote_con_id]->status = READY;
506
                                // change pmtusize in the connection_data: not needed. receiving a CONNECT means our INVITE went through. So why change pmtu?
507
                                //connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
508

    
509
                                // send the READY
510
                                send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
511

    
512
                                if (receive_Connection_cb != NULL)
513
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
514

    
515
                                // call all registered callbacks
516
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
517
                                        struct receive_connection_cb_list *temp;
518
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
519
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
520
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
521
                                        free(temp);
522
                                }
523
                                connectbuf[msg_h->remote_con_id]->connection_head =
524
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
525
                        } else {
526
                                // send the READY
527
                                send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
528
                        }
529

    
530
                        debug("ML: active connection established\n");
531
                        break;
532

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

    
552
                                if (receive_Connection_cb != NULL)
553
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
554

    
555
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
556
                                        struct receive_connection_cb_list *temp;
557
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
558
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
559
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
560
                                        free(temp);
561
                                }
562
                                connectbuf[msg_h->remote_con_id]->connection_head =
563
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
564
                                debug("ML: passive connection established\n");
565
                        }
566
                        break;
567
        }
568
}
569

    
570
void recv_stun_msg(char *msgbuf, int recvSize)
571
{
572
        /*
573
        * create empty stun message struct
574
        */
575
        StunMessage resp;
576
        memset(&resp, 0, sizeof(StunMessage));
577
        /*
578
        * parse the message
579
        */
580
        int returnValue = 0;
581
        returnValue = recv_stun_message(msgbuf, recvSize, &resp);
582

    
583
        if (returnValue == 0) {
584
                /*
585
                * read the reflexive Address into the local_socketID
586
                */
587
                struct sockaddr_in reflexiveAddr;
588
                reflexiveAddr.sin_family = AF_INET;
589
                reflexiveAddr.sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
590
                reflexiveAddr.sin_port = htons(resp.mappedAddress.ipv4.port);
591
                socketaddrgen reflexiveAddres;
592
                reflexiveAddres.udpaddr = reflexiveAddr;
593
                local_socketID.external_addr = reflexiveAddres;
594
                NAT_traversal = true;
595
                // callback to the upper layer indicating that the socketID is now
596
                // ready to use
597
                (receive_SocketID_cb) (&local_socketID, 0);
598
        }
599
}
600

    
601
//done
602
void recv_timeout_cb(int fd, short event, void *arg)
603
{
604
        int recv_id = (long) arg;
605
        debug("ML: recv_timeout_cb called. Timeout for id:%d\n",recv_id);
606

    
607
        if (recvdatabuf[recv_id] == NULL) {
608
                return;
609
        }
610

    
611

    
612
/*        if(recvdatabuf[recv_id]->status == ACTIVE) {
613
                //TODO make timeout at least a DEFINE
614
                struct timeval timeout = { 4, 0 };
615
                recvdatabuf[recv_id]->status = INACTIVE;
616
                event_base_once(base, -1, EV_TIMEOUT, recv_timeout_cb,
617
                        arg, &timeout);
618
                return;
619
        }
620
*/
621

    
622
        if(recvdatabuf[recv_id]->status == ACTIVE) {
623
                // Monitoring layer hook
624
                if(get_Recv_data_inf_cb != NULL) {
625
                        mon_data_inf recv_data_inf;
626

    
627
                        recv_data_inf.remote_socketID =
628
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
629
                        recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
630
                        recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
631
                        recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
632
                        recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
633
                        recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
634
                                recvdatabuf[recv_id]->recvbuf : NULL;
635
                        gettimeofday(&recv_data_inf.arrival_time, NULL);
636
                        recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
637
                        recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
638
                        recv_data_inf.priority = false;
639
                        recv_data_inf.padding = false;
640
                        recv_data_inf.confirmation = false;
641
                        recv_data_inf.reliable = false;
642

    
643
                        // send data recv callback to monitoring module
644

    
645
                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
646
                }
647

    
648
                // Get the right callback
649
                receive_data_cb receive_data_callback = recvcbbuf[recvdatabuf[recv_id]->msgtype];
650

    
651
                recv_params rParams;
652

    
653
                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
654
                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
655
                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
656
                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
657
                rParams.remote_socketID =
658
                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
659
                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
660

    
661
                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
662
                        recvdatabuf[recv_id]->msgtype, &rParams);
663

    
664
                //clean up
665
                free(recvdatabuf[recv_id]->recvbuf);
666
                free(recvdatabuf[recv_id]);
667
                recvdatabuf[recv_id] = NULL;
668
        }
669
}
670

    
671
// process a single recv data message
672
void recv_data_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
673
{
674
        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);
675

    
676
        int recv_id, free_recv_id = -1;
677

    
678
        if(connectbuf[msg_h->remote_con_id] == NULL) {
679
                debug("ML: Received a message not related to any opened connection!\n");
680
                return;
681
        }
682

    
683
        // check if a recv_data exist and enter data
684
        for (recv_id = 0; recv_id < RECVDATABUFSIZE; recv_id++)
685
                if (recvdatabuf[recv_id] != NULL) {
686
                        if (msg_h->remote_con_id == recvdatabuf[recv_id]->connectionID &&
687
                                        msg_h->msg_seq_num == recvdatabuf[recv_id]->seqnr)
688
                                                break;
689
                } else
690
                        if(free_recv_id == -1)
691
                                free_recv_id = recv_id;
692

    
693

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

    
713
                // fill the buffer with zeros
714
                memset(recvdatabuf[recv_id]->recvbuf, 0, msg_h->msg_length);
715
                debug(" new @ id:%d\n",recv_id);
716
        } else {        //message structure already exists, no need to create new
717
                debug(" found @ id:%d (arrived before this packet: bytes:%d fragments%d\n",recv_id, recvdatabuf[recv_id]->arrivedBytes, recvdatabuf[recv_id]->recvFragments);
718
        }
719

    
720
        if (msg_h->offset == 0)
721
                recvdatabuf[recv_id]->firstPacketArrived = 1;
722

    
723

    
724
        // increment fragmentnr
725
        recvdatabuf[recv_id]->recvFragments++;
726
        // increment the arrivedBytes
727
        recvdatabuf[recv_id]->arrivedBytes += bufsize;
728

    
729
        // enter the data into the buffer
730
        memcpy(recvdatabuf[recv_id]->recvbuf + msg_h->offset, msgbuf, bufsize);
731

    
732
        //TODO very basic checkif all fragments arrived: has to be reviewed
733
        if(recvdatabuf[recv_id]->arrivedBytes == recvdatabuf[recv_id]->bufsize)
734
                recvdatabuf[recv_id]->status = COMPLETE; //buffer full -> msg completly arrived
735
        else
736
                recvdatabuf[recv_id]->status = ACTIVE;
737

    
738
        if (recv_data_callback) {
739
                if(recvdatabuf[recv_id]->status == COMPLETE) {
740
                        // Monitoring layer hook
741
                        if(get_Recv_data_inf_cb != NULL) {
742
                                mon_data_inf recv_data_inf;
743

    
744
                                recv_data_inf.remote_socketID =
745
                                         &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
746
                                recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
747
                                recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
748
                                recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
749
                                recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
750
                                recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
751
                                        recvdatabuf[recv_id]->recvbuf : NULL;
752
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
753
                                recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
754
                                recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
755
                                recv_data_inf.priority = false;
756
                                recv_data_inf.padding = false;
757
                                recv_data_inf.confirmation = false;
758
                                recv_data_inf.reliable = false;
759

    
760
                                // send data recv callback to monitoring module
761

    
762
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
763
                        }
764

    
765
                        // Get the right callback
766
                        receive_data_cb receive_data_callback = recvcbbuf[msg_h->msg_type];
767
                        if (receive_data_callback) {
768

    
769
                                recv_params rParams;
770

    
771
                                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
772
                                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
773
                                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
774
                                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
775
                                rParams.remote_socketID =
776
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
777

    
778
                                char str[1000];
779
                                mlSocketIDToString(rParams.remote_socketID,str,999);
780
                                debug("ML: received message from conID:%d, %s\n",recvdatabuf[recv_id]->connectionID,str);
781
                                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
782

    
783
                                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
784
                                        recvdatabuf[recv_id]->msgtype, (void *) &rParams);
785
                        } else {
786
                            warn("ML: callback not initialized for this message type: %d!\n",msg_h->msg_type);
787
                        }
788

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

    
814
//done
815
void pmtu_timeout_cb(int fd, short event, void *arg)
816
{
817

    
818
        int con_id = (long) arg;
819
        pmtu new_pmtusize;
820
        struct timeval timeout;
821

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

    
824
        if(connectbuf[con_id] == NULL) {
825
                error("ML: pmtu timeout called on non existing con_id\n");
826
                return;
827
        }
828

    
829
        if(connectbuf[con_id]->status == READY) {
830
                // nothing to do anymore
831
                event_del(connectbuf[con_id]->timeout_event);
832
                event_free(connectbuf[con_id]->timeout_event);
833
                connectbuf[con_id]->timeout_event = NULL;
834
                return;
835
        }
836

    
837
        info("ML: pmtu timeout while connecting(to:%s lcon:%d status:%d)\n",conid_to_string(con_id), con_id, connectbuf[con_id]->status);
838

    
839
        timeout = connectbuf[con_id]->timeout_value;
840

    
841
        if(connectbuf[con_id]->delay || connectbuf[con_id]->trials == MAX_TRIALS - 1) {
842
                double delay = timeout.tv_sec + timeout.tv_usec / 1000000.0;
843
                delay = delay * 2;
844
                info("\tML: increasing pmtu timeout to %f sec\n", delay);
845
                timeout.tv_sec = floor(delay);
846
                timeout.tv_usec = fmod(delay, 1.0) * 1000000.0;
847
                if(connectbuf[con_id]->delay) {
848
                        connectbuf[con_id]->delay = false;
849
                        reschedule_conn_msg(con_id);
850
                }
851
        }
852

    
853
        if(connectbuf[con_id]->trials == MAX_TRIALS) {
854
                // decrement the pmtu size
855
                struct timeval tout = PMTU_TIMEOUT;
856
                info("\tML: decreasing pmtu estimate from %d to %d\n", connectbuf[con_id]->pmtusize, pmtu_decrement(connectbuf[con_id]->pmtusize));
857
                connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
858
                connectbuf[con_id]->timeout_value = tout; 
859
                connectbuf[con_id]->trials = 0;
860
        }
861

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

    
880
        //retry with new pmtu size
881
        connectbuf[con_id]->trials++;
882
        resend_conn_msg(con_id);
883
}
884

    
885

    
886
int schedule_pmtu_timeout(int con_id)
887
{
888
        if (! connectbuf[con_id]->timeout_event) {
889
                struct timeval tout = PMTU_TIMEOUT;
890
                connectbuf[con_id]->timeout_value = tout;
891
                connectbuf[con_id]->trials = 1;
892
                connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
893
                evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
894
        }
895
}
896

    
897
/*
898
 * decrements the mtu size
899
 */
900
pmtu pmtu_decrement(pmtu pmtusize)
901
{
902
        pmtu pmtu_return_size;
903
        switch(pmtusize) {
904
        case MAX:
905
                return DSL;
906
        case DSL:
907
                return DSLMEDIUM;
908
        case DSLMEDIUM:
909
                return DSLSLIM;
910
        case DSLSLIM:
911
                return BELOWDSL;
912
        case BELOWDSL:
913
                return MIN;
914
        case MIN:
915
                return ERROR;
916
        default:
917
                warn("ML: strange pmtu size encountered:%d, changing to some safe value:%d\n", pmtusize, MIN);
918
                return MIN;
919
        }
920
}
921

    
922
// called when an ICMP pmtu error message (type 3, code 4) is received
923
void pmtu_error_cb_th(char *msg, int msglen)
924
{
925
        debug("ML: pmtu_error callback called msg_size: %d\n",msglen);
926
        //TODO debug
927
        return;
928

    
929
    char *msgbufptr = NULL;
930
    int msgtype;
931
    int connectionID;
932
    pmtu pmtusize;
933
    pmtu new_pmtusize;
934
    int dead = 0;
935

    
936
    // check the packettype
937
    msgbufptr = &msg[0];
938

    
939
    // check the msgtype
940
    msgbufptr = &msg[1];
941
    memcpy(&msgtype, msgbufptr, 4);
942

    
943
    if (msgtype == 0) {
944

    
945
        // get the connectionID
946
        msgbufptr = &msg[5];
947
        memcpy(&connectionID, msgbufptr, 4);
948

    
949
        int msgtype_c = connectbuf[connectionID]->status;
950
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
951

    
952
        if (msgtype_c != msgtype) {
953
            dead = 1;
954
        }
955

    
956

    
957
    } else if (msgtype == 1) {
958

    
959
        // read the connectionID
960
        msgbufptr = &msg[9];
961
        memcpy(&connectionID, msgbufptr, 4);
962

    
963
        int msgtype_c = connectbuf[connectionID]->status;
964
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
965

    
966
        if (msgtype_c != msgtype) {
967
            dead = 1;
968
        }
969

    
970
    }
971
    // decrement the pmtu size
972
    new_pmtusize = pmtu_decrement(pmtusize);
973

    
974
//    connectbuf[connectionID]->pmtutrysize = new_pmtusize;
975

    
976
    if (new_pmtusize == ERROR) {
977
                error("ML:  Could not create connection with connectionID %i !\n",
978
                        connectionID);
979

    
980
                if(failed_Connection_cb != NULL)
981
                        (failed_Connection_cb) (connectionID, NULL);
982
                // set the message type to a non existent message
983
                msgtype = 2;
984
                // delete the connection entry
985
                 mlCloseConnection(connectionID);
986
        }
987

    
988
    if (msgtype == 0 && dead != 1) {
989

    
990
        // stop the timeout event
991
        // timeout_del(connectbuf[connectionID]->timeout);
992
        /*
993
         * libevent2
994
         */
995

    
996
        // event_del(connectbuf[connectionID]->timeout);
997

    
998

    
999
        // create and send a connection message
1000
//         create_conn_msg(new_pmtusize, connectionID,
1001
//                         &local_socketID, INVITE);
1002

    
1003
//        send_conn_msg(connectionID, new_pmtusize);
1004

    
1005
        // set a timeout event for the pmtu discovery
1006
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
1007
        // *)&connectionID);
1008

    
1009
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1010

    
1011
        /*
1012
         * libevent2
1013
         */
1014

    
1015
        struct event *ev;
1016
        ev = evtimer_new(base, pmtu_timeout_cb,
1017
                         (void *) connectbuf[connectionID]);
1018

    
1019
        // connectbuf[connectionID]->timeout = ev;
1020

    
1021
        event_add(ev, &connectbuf[connectionID]->timeout_value);
1022

    
1023
    } else if (msgtype == 1 && dead != 1) {
1024

    
1025
        // stop the timeout event
1026
        // timeout_del(connectbuf[connectionID]->timeout);
1027

    
1028
        /*
1029
         * libevent2
1030
         */
1031
        // info("still here 11 \n");
1032
        // printf("ev %d \n",connectbuf[connectionID]->timeout);
1033
        // event_del(connectbuf[connectionID]->timeout );
1034
        // evtimer_del(connectbuf[connectionID]->timeout );
1035

    
1036

    
1037
//         // create and send a connection message
1038
//         create_conn_msg(new_pmtusize,
1039
//                         connectbuf[connectionID]->connectionID,
1040
//                         NULL, CONNECT);
1041

    
1042
        //send_conn_msg(connectionID, new_pmtusize);
1043

    
1044
        // set a timeout event for the pmtu discovery
1045
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
1046
        // *)&connectionID);
1047
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1048

    
1049
        /*
1050
         * libevent2
1051
         */
1052
        // struct event *ev;
1053
        // ev = evtimer_new(base,pmtu_timeout_cb, (void
1054
        // *)connectbuf[connectionID]);
1055
        // connectbuf[connectionID]->timeout = ev;
1056
        // event_add(ev,&connectbuf[connectionID]->timeout_value);
1057

    
1058
    }
1059
}
1060

    
1061
/*
1062
 * what to do once a packet arrived if it is a conn packet send it to
1063
 * recv_conn handler if it is a data packet send it to the recv_data
1064
 * handler
1065
 */
1066

    
1067
//done --
1068
void recv_pkg(int fd, short event, void *arg)
1069
{
1070
        debug("ML: recv_pkg called\n");
1071

    
1072
        struct msg_header *msg_h;
1073
        char msgbuf[MAX];
1074
        pmtu recvSize = MAX;
1075
        char *bufptr = msgbuf;
1076
        int ttl;
1077
        struct sockaddr_in recv_addr;
1078
        int msg_size;
1079

    
1080
        recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
1081

    
1082

    
1083
        // check if it is not just an ERROR message
1084
        if(recvSize < 0)
1085
                return;
1086

    
1087
        // @TODO check if this simplistic STUN message recognition really always works, probably not
1088
        unsigned short stun_bind_response = 0x0101;
1089
        unsigned short * msgspot = (unsigned short *) msgbuf;
1090
        if (*msgspot == stun_bind_response) {
1091
                debug("ML: recv_pkg: parse stun message called\n");
1092
                recv_stun_msg(msgbuf, recvSize);
1093
                return;
1094
        }
1095

    
1096
        msg_h = (struct msg_header *) msgbuf;
1097
        bufptr += MSG_HEADER_SIZE + msg_h->len_mon_packet_hdr;
1098
        msg_size = recvSize - MSG_HEADER_SIZE - msg_h->len_mon_packet_hdr;
1099

    
1100

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

    
1126

    
1127
        switch(msg_h->msg_type) {
1128
                case ML_CON_MSG:
1129
                        debug("ML: received conn pkg\n");
1130
                        recv_conn_msg(msg_h, bufptr, msg_size);
1131
                        break;
1132
                default:
1133
                        if(msg_h->msg_type < 127) {
1134
                                debug("ML: received data pkg\n");
1135
                                recv_data_msg(msg_h, bufptr, msg_size);
1136
                                break;
1137
                        }
1138
                        debug("ML: unrecognised msg_type\n");
1139
                        break;
1140
        }
1141
}
1142

    
1143
/*
1144
 * compare the external IP address of two socketIDs
1145
 */
1146
int
1147
compare_external_address_socketIDs(socketID_handle sock1, socketID_handle sock2)
1148
{
1149
        if( sock1->external_addr.udpaddr.sin_addr.s_addr == sock2->external_addr.udpaddr.sin_addr.s_addr)
1150
                return 0;
1151
        return 1;
1152
}
1153

    
1154
void try_stun();
1155

    
1156
/*
1157
 * the timeout of the NAT traversal
1158
 */
1159
void nat_traversal_timeout(int fd, short event, void *arg)
1160
{
1161
        if (NAT_traversal == false) {
1162
                debug("ML: NAT traversal request re-send\n");
1163
                if(receive_SocketID_cb)
1164
                        (receive_SocketID_cb) (&local_socketID, 2);
1165
                try_stun();
1166
        }
1167
}
1168

    
1169
unsigned long resolve(const char *ipaddr)
1170
{
1171
        struct hostent *h = gethostbyname(ipaddr);
1172
        if (!h) {
1173
                error("ML: Unable to resolve host name %s\n", ipaddr);
1174
        exit(-1);
1175
    }
1176
    unsigned long *addr = (unsigned long *) (h->h_addr);
1177
    return *addr;
1178
}
1179

    
1180

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

    
1204
        socketaddrgen udpgen;
1205
        memset(&udpgen,0,sizeof(socketaddrgen));        //this will be sent over the net, so set it to 0
1206
        udpgen.udpaddr = udpaddr;
1207
        local_socketID.internal_addr = udpgen;
1208

    
1209
        socketfd = createSocket(port, ipaddr);
1210

    
1211
        struct event *ev;
1212
        ev = event_new(base, socketfd, EV_READ | EV_PERSIST, recv_pkg, NULL);
1213

    
1214
        event_add(ev, NULL);
1215

    
1216
        try_stun();
1217
}
1218

    
1219
/*
1220
 * try to figure out external IP using STUN, if defined
1221
 */
1222
void try_stun()
1223
{
1224
        if (isStunDefined()) {
1225
                /*
1226
                * send the NAT traversal STUN request
1227
                */
1228
                 send_stun_request(socketfd, &stun_server);
1229

    
1230
                /*
1231
                * enter a NAT traversal timeout that takes care of retransmission
1232
                */
1233
                struct event *ev1;
1234
                struct timeval timeout_value_NAT_traversal = NAT_TRAVERSAL_TIMEOUT;
1235
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1236
                event_add(ev1, &timeout_value_NAT_traversal);
1237

    
1238
                NAT_traversal = false;
1239
        } else {
1240
                /*
1241
                * Assume we have accessibility and copy internal address to external one
1242
                */
1243
                local_socketID.external_addr = local_socketID.internal_addr;
1244
                NAT_traversal = true; // @TODO: this is not really NAT traversal, but a flag that init is over
1245
                // callback to the upper layer indicating that the socketID is now
1246
                // ready to use
1247
                if(receive_SocketID_cb)
1248
                        (receive_SocketID_cb) (&local_socketID, 0); //success
1249
        }
1250
}
1251

    
1252
/**************************** END OF INTERNAL ***********************/
1253

    
1254
/**************************** MONL functions *************************/
1255

    
1256
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){
1257

    
1258
        base = (struct event_base *) arg;
1259
        recv_data_callback = recv_data_cb;
1260
        mlSetRecvTimeout(timeout_value);
1261
        if (stun_ipaddr) {
1262
                 mlSetStunServer(stun_port, stun_ipaddr);
1263
        } else {
1264

    
1265
        }
1266
        register_recv_localsocketID_cb(local_socketID_cb);
1267
        create_socket(port, ipaddr);
1268

    
1269
}
1270

    
1271
/* register callbacks  */
1272
void mlRegisterGetRecvPktInf(get_recv_pkt_inf_cb recv_pkt_inf_cb){
1273

    
1274
        if (recv_pkt_inf_cb == NULL)
1275
                error("ML: Register get_recv_pkt_inf_cb failed: NULL ptr  \n");
1276
        else
1277
                get_Recv_pkt_inf_cb = recv_pkt_inf_cb;
1278

    
1279
}
1280

    
1281
void mlRegisterGetSendPktInf(get_send_pkt_inf_cb  send_pkt_inf_cb){
1282

    
1283
        if (send_pkt_inf_cb == NULL)
1284
                error("ML: Register get_send_pkt_inf_cb: NULL ptr  \n");
1285
        else
1286
                get_Send_pkt_inf_cb = send_pkt_inf_cb;
1287

    
1288
}
1289

    
1290

    
1291
void mlRegisterSetMonitoringHeaderPktCb(set_monitoring_header_pkt_cb monitoring_header_pkt_cb ){
1292

    
1293
        if (monitoring_header_pkt_cb == NULL)
1294
                error("ML: Register set_monitoring_header_pkt_cb: NULL ptr  \n");
1295
        else
1296
                set_Monitoring_header_pkt_cb = monitoring_header_pkt_cb;
1297

    
1298
}
1299

    
1300
void mlRegisterGetRecvDataInf(get_recv_data_inf_cb recv_data_inf_cb){
1301

    
1302
        if (recv_data_inf_cb == NULL)
1303
                error("ML: Register get_recv_data_inf_cb: NULL ptr  \n");
1304
        else
1305
                get_Recv_data_inf_cb = recv_data_inf_cb;
1306

    
1307
}
1308

    
1309
void mlRegisterGetSendDataInf(get_send_data_inf_cb  send_data_inf_cb){
1310

    
1311
        if (send_data_inf_cb == NULL)
1312
                error("ML: Register get_send_data_inf_cb: NULL ptr  \n");
1313
        else
1314
                get_Send_data_inf_cb = send_data_inf_cb;
1315

    
1316
}
1317

    
1318
void mlRegisterSetMonitoringHeaderDataCb(set_monitoring_header_data_cb monitoring_header_data_cb){
1319

    
1320
        if (monitoring_header_data_cb == NULL)
1321
                error("ML: Register set_monitoring_header_data_cb : NULL ptr  \n");
1322
        else
1323
        set_Monitoring_header_data_cb = monitoring_header_data_cb;
1324

    
1325
}
1326

    
1327
void mlSetRecvTimeout(struct timeval timeout_value){
1328

    
1329
        recv_timeout = timeout_value;
1330

    
1331
}
1332

    
1333
int mlGetStandardTTL(socketID_handle socketID,uint8_t *ttl){
1334

    
1335
        return getTTL(socketfd, ttl);
1336

    
1337
}
1338

    
1339
socketID_handle mlGetLocalSocketID(int *errorstatus){
1340

    
1341
        if (NAT_traversal == false) {
1342
                *errorstatus = 2;
1343
                return NULL;
1344
        }
1345

    
1346
        *errorstatus = 0;
1347
        return &local_socketID;
1348

    
1349
}
1350

    
1351

    
1352
/**************************** END of MONL functions *************************/
1353

    
1354
/**************************** GENERAL functions *************************/
1355

    
1356
void mlRegisterRecvConnectionCb(receive_connection_cb recv_conn_cb){
1357

    
1358
        if (recv_conn_cb == NULL)
1359
                error("ML: Register receive_connection_cb: NULL ptr  \n");
1360
        else
1361
                receive_Connection_cb = recv_conn_cb;
1362

    
1363
}
1364

    
1365
void mlRegisterErrorConnectionCb(connection_failed_cb conn_failed){
1366

    
1367
        if (conn_failed == NULL)
1368
                error("ML: Register connection_failed_cb: NULL ptr  \n");
1369
        else
1370
        failed_Connection_cb = conn_failed;
1371

    
1372
}
1373

    
1374
void mlRegisterRecvDataCb(receive_data_cb data_cb,unsigned char msgtype){
1375

    
1376
    if (msgtype > 126) {
1377

    
1378
            error
1379
            ("ML: Could not register recv_data callback. Msgtype is greater then 126 \n");
1380

    
1381
    }
1382

    
1383
    if (data_cb == NULL) {
1384

    
1385
            error("ML: Register receive data callback: NUll ptr \n ");
1386

    
1387
    } else {
1388

    
1389
        recvcbbuf[msgtype] = data_cb;
1390

    
1391
    }
1392

    
1393
}
1394

    
1395
void mlCloseSocket(socketID_handle socketID){
1396

    
1397
        free(socketID);
1398

    
1399
}
1400

    
1401
void keepalive_fn(evutil_socket_t fd, short what, void *arg) {
1402
        socketID_handle peer = arg;
1403

    
1404
        int con_id = mlConnectionExist(peer, false);
1405
        if (con_id < 0 || connectbuf[con_id]->defaultSendParams.keepalive <= 0) {
1406
                /* Connection fell from under us or keepalive was disabled */
1407
                free(arg);
1408
                return;
1409
        }
1410

    
1411
        /* do what we gotta do */
1412
        if ( connectbuf[con_id]->status == READY) {
1413
                char keepaliveMsg[32] = "";
1414
                sprintf(keepaliveMsg, "KEEPALIVE %d", connectbuf[con_id]->keepalive_seq++);
1415
                send_msg(con_id, MSG_TYPE_ML_KEEPALIVE, keepaliveMsg, 1 + strlen(keepaliveMsg), false, 
1416
                        &(connectbuf[con_id]->defaultSendParams));
1417
        }
1418

    
1419
        /* re-schedule */
1420
        struct timeval t = { 0,0 };
1421
        t.tv_sec = connectbuf[con_id]->defaultSendParams.keepalive;
1422
        if (connectbuf[con_id]->defaultSendParams.keepalive) 
1423
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1424
}
1425

    
1426
void setupKeepalive(int conn_id) {
1427
        /* Save the peer's address for us */
1428
        socketID_handle peer = malloc(sizeof(socket_ID));
1429
        memcpy(peer, &connectbuf[conn_id]->external_socketID, sizeof(socket_ID));
1430

    
1431
        struct timeval t = { 0,0 };
1432
        t.tv_sec = connectbuf[conn_id]->defaultSendParams.keepalive;
1433

    
1434
        if (connectbuf[conn_id]->defaultSendParams.keepalive) 
1435
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1436
}
1437

    
1438
/* connection functions */
1439
int mlOpenConnection(socketID_handle external_socketID,receive_connection_cb connection_cb,void *arg, const send_params defaultSendParams){
1440

    
1441
        int con_id;
1442
        if (external_socketID == NULL) {
1443
                error("ML: cannot open connection: one of the socketIDs is NULL\n");
1444
                return -1;
1445
        }
1446
        if (NAT_traversal == false) {
1447
                error("ML: cannot open connection: NAT traversal for socketID still in progress\n");
1448
                return -1;
1449
        }
1450
        if (connection_cb == NULL) {
1451
                error("ML: cannot open connection: connection_cb is NULL\n");
1452
                return -1;
1453
        }
1454

    
1455
        // check if that connection already exist
1456

    
1457
        con_id = mlConnectionExist(external_socketID, false);
1458
        if (con_id >= 0) {
1459
                // overwrite defaultSendParams
1460
                bool newKeepalive = 
1461
                        connectbuf[con_id]->defaultSendParams.keepalive == 0 && defaultSendParams.keepalive != 0;
1462
                connectbuf[con_id]->defaultSendParams = defaultSendParams;
1463
                if (newKeepalive) setupKeepalive(con_id);
1464
                // if so check if it is ready to use
1465
                if (connectbuf[con_id]->status == READY) {
1466
                                // if so use the callback immediately
1467
                                (connection_cb) (con_id, arg);
1468

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

    
1499
                        connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
1500
                        connectbuf[con_id]->connection_last->next = NULL;
1501
                        connectbuf[con_id]->connection_last->connection_cb = connection_cb;
1502
                        connectbuf[con_id]->connection_last->arg = arg;
1503
                        connectbuf[con_id]->external_connectionID = -1;
1504

    
1505
                        connectbuf[con_id]->defaultSendParams = defaultSendParams;
1506
                        if (defaultSendParams.keepalive) setupKeepalive(con_id);
1507
                        break;
1508
                }
1509
        } //end of for
1510

    
1511
        if (con_id == CONNECTBUFSIZE) {
1512
                error("ML: Could not open connection: connection buffer full\n");
1513
                return -1;
1514
        }
1515

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

    
1520
        return con_id;
1521

    
1522
}
1523

    
1524
void mlCloseConnection(const int connectionID){
1525

    
1526
        // remove it from the connection array
1527
        if(connectbuf[connectionID]) {
1528
                if(connectbuf[connectionID]->ctrl_msg_buf) {
1529
                        free(connectbuf[connectionID]->ctrl_msg_buf);
1530
                }
1531
                // remove related events
1532
                if (connectbuf[connectionID]->timeout_event) {
1533
                        event_del(connectbuf[connectionID]->timeout_event);
1534
                        event_free(connectbuf[connectionID]->timeout_event);
1535
                        connectbuf[connectionID]->timeout_event = NULL;
1536
                }
1537
                free(connectbuf[connectionID]);
1538
                connectbuf[connectionID] = NULL;
1539
        }
1540

    
1541
}
1542

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

    
1545
        if (connectionID < 0) {
1546
                error("ML: send data failed: connectionID does not exist\n");
1547
                return;
1548
        }
1549

    
1550
        if (connectbuf[connectionID] == NULL) {
1551
                error("ML: send data failed: connectionID does not exist\n");
1552
                return;
1553
        }
1554
        if (connectbuf[connectionID]->status != READY) {
1555
            error("ML: send data failed: connection is not active\n");
1556
            return;
1557
        }
1558

    
1559
        if (sParams == NULL) {
1560
                sParams = &(connectbuf[connectionID]->defaultSendParams);
1561
        }
1562

    
1563
        send_msg(connectionID, msgtype, sendbuf, bufsize, false, sParams);
1564

    
1565
}
1566

    
1567
/* transmit data functions  */
1568
int mlSendAllData(const int connectionID,send_all_data_container *container,int nr_entries,unsigned char msgtype,send_params *sParams){
1569

    
1570
    if (nr_entries < 1 || nr_entries > 5) {
1571

    
1572
        error
1573
            ("ML : sendALlData : nr_enties is not between 1 and 5 \n ");
1574
        return 0;
1575

    
1576
    } else {
1577

    
1578
        if (nr_entries == 1) {
1579

    
1580
                mlSendData(connectionID, container->buffer_1,
1581
                      container->length_1, msgtype, sParams);
1582

    
1583
            return 1;
1584

    
1585
        } else if (nr_entries == 2) {
1586

    
1587
            int buflen = container->length_1 + container->length_2;
1588
            char buf[buflen];
1589
            memcpy(buf, container->buffer_1, container->length_1);
1590
            memcpy(&buf[container->length_1], container->buffer_2,
1591
                   container->length_2);
1592
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1593

    
1594
            return 1;
1595

    
1596
        } else if (nr_entries == 3) {
1597

    
1598
            int buflen =
1599
                container->length_1 + container->length_2 +
1600
                container->length_3;
1601
            char buf[buflen];
1602
            memcpy(buf, container->buffer_1, container->length_1);
1603
            memcpy(&buf[container->length_1], container->buffer_2,
1604
                   container->length_2);
1605
            memcpy(&buf[container->length_2], container->buffer_3,
1606
                   container->length_3);
1607
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1608

    
1609

    
1610
            return 1;
1611

    
1612
        } else if (nr_entries == 4) {
1613

    
1614
            int buflen =
1615
                container->length_1 + container->length_2 +
1616
                container->length_3 + container->length_4;
1617
            char buf[buflen];
1618
            memcpy(buf, container->buffer_1, container->length_1);
1619
            memcpy(&buf[container->length_1], container->buffer_2,
1620
                   container->length_2);
1621
            memcpy(&buf[container->length_2], container->buffer_3,
1622
                   container->length_3);
1623
            memcpy(&buf[container->length_3], container->buffer_4,
1624
                   container->length_4);
1625
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1626

    
1627
            return 1;
1628

    
1629
        } else {
1630

    
1631
            int buflen =
1632
                container->length_1 + container->length_2 +
1633
                container->length_3 + container->length_4 +
1634
                container->length_5;
1635
            char buf[buflen];
1636
            memcpy(buf, container->buffer_1, container->length_1);
1637
            memcpy(&buf[container->length_1], container->buffer_2,
1638
                   container->length_2);
1639
            memcpy(&buf[container->length_2], container->buffer_3,
1640
                   container->length_3);
1641
            memcpy(&buf[container->length_3], container->buffer_4,
1642
                   container->length_4);
1643
            memcpy(&buf[container->length_4], container->buffer_5,
1644
                   container->length_5);
1645
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1646

    
1647
            return 1;
1648
        }
1649

    
1650
    }
1651

    
1652
}
1653

    
1654
int mlRecvData(const int connectionID,char *recvbuf,int *bufsize,recv_params *rParams){
1655

    
1656
        //TODO yet to be converted
1657
        return 0;
1658
#if 0
1659
        if (rParams == NULL) {
1660
                error("ML: recv_data failed: recv_params is a NULL ptr\n");
1661
                return 0;
1662
    } else {
1663

1664
        info("ML: recv data called \n");
1665

1666
        int i = 0;
1667
        int returnValue = 0;
1668
        double timeout = (double) recv_timeout.tv_sec;
1669
        time_t endtime = time(NULL);
1670

1671
        for (i = 0; i < RECVDATABUFSIZE; i++) {
1672

1673
            if (recvdatabuf[i] != NULL) {
1674

1675
                if (recvdatabuf[i]->connectionID == connectionID) {
1676

1677
                    info("ML: recv data has entry  \n");
1678

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

1681
                    // check if the specified connection has data and it
1682
                    // is complete
1683
                    // check the data seqnr
1684
                    // if(connectionID == recvdatabuf[i]->connectionID &&
1685
                    // 1 == recvdatabuf[i]->status){
1686

1687
                    if (1 == recvdatabuf[i]->status) {
1688

1689
                        // info("transmissionHandler: recv_data set is
1690
                        // complete \n" );
1691

1692
                        // debug("debud \n");
1693

1694
                        // exchange the pointers
1695
                        int buffersize = 0;
1696
                        buffersize = recvdatabuf[i]->bufsize;
1697
                        *bufsize = buffersize;
1698
                        // recvbuf = recvdatabuf[i]->recvbuf;
1699

1700
                        // info("buffersize %d \n",buffersize);
1701
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1702
                               buffersize);
1703
                        // debug(" recvbuf %s \n",recvbuf );
1704

1705
//                         double nrMissFrags =
1706
//                             (double) recvdatabuf[i]->nrFragments /
1707
//                             (double) recvdatabuf[i]->recvFragments;
1708
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
1709

1710
//                        rParams->nrMissingFragments = nrMissingFragments;
1711
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
1712
                        rParams->msgtype = recvdatabuf[i]->msgtype;
1713
                        rParams->connectionID =
1714
                            recvdatabuf[i]->connectionID;
1715

1716
                        // break from the loop
1717
                        // debug(" recvbuf %s \n ",recvbuf);
1718

1719
                        // double nrMissFrags =
1720
                        // (double)recvdatabuf[i]->nrFragments /
1721
                        // (double)recvdatabuf[i]->recvFragments;
1722
                        // int nrMissingFragments =
1723
                        // (int)ceil(nrMissFrags);
1724

1725
                        if(get_Recv_data_inf_cb != NULL) {
1726
                                mon_data_inf recv_data_inf;
1727

1728
                                recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1729
                                recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1730
                                recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1731
                                recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1732
//                                 recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1733
//                                 recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1734
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
1735
                                recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1736
                                recv_data_inf.nrMissingFragments = nrMissingFragments;
1737
                                recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1738
                                recv_data_inf.priority = false;
1739
                                recv_data_inf.padding = false;
1740
                                recv_data_inf.confirmation = false;
1741
                                recv_data_inf.reliable = false;
1742

1743
                                // send data recv callback to monitoring module
1744

1745
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1746
                        }
1747

1748

1749
                        // free the allocated memory
1750
                        free(recvdatabuf[i]);
1751
                        recvdatabuf[i] = NULL;
1752

1753
                        returnValue = 1;
1754
                        break;
1755

1756
                    }
1757

1758
                    if (recvdatabuf[i] != NULL) {
1759

1760
                        if (timepass > timeout) {
1761

1762
                            info("ML: recv_data timeout called  \n");
1763

1764
                            // some data about the missing chunks should
1765
                            // be added here
1766
                            // exchange the pointers
1767
                            int buffersize = 0;
1768
                            buffersize = recvdatabuf[i]->bufsize;
1769
                            *bufsize = buffersize;
1770
                            // recvbuf = recvdatabuf[i]->recvbuf;
1771

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

1778
                            // debug(" recvbuf %s \n",recvbuf );
1779

1780
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1781
                                   buffersize);
1782

1783
                            rParams->nrMissingFragments =
1784
                                nrMissingFragments;
1785
                            rParams->nrFragments =
1786
                                recvdatabuf[i]->nrFragments;
1787
                            rParams->msgtype = recvdatabuf[i]->msgtype;
1788
                            rParams->connectionID =
1789
                                recvdatabuf[i]->connectionID;
1790

1791
                                if(get_Recv_data_inf_cb != NULL) {
1792
                                        mon_data_inf recv_data_inf;
1793

1794
                                        recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1795
                                        recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1796
                                        recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1797
                                        recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1798
                                        recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1799
                                        recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1800
                                        gettimeofday(&recv_data_inf.arrival_time, NULL);
1801
                                        recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1802
                                        recv_data_inf.nrMissingFragments = nrMissingFragments;
1803
                                        recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1804
                                        recv_data_inf.priority = false;
1805
                                        recv_data_inf.padding = false;
1806
                                        recv_data_inf.confirmation = false;
1807
                                        recv_data_inf.reliable = false;
1808

1809
                                        // send data recv callback to monitoring module
1810

1811
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1812
                                }
1813

1814
                            // free the allocated memory
1815
                            free(recvdatabuf[i]);
1816
                            recvdatabuf[i] = NULL;
1817

1818
                            returnValue = 1;
1819
                            break;
1820

1821
                        }
1822
                    }
1823

1824
                }
1825

1826
            }
1827
            // debug("2 recvbuf %s \n ",recvbuf);
1828
        }
1829
        return returnValue;
1830
    }
1831
#endif
1832

    
1833
}
1834

    
1835
int mlSocketIDToString(socketID_handle socketID,char* socketID_string, size_t len){
1836

    
1837
        char internal_addr[INET_ADDRSTRLEN];
1838
        char external_addr[INET_ADDRSTRLEN];
1839
        inet_ntop(AF_INET, &(socketID->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1840
        inet_ntop(AF_INET, &(socketID->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1841

    
1842
        snprintf(socketID_string,len,"%s:%d-%s:%d", internal_addr, ntohs(socketID->internal_addr.udpaddr.sin_port),
1843
                external_addr,        ntohs(socketID->external_addr.udpaddr.sin_port));
1844
        return 0;
1845

    
1846
}
1847

    
1848
int mlStringToSocketID(const char* socketID_string, socketID_handle socketID){
1849

    
1850
        //@TODO add checks against malformed string
1851
        char external_addr[INET_ADDRSTRLEN];
1852
        int external_port;
1853
        char internal_addr[INET_ADDRSTRLEN];
1854
        int internal_port;
1855

    
1856
        char *pch;
1857
        char *s = strdup(socketID_string);
1858

    
1859
        //replace ':' with a blank
1860
        pch=strchr(s,':');
1861
        while (pch!=NULL){
1862
                                *pch = ' ';
1863
                pch=strchr(pch+1,':');
1864
        }
1865
        pch=strchr(s,'-');
1866
        if(pch) *pch = ' ';
1867

    
1868
        sscanf(s,"%s %d %s %d", internal_addr, &internal_port,
1869
                external_addr, &external_port);
1870

    
1871
        if(inet_pton(AF_INET, internal_addr, &(socketID->internal_addr.udpaddr.sin_addr)) == 0)
1872
                return EINVAL;
1873
        socketID->internal_addr.udpaddr.sin_family = AF_INET;
1874
        socketID->internal_addr.udpaddr.sin_port = htons(internal_port);
1875

    
1876

    
1877
        if(inet_pton(AF_INET, external_addr, &(socketID->external_addr.udpaddr.sin_addr)) ==0)
1878
                return EINVAL;
1879
        socketID->external_addr.udpaddr.sin_family = AF_INET;
1880
        socketID->external_addr.udpaddr.sin_port = htons(external_port);
1881

    
1882
        free(s);
1883
        return 0;
1884

    
1885
}
1886

    
1887
int mlGetConnectionStatus(int connectionID){
1888

    
1889
        if(connectbuf[connectionID])
1890
                return connectbuf[connectionID]->status == READY;
1891
        return -1;
1892
    
1893
}
1894

    
1895

    
1896
int mlConnectionExist(socketID_handle socketID, bool ready){
1897

    
1898
    /*
1899
     * check if another connection for the external connectionID exist
1900
     * that was established \ within the last 2 seconds
1901
     */
1902
        int i;
1903
        for (i = 0; i < CONNECTBUFSIZE; i++)
1904
                if (connectbuf[i] != NULL)
1905
                        if (mlCompareSocketIDs(&(connectbuf[i]->external_socketID), socketID) == 0) {
1906
                                if (ready) return (connectbuf[i]->status == READY ? i : -1);;
1907
                                return i;
1908
                                }
1909

    
1910
    return -1;
1911

    
1912
}
1913

    
1914
//Added by Robert Birke as comodity functions
1915

    
1916
//int mlPrintSocketID(socketID_handle socketID) {
1917
//        char str[SOCKETID_STRING_SIZE];
1918
//        mlSocketIDToString(socketID, str, sizeof(str));
1919
//        printf(stderr,"int->%s<-ext\n",str);
1920
//}
1921

    
1922
/*
1923
 * hash code of a socketID
1924
 * TODO might think of a better way
1925
 */
1926
int mlHashSocketID(socketID_handle sock) {
1927
    return sock->internal_addr.udpaddr.sin_port +
1928
                          sock->external_addr.udpaddr.sin_port;
1929
}
1930

    
1931
int mlCompareSocketIDs(socketID_handle sock1, socketID_handle sock2) {
1932
        /*
1933
        * compare internal addr
1934
        */
1935
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr !=
1936
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
1937
                        return 1;
1938

    
1939
        if (sock1->internal_addr.udpaddr.sin_port !=
1940
                 sock2->internal_addr.udpaddr.sin_port)
1941
                        return 1;
1942

    
1943
        /*
1944
        * compare external addr
1945
        */
1946
        if (sock1->external_addr.udpaddr.sin_addr.s_addr !=
1947
            sock2->external_addr.udpaddr.sin_addr.s_addr)
1948
                        return 1;
1949

    
1950
        if (sock1->external_addr.udpaddr.sin_port !=
1951
                 sock2->external_addr.udpaddr.sin_port)
1952
                        return 1;
1953

    
1954
        return 0;
1955
}
1956

    
1957
int mlCompareSocketIDsByPort(socketID_handle sock1, socketID_handle sock2)
1958
{ 
1959
        if (sock1->internal_addr.udpaddr.sin_port !=
1960
                 sock2->internal_addr.udpaddr.sin_port)
1961
                        return 1;
1962

    
1963
        if (sock1->external_addr.udpaddr.sin_port !=
1964
                 sock2->external_addr.udpaddr.sin_port)
1965
                        return 1;
1966
        return 0;
1967
}
1968

    
1969
int mlGetPathMTU(int ConnectionId) {
1970
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
1971
                return -1;
1972
        if (connectbuf[ConnectionId] != NULL)
1973
                return connectbuf[ConnectionId]->pmtusize;
1974
        return -1;
1975
}
1976

    
1977
/**************************** END of GENERAL functions *************************/
1978

    
1979
/**************************** NAT functions *************************/
1980

    
1981
/* setter  */
1982
void mlSetStunServer(const int port,const char *ipaddr){
1983

    
1984
        stun_server.sin_family = AF_INET;
1985
        if (ipaddr == NULL)
1986
                stun_server.sin_addr.s_addr = htonl(INADDR_NONE);
1987
        else
1988
                stun_server.sin_addr.s_addr = resolve(ipaddr);
1989
        stun_server.sin_port = htons(port);
1990

    
1991
}
1992

    
1993
int mlGetExternalIP(char* external_addr){
1994

    
1995
        socketaddrgen udpgen;
1996
        struct sockaddr_in udpaddr;
1997

    
1998
        udpgen = local_socketID.external_addr;
1999
        udpaddr = udpgen.udpaddr;
2000

    
2001
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
2002
                        INET_ADDRSTRLEN);
2003

    
2004
        if (external_addr == NULL) {
2005

    
2006
        return -1;
2007

    
2008
        } else {
2009

    
2010
        return 0;
2011

    
2012
        }
2013

    
2014
}
2015

    
2016
/**************************** END of NAT functions *************************/