Statistics
| Branch: | Revision:

ml / ml.c @ 980f3707

History | View | Annotate | Download (55.3 KB)

1
/*
2
 *          Policy Management
3
 *
4
 *          NEC Europe Ltd. PROPRIETARY INFORMATION
5
 *
6
 * This software is supplied under the terms of a license agreement
7
 * or nondisclosure agreement with NEC Europe Ltd. and may not be
8
 * copied or disclosed except in accordance with the terms of that
9
 * agreement.
10
 *
11
 *      Copyright (c) 2009 NEC Europe Ltd. All Rights Reserved.
12
 *
13
 * Authors: Kristian Beckers  <beckers@nw.neclab.eu>
14
 *          Sebastian Kiesel  <kiesel@nw.neclab.eu>
15
 *          
16
 *
17
 * NEC Europe Ltd. DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED,
18
 * INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY
19
 * AND FITNESS FOR A PARTICULAR PURPOSE AND THE WARRANTY AGAINST LATENT
20
 * DEFECTS, WITH RESPECT TO THE PROGRAM AND THE ACCOMPANYING
21
 * DOCUMENTATION.
22
 *
23
 * No Liability For Consequential Damages IN NO EVENT SHALL NEC Europe
24
 * Ltd., NEC Corporation OR ANY OF ITS SUBSIDIARIES BE LIABLE FOR ANY
25
 * DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS
26
 * OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF INFORMATION, OR
27
 * OTHER PECUNIARY LOSS AND INDIRECT, CONSEQUENTIAL, INCIDENTAL,
28
 * ECONOMIC OR PUNITIVE DAMAGES) ARISING OUT OF THE USE OF OR INABILITY
29
 * TO USE THIS PROGRAM, EVEN IF NEC Europe Ltd. HAS BEEN ADVISED OF THE
30
 * POSSIBILITY OF SUCH DAMAGES.
31
 *
32
 *     THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
33
 */
34

    
35
#include <arpa/inet.h>
36
#include <netinet/in.h>
37
#include <sys/socket.h>
38
#include <fcntl.h>
39
#include <event2/event.h>
40
#include <stdlib.h>
41
#include <unistd.h>
42
#include <stdio.h>
43
#include <stddef.h>
44
#include <stdint.h>
45
#include <string.h>
46
#include <sys/types.h>
47
#include <arpa/inet.h>
48
#include <netdb.h>
49
#include <errno.h>
50
#include <time.h>
51
#include <math.h>
52
#include "msg_types.h"
53
#include "util/udpSocket.h"
54
#include "util/stun.h"
55
#include "transmissionHandler.h"
56

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

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

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

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

    
80
/*
81
 * global variables
82
 */
83
/*
84
 * define a buffer of pointers to connect structures
85
 */
86
connect_data *connectbuf[CONNECTBUFSIZE];
87

    
88
/*
89
 * define a pointer buffer with pointers to recv_data structures
90
 */
91
recvdata *recvdatabuf[RECVDATABUFSIZE];
92

    
93
/*
94
 * define a pointer buffer for message multiplexing
95
 */
96
receive_data_cb recvcbbuf[MSGMULTIPLEXSIZE];
97

    
98
/*
99
 * stun server address
100
 */
101
struct sockaddr_in stun_server;
102

    
103
/*
104
 * receive timeout
105
 */
106
struct timeval recv_timeout;
107

    
108
/*
109
 * boolean NAT traversal successful if true
110
 */
111
boolean NAT_traversal;
112

    
113
/*
114
 * file descriptor for local socket
115
 */
116
evutil_socket_t socketfd;
117

    
118
/*
119
 * local socketID
120
 */
121
socket_ID local_socketID;
122

    
123
socketID_handle loc_socketID = &local_socketID;
124

    
125
/*
126
 * callback function pointers
127
 */
128
/*
129
 * monitoring module callbacks
130
 */
131
get_recv_pkt_inf_cb get_Recv_pkt_inf_cb = NULL;
132
get_send_pkt_inf_cb get_Send_pkt_inf_cb = NULL;
133
set_monitoring_header_pkt_cb set_Monitoring_header_pkt_cb = NULL;
134
get_recv_data_inf_cb get_Recv_data_inf_cb = NULL;
135
get_send_data_inf_cb get_Send_data_inf_cb = NULL;
136
set_monitoring_header_data_cb set_Monitoring_header_data_cb = NULL;
137
/*
138
 * connection callbacks
139
 */
140
receive_connection_cb receive_Connection_cb = NULL;
141
connection_failed_cb failed_Connection_cb = NULL;
142
/*
143
 * local socketID callback
144
 */
145
receive_localsocketID_cb receive_SocketID_cb;
146

    
147
/*
148
 * boolean that defines if received data is transmitted to the upper layer
149
 * via callback or via upper layer polling
150
 */
151
boolean recv_data_callback;
152

    
153
/*
154
 * helper function to get rid of a warning
155
 */
156
int min(int a, int b) {
157
        if (a > b) return b;
158
        return a;
159
}
160

    
161
void register_recv_localsocketID_cb(receive_localsocketID_cb local_socketID_cb)
162
{
163
        if (local_socketID_cb == NULL)
164
                error("ML : Register receive_localsocketID_cb: NULL ptr \n");
165
        else
166
        receive_SocketID_cb = local_socketID_cb;
167
}
168

    
169

    
170
//void keep_connection_alive(const int connectionID)
171
//{
172
//
173
//    // to be done with the NAT traversal
174
//    // send a message over the wire
175
//    printf("\n");
176
//
177
//}
178

    
179
void unsetStunServer()
180
{
181
        stun_server.sin_addr.s_addr = 0;
182
}
183

    
184
bool isStunDefined()
185
{
186
        return stun_server.sin_addr.s_addr;
187
}
188

    
189
void send_msg(int con_id, int msg_type, char* msg, int msg_len, bool truncable, send_params * sParams) {
190
        socketaddrgen udpgen;
191
        bool retry;
192
        int pkt_len, offset;
193
        struct iovec iov[4];
194

    
195
        char h_pkt[MON_HEADER_SPACE];
196
        char h_data[MON_HEADER_SPACE];
197

    
198
        struct msg_header msg_h;
199

    
200
        char str[1000];
201
        mlSocketIDToString(&connectbuf[con_id]->external_socketID,str,999);
202
        debug("ML: send_msg to conID:%d extID:%d, %s\n",con_id,connectbuf[con_id]->external_connectionID,str);
203

    
204
        iov[0].iov_base = &msg_h;
205
        iov[0].iov_len = MSG_HEADER_SIZE;
206

    
207
        msg_h.local_con_id = con_id;
208
        msg_h.remote_con_id = connectbuf[con_id]->external_connectionID;
209
        msg_h.msg_type = msg_type;
210
        msg_h.msg_seq_num = connectbuf[con_id]->seqnr++;
211

    
212

    
213
        iov[1].iov_len = iov[2].iov_len = 0;
214
        iov[1].iov_base = h_pkt;
215
        iov[2].iov_base = h_data;
216

    
217

    
218
        if (connectbuf[con_id]->internal_connect)
219
                udpgen = connectbuf[con_id]->external_socketID.internal_addr;
220
        else
221
                udpgen = connectbuf[con_id]->external_socketID.external_addr;
222

    
223
        do{
224
                offset = 0;
225
                retry = false;
226
                // Monitoring layer hook
227
                if(set_Monitoring_header_data_cb != NULL) {
228
                        iov[2].iov_len = ((set_Monitoring_header_data_cb) (&(connectbuf[con_id]->external_socketID), msg_type));
229
                }
230
                msg_h.len_mon_data_hdr = iov[2].iov_len;
231

    
232
                if(get_Send_data_inf_cb != NULL && iov[2].iov_len != 0) {
233
                        mon_data_inf sd_data_inf;
234

    
235
                        sd_data_inf.remote_socketID = &(connectbuf[con_id]->external_socketID);
236
                        sd_data_inf.buffer = msg;
237
                        sd_data_inf.bufSize = msg_len;
238
                        sd_data_inf.msgtype = msg_type;
239
                        sd_data_inf.monitoringDataHeader = iov[2].iov_base;
240
                        sd_data_inf.monitoringDataHeaderLen = iov[2].iov_len;
241
                        sd_data_inf.priority = sParams->priority;
242
                        sd_data_inf.padding = sParams->padding;
243
                        sd_data_inf.confirmation = sParams->confirmation;
244
                        sd_data_inf.reliable = sParams->reliable;
245
                        memset(&sd_data_inf.arrival_time, 0, sizeof(struct timeval));
246

    
247
                        (get_Send_data_inf_cb) ((void *) &sd_data_inf);
248
                }
249

    
250
                do {
251
                        if(set_Monitoring_header_pkt_cb != NULL) {
252
                                iov[1].iov_len = (set_Monitoring_header_pkt_cb) (&(connectbuf[con_id]->external_socketID), msg_type);
253
                        }
254
                        pkt_len = min(connectbuf[con_id]->pmtusize - iov[2].iov_len - iov[1].iov_len - iov[0].iov_len, msg_len - offset) ;
255

    
256
                        iov[3].iov_len = pkt_len;
257
                        iov[3].iov_base = msg + offset;
258

    
259
                        //fill header
260
                        msg_h.len_mon_packet_hdr = iov[1].iov_len;
261
                        msg_h.offset = offset;
262
                        msg_h.msg_length = truncable ? pkt_len : msg_len;
263

    
264
                        //monitoring layer hook
265
                        if(get_Send_pkt_inf_cb != NULL && iov[1].iov_len) {
266
                                mon_pkt_inf pkt_info;
267

    
268
                                pkt_info.remote_socketID = &(connectbuf[con_id]->external_socketID);
269
                                pkt_info.buffer = msg + offset;
270
                                pkt_info.bufSize = pkt_len;
271
                                pkt_info.msgtype = msg_type;
272
                                pkt_info.dataID = connectbuf[con_id]->seqnr;
273
                                pkt_info.offset = offset;
274
                                pkt_info.datasize = msg_len;
275
                                pkt_info.monitoringHeaderLen = iov[1].iov_len;
276
                                pkt_info.monitoringHeader = iov[1].iov_base;
277
                                pkt_info.ttl = -1;
278
                                memset(&(pkt_info.arrival_time),0,sizeof(struct timeval));
279

    
280
                                (get_Send_pkt_inf_cb) ((void *) &pkt_info);
281
                        }
282

    
283
                        debug("ML: sending packet with rconID:%d lconID:%d\n",msg_h.remote_con_id,msg_h.local_con_id);
284
                        switch(sendPacket(socketfd, iov, 4, &udpgen.udpaddr)) {
285
                                case MSGLEN:
286
                                        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);
287
                                        connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
288
                                        connectbuf[con_id]->delay = true;
289
                                        retry = true;
290
                                        offset = msg_len + msg_h.len_mon_data_hdr; // exit the while
291
                                        break;
292
                                case FAILURE:
293
                                        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);
294
                                        offset = msg_len + msg_h.len_mon_data_hdr; // exit the while
295
                                        break;
296
                                case OK:
297
                                        //update
298
                                        offset += pkt_len + iov[2].iov_len;
299
                                        //transmit data header only in the first packet
300
                                        iov[2].iov_len = 0;
301
                                        break;
302
                        }
303
                } while(offset != msg_len + msg_h.len_mon_data_hdr && !truncable);
