Statistics
| Branch: | Revision:

ml / ml.c @ b5894e65

History | View | Annotate | Download (53.1 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
        iov[0].iov_base = &msg_h;
201
        iov[0].iov_len = MSG_HEADER_SIZE;
202

    
203
        msg_h.local_con_id = con_id;
204
        msg_h.remote_con_id = connectbuf[con_id]->external_connectionID;
205
        msg_h.msg_type = msg_type;
206
        msg_h.msg_seq_num = connectbuf[con_id]->seqnr++;
207

    
208

    
209
        iov[1].iov_len = iov[2].iov_len = 0;
210
        iov[1].iov_base = h_pkt;
211
        iov[2].iov_base = h_data;
212

    
213

    
214
        if (connectbuf[con_id]->internal_connect)
215
                udpgen = connectbuf[con_id]->external_socketID.internal_addr;
216
        else
217
                udpgen = connectbuf[con_id]->external_socketID.external_addr;
218

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

    
228
                if(get_Send_data_inf_cb != NULL && iov[2].iov_len != 0) {
229
                        mon_data_inf sd_data_inf;
230

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

    
243
                        (get_Send_data_inf_cb) ((void *) &sd_data_inf);
244
                }
245

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

    
252
                        iov[3].iov_len = pkt_len;
253
                        iov[3].iov_base = msg + offset;
254

    
255
                        //fill header
256
                        msg_h.len_mon_packet_hdr = iov[1].iov_len;
257
                        msg_h.offset = offset;
258
                        msg_h.msg_length = truncable ? pkt_len : msg_len;
259

    
260
                        //monitoring layer hook
261
                        if(get_Send_pkt_inf_cb != NULL && iov[1].iov_len) {
262
                                mon_pkt_inf pkt_info;
263

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

    
276
                                (get_Send_pkt_inf_cb) ((void *) &pkt_info);
277
                        }
278

    
279

    
280
                        switch(sendPacket(socketfd, iov, 4, &udpgen.udpaddr)) {
281
                                case MSGLEN:
282
                                        connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
283
                                        connectbuf[con_id]->delay = true;
284
                                        retry = true;
285
                                        offset = msg_len; // exit the while
286
                                        break;
287
                                case FAILURE:
288
                                        offset = msg_len; // exit the while
289
                                        break;
290
                                case OK:
291
                                        //update
292
                                        offset += pkt_len + iov[2].iov_len;
293
                                        //transmit data header only in the first packet
294
                                        iov[2].iov_len = 0;
295
                                        break;
296
                        }
297
                } while(offset != msg_len + msg_h.len_mon_data_hdr && !truncable);
298
        } while(retry);
299
}
300

    
301
void send_conn_msg(int con_id, int buf_size, int command_type)
302
{
303
        if (buf_size < sizeof(struct conn_msg)) {
304
                error("ML: requested connection message size is too small\n");
305
                return;
306
        }
307

    
308
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
309
                connectbuf[con_id]->ctrl_msg_buf = malloc(buf_size);
310
                memset(connectbuf[con_id]->ctrl_msg_buf, 0, buf_size);
311
        }
312

    
313
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
314
                error("ML: can not allocate memory for connection message\n");
315
                return;
316
        }
317

    
318
        struct conn_msg *msg_header = (struct conn_msg*) connectbuf[con_id]->ctrl_msg_buf;
319

    
320
        msg_header->comand_type = command_type;
321
        msg_header->pmtu_size = connectbuf[con_id]->pmtusize;
322

    
323
        memcpy(&(msg_header->sock_id), loc_socketID, sizeof(socket_ID));
324

    
325
        send_msg(con_id, ML_CON_MSG, connectbuf[con_id]->ctrl_msg_buf, buf_size, true, &(connectbuf[con_id]->defaultSendParams));
326
}
327

    
328
void
329
recv_conn_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
330
{
331
        struct conn_msg *con_msg;
332
        int free_con_id, con_id;
333

    
334
        time_t now = time(NULL);
335
        double timediff = 0.0;
336

    
337
        // Monitoring layer hook
338
        if(get_Recv_data_inf_cb != NULL && msg_h->len_mon_data_hdr != 0) {
339
                // update pointer to the real data
340
                msgbuf += msg_h->len_mon_data_hdr;
341
                bufsize -= msg_h->len_mon_data_hdr;
342
                con_msg = (struct conn_msg *)msgbuf;
343

    
344
                mon_data_inf recv_data_inf;
345
                recv_data_inf.remote_socketID = &(con_msg->sock_id);
346
                recv_data_inf.buffer = msgbuf;
347
                recv_data_inf.bufSize = bufsize;
348
                recv_data_inf.msgtype = msg_h->msg_type;
349
                recv_data_inf.monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
350
                recv_data_inf.monitoringDataHeader = msg_h->len_mon_data_hdr ? msgbuf : NULL;
351
                gettimeofday(&recv_data_inf.arrival_time, NULL);
352
                recv_data_inf.firstPacketArrived = true;
353
                recv_data_inf.recvFragments = 1;
354
                recv_data_inf.priority = false;
355
                recv_data_inf.padding = false;
356
                recv_data_inf.confirmation = false;
357
                recv_data_inf.reliable = false;
358

    
359
                // send data recv callback to monitoring module
360
                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
361
        } else
362
                con_msg = (struct conn_msg *) msgbuf;
363

    
364
        // check the connection command type
365
        switch (con_msg->comand_type) {
366
                /*
367
                * if INVITE: enter a new socket make new entry in connect array
368
                * send an ok
369
                */
370
                case INVITE:
371
                        debug("ML: received INVITE\n");
372
                        /*
373
                        * check if another connection for the external connectionID exist
374
                        * that was established within the last 2 seconds
375
                        */
376
                        free_con_id = -1;
377
                        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
378
                                if (connectbuf[con_id] != NULL) {
379
                                        if (mlCompareSocketIDs(&(connectbuf[con_id]->external_socketID), &(con_msg->sock_id)) == 0) {
380
                                                timediff = difftime(now, connectbuf[con_id]->starttime);
381
                                                if (timediff < 2)
382
                                                        break;
383
                                        }
384
                                } else if(free_con_id == -1)
385
                                        free_con_id = con_id;
386
                        }
387

    
388
                        if (con_id == CONNECTBUFSIZE) {
389
                                // create an entry in the connecttrybuf
390
                                if(free_con_id == -1) {
391
                                        error("ML: no new connect_buf available\n");
392
                                        return;
393
                                }
394
                                connectbuf[free_con_id] = (connect_data *) malloc(sizeof(connect_data));
395
                                memset(connectbuf[free_con_id],0,sizeof(connect_data));
396
                                connectbuf[free_con_id]->connection_head = connectbuf[free_con_id]->connection_last = NULL;
397
                                connectbuf[free_con_id]->starttime = time(NULL);
398
                                memcpy(&(connectbuf[free_con_id]->external_socketID), &(con_msg->sock_id), sizeof(socket_ID));
399
                                connectbuf[free_con_id]->pmtusize = con_msg->pmtu_size;
400
                                connectbuf[free_con_id]->external_connectionID = msg_h->local_con_id;
401
                                connectbuf[free_con_id]->internal_connect =
402
                                        !compare_external_address_socketIDs(&(con_msg->sock_id), loc_socketID);
403
                                con_id = free_con_id;
404
                        }
405

    
406
                        if(connectbuf[con_id]->status <= CONNECT) {
407
                                //update status and send back answer
408
                                connectbuf[con_id]->status = CONNECT;
409
                                send_conn_msg(con_id, con_msg->pmtu_size, CONNECT);
410
                        }
411
                        break;
412
                case CONNECT:
413
                        debug("ML: received CONNECT\n");
414

    
415
                        if(msg_h->remote_con_id != -1 && connectbuf[msg_h->remote_con_id] == NULL) {
416
                                error("ML: received CONNECT for inexistent connection\n");
417
                                return;
418
                        }
419

    
420
                        /*
421
                        * check if the connection status is not already 1 or 2
422
                        */
423
                        if (connectbuf[msg_h->remote_con_id]->status == INVITE) {
424
                                // set the external connectionID
425
                                connectbuf[msg_h->remote_con_id]->external_connectionID = msg_h->local_con_id;
426
                                // change status con_msg the connection_data
427
                                connectbuf[msg_h->remote_con_id]->status = READY;
428
                                // change pmtusize in the connection_data
429
                                connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
430

    
431
                                // send the READY
432
                                send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
433

    
434
                                if (receive_Connection_cb != NULL)
435
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
436

    
437
                                // call all registered callbacks
438
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
439
                                        struct receive_connection_cb_list *temp;
440
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
441
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
442
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
443
                                        free(temp);
444
                                }
445
                                connectbuf[msg_h->remote_con_id]->connection_head =
446
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
447
                        } else
