Statistics
| Branch: | Revision:

ml / ml.c @ 68d98e77

History | View | Annotate | Download (55.6 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
 * default timeout value between the first and the last received packet of a message
88
 */
89
#define RECV_TIMEOUT_DEFAULT { 2, 0 }
90

    
91
/*
92
 * global variables
93
 */
94
/*
95
 * define a buffer of pointers to connect structures
96
 */
97
connect_data *connectbuf[CONNECTBUFSIZE];
98

    
99
/*
100
 * define a pointer buffer with pointers to recv_data structures
101
 */
102
recvdata *recvdatabuf[RECVDATABUFSIZE];
103

    
104
/*
105
 * define a pointer buffer for message multiplexing
106
 */
107
receive_data_cb recvcbbuf[MSGMULTIPLEXSIZE];
108

    
109
/*
110
 * stun server address
111
 */
112
struct sockaddr_in stun_server;
113

    
114
/*
115
 * receive timeout
116
 */
117
static struct timeval recv_timeout = RECV_TIMEOUT_DEFAULT;
118
struct timeval recv_timeout;
119

    
120
/*
121
 * boolean NAT traversal successful if true
122
 */
123
boolean NAT_traversal;
124

    
125
/*
126
 * file descriptor for local socket
127
 */
128
evutil_socket_t socketfd;
129

    
130
/*
131
 * local socketID
132
 */
133
socket_ID local_socketID;
134

    
135
socketID_handle loc_socketID = &local_socketID;
136

    
137
/*
138
 * callback function pointers
139
 */
140
/*
141
 * monitoring module callbacks
142
 */
143
get_recv_pkt_inf_cb get_Recv_pkt_inf_cb = NULL;
144
get_send_pkt_inf_cb get_Send_pkt_inf_cb = NULL;
145
set_monitoring_header_pkt_cb set_Monitoring_header_pkt_cb = NULL;
146
get_recv_data_inf_cb get_Recv_data_inf_cb = NULL;
147
get_send_data_inf_cb get_Send_data_inf_cb = NULL;
148
set_monitoring_header_data_cb set_Monitoring_header_data_cb = NULL;
149
/*
150
 * connection callbacks
151
 */
152
receive_connection_cb receive_Connection_cb = NULL;
153
connection_failed_cb failed_Connection_cb = NULL;
154
/*
155
 * local socketID callback
156
 */
157
receive_localsocketID_cb receive_SocketID_cb;
158

    
159
/*
160
 * boolean that defines if received data is transmitted to the upper layer
161
 * via callback or via upper layer polling
162
 */
163
boolean recv_data_callback;
164

    
165
/*
166
 * helper function to get rid of a warning
167
 */
168
int min(int a, int b) {
169
        if (a > b) return b;
170
        return a;
171
}
172

    
173
void register_recv_localsocketID_cb(receive_localsocketID_cb local_socketID_cb)
174
{
175
        if (local_socketID_cb == NULL)
176
                error("ML : Register receive_localsocketID_cb: NULL ptr \n");
177
        else
178
        receive_SocketID_cb = local_socketID_cb;
179
}
180

    
181

    
182
//void keep_connection_alive(const int connectionID)
183
//{
184
//
185
//    // to be done with the NAT traversal
186
//    // send a message over the wire
187
//    printf("\n");
188
//
189
//}
190

    
191
void unsetStunServer()
192
{
193
        stun_server.sin_addr.s_addr = 0;
194
}
195

    
196
bool isStunDefined()
197
{
198
        return stun_server.sin_addr.s_addr;
199
}
200

    
201
void send_msg(int con_id, int msg_type, char* msg, int msg_len, bool truncable, send_params * sParams) {
202
        socketaddrgen udpgen;
203
        bool retry;
204
        int pkt_len, offset;
205
        struct iovec iov[4];
206

    
207
        char h_pkt[MON_HEADER_SPACE];
208
        char h_data[MON_HEADER_SPACE];
209

    
210
        struct msg_header msg_h;
211

    
212
        char str[1000];
213
        mlSocketIDToString(&connectbuf[con_id]->external_socketID,str,999);
214
        debug("ML: send_msg to conID:%d extID:%d, %s\n",con_id,connectbuf[con_id]->external_connectionID,str);
215

    
216
        iov[0].iov_base = &msg_h;
217
        iov[0].iov_len = MSG_HEADER_SIZE;
218

    
219
        msg_h.local_con_id = con_id;
220
        msg_h.remote_con_id = connectbuf[con_id]->external_connectionID;
221
        msg_h.msg_type = msg_type;
222
        msg_h.msg_seq_num = connectbuf[con_id]->seqnr++;
223

    
224

    
225
        iov[1].iov_len = iov[2].iov_len = 0;
226
        iov[1].iov_base = h_pkt;
227
        iov[2].iov_base = h_data;
228

    
229

    
230
        if (connectbuf[con_id]->internal_connect)
231
                udpgen = connectbuf[con_id]->external_socketID.internal_addr;
232
        else
233
                udpgen = connectbuf[con_id]->external_socketID.external_addr;
234

    
235
        do{
236
                offset = 0;
237
                retry = false;
238
                // Monitoring layer hook
239
                if(set_Monitoring_header_data_cb != NULL) {
240
                        iov[2].iov_len = ((set_Monitoring_header_data_cb) (&(connectbuf[con_id]->external_socketID), msg_type));
241
                }
242
                msg_h.len_mon_data_hdr = iov[2].iov_len;
243

    
244
                if(get_Send_data_inf_cb != NULL && iov[2].iov_len != 0) {
245
                        mon_data_inf sd_data_inf;
246

    
247
                        sd_data_inf.remote_socketID = &(connectbuf[con_id]->external_socketID);
248
                        sd_data_inf.buffer = msg;
249
                        sd_data_inf.bufSize = msg_len;
250
                        sd_data_inf.msgtype = msg_type;
251
                        sd_data_inf.monitoringDataHeader = iov[2].iov_base;
252
                        sd_data_inf.monitoringDataHeaderLen = iov[2].iov_len;
253
                        sd_data_inf.priority = sParams->priority;
254
                        sd_data_inf.padding = sParams->padding;
255
                        sd_data_inf.confirmation = sParams->confirmation;
256
                        sd_data_inf.reliable = sParams->reliable;
257
                        memset(&sd_data_inf.arrival_time, 0, sizeof(struct timeval));
258

    
259
                        (get_Send_data_inf_cb) ((void *) &sd_data_inf);
260
                }
261

    
262
                do {
263
                        if(set_Monitoring_header_pkt_cb != NULL) {
264
                                iov[1].iov_len = (set_Monitoring_header_pkt_cb) (&(connectbuf[con_id]->external_socketID), msg_type);
265
                        }
266
                        pkt_len = min(connectbuf[con_id]->pmtusize - iov[2].iov_len - iov[1].iov_len - iov[0].iov_len, msg_len - offset) ;
267

    
268
                        iov[3].iov_len = pkt_len;
269
                        iov[3].iov_base = msg + offset;
270

    
271
                        //fill header
272
                        msg_h.len_mon_packet_hdr = iov[1].iov_len;
273
                        msg_h.offset = offset;
274
                        msg_h.msg_length = truncable ? pkt_len : msg_len;
275

    
276
                        //monitoring layer hook
277
                        if(get_Send_pkt_inf_cb != NULL && iov[1].iov_len) {
278
                                mon_pkt_inf pkt_info;
279

    
280
                                pkt_info.remote_socketID = &(connectbuf[con_id]->external_socketID);
281
                                pkt_info.buffer = msg + offset;
282
                                pkt_info.bufSize = pkt_len;
283
                                pkt_info.msgtype = msg_type;
284
                                pkt_info.dataID = connectbuf[con_id]->seqnr;
285
                                pkt_info.offset = offset;
286
                                pkt_info.datasize = msg_len;
287
                                pkt_info.monitoringHeaderLen = iov[1].iov_len;
288
                                pkt_info.monitoringHeader = iov[1].iov_base;
289
                                pkt_info.ttl = -1;
290
                                memset(&(pkt_info.arrival_time),0,sizeof(struct timeval));
291

    
292
                                (get_Send_pkt_inf_cb) ((void *) &pkt_info);
293
                        }
294

    
295
                        debug("ML: sending packet with rconID:%d lconID:%d\n",msg_h.remote_con_id,msg_h.local_con_id);
296
                        switch(sendPacket(socketfd, iov, 4, &udpgen.udpaddr)) {
297
                                case MSGLEN:
298
                                        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);
299
                                        connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
300
                                        connectbuf[con_id]->delay = true;
301
                                        retry = true;
302
                                        offset = msg_len + msg_h.len_mon_data_hdr; // exit the while
303
                                        break;
304
                                case FAILURE:
305
                                        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);
306
                                        offset = msg_len + msg_h.len_mon_data_hdr; // exit the while
307
                                        break;
308
                                case OK:
309
                                        //update
310
                                        offset += pkt_len + iov[2].iov_len;
311
                                        //transmit data header only in the first packet
312
                                        iov[2].iov_len = 0;
313
                                        break;
314
                        }
315
                } while(offset != msg_len + msg_h.len_mon_data_hdr && !truncable);
316
        } while(retry);