304
        } while(retry);
305
}
306

    
307
void send_conn_msg(int con_id, int buf_size, int command_type)
308
{
309
        if (buf_size < sizeof(struct conn_msg)) {
310
                error("ML: requested connection message size is too small\n");
311
                return;
312
        }
313

    
314
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
315
                connectbuf[con_id]->ctrl_msg_buf = malloc(buf_size);
316
                memset(connectbuf[con_id]->ctrl_msg_buf, 0, buf_size);
317
        }
318

    
319
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
320
                error("ML: can not allocate memory for connection message\n");
321
                return;
322
        }
323

    
324
        struct conn_msg *msg_header = (struct conn_msg*) connectbuf[con_id]->ctrl_msg_buf;
325

    
326
        msg_header->comand_type = command_type;
327
        msg_header->pmtu_size = connectbuf[con_id]->pmtusize;
328

    
329
        memcpy(&(msg_header->sock_id), loc_socketID, sizeof(socket_ID));
330

    
331
        send_msg(con_id, ML_CON_MSG, connectbuf[con_id]->ctrl_msg_buf, buf_size, true, &(connectbuf[con_id]->defaultSendParams));
332
}
333

    
334
void
335
recv_conn_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
336
{
337
        struct conn_msg *con_msg;
338
        int free_con_id, con_id;
339

    
340
        time_t now = time(NULL);
341
        double timediff = 0.0;
342
        char str[1000];
343

    
344
        // Monitoring layer hook
345
        if(get_Recv_data_inf_cb != NULL && msg_h->len_mon_data_hdr != 0) {
346
                // update pointer to the real data
347
                msgbuf += msg_h->len_mon_data_hdr;
348
                bufsize -= msg_h->len_mon_data_hdr;
349
                con_msg = (struct conn_msg *)msgbuf;
350

    
351
                mon_data_inf recv_data_inf;
352
                recv_data_inf.remote_socketID = &(con_msg->sock_id);
353
                recv_data_inf.buffer = msgbuf;
354
                recv_data_inf.bufSize = bufsize;
355
                recv_data_inf.msgtype = msg_h->msg_type;
356
                recv_data_inf.monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
357
                recv_data_inf.monitoringDataHeader = msg_h->len_mon_data_hdr ? msgbuf : NULL;
358
                gettimeofday(&recv_data_inf.arrival_time, NULL);
359
                recv_data_inf.firstPacketArrived = true;
360
                recv_data_inf.recvFragments = 1;
361
                recv_data_inf.priority = false;
362
                recv_data_inf.padding = false;
363
                recv_data_inf.confirmation = false;
364
                recv_data_inf.reliable = false;
365

    
366
                // send data recv callback to monitoring module
367
                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
368
        } else {
369
                con_msg = (struct conn_msg *) msgbuf;
370
        }
371

    
372
        //decode sock_id for debug messages
373
        mlSocketIDToString(&con_msg->sock_id,str,999);
374

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

    
404
                        if (con_id == CONNECTBUFSIZE) {
405
                                // create an entry in the connecttrybuf
406
                                if(free_con_id == -1) {
407
                                        error("ML: no new connect_buf available\n");
408
                                        return;
409
                                }
410
                                connectbuf[free_con_id] = (connect_data *) malloc(sizeof(connect_data));
411
                                memset(connectbuf[free_con_id],0,sizeof(connect_data));
412
                                connectbuf[free_con_id]->connection_head = connectbuf[free_con_id]->connection_last = NULL;
413
                                connectbuf[free_con_id]->starttime = time(NULL);
414
                                memcpy(&(connectbuf[free_con_id]->external_socketID), &(con_msg->sock_id), sizeof(socket_ID));
415
                                connectbuf[free_con_id]->pmtusize = con_msg->pmtu_size;
416
                                connectbuf[free_con_id]->external_connectionID = msg_h->local_con_id;
417
                                connectbuf[free_con_id]->internal_connect =
418
                                        !compare_external_address_socketIDs(&(con_msg->sock_id), loc_socketID);
419
                                con_id = free_con_id;
420
                        }
421

    
422
                        //if(connectbuf[con_id]->status <= CONNECT) { //TODO: anwer anyway. Why the outher would invite otherwise?
423
                                //update status and send back answer
424
                                connectbuf[con_id]->status = CONNECT;
425
                                send_conn_msg(con_id, con_msg->pmtu_size, CONNECT);
426
                        //}
427
                        break;
428
                case CONNECT:
429
                        info("ML: received CONNECT from %s\n",str);
430

    
431
                        if(msg_h->remote_con_id != -1 && connectbuf[msg_h->remote_con_id] == NULL) {
432
                                error("ML: received CONNECT for inexistent connection rconID:%d\n",msg_h->remote_con_id);
433
                                return;
434
                        }
435

    
436
                        /*
437
                        * check if the connection status is not already 1 or 2
438
                        */
439
                        if (connectbuf[msg_h->remote_con_id]->status == INVITE) {
440
                                // set the external connectionID
441
                                connectbuf[msg_h->remote_con_id]->external_connectionID = msg_h->local_con_id;
442
                                // change status con_msg the connection_data
443
                                connectbuf[msg_h->remote_con_id]->status = READY;
444
                                // change pmtusize in the connection_data
445
                                connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
446

    
447
                                // send the READY
448
                                send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
449

    
450
                                if (receive_Connection_cb != NULL)
451
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
452

    
453
                                // call all registered callbacks
454
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
455
                                        struct receive_connection_cb_list *temp;
456
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
457
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
458
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
459
                                        free(temp);
460
                                }
461
                                connectbuf[msg_h->remote_con_id]->connection_head =
462
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
463
                        } else