448
                                // send the READY
449
                                send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
450

    
451
                        debug("ML: active connection established\n");
452
                        break;
453

    
454
                        /*
455
                        * if READY: find the entry in the connection array set the
456
                        * connection active change the pmtu size
457
                        */
458
                case READY:
459
                        debug("ML: received READY\n");
460
                        if(connectbuf[msg_h->remote_con_id] == NULL) {
461
                                error("ML: received READY for inexistent connection\n");
462
                                return;
463
                        }
464
                        /*
465
                        * checks if the connection is not already established
466
                        */
467
                        if (connectbuf[msg_h->remote_con_id]->status == CONNECT) {
468
                                // change status of the connection
469
                                connectbuf[msg_h->remote_con_id]->status = 2;
470
                                // change pmtusize
471
                                connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
472

    
473
                                if (receive_Connection_cb != NULL)
474
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
475

    
476
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
477
                                        struct receive_connection_cb_list *temp;
478
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
479
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
480
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
481
                                        free(temp);
482
                                }
483
                                connectbuf[msg_h->remote_con_id]->connection_head =
484
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
485
                                debug("ML: passive connection established\n");
486
                        }
487
                        break;
488
        }
489
}
490

    
491
void recv_stun_msg(char *msgbuf, int recvSize)
492
{
493
        /*
494
        * create empty stun message struct
495
        */
496
        StunMessage resp;
497
        memset(&resp, 0, sizeof(StunMessage));
498
        /*
499
        * parse the message
500
        */
501
        int returnValue = 0;
502
        returnValue = recv_stun_message(msgbuf, recvSize, &resp);
503

    
504
        if (returnValue == 0) {
505
                /*
506
                * read the reflexive Address into the local_socketID
507
                */
508
                struct sockaddr_in reflexiveAddr;
509
                reflexiveAddr.sin_family = AF_INET;
510
                reflexiveAddr.sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
511
                reflexiveAddr.sin_port = htons(resp.mappedAddress.ipv4.port);
512
                socketaddrgen reflexiveAddres;
513
                reflexiveAddres.udpaddr = reflexiveAddr;
514
                local_socketID.external_addr = reflexiveAddres;
515
                NAT_traversal = true;
516
                // callback to the upper layer indicating that the socketID is now
517
                // ready to use
518
                (receive_SocketID_cb) (&local_socketID, 0);
519
        }
520
}
521

    
522
//done
523
void recv_timeout_cb(int fd, short event, void *arg)
524
{
525
        int recv_id = (long) arg;
526
        debug("ML: recv_timeout_cb called. Timeout for id:%d\n",recv_id);
527

    
528
        if (recvdatabuf[recv_id] == NULL) {
529
                return;
530
        }
531

    
532

    
533
/*        if(recvdatabuf[recv_id]->status == ACTIVE) {
534
                //TODO make timeout at least a DEFINE
535
                struct timeval timeout = { 4, 0 };
536
                recvdatabuf[recv_id]->status = INACTIVE;
537
                event_base_once(base, -1, EV_TIMEOUT, recv_timeout_cb,
538
                        arg, &timeout);
539
                return;
540
        }
541
*/
542

    
543
        if(recvdatabuf[recv_id]->status == ACTIVE) {
544
                // Monitoring layer hook
545
                if(get_Recv_data_inf_cb != NULL) {
546
                        mon_data_inf recv_data_inf;
547

    
548
                        recv_data_inf.remote_socketID =
549
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
550
                        recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
551
                        recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
552
                        recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
553
                        recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
554
                        recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
555
                                recvdatabuf[recv_id]->recvbuf : NULL;
556
                        gettimeofday(&recv_data_inf.arrival_time, NULL);
557
                        recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
558
                        recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
559
                        recv_data_inf.priority = false;
560
                        recv_data_inf.padding = false;
561
                        recv_data_inf.confirmation = false;
562
                        recv_data_inf.reliable = false;
563

    
564
                        // send data recv callback to monitoring module
565

    
566
                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
567
                }
568

    
569
                // Get the right callback
570
                receive_data_cb receive_data_callback = recvcbbuf[recvdatabuf[recv_id]->msgtype];
571

    
572
                recv_params rParams;
573

    
574
                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
575
                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
576
                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
577
                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
578
                rParams.remote_socketID =
579
                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
580
                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
581

    
582
                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
583
                        recvdatabuf[recv_id]->msgtype, &rParams);
584

    
585
                //clean up
586
                free(recvdatabuf[recv_id]->recvbuf);
587
                free(recvdatabuf[recv_id]);
588
                recvdatabuf[recv_id] = NULL;
589
        }