317
}
318

    
319
void send_conn_msg(int con_id, int buf_size, int command_type)
320
{
321
        if (buf_size < sizeof(struct conn_msg)) {
322
                error("ML: requested connection message size is too small\n");
323
                return;
324
        }
325

    
326
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
327
                connectbuf[con_id]->ctrl_msg_buf = malloc(buf_size);
328
                memset(connectbuf[con_id]->ctrl_msg_buf, 0, buf_size);
329
        }
330

    
331
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
332
                error("ML: can not allocate memory for connection message\n");
333
                return;
334
        }
335

    
336
        struct conn_msg *msg_header = (struct conn_msg*) connectbuf[con_id]->ctrl_msg_buf;
337

    
338
        msg_header->comand_type = command_type;
339
        msg_header->pmtu_size = connectbuf[con_id]->pmtusize;
340

    
341
        memcpy(&(msg_header->sock_id), loc_socketID, sizeof(socket_ID));
342

    
343
        send_msg(con_id, ML_CON_MSG, connectbuf[con_id]->ctrl_msg_buf, buf_size, true, &(connectbuf[con_id]->defaultSendParams));
344
}
345

    
346
void
347
recv_conn_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
348
{
349
        struct conn_msg *con_msg;
350
        int free_con_id, con_id;
351

    
352
        time_t now = time(NULL);
353
        double timediff = 0.0;
354
        char str[1000];
355

    
356
        // Monitoring layer hook
357
        if(get_Recv_data_inf_cb != NULL && msg_h->len_mon_data_hdr != 0) {
358
                // update pointer to the real data
359
                msgbuf += msg_h->len_mon_data_hdr;
360
                bufsize -= msg_h->len_mon_data_hdr;
361
                con_msg = (struct conn_msg *)msgbuf;
362

    
363
                mon_data_inf recv_data_inf;
364
                recv_data_inf.remote_socketID = &(con_msg->sock_id);
365
                recv_data_inf.buffer = msgbuf;
366
                recv_data_inf.bufSize = bufsize;
367
                recv_data_inf.msgtype = msg_h->msg_type;
368
                recv_data_inf.monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
369
                recv_data_inf.monitoringDataHeader = msg_h->len_mon_data_hdr ? msgbuf : NULL;
370
                gettimeofday(&recv_data_inf.arrival_time, NULL);
371
                recv_data_inf.firstPacketArrived = true;
372
                recv_data_inf.recvFragments = 1;
373
                recv_data_inf.priority = false;
374
                recv_data_inf.padding = false;
375
                recv_data_inf.confirmation = false;
376
                recv_data_inf.reliable = false;
377

    
378
                // send data recv callback to monitoring module
379
                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
380
        } else {
381
                con_msg = (struct conn_msg *) msgbuf;
382
        }
383

    
384
        //decode sock_id for debug messages
385
        mlSocketIDToString(&con_msg->sock_id,str,999);
386

    
387
        // check the connection command type
388
        switch (con_msg->comand_type) {
389
                /*
390
                * if INVITE: enter a new socket make new entry in connect array
391
                * send an ok
392
                */
393
                case INVITE:
394
                        info("ML: received INVITE from %s\n",str);
395
                        /*
396
                        * check if another connection for the external connectionID exist
397
                        * that was established within the last 2 seconds
398
                        */
399
                        free_con_id = -1;
400
                        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
401
                                if (connectbuf[con_id] != NULL) {
402
                                        if (mlCompareSocketIDs(&(connectbuf[con_id]->external_socketID), &(con_msg->sock_id)) == 0) {
403
                                                //timediff = difftime(now, connectbuf[con_id]->starttime);        //TODO: why this timeout? Shouldn't the connection be closed instead if there is a timeout?
404
                                                //if (timediff < 2)
405
                                                //update remote connection ID
406
                                                if (connectbuf[con_id]->external_connectionID != msg_h->local_con_id) {
407
                                                        warn("ML: updating remote connection ID for %s: from %d to %d\n",str, connectbuf[con_id]->external_connectionID, msg_h->local_con_id);
408
                                                        connectbuf[con_id]->external_connectionID = msg_h->local_con_id;
409
                                                }
410
                                                break;
411
                                        }
412
                                } else if(free_con_id == -1)
413
                                        free_con_id = con_id;
414
                        }
415

    
416
                        if (con_id == CONNECTBUFSIZE) {
417
                                // create an entry in the connecttrybuf
418
                                if(free_con_id == -1) {
419
                                        error("ML: no new connect_buf available\n");
420
                                        return;
421
                                }
422
                                connectbuf[free_con_id] = (connect_data *) malloc(sizeof(connect_data));
423
                                memset(connectbuf[free_con_id],0,sizeof(connect_data));
424
                                connectbuf[free_con_id]->connection_head = connectbuf[free_con_id]->connection_last = NULL;
425
                                connectbuf[free_con_id]->starttime = time(NULL);
426
                                memcpy(&(connectbuf[free_con_id]->external_socketID), &(con_msg->sock_id), sizeof(socket_ID));
427
                                connectbuf[free_con_id]->pmtusize = con_msg->pmtu_size;
428
                                connectbuf[free_con_id]->external_connectionID = msg_h->local_con_id;
429
                                connectbuf[free_con_id]->internal_connect =
430
                                        !compare_external_address_socketIDs(&(con_msg->sock_id), loc_socketID);
431
                                con_id = free_con_id;
432
                        }
433

    
434
                        //if(connectbuf[con_id]->status <= CONNECT) { //TODO: anwer anyway. Why the outher would invite otherwise?
435
                                //update status and send back answer
436
                                connectbuf[con_id]->status = CONNECT;
437
                                send_conn_msg(con_id, con_msg->pmtu_size, CONNECT);
438
                        //}
439
                        break;
440
                case CONNECT:
441
                        info("ML: received CONNECT from %s\n",str);
442

    
443
                        if(msg_h->remote_con_id != -1 && connectbuf[msg_h->remote_con_id] == NULL) {
444
                                error("ML: received CONNECT for inexistent connection rconID:%d\n",msg_h->remote_con_id);
445
                                return;
446
                        }
447

    
448
                        /*
449
                        * check if the connection status is not already 1 or 2
450
                        */
451
                        if (connectbuf[msg_h->remote_con_id]->status == INVITE) {
452
                                // set the external connectionID
453
                                connectbuf[msg_h->remote_con_id]->external_connectionID = msg_h->local_con_id;
454
                                // change status con_msg the connection_data
455
                                connectbuf[msg_h->remote_con_id]->status = READY;
456
                                // change pmtusize in the connection_data
457
                                connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
458

    
459
                                // send the READY
460
                                send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
461

    
462
                                if (receive_Connection_cb != NULL)
463
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
464

    
465
                                // call all registered callbacks
466
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
467
                                        struct receive_connection_cb_list *temp;
468
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
469
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
470
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
471
                                        free(temp);
472
                                }
473
                                connectbuf[msg_h->remote_con_id]->connection_head =
474
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
475
                        } else
476
                                // send the READY
477
                                send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
478

    
479
                        debug("ML: active connection established\n");
480
                        break;
481

    
482
                        /*
483
                        * if READY: find the entry in the connection array set the
484
                        * connection active change the pmtu size
485
                        */
486
                case READY:
487
                        info("ML: received READY from %s\n",str);
488
                        if(connectbuf[msg_h->remote_con_id] == NULL) {
489
                                error("ML: received READY for inexistent connection\n");
490
                                return;
491
                        }
492
                        /*
493
                        * checks if the connection is not already established
494
                        */
495
                        if (connectbuf[msg_h->remote_con_id]->status == CONNECT) {
496
                                // change status of the connection
497
                                connectbuf[msg_h->remote_con_id]->status = 2;
498
                                // change pmtusize
499
                                connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
500

    
501
                                if (receive_Connection_cb != NULL)
502
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
503

    
504
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
505
                                        struct receive_connection_cb_list *temp;
506
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
507
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
508
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
509
                                        free(temp);
510
                                }
511
                                connectbuf[msg_h->remote_con_id]->connection_head =
512
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
513
                                debug("ML: passive connection established\n");
514
                        }
515
                        break;
516
        }