464
                                // send the READY
465
                                send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
466

    
467
                        debug("ML: active connection established\n");
468
                        break;
469

    
470
                        /*
471
                        * if READY: find the entry in the connection array set the
472
                        * connection active change the pmtu size
473
                        */
474
                case READY:
475
                        info("ML: received READY from %s\n",str);
476
                        if(connectbuf[msg_h->remote_con_id] == NULL) {
477
                                error("ML: received READY for inexistent connection\n");
478
                                return;
479
                        }
480
                        /*
481
                        * checks if the connection is not already established
482
                        */
483
                        if (connectbuf[msg_h->remote_con_id]->status == CONNECT) {
484
                                // change status of the connection
485
                                connectbuf[msg_h->remote_con_id]->status = 2;
486
                                // change pmtusize
487
                                connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
488

    
489
                                if (receive_Connection_cb != NULL)
490
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
491

    
492
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
493
                                        struct receive_connection_cb_list *temp;
494
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
495
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
496
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
497
                                        free(temp);
498
                                }
499
                                connectbuf[msg_h->remote_con_id]->connection_head =
500
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
501
                                debug("ML: passive connection established\n");
502
                        }
503
                        break;
504
        }
505
}
506

    
507
void recv_stun_msg(char *msgbuf, int recvSize)
508
{
509
        /*
510
        * create empty stun message struct
511
        */
512
        StunMessage resp;
513
        memset(&resp, 0, sizeof(StunMessage));
514
        /*
515
        * parse the message
516
        */
517
        int returnValue = 0;
518
        returnValue = recv_stun_message(msgbuf, recvSize, &resp);
519

    
520
        if (returnValue == 0) {
521
                /*
522
                * read the reflexive Address into the local_socketID
523
                */
524
                struct sockaddr_in reflexiveAddr;
525
                reflexiveAddr.sin_family = AF_INET;
526
                reflexiveAddr.sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
527
                reflexiveAddr.sin_port = htons(resp.mappedAddress.ipv4.port);
528
                socketaddrgen reflexiveAddres;
529
                reflexiveAddres.udpaddr = reflexiveAddr;
530
                local_socketID.external_addr = reflexiveAddres;
531
                NAT_traversal = true;
532
                // callback to the upper layer indicating that the socketID is now
533
                // ready to use
534
                (receive_SocketID_cb) (&local_socketID, 0);
535
        }
536
}
537

    
538
//done
539
void recv_timeout_cb(int fd, short event, void *arg)
540
{
541
        int recv_id = (long) arg;
542
        debug("ML: recv_timeout_cb called. Timeout for id:%d\n",recv_id);
543

    
544
        if (recvdatabuf[recv_id] == NULL) {
545
                return;
546
        }
547

    
548

    
549
/*        if(recvdatabuf[recv_id]->status == ACTIVE) {
550
                //TODO make timeout at least a DEFINE
551
                struct timeval timeout = { 4, 0 };
552
                recvdatabuf[recv_id]->status = INACTIVE;
553
                event_base_once(base, -1, EV_TIMEOUT, recv_timeout_cb,
554
                        arg, &timeout);
555
                return;
556
        }
557
*/
558

    
559
        if(recvdatabuf[recv_id]->status == ACTIVE) {
560
                // Monitoring layer hook
561
                if(get_Recv_data_inf_cb != NULL) {
562
                        mon_data_inf recv_data_inf;
563

    
564
                        recv_data_inf.remote_socketID =
565
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
566
                        recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
567
                        recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
568
                        recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
569
                        recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
570
                        recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
571
                                recvdatabuf[recv_id]->recvbuf : NULL;
572
                        gettimeofday(&recv_data_inf.arrival_time, NULL);
573
                        recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
574
                        recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
575
                        recv_data_inf.priority = false;
576
                        recv_data_inf.padding = false;
577
                        recv_data_inf.confirmation = false;
578
                        recv_data_inf.reliable = false;
579

    
580
                        // send data recv callback to monitoring module
581

    
582
                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
583
                }
584

    
585
                // Get the right callback
586
                receive_data_cb receive_data_callback = recvcbbuf[recvdatabuf[recv_id]->msgtype];
587

    
588
                recv_params rParams;
589

    
590
                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
591
                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
592
                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
593
                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
594
                rParams.remote_socketID =
595
                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
596
                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
597

    
598
                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
599
                        recvdatabuf[recv_id]->msgtype, &rParams);
600

    
601
                //clean up
602
                free(recvdatabuf[recv_id]->recvbuf);
603
                free(recvdatabuf[recv_id]);
604
                recvdatabuf[recv_id] = NULL;
605
        }
606
}
607

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

    
613
        int recv_id, free_recv_id = -1;
614

    
615
        if(connectbuf[msg_h->remote_con_id] == NULL) {
616
                debug("ML: Received a message not related to any opened connection!\n");
617
                return;
618
        }
619

    
620
        // check if a recv_data exist and enter data
621
        for (recv_id = 0; recv_id < RECVDATABUFSIZE; recv_id++)
622
                if (recvdatabuf[recv_id] != NULL) {
623
                        if (msg_h->remote_con_id == recvdatabuf[recv_id]->connectionID &&
624
                                        msg_h->msg_seq_num == recvdatabuf[recv_id]->seqnr)
625
                                                break;
626
                } else
627
                        if(free_recv_id == -1)
628
                                free_recv_id = recv_id;
629

    
630

    
631
        if(recv_id == RECVDATABUFSIZE) {
632
                //no recv_data found: create one
633
                recv_id = free_recv_id;
634
                recvdatabuf[recv_id] = (recvdata *) malloc(sizeof(recvdata));
635
                memset(recvdatabuf[recv_id], 0, sizeof(recvdata));
636
                recvdatabuf[recv_id]->connectionID = msg_h->remote_con_id;
637
                recvdatabuf[recv_id]->seqnr = msg_h->msg_seq_num;
638
                recvdatabuf[recv_id]->monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
639
                recvdatabuf[recv_id]->bufsize = msg_h->msg_length + msg_h->len_mon_data_hdr;
640
                recvdatabuf[recv_id]->recvbuf = (char *) malloc(recvdatabuf[recv_id]->bufsize);
641
                /*
642
                * read the timeout data and set it
643
                */
644
                recvdatabuf[recv_id]->timeout_value.tv_sec = recv_timeout.tv_sec;
645
                recvdatabuf[recv_id]->timeout_value.tv_usec = recv_timeout.tv_usec;
646
                recvdatabuf[recv_id]->timeout_event = NULL;
647
                recvdatabuf[recv_id]->recvID = recv_id;
648
                recvdatabuf[recv_id]->starttime = time(NULL);
649
                recvdatabuf[recv_id]->msgtype = msg_h->msg_type;
650

    
651
                // fill the buffer with zeros
652
                memset(recvdatabuf[recv_id]->recvbuf, 0, msg_h->msg_length);
653
                debug(" new @ id:%d\n",recv_id);
654
        } else {        //message structure already exists, no need to create new
655
                debug(" found @ id:%d\n",recv_id);
656
        }
657

    
658
        if (msg_h->offset == 0)
659
                recvdatabuf[recv_id]->firstPacketArrived = 1;
660

    
661

    
662
        // increment fragmentnr
663
        recvdatabuf[recv_id]->recvFragments++;
664
        // increment the arrivedBytes
665
        recvdatabuf[recv_id]->arrivedBytes += bufsize;
666

    
667
        // enter the data into the buffer
668
        memcpy(recvdatabuf[recv_id]->recvbuf + msg_h->offset, msgbuf, bufsize);
669

    
670
        //TODO very basic checkif all fragments arrived: has to be reviewed
671
        if(recvdatabuf[recv_id]->arrivedBytes == recvdatabuf[recv_id]->bufsize)
672
                recvdatabuf[recv_id]->status = COMPLETE; //buffer full -> msg completly arrived
673
        else
674
                recvdatabuf[recv_id]->status = ACTIVE;