590
}
591

    
592
// process a single recv data message
593
void recv_data_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
594
{
595
        debug("ML: reveived packet of size %d",bufsize);
596

    
597
        int recv_id, free_recv_id = -1;
598

    
599
        if(connectbuf[msg_h->remote_con_id] == NULL) {
600
                debug("ML: Received a message not related to any opened connection!\n");
601
                return;
602
        }
603

    
604
        // check if a recv_data exist and enter data
605
        for (recv_id = 0; recv_id < RECVDATABUFSIZE; recv_id++)
606
                if (recvdatabuf[recv_id] != NULL) {
607
                        if (msg_h->remote_con_id == recvdatabuf[recv_id]->connectionID &&
608
                                        msg_h->msg_seq_num == recvdatabuf[recv_id]->seqnr)
609
                                                break;
610
                } else
611
                        if(free_recv_id == -1)
612
                                free_recv_id = recv_id;
613

    
614

    
615
        if(recv_id == RECVDATABUFSIZE) {
616
                //no recv_data found: create one
617
                recv_id = free_recv_id;
618
                recvdatabuf[recv_id] = (recvdata *) malloc(sizeof(recvdata));
619
                memset(recvdatabuf[recv_id], 0, sizeof(recvdata));
620
                recvdatabuf[recv_id]->connectionID = msg_h->remote_con_id;
621
                recvdatabuf[recv_id]->seqnr = msg_h->msg_seq_num;
622
                recvdatabuf[recv_id]->monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
623
                recvdatabuf[recv_id]->bufsize = msg_h->msg_length + msg_h->len_mon_data_hdr;
624
                recvdatabuf[recv_id]->recvbuf = (char *) malloc(recvdatabuf[recv_id]->bufsize);
625
                /*
626
                * read the timeout data and set it
627
                */
628
                recvdatabuf[recv_id]->timeout_value.tv_sec = recv_timeout.tv_sec;
629
                recvdatabuf[recv_id]->timeout_value.tv_usec = recv_timeout.tv_usec;
630
                recvdatabuf[recv_id]->timeout_event = NULL;
631
                recvdatabuf[recv_id]->recvID = recv_id;
632
                recvdatabuf[recv_id]->starttime = time(NULL);
633
                recvdatabuf[recv_id]->msgtype = msg_h->msg_type;
634

    
635
                // fill the buffer with zeros
636
                memset(recvdatabuf[recv_id]->recvbuf, 0, msg_h->msg_length);
637
                debug(" new @ id:%d\n",recv_id);
638
        } else {
639
                debug(" found @ id:%d\n",recv_id);
640
        }
641

    
642
        if (msg_h->offset == 0)
643
                recvdatabuf[recv_id]->firstPacketArrived = 1;
644

    
645

    
646
        // increment fragmentnr
647
        recvdatabuf[recv_id]->recvFragments++;
648
        // increment the arrivedBytes
649
        recvdatabuf[recv_id]->arrivedBytes += bufsize;
650

    
651
        // enter the data into the buffer
652
        memcpy(recvdatabuf[recv_id]->recvbuf + msg_h->offset, msgbuf, bufsize);
653

    
654
        //TODO very basic checkif all fragments arrived: has to be reviewed
655
        if(recvdatabuf[recv_id]->arrivedBytes == recvdatabuf[recv_id]->bufsize)
656
                recvdatabuf[recv_id]->status = COMPLETE; //buffer full -> msg completly arrived
657
        else
658
                recvdatabuf[recv_id]->status = ACTIVE;
659

    
660
        if (recv_data_callback) {
661
                if(recvdatabuf[recv_id]->status == COMPLETE) {
662
                        // Monitoring layer hook
663
                        if(get_Recv_data_inf_cb != NULL) {
664
                                mon_data_inf recv_data_inf;
665

    
666
                                recv_data_inf.remote_socketID =
667
                                         &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
668
                                recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
669
                                recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
670
                                recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
671
                                recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
672
                                recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
673
                                        recvdatabuf[recv_id]->recvbuf : NULL;
674
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
675
                                recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
676
                                recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
677
                                recv_data_inf.priority = false;
678
                                recv_data_inf.padding = false;
679
                                recv_data_inf.confirmation = false;
680
                                recv_data_inf.reliable = false;
681

    
682
                                // send data recv callback to monitoring module
683

    
684
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
685
                        }
686

    
687
                        // Get the right callback
688
                        receive_data_cb receive_data_callback = recvcbbuf[msg_h->msg_type];
689
                        if (receive_data_callback) {
690

    
691
                                recv_params rParams;
692

    
693
                                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
694
                                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
695
                                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
696
                                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
697
                                rParams.remote_socketID =
698
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
699
                                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
700

    
701
                                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
702
                                        recvdatabuf[recv_id]->msgtype, (void *) &rParams);
703
                        } else {
704
                            warn("ML: callback not initialized for this message type: %d!\n",msg_h->msg_type);
705
                        }
706

    
707
                        //clean up
708
                        if (recvdatabuf[recv_id]->timeout_event) {
709
                                int ret;
710
                                debug("ML: freeing timeout for %d",recv_id);
711
                                ret = event_del(recvdatabuf[recv_id]->timeout_event);
712
                                event_free(recvdatabuf[recv_id]->timeout_event);
713
                                debug(" ret: %d\n",ret);
714
                        } else {
715
                                debug("ML: received in 1 packet\n",recv_id);
716
                        }
717
                        free(recvdatabuf[recv_id]->recvbuf);
718
                        free(recvdatabuf[recv_id]);
719
                        recvdatabuf[recv_id] = NULL;
720
                } else { // not COMPLETE
721
                        if (!recvdatabuf[recv_id]->timeout_event) {
722
                                //start time out
723
                                //TODO make timeout at least a DEFINE
724
                                struct timeval timeout = { 4, 0 };
725
                                recvdatabuf[recv_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &recv_timeout_cb, (void *) (long)recv_id);
726
                                evtimer_add(recvdatabuf[recv_id]->timeout_event, &timeout);
727
                        }
728
                }
729
        }
730
}
731

    
732
//done
733
void pmtu_timeout_cb(int fd, short event, void *arg)
734
{
735
        debug("ML: pmtu timeout called\n");
736

    
737
        int con_id = (long) arg;
738
        pmtu new_pmtusize;
739
        struct timeval timeout;
740

    
741
        if(connectbuf[con_id] == NULL) {
742
                error("ML: pmtu timeout called on non existing con_id\n");
743
                return;
744
        }
745

    
746
        if(connectbuf[con_id]->status == READY) {
747
                // nothing to do anymore
748
                return;
749
        }
750

    
751
        timeout = connectbuf[con_id]->timeout_value;
752

    
753
        if(connectbuf[con_id]->delay || connectbuf[con_id]->trials == MAX_TRIALS - 1) {
754
                double delay = timeout.tv_sec + timeout.tv_usec / 1000000.0;
755
                delay = delay * 5;
756
                timeout.tv_sec = floor(delay);
757
                timeout.tv_usec = fmod(delay, 1.0) * 1000000.0;
758
                if(connectbuf[con_id]->delay) {
759
                        connectbuf[con_id]->delay = false;
760
                        goto reschedule;
761
                }
762
        }
763

    
764
        if(connectbuf[con_id]->trials == MAX_TRIALS) {
765
                // decrement the pmtu size
766
                connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
767
                connectbuf[con_id]->trials = 0;
768
        }
769

    
770
        //error in PMTU discovery?
771
        if (connectbuf[con_id]->pmtusize == ERROR) {
772
                if (connectbuf[con_id]->internal_connect == true) {
773
                        //as of now we tried directly connecting, now let's try trough the NAT
774
                        connectbuf[con_id]->internal_connect = false;
775
                        connectbuf[con_id]->pmtusize = MAX;
776
                } else {
777
                        //nothing to do we have to give up
778
                        error("ML: Could not create connection with connectionID %i!\n",con_id);
779
                        // envoke the callback for failed connection establishment
780
                        if(failed_Connection_cb != NULL)
781
                                (failed_Connection_cb) (con_id, NULL);
782
                        // delete the connection entry
783
                        mlCloseConnection(con_id);
784
                        return;
785
                }
786
        }
787

    
788
        //retry with new pmtu size
789
        connectbuf[con_id]->trials++;
790
        send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
791

    
792
reschedule:
793
        /* reschedule */
794
        event_base_once(base, -1, EV_TIMEOUT, pmtu_timeout_cb, (void *) (long)con_id, &timeout);
795
}
796

    
797
/*
798
 * decrements the mtu size
799
 */