517
}
518

    
519
void recv_stun_msg(char *msgbuf, int recvSize)
520
{
521
        /*
522
        * create empty stun message struct
523
        */
524
        StunMessage resp;
525
        memset(&resp, 0, sizeof(StunMessage));
526
        /*
527
        * parse the message
528
        */
529
        int returnValue = 0;
530
        returnValue = recv_stun_message(msgbuf, recvSize, &resp);
531

    
532
        if (returnValue == 0) {
533
                /*
534
                * read the reflexive Address into the local_socketID
535
                */
536
                struct sockaddr_in reflexiveAddr;
537
                reflexiveAddr.sin_family = AF_INET;
538
                reflexiveAddr.sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
539
                reflexiveAddr.sin_port = htons(resp.mappedAddress.ipv4.port);
540
                socketaddrgen reflexiveAddres;
541
                reflexiveAddres.udpaddr = reflexiveAddr;
542
                local_socketID.external_addr = reflexiveAddres;
543
                NAT_traversal = true;
544
                // callback to the upper layer indicating that the socketID is now
545
                // ready to use
546
                (receive_SocketID_cb) (&local_socketID, 0);
547
        }
548
}
549

    
550
//done
551
void recv_timeout_cb(int fd, short event, void *arg)
552
{
553
        int recv_id = (long) arg;
554
        debug("ML: recv_timeout_cb called. Timeout for id:%d\n",recv_id);
555

    
556
        if (recvdatabuf[recv_id] == NULL) {
557
                return;
558
        }
559

    
560

    
561
/*        if(recvdatabuf[recv_id]->status == ACTIVE) {
562
                //TODO make timeout at least a DEFINE
563
                struct timeval timeout = { 4, 0 };
564
                recvdatabuf[recv_id]->status = INACTIVE;
565
                event_base_once(base, -1, EV_TIMEOUT, recv_timeout_cb,
566
                        arg, &timeout);
567
                return;
568
        }
569
*/
570

    
571
        if(recvdatabuf[recv_id]->status == ACTIVE) {
572
                // Monitoring layer hook
573
                if(get_Recv_data_inf_cb != NULL) {
574
                        mon_data_inf recv_data_inf;
575

    
576
                        recv_data_inf.remote_socketID =
577
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
578
                        recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
579
                        recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
580
                        recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
581
                        recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
582
                        recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
583
                                recvdatabuf[recv_id]->recvbuf : NULL;
584
                        gettimeofday(&recv_data_inf.arrival_time, NULL);
585
                        recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
586
                        recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
587
                        recv_data_inf.priority = false;
588
                        recv_data_inf.padding = false;
589
                        recv_data_inf.confirmation = false;
590
                        recv_data_inf.reliable = false;
591

    
592
                        // send data recv callback to monitoring module
593

    
594
                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
595
                }
596

    
597
                // Get the right callback
598
                receive_data_cb receive_data_callback = recvcbbuf[recvdatabuf[recv_id]->msgtype];
599

    
600
                recv_params rParams;
601

    
602
                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
603
                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
604
                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
605
                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
606
                rParams.remote_socketID =
607
                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
608
                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
609

    
610
                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
611
                        recvdatabuf[recv_id]->msgtype, &rParams);
612

    
613
                //clean up
614
                free(recvdatabuf[recv_id]->recvbuf);
615
                free(recvdatabuf[recv_id]);
616
                recvdatabuf[recv_id] = NULL;
617
        }
618
}
619

    
620
// process a single recv data message
621
void recv_data_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
622
{
623
        debug("ML: received packet of size %d with rconID:%d lconID:%d\n",bufsize,msg_h->remote_con_id,msg_h->local_con_id);
624

    
625
        int recv_id, free_recv_id = -1;
626

    
627
        if(connectbuf[msg_h->remote_con_id] == NULL) {
628
                debug("ML: Received a message not related to any opened connection!\n");
629
                return;
630
        }
631

    
632
        // check if a recv_data exist and enter data
633
        for (recv_id = 0; recv_id < RECVDATABUFSIZE; recv_id++)
634
                if (recvdatabuf[recv_id] != NULL) {
635
                        if (msg_h->remote_con_id == recvdatabuf[recv_id]->connectionID &&
636
                                        msg_h->msg_seq_num == recvdatabuf[recv_id]->seqnr)
637
                                                break;
638
                } else
639
                        if(free_recv_id == -1)
640
                                free_recv_id = recv_id;
641

    
642

    
643
        if(recv_id == RECVDATABUFSIZE) {
644
                //no recv_data found: create one
645
                recv_id = free_recv_id;
646
                recvdatabuf[recv_id] = (recvdata *) malloc(sizeof(recvdata));
647
                memset(recvdatabuf[recv_id], 0, sizeof(recvdata));
648
                recvdatabuf[recv_id]->connectionID = msg_h->remote_con_id;
649
                recvdatabuf[recv_id]->seqnr = msg_h->msg_seq_num;
650
                recvdatabuf[recv_id]->monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
651
                recvdatabuf[recv_id]->bufsize = msg_h->msg_length + msg_h->len_mon_data_hdr;
652
                recvdatabuf[recv_id]->recvbuf = (char *) malloc(recvdatabuf[recv_id]->bufsize);
653
                /*
654
                * read the timeout data and set it
655
                */
656
                recvdatabuf[recv_id]->timeout_value.tv_sec = recv_timeout.tv_sec;
657
                recvdatabuf[recv_id]->timeout_value.tv_usec = recv_timeout.tv_usec;
658
                recvdatabuf[recv_id]->timeout_event = NULL;
659
                recvdatabuf[recv_id]->recvID = recv_id;
660
                recvdatabuf[recv_id]->starttime = time(NULL);
661
                recvdatabuf[recv_id]->msgtype = msg_h->msg_type;
662

    
663
                // fill the buffer with zeros
664
                memset(recvdatabuf[recv_id]->recvbuf, 0, msg_h->msg_length);
665
                debug(" new @ id:%d\n",recv_id);
666
        } else {        //message structure already exists, no need to create new
667
                debug(" found @ id:%d\n",recv_id);
668
        }
669

    
670
        if (msg_h->offset == 0)
671
                recvdatabuf[recv_id]->firstPacketArrived = 1;
672

    
673

    
674
        // increment fragmentnr
675
        recvdatabuf[recv_id]->recvFragments++;
676
        // increment the arrivedBytes
677
        recvdatabuf[recv_id]->arrivedBytes += bufsize;
678

    
679
        // enter the data into the buffer
680
        memcpy(recvdatabuf[recv_id]->recvbuf + msg_h->offset, msgbuf, bufsize);
681

    
682
        //TODO very basic checkif all fragments arrived: has to be reviewed
683
        if(recvdatabuf[recv_id]->arrivedBytes == recvdatabuf[recv_id]->bufsize)
684
                recvdatabuf[recv_id]->status = COMPLETE; //buffer full -> msg completly arrived
685
        else
686
                recvdatabuf[recv_id]->status = ACTIVE;
687

    
688
        if (recv_data_callback) {
689
                if(recvdatabuf[recv_id]->status == COMPLETE) {
690
                        // Monitoring layer hook
691
                        if(get_Recv_data_inf_cb != NULL) {
692
                                mon_data_inf recv_data_inf;
693

    
694
                                recv_data_inf.remote_socketID =
695
                                         &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
696
                                recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
697
                                recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
698
                                recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
699
                                recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
700
                                recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
701
                                        recvdatabuf[recv_id]->recvbuf : NULL;
702
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
703
                                recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
704
                                recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
705
                                recv_data_inf.priority = false;
706
                                recv_data_inf.padding = false;
707
                                recv_data_inf.confirmation = false;
708
                                recv_data_inf.reliable = false;
709

    
710
                                // send data recv callback to monitoring module
711

    
712
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
713
                        }
714

    
715
                        // Get the right callback
716
                        receive_data_cb receive_data_callback = recvcbbuf[msg_h->msg_type];
717
                        if (receive_data_callback) {
718

    
719
                                recv_params rParams;
720

    
721
                                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
722
                                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
723
                                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
724
                                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
725
                                rParams.remote_socketID =
726
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
727

    
728
                                char str[1000];
729
                                mlSocketIDToString(rParams.remote_socketID,str,999);
730
                                debug("ML: received message from conID:%d, %s\n",recvdatabuf[recv_id]->connectionID,str);
731
                                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
732

    
733
                                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
734
                                        recvdatabuf[recv_id]->msgtype, (void *) &rParams);
735
                        } else {
736
                            warn("ML: callback not initialized for this message type: %d!\n",msg_h->msg_type);
737
                        }
738

    
739
                        //clean up
740
                        if (recvdatabuf[recv_id]->timeout_event) {
741
                                int ret;
742
                                debug("ML: freeing timeout for %d",recv_id);
743
                                ret = event_del(recvdatabuf[recv_id]->timeout_event);
744
                                event_free(recvdatabuf[recv_id]->timeout_event);
745
                                debug(" ret: %d\n",ret);
746
                        } else {
747
                                debug("ML: received in 1 packet\n",recv_id);
748
                        }
749
                        free(recvdatabuf[recv_id]->recvbuf);
750
                        free(recvdatabuf[recv_id]);
751
                        recvdatabuf[recv_id] = NULL;
752
                } else { // not COMPLETE
753
                        if (!recvdatabuf[recv_id]->timeout_event) {
754
                                //start time out
755
                                //TODO make timeout at least a DEFINE
756
                                struct timeval timeout = { 2, 0 };        //TODO: use some configurable timeout here
757
                                recvdatabuf[recv_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &recv_timeout_cb, (void *) (long)recv_id);
758
                                evtimer_add(recvdatabuf[recv_id]->timeout_event, &timeout);
759
                        }
760
                }
761
        }