675

    
676
        if (recv_data_callback) {
677
                if(recvdatabuf[recv_id]->status == COMPLETE) {
678
                        // Monitoring layer hook
679
                        if(get_Recv_data_inf_cb != NULL) {
680
                                mon_data_inf recv_data_inf;
681

    
682
                                recv_data_inf.remote_socketID =
683
                                         &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
684
                                recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
685
                                recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
686
                                recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
687
                                recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
688
                                recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
689
                                        recvdatabuf[recv_id]->recvbuf : NULL;
690
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
691
                                recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
692
                                recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
693
                                recv_data_inf.priority = false;
694
                                recv_data_inf.padding = false;
695
                                recv_data_inf.confirmation = false;
696
                                recv_data_inf.reliable = false;
697

    
698
                                // send data recv callback to monitoring module
699

    
700
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
701
                        }
702

    
703
                        // Get the right callback
704
                        receive_data_cb receive_data_callback = recvcbbuf[msg_h->msg_type];
705
                        if (receive_data_callback) {
706

    
707
                                recv_params rParams;
708

    
709
                                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
710
                                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
711
                                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
712
                                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
713
                                rParams.remote_socketID =
714
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
715

    
716
                                char str[1000];
717
                                mlSocketIDToString(rParams.remote_socketID,str,999);
718
                                debug("ML: received message from conID:%d, %s\n",recvdatabuf[recv_id]->connectionID,str);
719
                                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
720

    
721
                                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
722
                                        recvdatabuf[recv_id]->msgtype, (void *) &rParams);
723
                        } else {
724
                            warn("ML: callback not initialized for this message type: %d!\n",msg_h->msg_type);
725
                        }
726

    
727
                        //clean up
728
                        if (recvdatabuf[recv_id]->timeout_event) {
729
                                int ret;
730
                                debug("ML: freeing timeout for %d",recv_id);
731
                                ret = event_del(recvdatabuf[recv_id]->timeout_event);
732
                                event_free(recvdatabuf[recv_id]->timeout_event);
733
                                debug(" ret: %d\n",ret);
734
                        } else {
735
                                debug("ML: received in 1 packet\n",recv_id);
736
                        }
737
                        free(recvdatabuf[recv_id]->recvbuf);
738
                        free(recvdatabuf[recv_id]);
739
                        recvdatabuf[recv_id] = NULL;
740
                } else { // not COMPLETE
741
                        if (!recvdatabuf[recv_id]->timeout_event) {
742
                                //start time out
743
                                //TODO make timeout at least a DEFINE
744
                                struct timeval timeout = { 2, 0 };        //TODO: use some configurable timeout here
745
                                recvdatabuf[recv_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &recv_timeout_cb, (void *) (long)recv_id);
746
                                evtimer_add(recvdatabuf[recv_id]->timeout_event, &timeout);
747
                        }
748
                }
749
        }
750
}
751

    
752
//done
753
void pmtu_timeout_cb(int fd, short event, void *arg)
754
{
755
        debug("ML: pmtu timeout called\n");
756

    
757
        int con_id = (long) arg;
758
        pmtu new_pmtusize;
759
        struct timeval timeout;
760

    
761
        if(connectbuf[con_id] == NULL) {
762
                error("ML: pmtu timeout called on non existing con_id\n");
763
                return;
764
        }
765

    
766
        if(connectbuf[con_id]->status == READY) {
767
                // nothing to do anymore
768
                return;
769
        }
770

    
771
        timeout = connectbuf[con_id]->timeout_value;
772

    
773
        if(connectbuf[con_id]->delay || connectbuf[con_id]->trials == MAX_TRIALS - 1) {
774
                double delay = timeout.tv_sec + timeout.tv_usec / 1000000.0;
775
                delay = delay * 2;
776
                timeout.tv_sec = floor(delay);
777
                timeout.tv_usec = fmod(delay, 1.0) * 1000000.0;
778
                if(connectbuf[con_id]->delay) {
779
                        connectbuf[con_id]->delay = false;
780
                        goto reschedule;
781
                }
782
        }
783

    
784
        if(connectbuf[con_id]->trials == MAX_TRIALS) {
785
                // decrement the pmtu size
786
                connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
787
                connectbuf[con_id]->trials = 0;
788
        }
789

    
790
        //error in PMTU discovery?
791
        if (connectbuf[con_id]->pmtusize == ERROR) {
792
                if (connectbuf[con_id]->internal_connect == true) {
793
                        //as of now we tried directly connecting, now let's try trough the NAT
794
                        connectbuf[con_id]->internal_connect = false;
795
                        connectbuf[con_id]->pmtusize = MAX;
796
                } else {
797
                        //nothing to do we have to give up
798
                        error("ML: Could not create connection with connectionID %i!\n",con_id);
799
                        // envoke the callback for failed connection establishment
800
                        if(failed_Connection_cb != NULL)
801
                                (failed_Connection_cb) (con_id, NULL);
802
                        // delete the connection entry
803
                        mlCloseConnection(con_id);
804
                        return;
805
                }
806
        }
807

    
808
        //retry with new pmtu size
809
        connectbuf[con_id]->trials++;
810
        send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
811

    
812
reschedule:
813
        /* reschedule */
814
        event_base_once(base, -1, EV_TIMEOUT, pmtu_timeout_cb, (void *) (long)con_id, &timeout);
815
}
816

    
817
/*
818
 * decrements the mtu size
819
 */
820
pmtu pmtu_decrement(pmtu pmtusize)
821
{
822
        pmtu pmtu_return_size;
823
        switch(pmtusize) {
824
        case MAX:
825
                return DSL;
826
        case DSL:
827
                return DSLMEDIUM;
828
        case DSLMEDIUM:
829
                return DSLSLIM;
830
        case DSLSLIM:
831
                return BELOWDSL;
832
        case BELOWDSL:
833
                return MIN;
834
        default:
835
                return ERROR;
836
        }
837
}
838

    
839
void pmtu_error_cb_th(char *msg, int msglen)
840
{
841
        debug("ML: pmtu_error callback called msg_size: %d\n",msglen);
842
        //TODO debug
843
        return;
844

    
845
    char *msgbufptr = NULL;
846
    int msgtype;
847
    int connectionID;
848
    pmtu pmtusize;
849
    pmtu new_pmtusize;
850
    int dead = 0;
851

    
852
    // check the packettype
853
    msgbufptr = &msg[0];
854

    
855
    // check the msgtype
856
    msgbufptr = &msg[1];
857
    memcpy(&msgtype, msgbufptr, 4);
858

    
859
    if (msgtype == 0) {
860

    
861
        // get the connectionID
862
        msgbufptr = &msg[5];
863
        memcpy(&connectionID, msgbufptr, 4);
864

    
865
        int msgtype_c = connectbuf[connectionID]->status;
866
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
867

    
868
        if (msgtype_c != msgtype) {
869
            dead = 1;
870
        }
871

    
872

    
873
    } else if (msgtype == 1) {
874

    
875
        // read the connectionID
876
        msgbufptr = &msg[9];
877
        memcpy(&connectionID, msgbufptr, 4);
878

    
879
        int msgtype_c = connectbuf[connectionID]->status;
880
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
881

    
882
        if (msgtype_c != msgtype) {
883
            dead = 1;
884
        }
885

    
886
    }
887
    // decrement the pmtu size
888
    new_pmtusize = pmtu_decrement(pmtusize);
889

    
890
//    connectbuf[connectionID]->pmtutrysize = new_pmtusize;
891

    
892
    if (new_pmtusize == ERROR) {
893
                error("ML:  Could not create connection with connectionID %i !\n",
894
                        connectionID);
895

    
896
                if(failed_Connection_cb != NULL)
897
                        (failed_Connection_cb) (connectionID, NULL);
898
                // set the message type to a non existent message
899
                msgtype = 2;
900
                // delete the connection entry
901
                 mlCloseConnection(connectionID);
902
        }
903

    
904
    if (msgtype == 0 && dead != 1) {
905

    
906
        // stop the timeout event
907
        // timeout_del(connectbuf[connectionID]->timeout);
908
        /*
909
         * libevent2
910
         */
911

    
912
        // event_del(connectbuf[connectionID]->timeout);
913

    
914

    
915
        // create and send a connection message
916
//         create_conn_msg(new_pmtusize, connectionID,
917
//                         &local_socketID, INVITE);
918

    
919
//        send_conn_msg(connectionID, new_pmtusize);
920

    
921
        // set a timeout event for the pmtu discovery
922
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
923
        // *)&connectionID);
924

    
925
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
926

    
927
        /*
928
         * libevent2
929
         */
930

    
931
        struct event *ev;
932
        ev = evtimer_new(base, pmtu_timeout_cb,
933
                         (void *) connectbuf[connectionID]);
934

    
935
        // connectbuf[connectionID]->timeout = ev;
936

    
937
        event_add(ev, &connectbuf[connectionID]->timeout_value);
938

    
939
    } else if (msgtype == 1 && dead != 1) {
940

    
941
        // stop the timeout event
942
        // timeout_del(connectbuf[connectionID]->timeout);
943

    
944
        /*
945
         * libevent2
946
         */
947
        // info("still here 11 \n");
948
        // printf("ev %d \n",connectbuf[connectionID]->timeout);
949
        // event_del(connectbuf[connectionID]->timeout );
950
        // evtimer_del(connectbuf[connectionID]->timeout );
951

    
952

    
953
//         // create and send a connection message
954
//         create_conn_msg(new_pmtusize,
955
//                         connectbuf[connectionID]->connectionID,
956
//                         NULL, CONNECT);
957

    
958
        //send_conn_msg(connectionID, new_pmtusize);
959

    
960
        // set a timeout event for the pmtu discovery
961
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
962
        // *)&connectionID);
963
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
964

    
965
        /*
966
         * libevent2
967
         */
968
        // struct event *ev;
969
        // ev = evtimer_new(base,pmtu_timeout_cb, (void
970
        // *)connectbuf[connectionID]);
971
        // connectbuf[connectionID]->timeout = ev;
972
        // event_add(ev,&connectbuf[connectionID]->timeout_value);
973

    
974
    }
975
}
976

    
977
/*
978
 * what to do once a packet arrived if it is a conn packet send it to
979
 * recv_conn handler if it is a data packet send it to the recv_data
980
 * handler
981
 */