800
pmtu pmtu_decrement(pmtu pmtusize)
801
{
802
        pmtu pmtu_return_size;
803
        switch(pmtusize) {
804
        case MAX:
805
                return DSL;
806
        case DSL:
807
                return DSLMEDIUM;
808
        case DSLMEDIUM:
809
                return DSLSLIM;
810
        case DSLSLIM:
811
                return BELOWDSL;
812
        case BELOWDSL:
813
                return MIN;
814
        default:
815
                return ERROR;
816
        }
817
}
818

    
819
void pmtu_error_cb_th(char *msg, int msglen)
820
{
821
        debug("ML: pmtu_error callback called msg_size: %d\n",msglen);
822
        //TODO debug
823
        return;
824

    
825
    char *msgbufptr = NULL;
826
    int msgtype;
827
    int connectionID;
828
    pmtu pmtusize;
829
    pmtu new_pmtusize;
830
    int dead = 0;
831

    
832
    // check the packettype
833
    msgbufptr = &msg[0];
834

    
835
    // check the msgtype
836
    msgbufptr = &msg[1];
837
    memcpy(&msgtype, msgbufptr, 4);
838

    
839
    if (msgtype == 0) {
840

    
841
        // get the connectionID
842
        msgbufptr = &msg[5];
843
        memcpy(&connectionID, msgbufptr, 4);
844

    
845
        int msgtype_c = connectbuf[connectionID]->status;
846
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
847

    
848
        if (msgtype_c != msgtype) {
849
            dead = 1;
850
        }
851

    
852

    
853
    } else if (msgtype == 1) {
854

    
855
        // read the connectionID
856
        msgbufptr = &msg[9];
857
        memcpy(&connectionID, msgbufptr, 4);
858

    
859
        int msgtype_c = connectbuf[connectionID]->status;
860
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
861

    
862
        if (msgtype_c != msgtype) {
863
            dead = 1;
864
        }
865

    
866
    }
867
    // decrement the pmtu size
868
    new_pmtusize = pmtu_decrement(pmtusize);
869

    
870
//    connectbuf[connectionID]->pmtutrysize = new_pmtusize;
871

    
872
    if (new_pmtusize == ERROR) {
873
                error("ML:  Could not create connection with connectionID %i !\n",
874
                        connectionID);
875

    
876
                if(failed_Connection_cb != NULL)
877
                        (failed_Connection_cb) (connectionID, NULL);
878
                // set the message type to a non existent message
879
                msgtype = 2;
880
                // delete the connection entry
881
                 mlCloseConnection(connectionID);
882
        }
883

    
884
    if (msgtype == 0 && dead != 1) {
885

    
886
        // stop the timeout event
887
        // timeout_del(connectbuf[connectionID]->timeout);
888
        /*
889
         * libevent2
890
         */
891

    
892
        // event_del(connectbuf[connectionID]->timeout);
893

    
894

    
895
        // create and send a connection message
896
//         create_conn_msg(new_pmtusize, connectionID,
897
//                         &local_socketID, INVITE);
898

    
899
//        send_conn_msg(connectionID, new_pmtusize);
900

    
901
        // set a timeout event for the pmtu discovery
902
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
903
        // *)&connectionID);
904

    
905
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
906

    
907
        /*
908
         * libevent2
909
         */
910

    
911
        struct event *ev;
912
        ev = evtimer_new(base, pmtu_timeout_cb,
913
                         (void *) connectbuf[connectionID]);
914

    
915
        // connectbuf[connectionID]->timeout = ev;
916

    
917
        event_add(ev, &connectbuf[connectionID]->timeout_value);
918

    
919
    } else if (msgtype == 1 && dead != 1) {
920

    
921
        // stop the timeout event
922
        // timeout_del(connectbuf[connectionID]->timeout);
923

    
924
        /*
925
         * libevent2
926
         */
927
        // info("still here 11 \n");
928
        // printf("ev %d \n",connectbuf[connectionID]->timeout);
929
        // event_del(connectbuf[connectionID]->timeout );
930
        // evtimer_del(connectbuf[connectionID]->timeout );
931

    
932

    
933
//         // create and send a connection message
934
//         create_conn_msg(new_pmtusize,
935
//                         connectbuf[connectionID]->connectionID,
936
//                         NULL, CONNECT);
937

    
938
        //send_conn_msg(connectionID, new_pmtusize);
939

    
940
        // set a timeout event for the pmtu discovery
941
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
942
        // *)&connectionID);
943
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
944

    
945
        /*
946
         * libevent2
947
         */
948
        // struct event *ev;
949
        // ev = evtimer_new(base,pmtu_timeout_cb, (void
950
        // *)connectbuf[connectionID]);
951
        // connectbuf[connectionID]->timeout = ev;
952
        // event_add(ev,&connectbuf[connectionID]->timeout_value);
953

    
954
    }
955
}
956

    
957
/*
958
 * what to do once a packet arrived if it is a conn packet send it to
959
 * recv_conn handler if it is a data packet send it to the recv_data
960
 * handler
961
 */
962

    
963
//done --
964
void recv_pkg(int fd, short event, void *arg)
965
{
966
        debug("ML: recv_pkg called\n");
967

    
968
        struct msg_header *msg_h;
969
        char msgbuf[MAX];
970
        char *bufptr = msgbuf;
971
        int ttl;
972
        struct sockaddr_in recv_addr;
973
        pmtu recvSize = MAX;
974
        int msg_size;
975

    
976
        recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
977

    
978

    
979
        // check if it is not just an ERROR message
980
        if(recvSize < 0)
981
                return;
982

    
983
        // @TODO check if this simplistic STUN message recognition really always works, probably not
984
        unsigned short stun_bind_response = 0x0101;
985
        unsigned short * msgspot = (unsigned short *) msgbuf;
986
        if (*msgspot == stun_bind_response) {
987
                debug("ML: recv_pkg: parse stun message called\n");
988
                recv_stun_msg(msgbuf, recvSize);
989
                return;
990
        }
991

    
992
        msg_h = (struct msg_header *) msgbuf;
993
        bufptr += MSG_HEADER_SIZE + msg_h->len_mon_packet_hdr;
994
        msg_size = recvSize - MSG_HEADER_SIZE - msg_h->len_mon_packet_hdr;
995

    
996

    
997
        if(get_Recv_pkt_inf_cb != NULL && msg_h->len_mon_packet_hdr != 0) {
998
                mon_pkt_inf msginfNow;
999
                msginfNow.monitoringHeaderLen = msg_h->len_mon_packet_hdr;
1000
                msginfNow.monitoringHeader = msg_h->len_mon_packet_hdr ? &msgbuf[0] + MSG_HEADER_SIZE : NULL;
1001
                //TODO rethink this ...
1002
                if(msg_h->msg_type == ML_CON_MSG) {
1003
                        struct conn_msg *c_msg = (struct conn_msg *) bufptr;
1004
                        msginfNow.remote_socketID = &(c_msg->sock_id);
1005
                }
1006
                else if(connectbuf[msg_h->remote_con_id] == NULL) {
1007
                        error("ML: received pkg called with non existent connection\n");
1008
                        return;
1009
                } else
1010
                        msginfNow.remote_socketID = &(connectbuf[msg_h->remote_con_id]->external_socketID);
1011
                msginfNow.buffer = bufptr;
1012
                msginfNow.bufSize = recvSize;
1013
                msginfNow.msgtype = msg_h->msg_type;
1014
                msginfNow.ttl = ttl;
1015
                msginfNow.dataID = msg_h->msg_seq_num;
1016
                msginfNow.offset = msg_h->offset;
1017
                msginfNow.datasize = msg_h->msg_length;
1018
                gettimeofday(&msginfNow.arrival_time, NULL);
1019
                (get_Recv_pkt_inf_cb) ((void *) &msginfNow);
1020
        }
1021

    
1022

    
1023
        switch(msg_h->msg_type) {
1024
                case ML_CON_MSG:
1025
                        debug("ML: received conn pkg\n");
1026
                        recv_conn_msg(msg_h, bufptr, msg_size);
1027
                        break;
1028
                default:
1029
                        if(msg_h->msg_type < 127) {
1030
                                debug("ML: received data pkg\n");
1031
                                recv_data_msg(msg_h, bufptr, msg_size);
1032
                                break;
1033
                        }
1034
                        debug("ML: unrecognised msg_type\n");
1035
                        break;
1036
        }
1037
}
1038

    
1039
/*
1040
 * compare the external IP address of two socketIDs
1041
 */