762
}
763

    
764
//done
765
void pmtu_timeout_cb(int fd, short event, void *arg)
766
{
767
        debug("ML: pmtu timeout called\n");
768

    
769
        int con_id = (long) arg;
770
        pmtu new_pmtusize;
771
        struct timeval timeout;
772

    
773
        if(connectbuf[con_id] == NULL) {
774
                error("ML: pmtu timeout called on non existing con_id\n");
775
                return;
776
        }
777

    
778
        if(connectbuf[con_id]->status == READY) {
779
                // nothing to do anymore
780
                return;
781
        }
782

    
783
        timeout = connectbuf[con_id]->timeout_value;
784

    
785
        if(connectbuf[con_id]->delay || connectbuf[con_id]->trials == MAX_TRIALS - 1) {
786
                double delay = timeout.tv_sec + timeout.tv_usec / 1000000.0;
787
                delay = delay * 2;
788
                timeout.tv_sec = floor(delay);
789
                timeout.tv_usec = fmod(delay, 1.0) * 1000000.0;
790
                if(connectbuf[con_id]->delay) {
791
                        connectbuf[con_id]->delay = false;
792
                        goto reschedule;
793
                }
794
        }
795

    
796
        if(connectbuf[con_id]->trials == MAX_TRIALS) {
797
                // decrement the pmtu size
798
                connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
799
                connectbuf[con_id]->trials = 0;
800
        }
801

    
802
        //error in PMTU discovery?
803
        if (connectbuf[con_id]->pmtusize == ERROR) {
804
                if (connectbuf[con_id]->internal_connect == true) {
805
                        //as of now we tried directly connecting, now let's try trough the NAT
806
                        connectbuf[con_id]->internal_connect = false;
807
                        connectbuf[con_id]->pmtusize = MAX;
808
                } else {
809
                        //nothing to do we have to give up
810
                        error("ML: Could not create connection with connectionID %i!\n",con_id);
811
                        // envoke the callback for failed connection establishment
812
                        if(failed_Connection_cb != NULL)
813
                                (failed_Connection_cb) (con_id, NULL);
814
                        // delete the connection entry
815
                        mlCloseConnection(con_id);
816
                        return;
817
                }
818
        }
819

    
820
        //retry with new pmtu size
821
        connectbuf[con_id]->trials++;
822
        send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
823

    
824
reschedule:
825
        /* reschedule */
826
        event_base_once(base, -1, EV_TIMEOUT, pmtu_timeout_cb, (void *) (long)con_id, &timeout);
827
}
828

    
829
/*
830
 * decrements the mtu size
831
 */
832
pmtu pmtu_decrement(pmtu pmtusize)
833
{
834
        pmtu pmtu_return_size;
835
        switch(pmtusize) {
836
        case MAX:
837
                return DSL;
838
        case DSL:
839
                return DSLMEDIUM;
840
        case DSLMEDIUM:
841
                return DSLSLIM;
842
        case DSLSLIM:
843
                return BELOWDSL;
844
        case BELOWDSL:
845
                return MIN;
846
        default:
847
                return ERROR;
848
        }
849
}
850

    
851
void pmtu_error_cb_th(char *msg, int msglen)
852
{
853
        debug("ML: pmtu_error callback called msg_size: %d\n",msglen);
854
        //TODO debug
855
        return;
856

    
857
    char *msgbufptr = NULL;
858
    int msgtype;
859
    int connectionID;
860
    pmtu pmtusize;
861
    pmtu new_pmtusize;
862
    int dead = 0;
863

    
864
    // check the packettype
865
    msgbufptr = &msg[0];
866

    
867
    // check the msgtype
868
    msgbufptr = &msg[1];
869
    memcpy(&msgtype, msgbufptr, 4);
870

    
871
    if (msgtype == 0) {
872

    
873
        // get the connectionID
874
        msgbufptr = &msg[5];
875
        memcpy(&connectionID, msgbufptr, 4);
876

    
877
        int msgtype_c = connectbuf[connectionID]->status;
878
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
879

    
880
        if (msgtype_c != msgtype) {
881
            dead = 1;
882
        }
883

    
884

    
885
    } else if (msgtype == 1) {
886

    
887
        // read the connectionID
888
        msgbufptr = &msg[9];
889
        memcpy(&connectionID, msgbufptr, 4);
890

    
891
        int msgtype_c = connectbuf[connectionID]->status;
892
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
893

    
894
        if (msgtype_c != msgtype) {
895
            dead = 1;
896
        }
897

    
898
    }
899
    // decrement the pmtu size
900
    new_pmtusize = pmtu_decrement(pmtusize);
901

    
902
//    connectbuf[connectionID]->pmtutrysize = new_pmtusize;
903

    
904
    if (new_pmtusize == ERROR) {
905
                error("ML:  Could not create connection with connectionID %i !\n",
906
                        connectionID);
907

    
908
                if(failed_Connection_cb != NULL)
909
                        (failed_Connection_cb) (connectionID, NULL);
910
                // set the message type to a non existent message
911
                msgtype = 2;
912
                // delete the connection entry
913
                 mlCloseConnection(connectionID);
914
        }
915

    
916
    if (msgtype == 0 && dead != 1) {
917

    
918
        // stop the timeout event
919
        // timeout_del(connectbuf[connectionID]->timeout);
920
        /*
921
         * libevent2
922
         */
923

    
924
        // event_del(connectbuf[connectionID]->timeout);
925

    
926

    
927
        // create and send a connection message
928
//         create_conn_msg(new_pmtusize, connectionID,
929
//                         &local_socketID, INVITE);
930

    
931
//        send_conn_msg(connectionID, new_pmtusize);
932

    
933
        // set a timeout event for the pmtu discovery
934
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
935
        // *)&connectionID);
936

    
937
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
938

    
939
        /*
940
         * libevent2
941
         */
942

    
943
        struct event *ev;
944
        ev = evtimer_new(base, pmtu_timeout_cb,
945
                         (void *) connectbuf[connectionID]);
946

    
947
        // connectbuf[connectionID]->timeout = ev;
948

    
949
        event_add(ev, &connectbuf[connectionID]->timeout_value);
950

    
951
    } else if (msgtype == 1 && dead != 1) {
952

    
953
        // stop the timeout event
954
        // timeout_del(connectbuf[connectionID]->timeout);
955

    
956
        /*
957
         * libevent2
958
         */
959
        // info("still here 11 \n");
960
        // printf("ev %d \n",connectbuf[connectionID]->timeout);
961
        // event_del(connectbuf[connectionID]->timeout );
962
        // evtimer_del(connectbuf[connectionID]->timeout );
963

    
964

    
965
//         // create and send a connection message
966
//         create_conn_msg(new_pmtusize,
967
//                         connectbuf[connectionID]->connectionID,
968
//                         NULL, CONNECT);
969

    
970
        //send_conn_msg(connectionID, new_pmtusize);
971

    
972
        // set a timeout event for the pmtu discovery
973
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
974
        // *)&connectionID);
975
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
976

    
977
        /*
978
         * libevent2
979
         */
980
        // struct event *ev;
981
        // ev = evtimer_new(base,pmtu_timeout_cb, (void
982
        // *)connectbuf[connectionID]);
983
        // connectbuf[connectionID]->timeout = ev;
984
        // event_add(ev,&connectbuf[connectionID]->timeout_value);
985

    
986
    }
987
}
988

    
989
/*
990
 * what to do once a packet arrived if it is a conn packet send it to
991
 * recv_conn handler if it is a data packet send it to the recv_data
992
 * handler
993
 */