982

    
983
//done --
984
void recv_pkg(int fd, short event, void *arg)
985
{
986
        debug("ML: recv_pkg called\n");
987

    
988
        struct msg_header *msg_h;
989
        char msgbuf[MAX];
990
        char *bufptr = msgbuf;
991
        int ttl;
992
        struct sockaddr_in recv_addr;
993
        pmtu recvSize = MAX;
994
        int msg_size;
995

    
996
        recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
997

    
998

    
999
        // check if it is not just an ERROR message
1000
        if(recvSize < 0)
1001
                return;
1002

    
1003
        // @TODO check if this simplistic STUN message recognition really always works, probably not
1004
        unsigned short stun_bind_response = 0x0101;
1005
        unsigned short * msgspot = (unsigned short *) msgbuf;
1006
        if (*msgspot == stun_bind_response) {
1007
                debug("ML: recv_pkg: parse stun message called\n");
1008
                recv_stun_msg(msgbuf, recvSize);
1009
                return;
1010
        }
1011

    
1012
        msg_h = (struct msg_header *) msgbuf;
1013
        bufptr += MSG_HEADER_SIZE + msg_h->len_mon_packet_hdr;
1014
        msg_size = recvSize - MSG_HEADER_SIZE - msg_h->len_mon_packet_hdr;
1015

    
1016

    
1017
        if(get_Recv_pkt_inf_cb != NULL && msg_h->len_mon_packet_hdr != 0) {
1018
                mon_pkt_inf msginfNow;
1019
                msginfNow.monitoringHeaderLen = msg_h->len_mon_packet_hdr;
1020
                msginfNow.monitoringHeader = msg_h->len_mon_packet_hdr ? &msgbuf[0] + MSG_HEADER_SIZE : NULL;
1021
                //TODO rethink this ...
1022
                if(msg_h->msg_type == ML_CON_MSG) {
1023
                        struct conn_msg *c_msg = (struct conn_msg *) bufptr;
1024
                        msginfNow.remote_socketID = &(c_msg->sock_id);
1025
                }
1026
                else if(connectbuf[msg_h->remote_con_id] == NULL) {
1027
                        error("ML: received pkg called with non existent connection\n");
1028
                        return;
1029
                } else
1030
                        msginfNow.remote_socketID = &(connectbuf[msg_h->remote_con_id]->external_socketID);
1031
                msginfNow.buffer = bufptr;
1032
                msginfNow.bufSize = recvSize;
1033
                msginfNow.msgtype = msg_h->msg_type;
1034
                msginfNow.ttl = ttl;
1035
                msginfNow.dataID = msg_h->msg_seq_num;
1036
                msginfNow.offset = msg_h->offset;
1037
                msginfNow.datasize = msg_h->msg_length;
1038
                gettimeofday(&msginfNow.arrival_time, NULL);
1039
                (get_Recv_pkt_inf_cb) ((void *) &msginfNow);
1040
        }
1041

    
1042

    
1043
        switch(msg_h->msg_type) {
1044
                case ML_CON_MSG:
1045
                        debug("ML: received conn pkg\n");
1046
                        recv_conn_msg(msg_h, bufptr, msg_size);
1047
                        break;
1048
                default:
1049
                        if(msg_h->msg_type < 127) {
1050
                                debug("ML: received data pkg\n");
1051
                                recv_data_msg(msg_h, bufptr, msg_size);
1052
                                break;
1053
                        }
1054
                        debug("ML: unrecognised msg_type\n");
1055
                        break;
1056
        }
1057
}
1058

    
1059
/*
1060
 * compare the external IP address of two socketIDs
1061
 */
1062
int
1063
compare_external_address_socketIDs(socketID_handle sock1, socketID_handle sock2)
1064
{
1065
        if( sock1->external_addr.udpaddr.sin_addr.s_addr == sock2->external_addr.udpaddr.sin_addr.s_addr)
1066
                return 0;
1067
        return 1;
1068
}
1069

    
1070
void try_stun();
1071

    
1072
/*
1073
 * the timeout of the NAT traversal
1074
 */
1075
void nat_traversal_timeout(int fd, short event, void *arg)
1076
{
1077
        if (NAT_traversal == false) {
1078
                debug("ML: NAT traversal request re-send\n");
1079
                if(receive_SocketID_cb)
1080
                        (receive_SocketID_cb) (&local_socketID, 2);
1081
                try_stun();
1082
        }
1083
}
1084

    
1085
unsigned long resolve(const char *ipaddr)
1086
{
1087
        struct hostent *h = gethostbyname(ipaddr);
1088
        if (!h) {
1089
                error("ML: Unable to resolve host name %s\n", ipaddr);
1090
        exit(-1);
1091
    }
1092
    unsigned long *addr = (unsigned long *) (h->h_addr);
1093
    return *addr;
1094
}
1095

    
1096

    
1097
/*
1098
 * returns a handle to the socketID struct the ipaddr can be a null
1099
 * pointer. Then all available ipaddr on the machine are choosen.
1100
 */
1101
void create_socket(const int port, const char *ipaddr)
1102
{
1103
        struct sockaddr_in udpaddr;
1104
        udpaddr.sin_family = AF_INET;
1105
        if (ipaddr == NULL) {
1106
                /*
1107
                * try to guess the local IP address
1108
                */
1109
                const char *ipaddr_iface = mlAutodetectIPAddress();
1110
                if (ipaddr_iface) {
1111
                        udpaddr.sin_addr.s_addr = inet_addr(ipaddr_iface);
1112
                } else {
1113
                        udpaddr.sin_addr.s_addr = INADDR_ANY;
1114
                }
1115
        } else {
1116
                udpaddr.sin_addr.s_addr = inet_addr(ipaddr);
1117
        }
1118
        udpaddr.sin_port = htons(port);
1119

    
1120
        socketaddrgen udpgen;
1121
        memset(&udpgen,0,sizeof(socketaddrgen));        //this will be sent over the net, so set it to 0
1122
        udpgen.udpaddr = udpaddr;
1123
        local_socketID.internal_addr = udpgen;
1124

    
1125
        socketfd = createSocket(port, ipaddr);
1126

    
1127
        struct event *ev;
1128
        ev = event_new(base, socketfd, EV_READ | EV_PERSIST, recv_pkg, NULL);
1129

    
1130
        event_add(ev, NULL);
1131

    
1132
        try_stun();
1133
}
1134

    
1135
/*
1136
 * try to figure out external IP using STUN, if defined
1137
 */