1042
int
1043
compare_external_address_socketIDs(socketID_handle sock1, socketID_handle sock2)
1044
{
1045
        if( sock1->external_addr.udpaddr.sin_addr.s_addr == sock2->external_addr.udpaddr.sin_addr.s_addr)
1046
                return 0;
1047
        return 1;
1048
}
1049

    
1050
void try_stun();
1051

    
1052
/*
1053
 * the timeout of the NAT traversal
1054
 */
1055
void nat_traversal_timeout(int fd, short event, void *arg)
1056
{
1057
        if (NAT_traversal == false) {
1058
                debug("ML: NAT traversal request re-send\n");
1059
                if(receive_SocketID_cb)
1060
                        (receive_SocketID_cb) (&local_socketID, 2);
1061
                try_stun();
1062
        }
1063
}
1064

    
1065
unsigned long resolve(const char *ipaddr)
1066
{
1067
        struct hostent *h = gethostbyname(ipaddr);
1068
        if (!h) {
1069
                error("ML: Unable to resolve host name %s\n", ipaddr);
1070
        exit(-1);
1071
    }
1072
    unsigned long *addr = (unsigned long *) (h->h_addr);
1073
    return *addr;
1074
}
1075

    
1076

    
1077
/*
1078
 * returns a handle to the socketID struct the ipaddr can be a null
1079
 * pointer. Then all available ipaddr on the machine are choosen.
1080
 */
1081
void create_socket(const int port, const char *ipaddr)
1082
{
1083
        struct sockaddr_in udpaddr;
1084
        udpaddr.sin_family = AF_INET;
1085
        if (ipaddr == NULL) {
1086
                /*
1087
                * try to guess the local IP address
1088
                */
1089
                const char *ipaddr_iface = mlAutodetectIPAddress();
1090
                if (ipaddr_iface) {
1091
                        udpaddr.sin_addr.s_addr = inet_addr(ipaddr_iface);
1092
                } else {
1093
                        udpaddr.sin_addr.s_addr = INADDR_ANY;
1094
                }
1095
        } else {
1096
                udpaddr.sin_addr.s_addr = inet_addr(ipaddr);
1097
        }
1098
        udpaddr.sin_port = htons(port);
1099

    
1100
        socketaddrgen udpgen;
1101
        memset(&udpgen,0,sizeof(socketaddrgen));        //this will be sent over the net, so set it to 0
1102
        udpgen.udpaddr = udpaddr;
1103
        local_socketID.internal_addr = udpgen;
1104

    
1105
        socketfd = createSocket(port, ipaddr);
1106

    
1107
        struct event *ev;
1108
        ev = event_new(base, socketfd, EV_READ | EV_PERSIST, recv_pkg, NULL);
1109

    
1110
        event_add(ev, NULL);
1111

    
1112
        try_stun();
1113
}
1114

    
1115
/*
1116
 * try to figure out external IP using STUN, if defined
1117
 */