994

    
995
//done --
996
void recv_pkg(int fd, short event, void *arg)
997
{
998
        debug("ML: recv_pkg called\n");
999

    
1000
        struct msg_header *msg_h;
1001
        char msgbuf[MAX];
1002
        char *bufptr = msgbuf;
1003
        int ttl;
1004
        struct sockaddr_in recv_addr;
1005
        pmtu recvSize = MAX;
1006
        int msg_size;
1007

    
1008
        recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
1009

    
1010

    
1011
        // check if it is not just an ERROR message
1012
        if(recvSize < 0)
1013
                return;
1014

    
1015
        // @TODO check if this simplistic STUN message recognition really always works, probably not
1016
        unsigned short stun_bind_response = 0x0101;
1017
        unsigned short * msgspot = (unsigned short *) msgbuf;
1018
        if (*msgspot == stun_bind_response) {
1019
                debug("ML: recv_pkg: parse stun message called\n");
1020
                recv_stun_msg(msgbuf, recvSize);
1021
                return;
1022
        }
1023

    
1024
        msg_h = (struct msg_header *) msgbuf;
1025
        bufptr += MSG_HEADER_SIZE + msg_h->len_mon_packet_hdr;
1026
        msg_size = recvSize - MSG_HEADER_SIZE - msg_h->len_mon_packet_hdr;
1027

    
1028

    
1029
        if(get_Recv_pkt_inf_cb != NULL && msg_h->len_mon_packet_hdr != 0) {
1030
                mon_pkt_inf msginfNow;
1031
                msginfNow.monitoringHeaderLen = msg_h->len_mon_packet_hdr;
1032
                msginfNow.monitoringHeader = msg_h->len_mon_packet_hdr ? &msgbuf[0] + MSG_HEADER_SIZE : NULL;
1033
                //TODO rethink this ...
1034
                if(msg_h->msg_type == ML_CON_MSG) {
1035
                        struct conn_msg *c_msg = (struct conn_msg *) bufptr;
1036
                        msginfNow.remote_socketID = &(c_msg->sock_id);
1037
                }
1038
                else if(connectbuf[msg_h->remote_con_id] == NULL) {
1039
                        error("ML: received pkg called with non existent connection\n");
1040
                        return;
1041
                } else
1042
                        msginfNow.remote_socketID = &(connectbuf[msg_h->remote_con_id]->external_socketID);
1043
                msginfNow.buffer = bufptr;
1044
                msginfNow.bufSize = recvSize;
1045
                msginfNow.msgtype = msg_h->msg_type;
1046
                msginfNow.ttl = ttl;
1047
                msginfNow.dataID = msg_h->msg_seq_num;
1048
                msginfNow.offset = msg_h->offset;
1049
                msginfNow.datasize = msg_h->msg_length;
1050
                gettimeofday(&msginfNow.arrival_time, NULL);
1051
                (get_Recv_pkt_inf_cb) ((void *) &msginfNow);
1052
        }
1053

    
1054

    
1055
        switch(msg_h->msg_type) {
1056
                case ML_CON_MSG:
1057
                        debug("ML: received conn pkg\n");
1058
                        recv_conn_msg(msg_h, bufptr, msg_size);
1059
                        break;
1060
                default:
1061
                        if(msg_h->msg_type < 127) {
1062
                                debug("ML: received data pkg\n");
1063
                                recv_data_msg(msg_h, bufptr, msg_size);
1064
                                break;
1065
                        }
1066
                        debug("ML: unrecognised msg_type\n");
1067
                        break;
1068
        }
1069
}
1070

    
1071
/*
1072
 * compare the external IP address of two socketIDs
1073
 */
1074
int
1075
compare_external_address_socketIDs(socketID_handle sock1, socketID_handle sock2)
1076
{
1077
        if( sock1->external_addr.udpaddr.sin_addr.s_addr == sock2->external_addr.udpaddr.sin_addr.s_addr)
1078
                return 0;
1079
        return 1;
1080
}
1081

    
1082
void try_stun();
1083

    
1084
/*
1085
 * the timeout of the NAT traversal
1086
 */
1087
void nat_traversal_timeout(int fd, short event, void *arg)
1088
{
1089
        if (NAT_traversal == false) {
1090
                debug("ML: NAT traversal request re-send\n");
1091
                if(receive_SocketID_cb)
1092
                        (receive_SocketID_cb) (&local_socketID, 2);
1093
                try_stun();
1094
        }
1095
}
1096

    
1097
unsigned long resolve(const char *ipaddr)
1098
{
1099
        struct hostent *h = gethostbyname(ipaddr);
1100
        if (!h) {
1101
                error("ML: Unable to resolve host name %s\n", ipaddr);
1102
        exit(-1);
1103
    }
1104
    unsigned long *addr = (unsigned long *) (h->h_addr);
1105
    return *addr;
1106
}
1107

    
1108

    
1109
/*
1110
 * returns a handle to the socketID struct the ipaddr can be a null
1111
 * pointer. Then all available ipaddr on the machine are choosen.
1112
 */
1113
void create_socket(const int port, const char *ipaddr)
1114
{
1115
        struct sockaddr_in udpaddr;
1116
        udpaddr.sin_family = AF_INET;
1117
        if (ipaddr == NULL) {
1118
                /*
1119
                * try to guess the local IP address
1120
                */
1121
                const char *ipaddr_iface = mlAutodetectIPAddress();
1122
                if (ipaddr_iface) {
1123
                        udpaddr.sin_addr.s_addr = inet_addr(ipaddr_iface);
1124
                } else {
1125
                        udpaddr.sin_addr.s_addr = INADDR_ANY;
1126
                }
1127
        } else {
1128
                udpaddr.sin_addr.s_addr = inet_addr(ipaddr);
1129
        }
1130
        udpaddr.sin_port = htons(port);
1131

    
1132
        socketaddrgen udpgen;
1133
        memset(&udpgen,0,sizeof(socketaddrgen));        //this will be sent over the net, so set it to 0
1134
        udpgen.udpaddr = udpaddr;
1135
        local_socketID.internal_addr = udpgen;
1136

    
1137
        socketfd = createSocket(port, ipaddr);
1138

    
1139
        struct event *ev;
1140
        ev = event_new(base, socketfd, EV_READ | EV_PERSIST, recv_pkg, NULL);
1141

    
1142
        event_add(ev, NULL);
1143

    
1144
        try_stun();
1145
}
1146

    
1147
/*
1148
 * try to figure out external IP using STUN, if defined
1149
 */