1138
void try_stun()
1139
{
1140
        if (isStunDefined()) {
1141
                /*
1142
                * send the NAT traversal STUN request
1143
                */
1144
                 send_stun_request(socketfd, &stun_server);
1145

    
1146
                /*
1147
                * enter a NAT traversal timeout that takes care of retransmission
1148
                */
1149
                struct event *ev1;
1150
                struct timeval timeout_value_NAT_traversal = { 1, 0 };
1151
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1152
                event_add(ev1, &timeout_value_NAT_traversal);
1153

    
1154
                NAT_traversal = false;
1155
        } else {
1156
                /*
1157
                * Assume we have accessibility and copy internal address to external one
1158
                */
1159
                local_socketID.external_addr = local_socketID.internal_addr;
1160
                NAT_traversal = true; // @TODO: this is not really NAT traversal, but a flag that init is over
1161
                // callback to the upper layer indicating that the socketID is now
1162
                // ready to use
1163
                if(receive_SocketID_cb)
1164
                        (receive_SocketID_cb) (&local_socketID, 0); //success
1165
        }
1166
}
1167

    
1168
/**************************** END OF INTERNAL ***********************/
1169

    
1170
/**************************** MONL functions *************************/
1171

    
1172
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){
1173

    
1174
        base = (struct event_base *) arg;
1175
        recv_data_callback = recv_data_cb;
1176
        mlSetRecvTimeout(timeout_value);
1177
        if (stun_ipaddr) {
1178
                 mlSetStunServer(stun_port, stun_ipaddr);
1179
        } else {
1180

    
1181
        }
1182
        register_recv_localsocketID_cb(local_socketID_cb);
1183
        create_socket(port, ipaddr);
1184

    
1185
}
1186

    
1187
/* register callbacks  */
1188
void mlRegisterGetRecvPktInf(get_recv_pkt_inf_cb recv_pkt_inf_cb){
1189

    
1190
        if (recv_pkt_inf_cb == NULL)
1191
                error("ML: Register get_recv_pkt_inf_cb failed: NULL ptr  \n");
1192
        else
1193
                get_Recv_pkt_inf_cb = recv_pkt_inf_cb;
1194

    
1195
}
1196

    
1197
void mlRegisterGetSendPktInf(get_send_pkt_inf_cb  send_pkt_inf_cb){
1198

    
1199
        if (send_pkt_inf_cb == NULL)
1200
                error("ML: Register get_send_pkt_inf_cb: NULL ptr  \n");
1201
        else
1202
                get_Send_pkt_inf_cb = send_pkt_inf_cb;
1203

    
1204
}
1205

    
1206

    
1207
void mlRegisterSetMonitoringHeaderPktCb(set_monitoring_header_pkt_cb monitoring_header_pkt_cb ){
1208

    
1209
        if (monitoring_header_pkt_cb == NULL)
1210
                error("ML: Register set_monitoring_header_pkt_cb: NULL ptr  \n");
1211
        else
1212
                set_Monitoring_header_pkt_cb = monitoring_header_pkt_cb;
1213

    
1214
}
1215

    
1216
void mlRegisterGetRecvDataInf(get_recv_data_inf_cb recv_data_inf_cb){
1217

    
1218
        if (recv_data_inf_cb == NULL)
1219
                error("ML: Register get_recv_data_inf_cb: NULL ptr  \n");
1220
        else
1221
                get_Recv_data_inf_cb = recv_data_inf_cb;
1222

    
1223
}
1224

    
1225
void mlRegisterGetSendDataInf(get_send_data_inf_cb  send_data_inf_cb){
1226

    
1227
        if (send_data_inf_cb == NULL)
1228
                error("ML: Register get_send_data_inf_cb: NULL ptr  \n");
1229
        else
1230
                get_Send_data_inf_cb = send_data_inf_cb;
1231

    
1232
}
1233

    
1234
void mlRegisterSetMonitoringHeaderDataCb(set_monitoring_header_data_cb monitoring_header_data_cb){
1235

    
1236
        if (monitoring_header_data_cb == NULL)
1237
                error("ML: Register set_monitoring_header_data_cb : NULL ptr  \n");
1238
        else
1239
        set_Monitoring_header_data_cb = monitoring_header_data_cb;
1240

    
1241
}
1242

    
1243
void mlSetRecvTimeout(struct timeval timeout_value){
1244

    
1245
        recv_timeout = timeout_value;
1246

    
1247
}
1248

    
1249
int mlGetStandardTTL(socketID_handle socketID,uint8_t *ttl){
1250

    
1251
        return getTTL(socketfd, ttl);
1252

    
1253
}
1254

    
1255
socketID_handle mlGetLocalSocketID(int *errorstatus){
1256

    
1257
        if (NAT_traversal == false) {
1258
                *errorstatus = 2;
1259
                return NULL;
1260
        }
1261

    
1262
        *errorstatus = 0;
1263
        return &local_socketID;
1264

    
1265
}
1266

    
1267

    
1268
/**************************** END of MONL functions *************************/
1269

    
1270
/**************************** GENERAL functions *************************/
1271

    
1272
void mlRegisterRecvConnectionCb(receive_connection_cb recv_conn_cb){
1273

    
1274
        if (recv_conn_cb == NULL)
1275
                error("ML: Register receive_connection_cb: NULL ptr  \n");
1276
        else
1277
                receive_Connection_cb = recv_conn_cb;
1278

    
1279
}
1280

    
1281
void mlRegisterErrorConnectionCb(connection_failed_cb conn_failed){
1282

    
1283
        if (conn_failed == NULL)
1284
                error("ML: Register connection_failed_cb: NULL ptr  \n");
1285
        else
1286
        failed_Connection_cb = conn_failed;
1287

    
1288
}
1289

    
1290
void mlRegisterRecvDataCb(receive_data_cb data_cb,unsigned char msgtype){
1291

    
1292
    if (msgtype > 126) {
1293

    
1294
            error
1295
            ("ML: Could not register recv_data callback. Msgtype is greater then 126 \n");
1296

    
1297
    }
1298

    
1299
    if (data_cb == NULL) {
1300

    
1301
            error("ML: Register receive data callback: NUll ptr \n ");
1302

    
1303
    } else {
1304

    
1305
        recvcbbuf[msgtype] = data_cb;
1306

    
1307
    }
1308

    
1309
}
1310

    
1311
void mlCloseSocket(socketID_handle socketID){
1312

    
1313
        free(socketID);
1314

    
1315
}
1316

    
1317
void keepalive_fn(evutil_socket_t fd, short what, void *arg) {
1318
        socketID_handle peer = arg;
1319

    
1320
        int con_id = mlConnectionExist(peer, false);
1321
        if (con_id < 0 || connectbuf[con_id]->defaultSendParams.keepalive <= 0) {
1322
                /* Connection fell from under us or keepalive was disabled */
1323
                free(arg);
1324
                return;
1325
        }
1326

    
1327
        /* do what we gotta do */
1328
        if ( connectbuf[con_id]->status == READY) {
1329
                char keepaliveMsg[32] = "";
1330
                sprintf(keepaliveMsg, "KEEPALIVE %d", connectbuf[con_id]->keepalive_seq++);
1331
                send_msg(con_id, MSG_TYPE_ML_KEEPALIVE, keepaliveMsg, 1 + strlen(keepaliveMsg), false, 
1332
                        &(connectbuf[con_id]->defaultSendParams));
1333
        }
1334

    
1335
        /* re-schedule */
1336
        struct timeval t = { 0,0 };
1337
        t.tv_sec = connectbuf[con_id]->defaultSendParams.keepalive;
1338
        if (connectbuf[con_id]->defaultSendParams.keepalive) 
1339
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1340
}
1341

    
1342
void setupKeepalive(int conn_id) {
1343
        /* Save the peer's address for us */
1344
        socketID_handle peer = malloc(sizeof(socket_ID));
1345
        memcpy(peer, &connectbuf[conn_id]->external_socketID, sizeof(socket_ID));
1346

    
1347
        struct timeval t = { 0,0 };
1348
        t.tv_sec = connectbuf[conn_id]->defaultSendParams.keepalive;
1349

    
1350
        if (connectbuf[conn_id]->defaultSendParams.keepalive) 
1351
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1352
}
1353

    
1354
/* connection functions */
1355
int mlOpenConnection(socketID_handle external_socketID,receive_connection_cb connection_cb,void *arg, const send_params defaultSendParams){
1356

    
1357
        int con_id;
1358
        if (external_socketID == NULL) {
1359
                error("ML: cannot open connection: one of the socketIDs is NULL\n");
1360
                return -1;
1361
        }
1362
        if (NAT_traversal == false) {
1363
                error("ML: cannot open connection: NAT traversal for socketID still in progress\n");
1364
                return -1;
1365
        }
1366
        if (connection_cb == NULL) {
1367
                error("ML: cannot open connection: connection_cb is NULL\n");
1368
                return -1;
1369
        }
1370

    
1371
        // check if that connection already exist
1372

    
1373
        con_id = mlConnectionExist(external_socketID, false);
1374
        if (con_id >= 0) {
1375
                // overwrite defaultSendParams
1376
                bool newKeepalive = 
1377
                        connectbuf[con_id]->defaultSendParams.keepalive == 0 && defaultSendParams.keepalive != 0;
1378
                connectbuf[con_id]->defaultSendParams = defaultSendParams;
1379
                if (newKeepalive) setupKeepalive(con_id);
1380
                // if so check if it is ready to use
1381
                if (connectbuf[con_id]->status == READY) {
1382
                                // if so use the callback immediately
1383
                                (connection_cb) (con_id, arg);
1384

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

    
1419
                        connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
1420
                        connectbuf[con_id]->connection_last->next = NULL;
1421
                        connectbuf[con_id]->connection_last->connection_cb = connection_cb;
1422
                        connectbuf[con_id]->connection_last->arg = arg;
1423
                        connectbuf[con_id]->external_connectionID = -1;
1424

    
1425
                        connectbuf[con_id]->defaultSendParams = defaultSendParams;
1426
                        if (defaultSendParams.keepalive) setupKeepalive(con_id);
1427
                        break;
1428
                }
1429
        } //end of for
1430

    
1431
        if (con_id == CONNECTBUFSIZE) {
1432
                error("ML: Could not open connection: connection buffer full\n");
1433
                return -1;
1434
        }
1435

    
1436
        // create and send a connection message
1437
        send_conn_msg(con_id, MAX, INVITE);
1438

    
1439
        struct event *ev;
1440
        ev = evtimer_new(base, pmtu_timeout_cb, (void *) (long)con_id);
1441
        event_add(ev, &connectbuf[con_id]->timeout_value);
1442

    
1443
        return con_id;
1444

    
1445
}
1446

    
1447
void mlCloseConnection(const int connectionID){
1448

    
1449
        // remove it from the connection array
1450
        if(connectbuf[connectionID]) {
1451
                if(connectbuf[connectionID]->ctrl_msg_buf)
1452
                        free(connectbuf[connectionID]->ctrl_msg_buf);
1453
                free(connectbuf[connectionID]);
1454
                connectbuf[connectionID] = NULL;
1455
        }
1456

    
1457
}
1458

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

    
1461
        if (connectionID < 0) {
1462
                error("ML: send data failed: connectionID does not exist\n");
1463
                return;
1464
        }