1118
void try_stun()
1119
{
1120
        if (isStunDefined()) {
1121
                /*
1122
                * send the NAT traversal STUN request
1123
                */
1124
                 send_stun_request(socketfd, &stun_server);
1125

    
1126
                /*
1127
                * enter a NAT traversal timeout that takes care of retransmission
1128
                */
1129
                struct event *ev1;
1130
                struct timeval timeout_value_NAT_traversal = { 2, 0 };
1131
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1132
                event_add(ev1, &timeout_value_NAT_traversal);
1133

    
1134
                NAT_traversal = false;
1135
        } else {
1136
                /*
1137
                * Assume we have accessibility and copy internal address to external one
1138
                */
1139
                local_socketID.external_addr = local_socketID.internal_addr;
1140
                NAT_traversal = true; // @TODO: this is not really NAT traversal, but a flag that init is over
1141
                // callback to the upper layer indicating that the socketID is now
1142
                // ready to use
1143
                if(receive_SocketID_cb)
1144
                        (receive_SocketID_cb) (&local_socketID, 0); //success
1145
        }
1146
}
1147

    
1148
/**************************** END OF INTERNALS ***********************/
1149

    
1150
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){
1151

    
1152
        base = (struct event_base *) arg;
1153
        recv_data_callback = recv_data_cb;
1154
        mlSetRecvTimeout(timeout_value);
1155
        if (stun_ipaddr) {
1156
                 mlSetStunServer(stun_port, stun_ipaddr);
1157
        } else {
1158

    
1159
        }
1160
        register_recv_localsocketID_cb(local_socketID_cb);
1161
        create_socket(port, ipaddr);
1162

    
1163
}
1164

    
1165
/* register callbacks  */
1166
void mlRegisterGetRecvPktInf(get_recv_pkt_inf_cb recv_pkt_inf_cb){
1167

    
1168
        if (recv_pkt_inf_cb == NULL)
1169
                error("ML: Register get_recv_pkt_inf_cb failed: NULL ptr  \n");
1170
        else
1171
                get_Recv_pkt_inf_cb = recv_pkt_inf_cb;
1172

    
1173
}
1174

    
1175
void mlRegisterGetSendPktInf(get_send_pkt_inf_cb  send_pkt_inf_cb){
1176

    
1177
        if (send_pkt_inf_cb == NULL)
1178
                error("ML: Register get_send_pkt_inf_cb: NULL ptr  \n");
1179
        else
1180
                get_Send_pkt_inf_cb = send_pkt_inf_cb;
1181

    
1182
}
1183

    
1184

    
1185
void mlRegisterSetMonitoringHeaderPktCb(set_monitoring_header_pkt_cb monitoring_header_pkt_cb ){
1186

    
1187
        if (monitoring_header_pkt_cb == NULL)
1188
                error("ML: Register set_monitoring_header_pkt_cb: NULL ptr  \n");
1189
        else
1190
                set_Monitoring_header_pkt_cb = monitoring_header_pkt_cb;
1191

    
1192
}
1193

    
1194
void mlRegisterGetRecvDataInf(get_recv_data_inf_cb recv_data_inf_cb){
1195

    
1196
        if (recv_data_inf_cb == NULL)
1197
                error("ML: Register get_recv_data_inf_cb: NULL ptr  \n");
1198
        else
1199
                get_Recv_data_inf_cb = recv_data_inf_cb;
1200

    
1201
}
1202

    
1203
void mlRegisterGetSendDataInf(get_send_data_inf_cb  send_data_inf_cb){
1204

    
1205
        if (send_data_inf_cb == NULL)
1206
                error("ML: Register get_send_data_inf_cb: NULL ptr  \n");
1207
        else
1208
                get_Send_data_inf_cb = send_data_inf_cb;
1209

    
1210
}
1211

    
1212
void mlRegisterSetMonitoringHeaderDataCb(set_monitoring_header_data_cb monitoring_header_data_cb){
1213

    
1214
        if (monitoring_header_data_cb == NULL)
1215
                error("ML: Register set_monitoring_header_data_cb : NULL ptr  \n");
1216
        else
1217
        set_Monitoring_header_data_cb = monitoring_header_data_cb;
1218

    
1219
}
1220

    
1221
void mlRegisterRecvConnectionCb(receive_connection_cb recv_conn_cb){
1222

    
1223
        if (recv_conn_cb == NULL)
1224
                error("ML: Register receive_connection_cb: NULL ptr  \n");
1225
        else
1226
                receive_Connection_cb = recv_conn_cb;
1227

    
1228
}
1229

    
1230
void mlRegisterErrorConnectionCb(connection_failed_cb conn_failed){
1231

    
1232
        if (conn_failed == NULL)
1233
                error("ML: Register connection_failed_cb: NULL ptr  \n");
1234
        else
1235
        failed_Connection_cb = conn_failed;
1236

    
1237
}
1238

    
1239
void mlRegisterRecvDataCb(receive_data_cb data_cb,unsigned char msgtype){
1240

    
1241
    if (msgtype > 126) {
1242

    
1243
            error
1244
            ("ML: Could not register recv_data callback. Msgtype is greater then 126 \n");
1245

    
1246
    }
1247

    
1248
    if (data_cb == NULL) {
1249

    
1250
            error("ML: Register receive data callback: NUll ptr \n ");
1251

    
1252
    } else {
1253

    
1254
        recvcbbuf[msgtype] = data_cb;
1255

    
1256
    }
1257

    
1258
}
1259

    
1260
void mlCloseSocket(socketID_handle socketID){
1261

    
1262
        free(socketID);
1263

    
1264
}
1265

    
1266
void keepalive_fn(evutil_socket_t fd, short what, void *arg) {
1267
        socketID_handle peer = arg;
1268

    
1269
        int con_id = mlConnectionExist(peer, false);
1270
        if (con_id < 0 || connectbuf[con_id]->defaultSendParams.keepalive <= 0) {
1271
                /* Connection fell from under us or keepalive was disabled */
1272
                free(arg);
1273
                return;
1274
        }
1275

    
1276
        /* do what we gotta do */
1277
        if ( connectbuf[con_id]->status == READY) {
1278
                char keepaliveMsg[32] = "";
1279
                sprintf(keepaliveMsg, "KEEPALIVE %d", connectbuf[con_id]->keepalive_seq++);
1280
                send_msg(con_id, MSG_TYPE_ML_KEEPALIVE, keepaliveMsg, 1 + strlen(keepaliveMsg), false, 
1281
                        &(connectbuf[con_id]->defaultSendParams));
1282
        }
1283

    
1284
        /* re-schedule */
1285
        struct timeval t = { 0,0 };
1286
        t.tv_sec = connectbuf[con_id]->defaultSendParams.keepalive;
1287
        if (connectbuf[con_id]->defaultSendParams.keepalive) 
1288
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1289
}
1290

    
1291
void setupKeepalive(int conn_id) {
1292
        /* Save the peer's address for us */
1293
        socketID_handle peer = malloc(sizeof(socket_ID));
1294
        memcpy(peer, &connectbuf[conn_id]->external_socketID, sizeof(socket_ID));
1295

    
1296
        struct timeval t = { 0,0 };
1297
        t.tv_sec = connectbuf[conn_id]->defaultSendParams.keepalive;
1298

    
1299
        if (connectbuf[conn_id]->defaultSendParams.keepalive) 
1300
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1301
}
1302

    
1303
/* connection functions */
1304
int mlOpenConnection(socketID_handle external_socketID,receive_connection_cb connection_cb,void *arg, const send_params defaultSendParams){
1305

    
1306
        int con_id;
1307
        if (external_socketID == NULL) {
1308
                error("ML: cannot open connection: one of the socketIDs is NULL\n");
1309
                return -1;
1310
        }
1311
        if (NAT_traversal == false) {
1312
                error("ML: cannot open connection: NAT traversal for socketID still in progress\n");
1313
                return -1;
1314
        }
1315
        if (connection_cb == NULL) {
1316
                error("ML: cannot open connection: connection_cb is NULL\n");
1317
                return -1;
1318
        }
1319

    
1320
        // check if that connection already exist
1321

    
1322
        con_id = mlConnectionExist(external_socketID, false);
1323
        if (con_id >= 0) {
1324
                // overwrite defaultSendParams
1325
                bool newKeepalive = 
1326
                        connectbuf[con_id]->defaultSendParams.keepalive == 0 && defaultSendParams.keepalive != 0;
1327
                connectbuf[con_id]->defaultSendParams = defaultSendParams;
1328
                if (newKeepalive) setupKeepalive(con_id);
1329
                // if so check if it is ready to use
1330
                if (connectbuf[con_id]->status == READY) {
1331
                                // if so use the callback immediateley
1332
                                (connection_cb) (con_id, arg);
1333

    
1334
                // otherwise just write the connection cb and the arg pointer
1335
                // into the connection struct
1336
                } else {
1337
                        struct receive_connection_cb_list *temp;
1338
                        temp = malloc(sizeof(struct receive_connection_cb_list));
1339
                        temp->next = NULL;
1340
                        temp->connection_cb = connection_cb;
1341
                        temp->arg = arg;
1342
                        if(connectbuf[con_id]->connection_last != NULL) {
1343
                                connectbuf[con_id]->connection_last->next = temp;
1344
                                connectbuf[con_id]->connection_last = temp;
1345
                        } else
1346
                                connectbuf[con_id]->connection_last = connectbuf[con_id]->connection_head = temp;
1347
                }
1348
                return con_id;
1349
        }
1350
        // make entry in connection_establishment array
1351
        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
1352
                if (connectbuf[con_id] == NULL) {
1353
                        connectbuf[con_id] = (connect_data *) malloc(sizeof(connect_data));
1354
                        memset(connectbuf[con_id],0,sizeof(connect_data));
1355
                        connectbuf[con_id]->starttime = time(NULL);
1356
                        memcpy(&connectbuf[con_id]->external_socketID, external_socketID, sizeof(socket_ID));
1357
                        connectbuf[con_id]->pmtusize = MAX;
1358
                        connectbuf[con_id]->status = INVITE;
1359
                        connectbuf[con_id]->seqnr = 0;
1360
                        connectbuf[con_id]->internal_connect = !compare_external_address_socketIDs(external_socketID, &local_socketID);
1361
                        /*
1362
                        * timeout values for the pmtu discovery
1363
                        */
1364
                        connectbuf[con_id]->timeout_value.tv_sec = 15;
1365
                        connectbuf[con_id]->timeout_value.tv_usec = 0;
1366
                        connectbuf[con_id]->connectionID = con_id;
1367

    
1368
                        connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
1369
                        connectbuf[con_id]->connection_last->next = NULL;
1370
                        connectbuf[con_id]->connection_last->connection_cb = connection_cb;
1371
                        connectbuf[con_id]->connection_last->arg = arg;
1372
                        connectbuf[con_id]->external_connectionID = -1;
1373

    
1374
                        connectbuf[con_id]->defaultSendParams = defaultSendParams;
1375
                        if (defaultSendParams.keepalive) setupKeepalive(con_id);
1376
                        break;
1377
                }
1378
        } //end of for
1379

    
1380
        if (con_id == CONNECTBUFSIZE) {
1381
                error("ML: Could not open connection: connection buffer full\n");
1382
                return -1;
1383
        }
1384

    
1385
        // create and send a connection message
1386
        send_conn_msg(con_id, MAX, INVITE);
1387

    
1388
        struct event *ev;
1389
        ev = evtimer_new(base, pmtu_timeout_cb, (void *) (long)con_id);
1390
        event_add(ev, &connectbuf[con_id]->timeout_value);
1391

    
1392
        return con_id;
1393

    
1394
}
1395

    
1396
void mlCloseConnection(const int connectionID){
1397

    
1398
        // remove it from the connection array
1399
        if(connectbuf[connectionID]) {
1400
                if(connectbuf[connectionID]->ctrl_msg_buf)
1401
                        free(connectbuf[connectionID]->ctrl_msg_buf);
1402
                free(connectbuf[connectionID]);
1403
                connectbuf[connectionID] = NULL;
1404
        }
1405

    
1406
}
1407

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

    
1410
        if (connectionID < 0) {
1411
                error("ML: send data failed: connectionID does not exist\n");
1412
                return;
1413
        }