1150
void try_stun()
1151
{
1152
        if (isStunDefined()) {
1153
                /*
1154
                * send the NAT traversal STUN request
1155
                */
1156
                 send_stun_request(socketfd, &stun_server);
1157

    
1158
                /*
1159
                * enter a NAT traversal timeout that takes care of retransmission
1160
                */
1161
                struct event *ev1;
1162
                struct timeval timeout_value_NAT_traversal = NAT_TRAVERSAL_TIMEOUT;
1163
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1164
                event_add(ev1, &timeout_value_NAT_traversal);
1165

    
1166
                NAT_traversal = false;
1167
        } else {
1168
                /*
1169
                * Assume we have accessibility and copy internal address to external one
1170
                */
1171
                local_socketID.external_addr = local_socketID.internal_addr;
1172
                NAT_traversal = true; // @TODO: this is not really NAT traversal, but a flag that init is over
1173
                // callback to the upper layer indicating that the socketID is now
1174
                // ready to use
1175
                if(receive_SocketID_cb)
1176
                        (receive_SocketID_cb) (&local_socketID, 0); //success
1177
        }
1178
}
1179

    
1180
/**************************** END OF INTERNAL ***********************/
1181

    
1182
/**************************** MONL functions *************************/
1183

    
1184
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){
1185

    
1186
        base = (struct event_base *) arg;
1187
        recv_data_callback = recv_data_cb;
1188
        mlSetRecvTimeout(timeout_value);
1189
        if (stun_ipaddr) {
1190
                 mlSetStunServer(stun_port, stun_ipaddr);
1191
        } else {
1192

    
1193
        }
1194
        register_recv_localsocketID_cb(local_socketID_cb);
1195
        create_socket(port, ipaddr);
1196

    
1197
}
1198

    
1199
/* register callbacks  */
1200
void mlRegisterGetRecvPktInf(get_recv_pkt_inf_cb recv_pkt_inf_cb){
1201

    
1202
        if (recv_pkt_inf_cb == NULL)
1203
                error("ML: Register get_recv_pkt_inf_cb failed: NULL ptr  \n");
1204
        else
1205
                get_Recv_pkt_inf_cb = recv_pkt_inf_cb;
1206

    
1207
}
1208

    
1209
void mlRegisterGetSendPktInf(get_send_pkt_inf_cb  send_pkt_inf_cb){
1210

    
1211
        if (send_pkt_inf_cb == NULL)
1212
                error("ML: Register get_send_pkt_inf_cb: NULL ptr  \n");
1213
        else
1214
                get_Send_pkt_inf_cb = send_pkt_inf_cb;
1215

    
1216
}
1217

    
1218

    
1219
void mlRegisterSetMonitoringHeaderPktCb(set_monitoring_header_pkt_cb monitoring_header_pkt_cb ){
1220

    
1221
        if (monitoring_header_pkt_cb == NULL)
1222
                error("ML: Register set_monitoring_header_pkt_cb: NULL ptr  \n");
1223
        else
1224
                set_Monitoring_header_pkt_cb = monitoring_header_pkt_cb;
1225

    
1226
}
1227

    
1228
void mlRegisterGetRecvDataInf(get_recv_data_inf_cb recv_data_inf_cb){
1229

    
1230
        if (recv_data_inf_cb == NULL)
1231
                error("ML: Register get_recv_data_inf_cb: NULL ptr  \n");
1232
        else
1233
                get_Recv_data_inf_cb = recv_data_inf_cb;
1234

    
1235
}
1236

    
1237
void mlRegisterGetSendDataInf(get_send_data_inf_cb  send_data_inf_cb){
1238

    
1239
        if (send_data_inf_cb == NULL)
1240
                error("ML: Register get_send_data_inf_cb: NULL ptr  \n");
1241
        else
1242
                get_Send_data_inf_cb = send_data_inf_cb;
1243

    
1244
}
1245

    
1246
void mlRegisterSetMonitoringHeaderDataCb(set_monitoring_header_data_cb monitoring_header_data_cb){
1247

    
1248
        if (monitoring_header_data_cb == NULL)
1249
                error("ML: Register set_monitoring_header_data_cb : NULL ptr  \n");
1250
        else
1251
        set_Monitoring_header_data_cb = monitoring_header_data_cb;
1252

    
1253
}
1254

    
1255
void mlSetRecvTimeout(struct timeval timeout_value){
1256

    
1257
        recv_timeout = timeout_value;
1258

    
1259
}
1260

    
1261
int mlGetStandardTTL(socketID_handle socketID,uint8_t *ttl){
1262

    
1263
        return getTTL(socketfd, ttl);
1264

    
1265
}
1266

    
1267
socketID_handle mlGetLocalSocketID(int *errorstatus){
1268

    
1269
        if (NAT_traversal == false) {
1270
                *errorstatus = 2;
1271
                return NULL;
1272
        }
1273

    
1274
        *errorstatus = 0;
1275
        return &local_socketID;
1276

    
1277
}
1278

    
1279

    
1280
/**************************** END of MONL functions *************************/
1281

    
1282
/**************************** GENERAL functions *************************/
1283

    
1284
void mlRegisterRecvConnectionCb(receive_connection_cb recv_conn_cb){
1285

    
1286
        if (recv_conn_cb == NULL)
1287
                error("ML: Register receive_connection_cb: NULL ptr  \n");
1288
        else
1289
                receive_Connection_cb = recv_conn_cb;
1290

    
1291
}
1292

    
1293
void mlRegisterErrorConnectionCb(connection_failed_cb conn_failed){
1294

    
1295
        if (conn_failed == NULL)
1296
                error("ML: Register connection_failed_cb: NULL ptr  \n");
1297
        else
1298
        failed_Connection_cb = conn_failed;
1299

    
1300
}
1301

    
1302
void mlRegisterRecvDataCb(receive_data_cb data_cb,unsigned char msgtype){
1303

    
1304
    if (msgtype > 126) {
1305

    
1306
            error
1307
            ("ML: Could not register recv_data callback. Msgtype is greater then 126 \n");
1308

    
1309
    }
1310

    
1311
    if (data_cb == NULL) {
1312

    
1313
            error("ML: Register receive data callback: NUll ptr \n ");
1314

    
1315
    } else {
1316

    
1317
        recvcbbuf[msgtype] = data_cb;
1318

    
1319
    }
1320

    
1321
}
1322

    
1323
void mlCloseSocket(socketID_handle socketID){
1324

    
1325
        free(socketID);
1326

    
1327
}
1328

    
1329
void keepalive_fn(evutil_socket_t fd, short what, void *arg) {
1330
        socketID_handle peer = arg;
1331

    
1332
        int con_id = mlConnectionExist(peer, false);
1333
        if (con_id < 0 || connectbuf[con_id]->defaultSendParams.keepalive <= 0) {
1334
                /* Connection fell from under us or keepalive was disabled */
1335
                free(arg);
1336
                return;
1337
        }
1338

    
1339
        /* do what we gotta do */
1340
        if ( connectbuf[con_id]->status == READY) {
1341
                char keepaliveMsg[32] = "";
1342
                sprintf(keepaliveMsg, "KEEPALIVE %d", connectbuf[con_id]->keepalive_seq++);
1343
                send_msg(con_id, MSG_TYPE_ML_KEEPALIVE, keepaliveMsg, 1 + strlen(keepaliveMsg), false, 
1344
                        &(connectbuf[con_id]->defaultSendParams));
1345
        }
1346

    
1347
        /* re-schedule */
1348
        struct timeval t = { 0,0 };
1349
        t.tv_sec = connectbuf[con_id]->defaultSendParams.keepalive;
1350
        if (connectbuf[con_id]->defaultSendParams.keepalive) 
1351
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1352
}
1353

    
1354
void setupKeepalive(int conn_id) {
1355
        /* Save the peer's address for us */
1356
        socketID_handle peer = malloc(sizeof(socket_ID));
1357
        memcpy(peer, &connectbuf[conn_id]->external_socketID, sizeof(socket_ID));
1358

    
1359
        struct timeval t = { 0,0 };
1360
        t.tv_sec = connectbuf[conn_id]->defaultSendParams.keepalive;
1361

    
1362
        if (connectbuf[conn_id]->defaultSendParams.keepalive) 
1363
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1364
}
1365

    
1366
/* connection functions */
1367
int mlOpenConnection(socketID_handle external_socketID,receive_connection_cb connection_cb,void *arg, const send_params defaultSendParams){
1368

    
1369
        int con_id;
1370
        if (external_socketID == NULL) {
1371
                error("ML: cannot open connection: one of the socketIDs is NULL\n");
1372
                return -1;
1373
        }
1374
        if (NAT_traversal == false) {
1375
                error("ML: cannot open connection: NAT traversal for socketID still in progress\n");
1376
                return -1;
1377
        }
1378
        if (connection_cb == NULL) {
1379
                error("ML: cannot open connection: connection_cb is NULL\n");
1380
                return -1;
1381
        }
1382

    
1383
        // check if that connection already exist
1384

    
1385
        con_id = mlConnectionExist(external_socketID, false);
1386
        if (con_id >= 0) {
1387
                // overwrite defaultSendParams
1388
                bool newKeepalive = 
1389
                        connectbuf[con_id]->defaultSendParams.keepalive == 0 && defaultSendParams.keepalive != 0;
1390
                connectbuf[con_id]->defaultSendParams = defaultSendParams;
1391
                if (newKeepalive) setupKeepalive(con_id);
1392
                // if so check if it is ready to use
1393
                if (connectbuf[con_id]->status == READY) {
1394
                                // if so use the callback immediately
1395
                                (connection_cb) (con_id, arg);
1396

    
1397
                // otherwise just write the connection cb and the arg pointer
1398
                // into the connection struct
1399
                } else {
1400
                        struct receive_connection_cb_list *temp;
1401
                        temp = malloc(sizeof(struct receive_connection_cb_list));
1402
                        temp->next = NULL;
1403
                        temp->connection_cb = connection_cb;
1404
                        temp->arg = arg;
1405
                        if(connectbuf[con_id]->connection_last != NULL) {
1406
                                connectbuf[con_id]->connection_last->next = temp;
1407
                                connectbuf[con_id]->connection_last = temp;
1408
                        } else
1409
                                connectbuf[con_id]->connection_last = connectbuf[con_id]->connection_head = temp;
1410
                }
1411
                return con_id;
1412
        }
1413
        // make entry in connection_establishment array
1414
        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
1415
                if (connectbuf[con_id] == NULL) {
1416
                        connectbuf[con_id] = (connect_data *) malloc(sizeof(connect_data));
1417
                        memset(connectbuf[con_id],0,sizeof(connect_data));
1418
                        connectbuf[con_id]->starttime = time(NULL);
1419
                        memcpy(&connectbuf[con_id]->external_socketID, external_socketID, sizeof(socket_ID));
1420
                        connectbuf[con_id]->pmtusize = DSLSLIM;
1421
                        connectbuf[con_id]->status = INVITE;
1422
                        connectbuf[con_id]->seqnr = 0;
1423
                        connectbuf[con_id]->internal_connect = !compare_external_address_socketIDs(external_socketID, &local_socketID);
1424
                        /*
1425
                        * timeout values for the pmtu discovery
1426
                        */
1427
                        connectbuf[con_id]->timeout_value.tv_sec = 0;        //TODO: make this timeout configurable
1428
                        connectbuf[con_id]->timeout_value.tv_usec = 250000;
1429
                        connectbuf[con_id]->connectionID = con_id;
1430

    
1431
                        connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
1432
                        connectbuf[con_id]->connection_last->next = NULL;
1433
                        connectbuf[con_id]->connection_last->connection_cb = connection_cb;
1434
                        connectbuf[con_id]->connection_last->arg = arg;
1435
                        connectbuf[con_id]->external_connectionID = -1;
1436

    
1437
                        connectbuf[con_id]->defaultSendParams = defaultSendParams;
1438
                        if (defaultSendParams.keepalive) setupKeepalive(con_id);
1439
                        break;
1440
                }
1441
        } //end of for