1465

    
1466
        if (connectbuf[connectionID] == NULL) {
1467
                error("ML: send data failed: connectionID does not exist\n");
1468
                return;
1469
        }
1470
        if (connectbuf[connectionID]->status != READY) {
1471
            error("ML: send data failed: connection is not active\n");
1472
            return;
1473
        }
1474

    
1475
        if (sParams == NULL) {
1476
                sParams = &(connectbuf[connectionID]->defaultSendParams);
1477
        }
1478

    
1479
        send_msg(connectionID, msgtype, sendbuf, bufsize, false, sParams);
1480

    
1481
}
1482

    
1483
/* transmit data functions  */
1484
int mlSendAllData(const int connectionID,send_all_data_container *container,int nr_entries,unsigned char msgtype,send_params *sParams){
1485

    
1486
    if (nr_entries < 1 || nr_entries > 5) {
1487

    
1488
        error
1489
            ("ML : sendALlData : nr_enties is not between 1 and 5 \n ");
1490
        return 0;
1491

    
1492
    } else {
1493

    
1494
        if (nr_entries == 1) {
1495

    
1496
                mlSendData(connectionID, container->buffer_1,
1497
                      container->length_1, msgtype, sParams);
1498

    
1499
            return 1;
1500

    
1501
        } else if (nr_entries == 2) {
1502

    
1503
            int buflen = container->length_1 + container->length_2;
1504
            char buf[buflen];
1505
            memcpy(buf, container->buffer_1, container->length_1);
1506
            memcpy(&buf[container->length_1], container->buffer_2,
1507
                   container->length_2);
1508
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1509

    
1510
            return 1;
1511

    
1512
        } else if (nr_entries == 3) {
1513

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

    
1525

    
1526
            return 1;
1527

    
1528
        } else if (nr_entries == 4) {
1529

    
1530
            int buflen =
1531
                container->length_1 + container->length_2 +
1532
                container->length_3 + container->length_4;
1533
            char buf[buflen];
1534
            memcpy(buf, container->buffer_1, container->length_1);
1535
            memcpy(&buf[container->length_1], container->buffer_2,
1536
                   container->length_2);
1537
            memcpy(&buf[container->length_2], container->buffer_3,
1538
                   container->length_3);
1539
            memcpy(&buf[container->length_3], container->buffer_4,
1540
                   container->length_4);
1541
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1542

    
1543
            return 1;
1544

    
1545
        } else {
1546

    
1547
            int buflen =
1548
                container->length_1 + container->length_2 +
1549
                container->length_3 + container->length_4 +
1550
                container->length_5;
1551
            char buf[buflen];
1552
            memcpy(buf, container->buffer_1, container->length_1);
1553
            memcpy(&buf[container->length_1], container->buffer_2,
1554
                   container->length_2);
1555
            memcpy(&buf[container->length_2], container->buffer_3,
1556
                   container->length_3);
1557
            memcpy(&buf[container->length_3], container->buffer_4,
1558
                   container->length_4);
1559
            memcpy(&buf[container->length_4], container->buffer_5,
1560
                   container->length_5);
1561
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1562

    
1563
            return 1;
1564
        }
1565

    
1566
    }
1567

    
1568
}
1569

    
1570
int mlRecvData(const int connectionID,char *recvbuf,int *bufsize,recv_params *rParams){
1571

    
1572
        //TODO yet to be converted
1573
        return 0;
1574
#if 0
1575
        if (rParams == NULL) {
1576
                error("ML: recv_data failed: recv_params is a NULL ptr\n");
1577
                return 0;
1578
    } else {
1579

1580
        info("ML: recv data called \n");
1581

1582
        int i = 0;
1583
        int returnValue = 0;
1584
        double timeout = (double) recv_timeout.tv_sec;
1585
        time_t endtime = time(NULL);
1586

1587
        for (i = 0; i < RECVDATABUFSIZE; i++) {
1588

1589
            if (recvdatabuf[i] != NULL) {
1590

1591
                if (recvdatabuf[i]->connectionID == connectionID) {
1592

1593
                    info("ML: recv data has entry  \n");
1594

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

1597
                    // check if the specified connection has data and it
1598
                    // is complete
1599
                    // check the data seqnr
1600
                    // if(connectionID == recvdatabuf[i]->connectionID &&
1601
                    // 1 == recvdatabuf[i]->status){
1602

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

1605
                        // info("transmissionHandler: recv_data set is
1606
                        // complete \n" );
1607

1608
                        // debug("debud \n");
1609

1610
                        // exchange the pointers
1611
                        int buffersize = 0;
1612
                        buffersize = recvdatabuf[i]->bufsize;
1613
                        *bufsize = buffersize;
1614
                        // recvbuf = recvdatabuf[i]->recvbuf;
1615

1616
                        // info("buffersize %d \n",buffersize);
1617
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1618
                               buffersize);
1619
                        // debug(" recvbuf %s \n",recvbuf );
1620

1621
//                         double nrMissFrags =
1622
//                             (double) recvdatabuf[i]->nrFragments /
1623
//                             (double) recvdatabuf[i]->recvFragments;
1624
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
1625

1626
//                        rParams->nrMissingFragments = nrMissingFragments;
1627
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
1628
                        rParams->msgtype = recvdatabuf[i]->msgtype;
1629
                        rParams->connectionID =
1630
                            recvdatabuf[i]->connectionID;
1631

1632
                        // break from the loop
1633
                        // debug(" recvbuf %s \n ",recvbuf);
1634

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

1641
                        if(get_Recv_data_inf_cb != NULL) {
1642
                                mon_data_inf recv_data_inf;
1643

1644
                                recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1645
                                recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1646
                                recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1647
                                recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1648
//                                 recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1649
//                                 recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1650
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
1651
                                recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1652
                                recv_data_inf.nrMissingFragments = nrMissingFragments;
1653
                                recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1654
                                recv_data_inf.priority = false;
1655
                                recv_data_inf.padding = false;
1656
                                recv_data_inf.confirmation = false;
1657
                                recv_data_inf.reliable = false;
1658

1659
                                // send data recv callback to monitoring module
1660

1661
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1662
                        }
1663

1664

1665
                        // free the allocated memory
1666
                        free(recvdatabuf[i]);
1667
                        recvdatabuf[i] = NULL;
1668

1669
                        returnValue = 1;
1670
                        break;
1671

1672
                    }
1673

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

1676
                        if (timepass > timeout) {
1677

1678
                            info("ML: recv_data timeout called  \n");
1679

1680
                            // some data about the missing chunks should
1681
                            // be added here
1682
                            // exchange the pointers
1683
                            int buffersize = 0;
1684
                            buffersize = recvdatabuf[i]->bufsize;
1685
                            *bufsize = buffersize;
1686
                            // recvbuf = recvdatabuf[i]->recvbuf;
1687

1688
                            double nrMissFrags =
1689
                                (double) recvdatabuf[i]->nrFragments /
1690
                                (double) recvdatabuf[i]->recvFragments;
1691
                            int nrMissingFragments =
1692
                                (int) ceil(nrMissFrags);
1693

1694
                            // debug(" recvbuf %s \n",recvbuf );
1695

1696
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1697
                                   buffersize);
1698

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

1707
                                if(get_Recv_data_inf_cb != NULL) {
1708
                                        mon_data_inf recv_data_inf;
1709

1710
                                        recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1711
                                        recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1712
                                        recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1713
                                        recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1714
                                        recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1715
                                        recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1716
                                        gettimeofday(&recv_data_inf.arrival_time, NULL);
1717
                                        recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1718
                                        recv_data_inf.nrMissingFragments = nrMissingFragments;
1719
                                        recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1720
                                        recv_data_inf.priority = false;
1721
                                        recv_data_inf.padding = false;
1722
                                        recv_data_inf.confirmation = false;
1723
                                        recv_data_inf.reliable = false;
1724

1725
                                        // send data recv callback to monitoring module
1726

1727
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1728
                                }
1729

1730
                            // free the allocated memory
1731
                            free(recvdatabuf[i]);
1732
                            recvdatabuf[i] = NULL;
1733

1734
                            returnValue = 1;
1735
                            break;
1736

1737
                        }
1738
                    }
1739

1740
                }