1414

    
1415
        if (connectbuf[connectionID] == NULL) {
1416
                error("ML: send data failed: connectionID does not exist\n");
1417
                return;
1418
        }
1419
        if (connectbuf[connectionID]->status != READY) {
1420
            error("ML: send data failed: connection is not active\n");
1421
            return;
1422
        }
1423

    
1424
        if (sParams == NULL) {
1425
                sParams = &(connectbuf[connectionID]->defaultSendParams);
1426
        }
1427

    
1428
        send_msg(connectionID, msgtype, sendbuf, bufsize, false, sParams);
1429

    
1430
}
1431

    
1432
/* transmit data functions  */
1433
int mlSendAllData(const int connectionID,send_all_data_container *container,int nr_entries,unsigned char msgtype,send_params *sParams){
1434

    
1435
    if (nr_entries < 1 || nr_entries > 5) {
1436

    
1437
        error
1438
            ("ML : sendALlData : nr_enties is not between 1 and 5 \n ");
1439
        return 0;
1440

    
1441
    } else {
1442

    
1443
        if (nr_entries == 1) {
1444

    
1445
                mlSendData(connectionID, container->buffer_1,
1446
                      container->length_1, msgtype, sParams);
1447

    
1448
            return 1;
1449

    
1450
        } else if (nr_entries == 2) {
1451

    
1452
            int buflen = container->length_1 + container->length_2;
1453
            char buf[buflen];
1454
            memcpy(buf, container->buffer_1, container->length_1);
1455
            memcpy(&buf[container->length_1], container->buffer_2,
1456
                   container->length_2);
1457
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1458

    
1459
            return 1;
1460

    
1461
        } else if (nr_entries == 3) {
1462

    
1463
            int buflen =
1464
                container->length_1 + container->length_2 +
1465
                container->length_3;
1466
            char buf[buflen];
1467
            memcpy(buf, container->buffer_1, container->length_1);
1468
            memcpy(&buf[container->length_1], container->buffer_2,
1469
                   container->length_2);
1470
            memcpy(&buf[container->length_2], container->buffer_3,
1471
                   container->length_3);
1472
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1473

    
1474

    
1475
            return 1;
1476

    
1477
        } else if (nr_entries == 4) {
1478

    
1479
            int buflen =
1480
                container->length_1 + container->length_2 +
1481
                container->length_3 + container->length_4;
1482
            char buf[buflen];
1483
            memcpy(buf, container->buffer_1, container->length_1);
1484
            memcpy(&buf[container->length_1], container->buffer_2,
1485
                   container->length_2);
1486
            memcpy(&buf[container->length_2], container->buffer_3,
1487
                   container->length_3);
1488
            memcpy(&buf[container->length_3], container->buffer_4,
1489
                   container->length_4);
1490
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1491

    
1492
            return 1;
1493

    
1494
        } else {
1495

    
1496
            int buflen =
1497
                container->length_1 + container->length_2 +
1498
                container->length_3 + container->length_4 +
1499
                container->length_5;
1500
            char buf[buflen];
1501
            memcpy(buf, container->buffer_1, container->length_1);
1502
            memcpy(&buf[container->length_1], container->buffer_2,
1503
                   container->length_2);
1504
            memcpy(&buf[container->length_2], container->buffer_3,
1505
                   container->length_3);
1506
            memcpy(&buf[container->length_3], container->buffer_4,
1507
                   container->length_4);
1508
            memcpy(&buf[container->length_4], container->buffer_5,
1509
                   container->length_5);
1510
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1511

    
1512
            return 1;
1513
        }
1514

    
1515
    }
1516

    
1517
}
1518

    
1519
int mlRecvData(const int connectionID,char *recvbuf,int *bufsize,recv_params *rParams){
1520

    
1521
        //TODO yet to be converted
1522
        return 0;
1523
#if 0
1524
        if (rParams == NULL) {
1525
                error("ML: recv_data failed: recv_params is a NULL ptr\n");
1526
                return 0;
1527
    } else {
1528

1529
        info("ML: recv data called \n");
1530

1531
        int i = 0;
1532
        int returnValue = 0;
1533
        double timeout = (double) recv_timeout.tv_sec;
1534
        time_t endtime = time(NULL);
1535

1536
        for (i = 0; i < RECVDATABUFSIZE; i++) {
1537

1538
            if (recvdatabuf[i] != NULL) {
1539

1540
                if (recvdatabuf[i]->connectionID == connectionID) {
1541

1542
                    info("ML: recv data has entry  \n");
1543

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

1546
                    // check if the specified connection has data and it
1547
                    // is complete
1548
                    // check the data seqnr
1549
                    // if(connectionID == recvdatabuf[i]->connectionID &&
1550
                    // 1 == recvdatabuf[i]->status){
1551

1552
                    if (1 == recvdatabuf[i]->status) {
1553

1554
                        // info("transmissionHandler: recv_data set is
1555
                        // complete \n" );
1556

1557
                        // debug("debud \n");
1558

1559
                        // exchange the pointers
1560
                        int buffersize = 0;
1561
                        buffersize = recvdatabuf[i]->bufsize;
1562
                        *bufsize = buffersize;
1563
                        // recvbuf = recvdatabuf[i]->recvbuf;
1564

1565
                        // info("buffersize %d \n",buffersize);
1566
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1567
                               buffersize);
1568
                        // debug(" recvbuf %s \n",recvbuf );
1569

1570
//                         double nrMissFrags =
1571
//                             (double) recvdatabuf[i]->nrFragments /
1572
//                             (double) recvdatabuf[i]->recvFragments;
1573
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
1574

1575
//                        rParams->nrMissingFragments = nrMissingFragments;
1576
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
1577
                        rParams->msgtype = recvdatabuf[i]->msgtype;
1578
                        rParams->connectionID =
1579
                            recvdatabuf[i]->connectionID;
1580

1581
                        // break from the loop
1582
                        // debug(" recvbuf %s \n ",recvbuf);
1583

1584
                        // double nrMissFrags =
1585
                        // (double)recvdatabuf[i]->nrFragments /
1586
                        // (double)recvdatabuf[i]->recvFragments;
1587
                        // int nrMissingFragments =
1588
                        // (int)ceil(nrMissFrags);
1589

1590
                        if(get_Recv_data_inf_cb != NULL) {
1591
                                mon_data_inf recv_data_inf;
1592

1593
                                recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1594
                                recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1595
                                recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1596
                                recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1597
//                                 recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1598
//                                 recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1599
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
1600
                                recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1601
                                recv_data_inf.nrMissingFragments = nrMissingFragments;
1602
                                recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1603
                                recv_data_inf.priority = false;
1604
                                recv_data_inf.padding = false;
1605
                                recv_data_inf.confirmation = false;
1606
                                recv_data_inf.reliable = false;
1607

1608
                                // send data recv callback to monitoring module
1609

1610
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1611
                        }
1612

1613

1614
                        // free the allocated memory
1615
                        free(recvdatabuf[i]);
1616
                        recvdatabuf[i] = NULL;
1617

1618
                        returnValue = 1;
1619
                        break;
1620

1621
                    }
1622

1623
                    if (recvdatabuf[i] != NULL) {
1624

1625
                        if (timepass > timeout) {
1626

1627
                            info("ML: recv_data timeout called  \n");
1628

1629
                            // some data about the missing chunks should
1630
                            // be added here
1631
                            // exchange the pointers
1632
                            int buffersize = 0;
1633
                            buffersize = recvdatabuf[i]->bufsize;
1634
                            *bufsize = buffersize;
1635
                            // recvbuf = recvdatabuf[i]->recvbuf;
1636

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

1643
                            // debug(" recvbuf %s \n",recvbuf );
1644

1645
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1646
                                   buffersize);
1647

1648
                            rParams->nrMissingFragments =
1649
                                nrMissingFragments;
1650
                            rParams->nrFragments =
1651
                                recvdatabuf[i]->nrFragments;
1652
                            rParams->msgtype = recvdatabuf[i]->msgtype;
1653
                            rParams->connectionID =
1654
                                recvdatabuf[i]->connectionID;
1655

1656
                                if(get_Recv_data_inf_cb != NULL) {
1657
                                        mon_data_inf recv_data_inf;
1658

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

1674
                                        // send data recv callback to monitoring module
1675

1676
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1677
                                }
1678

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

1683
                            returnValue = 1;
1684
                            break;
1685

1686
                        }
1687
                    }
1688

1689
                }
1690

1691
            }
1692
            // debug("2 recvbuf %s \n ",recvbuf);
1693
        }