1442

    
1443
        if (con_id == CONNECTBUFSIZE) {
1444
                error("ML: Could not open connection: connection buffer full\n");
1445
                return -1;
1446
        }
1447

    
1448
        // create and send a connection message
1449
        send_conn_msg(con_id, MAX, INVITE);
1450

    
1451
        struct event *ev;
1452
        ev = evtimer_new(base, pmtu_timeout_cb, (void *) (long)con_id);
1453
        event_add(ev, &connectbuf[con_id]->timeout_value);
1454

    
1455
        return con_id;
1456

    
1457
}
1458

    
1459
void mlCloseConnection(const int connectionID){
1460

    
1461
        // remove it from the connection array
1462
        if(connectbuf[connectionID]) {
1463
                if(connectbuf[connectionID]->ctrl_msg_buf)
1464
                        free(connectbuf[connectionID]->ctrl_msg_buf);
1465
                free(connectbuf[connectionID]);
1466
                connectbuf[connectionID] = NULL;
1467
        }
1468

    
1469
}
1470

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

    
1473
        if (connectionID < 0) {
1474
                error("ML: send data failed: connectionID does not exist\n");
1475
                return;
1476
        }
1477

    
1478
        if (connectbuf[connectionID] == NULL) {
1479
                error("ML: send data failed: connectionID does not exist\n");
1480
                return;
1481
        }
1482
        if (connectbuf[connectionID]->status != READY) {
1483
            error("ML: send data failed: connection is not active\n");
1484
            return;
1485
        }
1486

    
1487
        if (sParams == NULL) {
1488
                sParams = &(connectbuf[connectionID]->defaultSendParams);
1489
        }
1490

    
1491
        send_msg(connectionID, msgtype, sendbuf, bufsize, false, sParams);
1492

    
1493
}
1494

    
1495
/* transmit data functions  */
1496
int mlSendAllData(const int connectionID,send_all_data_container *container,int nr_entries,unsigned char msgtype,send_params *sParams){
1497

    
1498
    if (nr_entries < 1 || nr_entries > 5) {
1499

    
1500
        error
1501
            ("ML : sendALlData : nr_enties is not between 1 and 5 \n ");
1502
        return 0;
1503

    
1504
    } else {
1505

    
1506
        if (nr_entries == 1) {
1507

    
1508
                mlSendData(connectionID, container->buffer_1,
1509
                      container->length_1, msgtype, sParams);
1510

    
1511
            return 1;
1512

    
1513
        } else if (nr_entries == 2) {
1514

    
1515
            int buflen = container->length_1 + container->length_2;
1516
            char buf[buflen];
1517
            memcpy(buf, container->buffer_1, container->length_1);
1518
            memcpy(&buf[container->length_1], container->buffer_2,
1519
                   container->length_2);
1520
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1521

    
1522
            return 1;
1523

    
1524
        } else if (nr_entries == 3) {
1525

    
1526
            int buflen =
1527
                container->length_1 + container->length_2 +
1528
                container->length_3;
1529
            char buf[buflen];
1530
            memcpy(buf, container->buffer_1, container->length_1);
1531
            memcpy(&buf[container->length_1], container->buffer_2,
1532
                   container->length_2);
1533
            memcpy(&buf[container->length_2], container->buffer_3,
1534
                   container->length_3);
1535
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1536

    
1537

    
1538
            return 1;
1539

    
1540
        } else if (nr_entries == 4) {
1541

    
1542
            int buflen =
1543
                container->length_1 + container->length_2 +
1544
                container->length_3 + container->length_4;
1545
            char buf[buflen];
1546
            memcpy(buf, container->buffer_1, container->length_1);
1547
            memcpy(&buf[container->length_1], container->buffer_2,
1548
                   container->length_2);
1549
            memcpy(&buf[container->length_2], container->buffer_3,
1550
                   container->length_3);
1551
            memcpy(&buf[container->length_3], container->buffer_4,
1552
                   container->length_4);
1553
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1554

    
1555
            return 1;
1556

    
1557
        } else {
1558

    
1559
            int buflen =
1560
                container->length_1 + container->length_2 +
1561
                container->length_3 + container->length_4 +
1562
                container->length_5;
1563
            char buf[buflen];
1564
            memcpy(buf, container->buffer_1, container->length_1);
1565
            memcpy(&buf[container->length_1], container->buffer_2,
1566
                   container->length_2);
1567
            memcpy(&buf[container->length_2], container->buffer_3,
1568
                   container->length_3);
1569
            memcpy(&buf[container->length_3], container->buffer_4,
1570
                   container->length_4);
1571
            memcpy(&buf[container->length_4], container->buffer_5,
1572
                   container->length_5);
1573
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1574

    
1575
            return 1;
1576
        }
1577

    
1578
    }
1579

    
1580
}
1581

    
1582
int mlRecvData(const int connectionID,char *recvbuf,int *bufsize,recv_params *rParams){
1583

    
1584
        //TODO yet to be converted
1585
        return 0;
1586
#if 0
1587
        if (rParams == NULL) {
1588
                error("ML: recv_data failed: recv_params is a NULL ptr\n");
1589
                return 0;
1590
    } else {
1591

1592
        info("ML: recv data called \n");
1593

1594
        int i = 0;
1595
        int returnValue = 0;
1596
        double timeout = (double) recv_timeout.tv_sec;
1597
        time_t endtime = time(NULL);
1598

1599
        for (i = 0; i < RECVDATABUFSIZE; i++) {
1600

1601
            if (recvdatabuf[i] != NULL) {
1602

1603
                if (recvdatabuf[i]->connectionID == connectionID) {
1604

1605
                    info("ML: recv data has entry  \n");
1606

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

1609
                    // check if the specified connection has data and it
1610
                    // is complete
1611
                    // check the data seqnr
1612
                    // if(connectionID == recvdatabuf[i]->connectionID &&
1613
                    // 1 == recvdatabuf[i]->status){
1614

1615
                    if (1 == recvdatabuf[i]->status) {
1616

1617
                        // info("transmissionHandler: recv_data set is
1618
                        // complete \n" );
1619

1620
                        // debug("debud \n");
1621

1622
                        // exchange the pointers
1623
                        int buffersize = 0;
1624
                        buffersize = recvdatabuf[i]->bufsize;
1625
                        *bufsize = buffersize;
1626
                        // recvbuf = recvdatabuf[i]->recvbuf;
1627

1628
                        // info("buffersize %d \n",buffersize);
1629
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1630
                               buffersize);
1631
                        // debug(" recvbuf %s \n",recvbuf );
1632

1633
//                         double nrMissFrags =
1634
//                             (double) recvdatabuf[i]->nrFragments /
1635
//                             (double) recvdatabuf[i]->recvFragments;
1636
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
1637

1638
//                        rParams->nrMissingFragments = nrMissingFragments;
1639
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
1640
                        rParams->msgtype = recvdatabuf[i]->msgtype;
1641
                        rParams->connectionID =
1642
                            recvdatabuf[i]->connectionID;
1643

1644
                        // break from the loop
1645
                        // debug(" recvbuf %s \n ",recvbuf);
1646

1647
                        // double nrMissFrags =
1648
                        // (double)recvdatabuf[i]->nrFragments /
1649
                        // (double)recvdatabuf[i]->recvFragments;
1650
                        // int nrMissingFragments =
1651
                        // (int)ceil(nrMissFrags);
1652

1653
                        if(get_Recv_data_inf_cb != NULL) {
1654
                                mon_data_inf recv_data_inf;
1655

1656
                                recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1657
                                recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1658
                                recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1659
                                recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1660
//                                 recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1661
//                                 recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1662
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
1663
                                recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1664
                                recv_data_inf.nrMissingFragments = nrMissingFragments;
1665
                                recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1666
                                recv_data_inf.priority = false;
1667
                                recv_data_inf.padding = false;
1668
                                recv_data_inf.confirmation = false;
1669
                                recv_data_inf.reliable = false;
1670

1671
                                // send data recv callback to monitoring module
1672

1673
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1674
                        }
1675

1676

1677
                        // free the allocated memory
1678
                        free(recvdatabuf[i]);
1679
                        recvdatabuf[i] = NULL;
1680

1681
                        returnValue = 1;
1682
                        break;
1683

1684
                    }
1685

1686
                    if (recvdatabuf[i] != NULL) {
1687

1688
                        if (timepass > timeout) {
1689

1690
                            info("ML: recv_data timeout called  \n");
1691

1692
                            // some data about the missing chunks should
1693
                            // be added here
1694
                            // exchange the pointers
1695
                            int buffersize = 0;
1696
                            buffersize = recvdatabuf[i]->bufsize;
1697
                            *bufsize = buffersize;
1698
                            // recvbuf = recvdatabuf[i]->recvbuf;
1699

1700
                            double nrMissFrags =
1701
                                (double) recvdatabuf[i]->nrFragments /
1702
                                (double) recvdatabuf[i]->recvFragments;
1703
                            int nrMissingFragments =
1704
                                (int) ceil(nrMissFrags);
1705

1706
                            // debug(" recvbuf %s \n",recvbuf );
1707

1708
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1709
                                   buffersize);
1710

1711
                            rParams->nrMissingFragments =
1712
                                nrMissingFragments;
1713
                            rParams->nrFragments =
1714
                                recvdatabuf[i]->nrFragments;
1715
                            rParams->msgtype = recvdatabuf[i]->msgtype;
1716
                            rParams->connectionID =
1717
                                recvdatabuf[i]->connectionID;
1718

1719
                                if(get_Recv_data_inf_cb != NULL) {
1720
                                        mon_data_inf recv_data_inf;
1721

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

1737
                                        // send data recv callback to monitoring module
1738

1739
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1740
                                }
1741

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

1746
                            returnValue = 1;
1747
                            break;
1748

1749
                        }
1750
                    }
1751

1752
                }
1753

1754
            }
1755
            // debug("2 recvbuf %s \n ",recvbuf);
1756
        }