1741

1742
            }
1743
            // debug("2 recvbuf %s \n ",recvbuf);
1744
        }
1745
        return returnValue;
1746
    }
1747
#endif
1748

    
1749
}
1750

    
1751
int mlSocketIDToString(socketID_handle socketID,char* socketID_string, size_t len){
1752

    
1753
        char internal_addr[INET_ADDRSTRLEN];
1754
        char external_addr[INET_ADDRSTRLEN];
1755
        inet_ntop(AF_INET, &(socketID->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1756
        inet_ntop(AF_INET, &(socketID->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1757

    
1758
        snprintf(socketID_string,len,"%s:%d-%s:%d", internal_addr, ntohs(socketID->internal_addr.udpaddr.sin_port),
1759
                external_addr,        ntohs(socketID->external_addr.udpaddr.sin_port));
1760
        return 0;
1761

    
1762
}
1763

    
1764
int mlStringToSocketID(const char* socketID_string, socketID_handle socketID){
1765

    
1766
        //@TODO add checks against malformed string
1767
        char external_addr[INET_ADDRSTRLEN];
1768
        int external_port;
1769
        char internal_addr[INET_ADDRSTRLEN];
1770
        int internal_port;
1771

    
1772
        char *pch;
1773
        char *s = strdup(socketID_string);
1774

    
1775
        //replace ':' with a blank
1776
        pch=strchr(s,':');
1777
        while (pch!=NULL){
1778
                                *pch = ' ';
1779
                pch=strchr(pch+1,':');
1780
        }
1781
        pch=strchr(s,'-');
1782
        if(pch) *pch = ' ';
1783

    
1784
        sscanf(s,"%s %d %s %d", internal_addr, &internal_port,
1785
                external_addr, &external_port);
1786

    
1787
        if(inet_pton(AF_INET, internal_addr, &(socketID->internal_addr.udpaddr.sin_addr)) == 0)
1788
                return EINVAL;
1789
        socketID->internal_addr.udpaddr.sin_family = AF_INET;
1790
        socketID->internal_addr.udpaddr.sin_port = htons(internal_port);
1791

    
1792

    
1793
        if(inet_pton(AF_INET, external_addr, &(socketID->external_addr.udpaddr.sin_addr)) ==0)
1794
                return EINVAL;
1795
        socketID->external_addr.udpaddr.sin_family = AF_INET;
1796
        socketID->external_addr.udpaddr.sin_port = htons(external_port);
1797

    
1798
        free(s);
1799
        return 0;
1800

    
1801
}
1802

    
1803
int mlGetConnectionStatus(int connectionID){
1804

    
1805
        if(connectbuf[connectionID])
1806
                return connectbuf[connectionID]->status == READY;
1807
        return -1;
1808
    
1809
}
1810

    
1811

    
1812
int mlConnectionExist(socketID_handle socketID, bool ready){
1813

    
1814
    /*
1815
     * check if another connection for the external connectionID exist
1816
     * that was established \ within the last 2 seconds
1817
     */
1818
        int i;
1819
        for (i = 0; i < CONNECTBUFSIZE; i++)
1820
                if (connectbuf[i] != NULL)
1821
                        if (mlCompareSocketIDs(&(connectbuf[i]->external_socketID), socketID) == 0) {
1822
                                if (ready) return (connectbuf[i]->status == READY ? i : -1);;
1823
                                return i;
1824
                                }
1825

    
1826
    return -1;
1827

    
1828
}
1829

    
1830
//Added by Robert Birke as comodity functions
1831

    
1832
//int mlPrintSocketID(socketID_handle socketID) {
1833
//        char str[SOCKETID_STRING_SIZE];
1834
//        mlSocketIDToString(socketID, str, sizeof(str));
1835
//        printf(stderr,"int->%s<-ext\n",str);
1836
//}
1837

    
1838
/*
1839
 * hash code of a socketID
1840
 * TODO might think of a better way
1841
 */
1842
int mlHashSocketID(socketID_handle sock) {
1843
    return sock->internal_addr.udpaddr.sin_port +
1844
                          sock->external_addr.udpaddr.sin_port;
1845
}
1846

    
1847
int mlCompareSocketIDs(socketID_handle sock1, socketID_handle sock2) {
1848
        /*
1849
        * compare internal addr
1850
        */
1851
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr !=
1852
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
1853
                        return 1;
1854

    
1855
        if (sock1->internal_addr.udpaddr.sin_port !=
1856
                 sock2->internal_addr.udpaddr.sin_port)
1857
                        return 1;
1858

    
1859
        /*
1860
        * compare external addr
1861
        */
1862
        if (sock1->external_addr.udpaddr.sin_addr.s_addr !=
1863
            sock2->external_addr.udpaddr.sin_addr.s_addr)
1864
                        return 1;
1865

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

    
1870
        return 0;
1871
}
1872

    
1873
int mlCompareSocketIDsByPort(socketID_handle sock1, socketID_handle sock2)
1874
{ 
1875
        if (sock1->internal_addr.udpaddr.sin_port !=
1876
                 sock2->internal_addr.udpaddr.sin_port)
1877
                        return 1;
1878

    
1879
        if (sock1->external_addr.udpaddr.sin_port !=
1880
                 sock2->external_addr.udpaddr.sin_port)
1881
                        return 1;
1882
        return 0;
1883
}
1884

    
1885
int mlGetPathMTU(int ConnectionId) {
1886
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
1887
                return -1;
1888
        if (connectbuf[ConnectionId] != NULL)
1889
                return connectbuf[ConnectionId]->pmtusize;
1890
        return -1;
1891
}
1892

    
1893
/**************************** END of GENERAL functions *************************/
1894

    
1895
/**************************** NAT functions *************************/
1896

    
1897
/* setter  */
1898
void mlSetStunServer(const int port,const char *ipaddr){
1899

    
1900
        stun_server.sin_family = AF_INET;
1901
        if (ipaddr == NULL)
1902
                stun_server.sin_addr.s_addr = htonl(INADDR_ANY);
1903
        else
1904
                stun_server.sin_addr.s_addr = resolve(ipaddr);
1905
        stun_server.sin_port = htons(port);
1906

    
1907
}
1908

    
1909
int mlGetExternalIP(char* external_addr){
1910

    
1911
        socketaddrgen udpgen;
1912
        struct sockaddr_in udpaddr;
1913

    
1914
        udpgen = local_socketID.external_addr;
1915
        udpaddr = udpgen.udpaddr;
1916

    
1917
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
1918
                        INET_ADDRSTRLEN);
1919

    
1920
        if (external_addr == NULL) {
1921

    
1922
        return -1;
1923

    
1924
        } else {
1925

    
1926
        return 0;
1927

    
1928
        }
1929

    
1930
}
1931

    
1932
/**************************** END of NAT functions *************************/