1694
        return returnValue;
1695
    }
1696
#endif
1697

    
1698
}
1699

    
1700
/* setter  */
1701
void mlSetStunServer(const int port,const char *ipaddr){
1702

    
1703
        stun_server.sin_family = AF_INET;
1704
        if (ipaddr == NULL)
1705
                stun_server.sin_addr.s_addr = htonl(INADDR_ANY);
1706
        else
1707
                stun_server.sin_addr.s_addr = resolve(ipaddr);
1708
        stun_server.sin_port = htons(port);
1709

    
1710
}
1711

    
1712
void mlSetRecvTimeout(struct timeval timeout_value){
1713

    
1714
        recv_timeout = timeout_value;
1715

    
1716
}
1717

    
1718
int mlGetStandardTTL(socketID_handle socketID,uint8_t *ttl){
1719

    
1720
        return getTTL(socketfd, ttl);
1721

    
1722
}
1723

    
1724
socketID_handle mlGetLocalSocketID(int *errorstatus){
1725

    
1726
        if (NAT_traversal == false) {
1727
                *errorstatus = 2;
1728
                return NULL;
1729
        }
1730

    
1731
        *errorstatus = 0;
1732
        return &local_socketID;
1733

    
1734
}
1735

    
1736
int mlGetExternalIP(char* external_addr){
1737

    
1738
        socketaddrgen udpgen;
1739
        struct sockaddr_in udpaddr;
1740

    
1741
        udpgen = local_socketID.external_addr;
1742
        udpaddr = udpgen.udpaddr;
1743

    
1744
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
1745
                        INET_ADDRSTRLEN);
1746

    
1747
        if (external_addr == NULL) {
1748

    
1749
        return -1;
1750

    
1751
        } else {
1752

    
1753
        return 0;
1754

    
1755
        }
1756

    
1757
}
1758

    
1759
int mlSocketIDToString(socketID_handle socketID,char* socketID_string, size_t len){
1760

    
1761
        char internal_addr[INET_ADDRSTRLEN];
1762
        char external_addr[INET_ADDRSTRLEN];
1763
        inet_ntop(AF_INET, &(socketID->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1764
        inet_ntop(AF_INET, &(socketID->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1765

    
1766
        snprintf(socketID_string,len,"%s:%d-%s:%d", internal_addr, ntohs(socketID->internal_addr.udpaddr.sin_port),
1767
                external_addr,        ntohs(socketID->external_addr.udpaddr.sin_port));
1768
        return 0;
1769

    
1770
}
1771

    
1772
int mlStringToSocketID(const char* socketID_string, socketID_handle socketID){
1773

    
1774
        //@TODO add checks against malformed string
1775
        char external_addr[INET_ADDRSTRLEN];
1776
        int external_port;
1777
        char internal_addr[INET_ADDRSTRLEN];
1778
        int internal_port;
1779

    
1780
        char *pch;
1781
        char *s = strdup(socketID_string);
1782

    
1783
        //replace ':' with a blank
1784
        pch=strchr(s,':');
1785
        while (pch!=NULL){
1786
                                *pch = ' ';
1787
                pch=strchr(pch+1,':');
1788
        }
1789
        pch=strchr(s,'-');
1790
        if(pch) *pch = ' ';
1791

    
1792
        sscanf(s,"%s %d %s %d", internal_addr, &internal_port,
1793
                external_addr, &external_port);
1794

    
1795
        if(inet_pton(AF_INET, internal_addr, &(socketID->internal_addr.udpaddr.sin_addr)) == 0)
1796
                return EINVAL;
1797
        socketID->internal_addr.udpaddr.sin_family = AF_INET;
1798
        socketID->internal_addr.udpaddr.sin_port = htons(internal_port);
1799

    
1800

    
1801
        if(inet_pton(AF_INET, external_addr, &(socketID->external_addr.udpaddr.sin_addr)) ==0)
1802
                return EINVAL;
1803
        socketID->external_addr.udpaddr.sin_family = AF_INET;
1804
        socketID->external_addr.udpaddr.sin_port = htons(external_port);
1805

    
1806
        free(s);
1807
        return 0;
1808

    
1809
}
1810

    
1811
int mlGetConnectionStatus(int connectionID){
1812

    
1813
        if(connectbuf[connectionID])
1814
                return connectbuf[connectionID]->status == READY;
1815
        return -1;
1816
    
1817
}
1818

    
1819

    
1820
int mlConnectionExist(socketID_handle socketID, bool ready){
1821

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

    
1834
    return -1;
1835

    
1836
}
1837

    
1838
//Added by Robert Birke as comodity functions
1839

    
1840
//int mlPrintSocketID(socketID_handle socketID) {
1841
//        char str[SOCKETID_STRING_SIZE];
1842
//        mlSocketIDToString(socketID, str, sizeof(str));
1843
//        printf(stderr,"int->%s<-ext\n",str);
1844
//}
1845

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

    
1855
int mlCompareSocketIDs(socketID_handle sock1, socketID_handle sock2) {
1856
        /*
1857
        * compare internal addr
1858
        */
1859
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr !=
1860
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
1861
                        return 1;
1862

    
1863
        if (sock1->internal_addr.udpaddr.sin_port !=
1864
                 sock2->internal_addr.udpaddr.sin_port)
1865
                        return 1;
1866

    
1867
        /*
1868
        * compare external addr
1869
        */
1870
        if (sock1->external_addr.udpaddr.sin_addr.s_addr !=
1871
            sock2->external_addr.udpaddr.sin_addr.s_addr)
1872
                        return 1;
1873

    
1874
        if (sock1->external_addr.udpaddr.sin_port !=
1875
                 sock2->external_addr.udpaddr.sin_port)
1876
                        return 1;
1877

    
1878
        return 0;
1879
}
1880

    
1881
int mlCompareSocketIDsByPort(socketID_handle sock1, socketID_handle sock2)
1882
{ 
1883
        if (sock1->internal_addr.udpaddr.sin_port !=
1884
                 sock2->internal_addr.udpaddr.sin_port)
1885
                        return 1;
1886

    
1887
        if (sock1->external_addr.udpaddr.sin_port !=
1888
                 sock2->external_addr.udpaddr.sin_port)
1889
                        return 1;
1890
        return 0;
1891
}
1892

    
1893
int mlGetPathMTU(int ConnectionId) {
1894
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
1895
                return -1;
1896
        if (connectbuf[ConnectionId] != NULL)
1897
                return connectbuf[ConnectionId]->pmtusize;
1898
        return -1;
1899
}