1757
        return returnValue;
1758
    }
1759
#endif
1760

    
1761
}
1762

    
1763
int mlSocketIDToString(socketID_handle socketID,char* socketID_string, size_t len){
1764

    
1765
        char internal_addr[INET_ADDRSTRLEN];
1766
        char external_addr[INET_ADDRSTRLEN];
1767
        inet_ntop(AF_INET, &(socketID->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1768
        inet_ntop(AF_INET, &(socketID->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1769

    
1770
        snprintf(socketID_string,len,"%s:%d-%s:%d", internal_addr, ntohs(socketID->internal_addr.udpaddr.sin_port),
1771
                external_addr,        ntohs(socketID->external_addr.udpaddr.sin_port));
1772
        return 0;
1773

    
1774
}
1775

    
1776
int mlStringToSocketID(const char* socketID_string, socketID_handle socketID){
1777

    
1778
        //@TODO add checks against malformed string
1779
        char external_addr[INET_ADDRSTRLEN];
1780
        int external_port;
1781
        char internal_addr[INET_ADDRSTRLEN];
1782
        int internal_port;
1783

    
1784
        char *pch;
1785
        char *s = strdup(socketID_string);
1786

    
1787
        //replace ':' with a blank
1788
        pch=strchr(s,':');
1789
        while (pch!=NULL){
1790
                                *pch = ' ';
1791
                pch=strchr(pch+1,':');
1792
        }
1793
        pch=strchr(s,'-');
1794
        if(pch) *pch = ' ';
1795

    
1796
        sscanf(s,"%s %d %s %d", internal_addr, &internal_port,
1797
                external_addr, &external_port);
1798

    
1799
        if(inet_pton(AF_INET, internal_addr, &(socketID->internal_addr.udpaddr.sin_addr)) == 0)
1800
                return EINVAL;
1801
        socketID->internal_addr.udpaddr.sin_family = AF_INET;
1802
        socketID->internal_addr.udpaddr.sin_port = htons(internal_port);
1803

    
1804

    
1805
        if(inet_pton(AF_INET, external_addr, &(socketID->external_addr.udpaddr.sin_addr)) ==0)
1806
                return EINVAL;
1807
        socketID->external_addr.udpaddr.sin_family = AF_INET;
1808
        socketID->external_addr.udpaddr.sin_port = htons(external_port);
1809

    
1810
        free(s);
1811
        return 0;
1812

    
1813
}
1814

    
1815
int mlGetConnectionStatus(int connectionID){
1816

    
1817
        if(connectbuf[connectionID])
1818
                return connectbuf[connectionID]->status == READY;
1819
        return -1;
1820
    
1821
}
1822

    
1823

    
1824
int mlConnectionExist(socketID_handle socketID, bool ready){
1825

    
1826
    /*
1827
     * check if another connection for the external connectionID exist
1828
     * that was established \ within the last 2 seconds
1829
     */
1830
        int i;
1831
        for (i = 0; i < CONNECTBUFSIZE; i++)
1832
                if (connectbuf[i] != NULL)
1833
                        if (mlCompareSocketIDs(&(connectbuf[i]->external_socketID), socketID) == 0) {
1834
                                if (ready) return (connectbuf[i]->status == READY ? i : -1);;
1835
                                return i;
1836
                                }
1837

    
1838
    return -1;
1839

    
1840
}
1841

    
1842
//Added by Robert Birke as comodity functions
1843

    
1844
//int mlPrintSocketID(socketID_handle socketID) {
1845
//        char str[SOCKETID_STRING_SIZE];
1846
//        mlSocketIDToString(socketID, str, sizeof(str));
1847
//        printf(stderr,"int->%s<-ext\n",str);
1848
//}
1849

    
1850
/*
1851
 * hash code of a socketID
1852
 * TODO might think of a better way
1853
 */
1854
int mlHashSocketID(socketID_handle sock) {
1855
    return sock->internal_addr.udpaddr.sin_port +
1856
                          sock->external_addr.udpaddr.sin_port;
1857
}
1858

    
1859
int mlCompareSocketIDs(socketID_handle sock1, socketID_handle sock2) {
1860
        /*
1861
        * compare internal addr
1862
        */
1863
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr !=
1864
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
1865
                        return 1;
1866

    
1867
        if (sock1->internal_addr.udpaddr.sin_port !=
1868
                 sock2->internal_addr.udpaddr.sin_port)
1869
                        return 1;
1870

    
1871
        /*
1872
        * compare external addr
1873
        */
1874
        if (sock1->external_addr.udpaddr.sin_addr.s_addr !=
1875
            sock2->external_addr.udpaddr.sin_addr.s_addr)
1876
                        return 1;
1877

    
1878
        if (sock1->external_addr.udpaddr.sin_port !=
1879
                 sock2->external_addr.udpaddr.sin_port)
1880
                        return 1;
1881

    
1882
        return 0;
1883
}
1884

    
1885
int mlCompareSocketIDsByPort(socketID_handle sock1, socketID_handle sock2)
1886
{ 
1887
        if (sock1->internal_addr.udpaddr.sin_port !=
1888
                 sock2->internal_addr.udpaddr.sin_port)
1889
                        return 1;
1890

    
1891
        if (sock1->external_addr.udpaddr.sin_port !=
1892
                 sock2->external_addr.udpaddr.sin_port)
1893
                        return 1;
1894
        return 0;
1895
}
1896

    
1897
int mlGetPathMTU(int ConnectionId) {
1898
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
1899
                return -1;
1900
        if (connectbuf[ConnectionId] != NULL)
1901
                return connectbuf[ConnectionId]->pmtusize;
1902
        return -1;
1903
}
1904

    
1905
/**************************** END of GENERAL functions *************************/
1906

    
1907
/**************************** NAT functions *************************/
1908

    
1909
/* setter  */
1910
void mlSetStunServer(const int port,const char *ipaddr){
1911

    
1912
        stun_server.sin_family = AF_INET;
1913
        if (ipaddr == NULL)
1914
                stun_server.sin_addr.s_addr = htonl(INADDR_ANY);
1915
        else
1916
                stun_server.sin_addr.s_addr = resolve(ipaddr);
1917
        stun_server.sin_port = htons(port);
1918

    
1919
}
1920

    
1921
int mlGetExternalIP(char* external_addr){
1922

    
1923
        socketaddrgen udpgen;
1924
        struct sockaddr_in udpaddr;
1925

    
1926
        udpgen = local_socketID.external_addr;
1927
        udpaddr = udpgen.udpaddr;
1928

    
1929
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
1930
                        INET_ADDRSTRLEN);
1931

    
1932
        if (external_addr == NULL) {
1933

    
1934
        return -1;
1935

    
1936
        } else {
1937

    
1938
        return 0;
1939

    
1940
        }
1941

    
1942
}
1943

    
1944
/**************************** END of NAT functions *************************/