Statistics
| Branch: | Revision:

ml / ml.c @ 11fce711

History | View | Annotate | Download (52.2 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(connectbuf[con_id]->ctrl_msg_buf == NULL)
304
                connectbuf[con_id]->ctrl_msg_buf = malloc(MAX);
305

    
306
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
307
                error("ML: can not allocate memory for connection message\n");
308
                return;
309
        }
310

    
311
        struct conn_msg *msg_header = (struct conn_msg*) connectbuf[con_id]->ctrl_msg_buf;
312

    
313
        msg_header->comand_type = command_type;
314
        msg_header->pmtu_size = connectbuf[con_id]->pmtusize;
315

    
316
        memcpy(&(msg_header->sock_id), loc_socketID, sizeof(socket_ID));
317

    
318
        send_msg(con_id, ML_CON_MSG, connectbuf[con_id]->ctrl_msg_buf, buf_size, true, &(connectbuf[con_id]->defaultSendParams));
319
}
320

    
321
void
322
recv_conn_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
323
{
324
        struct conn_msg *con_msg;
325
        int free_con_id, con_id;
326

    
327
        time_t now = time(NULL);
328
        double timediff = 0.0;
329

    
330
        // Monitoring layer hook
331
        if(get_Recv_data_inf_cb != NULL && msg_h->len_mon_data_hdr != 0) {
332
                // update pointer to the real data
333
                msgbuf += msg_h->len_mon_data_hdr;
334
                bufsize -= msg_h->len_mon_data_hdr;
335
                con_msg = (struct conn_msg *)msgbuf;
336

    
337
                mon_data_inf recv_data_inf;
338
                recv_data_inf.remote_socketID = &(con_msg->sock_id);
339
                recv_data_inf.buffer = msgbuf;
340
                recv_data_inf.bufSize = bufsize;
341
                recv_data_inf.msgtype = msg_h->msg_type;
342
                recv_data_inf.monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
343
                recv_data_inf.monitoringDataHeader = msg_h->len_mon_data_hdr ? msgbuf : NULL;
344
                gettimeofday(&recv_data_inf.arrival_time, NULL);
345
                recv_data_inf.firstPacketArrived = true;
346
                recv_data_inf.recvFragments = 1;
347
                recv_data_inf.priority = false;
348
                recv_data_inf.padding = false;
349
                recv_data_inf.confirmation = false;
350
                recv_data_inf.reliable = false;
351

    
352
                // send data recv callback to monitoring module
353
                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
354
        } else
355
                con_msg = (struct conn_msg *) msgbuf;
356

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

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

    
399
                        if(connectbuf[con_id]->status <= CONNECT) {
400
                                //update status and send back answer
401
                                connectbuf[con_id]->status = CONNECT;
402
                                send_conn_msg(con_id, con_msg->pmtu_size, CONNECT);
403
                        }
404
                        break;
405
                case CONNECT:
406
                        debug("ML: received CONNECT\n");
407

    
408
                        if(msg_h->remote_con_id != -1 && connectbuf[msg_h->remote_con_id] == NULL) {
409
                                error("ML: received CONNECT for inexistent connection\n");
410
                                return;
411
                        }
412

    
413
                        /*
414
                        * check if the connection status is not already 1 or 2
415
                        */
416
                        if (connectbuf[msg_h->remote_con_id]->status == INVITE) {
417
                                // set the external connectionID
418
                                connectbuf[msg_h->remote_con_id]->external_connectionID = msg_h->local_con_id;
419
                                // change status con_msg the connection_data
420
                                connectbuf[msg_h->remote_con_id]->status = READY;
421
                                // change pmtusize in the connection_data
422
                                connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
423

    
424
                                // send the READY
425
                                send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
426

    
427
                                if (receive_Connection_cb != NULL)
428
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
429

    
430
                                // call all registered callbacks
431
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
432
                                        struct receive_connection_cb_list *temp;
433
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
434
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
435
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
436
                                        free(temp);
437
                                }
438
                                connectbuf[msg_h->remote_con_id]->connection_head =
439
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
440
                        } else
441
                                // send the READY
442
                                send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
443

    
444
                        debug("ML: active connection established\n");
445
                        break;
446

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

    
466
                                if (receive_Connection_cb != NULL)
467
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
468

    
469
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
470
                                        struct receive_connection_cb_list *temp;
471
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
472
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
473
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
474
                                        free(temp);
475
                                }
476
                                connectbuf[msg_h->remote_con_id]->connection_head =
477
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
478
                                debug("ML: passive connection established\n");
479
                        }
480
                        break;
481
        }
482
}
483

    
484
void recv_stun_msg(char *msgbuf, int recvSize)
485
{
486
        /*
487
        * create empty stun message struct
488
        */
489
        StunMessage resp;
490
        memset(&resp, 0, sizeof(StunMessage));
491
        /*
492
        * parse the message
493
        */
494
        int returnValue = 0;
495
        returnValue = recv_stun_message(msgbuf, recvSize, &resp);
496

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

    
515
//done
516
void recv_timeout_cb(int fd, short event, void *arg)
517
{
518
        int recv_id = (long) arg;
519
        debug("ML: recv_timeout_cb called\n");
520

    
521
        if (recvdatabuf[recv_id] == NULL) {
522
                return;
523
        }
524

    
525

    
526
        if(recvdatabuf[recv_id]->status == ACTIVE) {
527
                //TODO make timeout at least a DEFINE
528
                struct timeval timeout = { 4, 0 };
529
                recvdatabuf[recv_id]->status = INACTIVE;
530
                event_base_once(base, -1, EV_TIMEOUT, recv_timeout_cb,
531
                        arg, &timeout);
532
                return;
533
        }
534

    
535
        if(recvdatabuf[recv_id]->status == INACTIVE) {
536
                // Monitoring layer hook
537
                if(get_Recv_data_inf_cb != NULL) {
538
                        mon_data_inf recv_data_inf;
539

    
540
                        recv_data_inf.remote_socketID =
541
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
542
                        recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
543
                        recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
544
                        recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
545
                        recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
546
                        recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
547
                                recvdatabuf[recv_id]->recvbuf : NULL;
548
                        gettimeofday(&recv_data_inf.arrival_time, NULL);
549
                        recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
550
                        recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
551
                        recv_data_inf.priority = false;
552
                        recv_data_inf.padding = false;
553
                        recv_data_inf.confirmation = false;
554
                        recv_data_inf.reliable = false;
555

    
556
                        // send data recv callback to monitoring module
557

    
558
                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
559
                }
560

    
561
                // Get the right callback
562
                receive_data_cb receive_data_callback = recvcbbuf[recvdatabuf[recv_id]->msgtype];
563

    
564
                recv_params rParams;
565

    
566
                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
567
                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
568
                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
569
                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
570
                rParams.remote_socketID =
571
                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
572
                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
573

    
574
                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
575
                        recvdatabuf[recv_id]->msgtype, &rParams);
576

    
577
                //clean up
578
                free(recvdatabuf[recv_id]->recvbuf);
579
                free(recvdatabuf[recv_id]);
580
                recvdatabuf[recv_id] = NULL;
581
        }
582
}
583

    
584
// process a single recv data message
585
void recv_data_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
586
{
587
        debug("ML: received data message called\n");
588

    
589
        int recv_id, free_recv_id = -1;
590

    
591
        if(connectbuf[msg_h->remote_con_id] == NULL) {
592
                debug("ML: Received a message not related to any opened connection!\n");
593
                return;
594
        }
595

    
596
        // check if a recv_data exist and enter data
597
        for (recv_id = 0; recv_id < RECVDATABUFSIZE; recv_id++)
598
                if (recvdatabuf[recv_id] != NULL) {
599
                        if (msg_h->remote_con_id == recvdatabuf[recv_id]->connectionID &&
600
                                        msg_h->msg_seq_num == recvdatabuf[recv_id]->seqnr)
601
                                                break;
602
                } else
603
                        if(free_recv_id == -1)
604
                                free_recv_id = recv_id;
605

    
606

    
607
        if(recv_id == RECVDATABUFSIZE) {
608
                //no recv_data found: create one
609
                recv_id = free_recv_id;
610
                recvdatabuf[recv_id] = (recvdata *) malloc(sizeof(recvdata));
611
                memset(recvdatabuf[recv_id], 0, sizeof(recvdata));
612
                recvdatabuf[recv_id]->connectionID = msg_h->remote_con_id;
613
                recvdatabuf[recv_id]->seqnr = msg_h->msg_seq_num;
614
                recvdatabuf[recv_id]->monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
615
                recvdatabuf[recv_id]->bufsize = msg_h->msg_length + msg_h->len_mon_data_hdr;
616
                recvdatabuf[recv_id]->recvbuf = (char *) malloc(recvdatabuf[recv_id]->bufsize);
617
                /*
618
                * read the timeout data and set it
619
                */
620
                recvdatabuf[recv_id]->timeout_value.tv_sec = recv_timeout.tv_sec;
621
                recvdatabuf[recv_id]->timeout_value.tv_usec = recv_timeout.tv_usec;
622
                recvdatabuf[recv_id]->recvID = recv_id;
623
                recvdatabuf[recv_id]->starttime = time(NULL);
624
                recvdatabuf[recv_id]->msgtype = msg_h->msg_type;
625

    
626
                // fill the buffer with zeros
627
                memset(recvdatabuf[recv_id]->recvbuf, 0, msg_h->msg_length);
628
        }
629

    
630
        if (msg_h->offset == 0)
631
                recvdatabuf[recv_id]->firstPacketArrived = 1;
632

    
633

    
634
        // increment fragmentnr
635
        recvdatabuf[recv_id]->recvFragments++;
636
        // increment the arrivedBytes
637
        recvdatabuf[recv_id]->arrivedBytes += bufsize;
638

    
639
        // enter the data into the buffer
640
        memcpy(recvdatabuf[recv_id]->recvbuf + msg_h->offset, msgbuf, bufsize);
641

    
642
        //TODO very basic checkif all fragments arrived: has to be reviewed
643
        if(recvdatabuf[recv_id]->arrivedBytes == recvdatabuf[recv_id]->bufsize)
644
                recvdatabuf[recv_id]->status = COMPLETE; //buffer full -> msg completly arrived
645
        else
646
                recvdatabuf[recv_id]->status = ACTIVE;
647

    
648
        if (recv_data_callback) {
649
                if(recvdatabuf[recv_id]->status == COMPLETE) {
650
                        // Monitoring layer hook
651
                        if(get_Recv_data_inf_cb != NULL) {
652
                                mon_data_inf recv_data_inf;
653

    
654
                                recv_data_inf.remote_socketID =
655
                                         &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
656
                                recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
657
                                recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
658
                                recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
659
                                recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
660
                                recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
661
                                        recvdatabuf[recv_id]->recvbuf : NULL;
662
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
663
                                recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
664
                                recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
665
                                recv_data_inf.priority = false;
666
                                recv_data_inf.padding = false;
667
                                recv_data_inf.confirmation = false;
668
                                recv_data_inf.reliable = false;
669

    
670
                                // send data recv callback to monitoring module
671

    
672
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
673
                        }
674

    
675
                        // Get the right callback
676
                        receive_data_cb receive_data_callback = recvcbbuf[msg_h->msg_type];
677
                        if (receive_data_callback) {
678

    
679
                                recv_params rParams;
680

    
681
                                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
682
                                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
683
                                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
684
                                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
685
                                rParams.remote_socketID =
686
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
687
                                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
688

    
689
                                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
690
                                        recvdatabuf[recv_id]->msgtype, (void *) &rParams);
691
                        } else {
692
                            fprintf(stderr,"ML: Warning: callback not initialized for this message type: %d!\n",msg_h->msg_type);
693
                        }
694

    
695
                        //clean up
696
                        free(recvdatabuf[recv_id]->recvbuf);
697
                        free(recvdatabuf[recv_id]);
698
                        recvdatabuf[recv_id] = NULL;
699
                } else { // not COMPLETE
700
                        //start time out
701
                        //TODO make timeout at least a DEFINE
702
                        struct timeval timeout = { 4, 0 };
703
                        event_base_once(base, -1, EV_TIMEOUT, &recv_timeout_cb, (void *) (long)recv_id, &timeout);
704
                }
705
        }
706
}
707

    
708
//done
709
void pmtu_timeout_cb(int fd, short event, void *arg)
710
{
711
        debug("ML: pmtu timeout called\n");
712

    
713
        int con_id = (long) arg;
714
        pmtu new_pmtusize;
715
        struct timeval timeout;
716

    
717
        if(connectbuf[con_id] == NULL) {
718
                error("ML: pmtu timeout called on non existing con_id\n");
719
                return;
720
        }
721

    
722
        if(connectbuf[con_id]->status == READY) {
723
                // nothing to do anymore
724
                return;
725
        }
726

    
727
        timeout = connectbuf[con_id]->timeout_value;
728

    
729
        if(connectbuf[con_id]->delay || connectbuf[con_id]->trials == MAX_TRIALS - 1) {
730
                double delay = timeout.tv_sec + timeout.tv_usec / 1000000.0;
731
                delay = delay * 5;
732
                timeout.tv_sec = floor(delay);
733
                timeout.tv_usec = fmod(delay, 1.0) * 1000000.0;
734
                if(connectbuf[con_id]->delay) {
735
                        connectbuf[con_id]->delay = false;
736
                        goto reschedule;
737
                }
738
        }
739

    
740
        if(connectbuf[con_id]->trials == MAX_TRIALS) {
741
                // decrement the pmtu size
742
                connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
743
                connectbuf[con_id]->trials = 0;
744
        }
745

    
746
        //error in PMTU discovery?
747
        if (connectbuf[con_id]->pmtusize == ERROR) {
748
                if (connectbuf[con_id]->internal_connect == true) {
749
                        //as of now we tried directly connecting, now let's try trough the NAT
750
                        connectbuf[con_id]->internal_connect = false;
751
                        connectbuf[con_id]->pmtusize = MAX;
752
                } else {
753
                        //nothing to do we have to give up
754
                        error("ML: Could not create connection with connectionID %i!\n",con_id);
755
                        // envoke the callback for failed connection establishment
756
                        if(failed_Connection_cb != NULL)
757
                                (failed_Connection_cb) (con_id, NULL);
758
                        // delete the connection entry
759
                        mlCloseConnection(con_id);
760
                        return;
761
                }
762
        }
763

    
764
        //retry with new pmtu size
765
        connectbuf[con_id]->trials++;
766
        send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
767

    
768
reschedule:
769
        /* reschedule */
770
        event_base_once(base, -1, EV_TIMEOUT, pmtu_timeout_cb, (void *) (long)con_id, &timeout);
771
}
772

    
773
/*
774
 * decrements the mtu size
775
 */
776
pmtu pmtu_decrement(pmtu pmtusize)
777
{
778
        pmtu pmtu_return_size;
779
        switch(pmtusize) {
780
        case MAX:
781
                return DSL;
782
        case DSL:
783
                return DSLMEDIUM;
784
        case DSLMEDIUM:
785
                return DSLSLIM;
786
        case DSLSLIM:
787
                return BELOWDSL;
788
        case BELOWDSL:
789
                return MIN;
790
        default:
791
                return ERROR;
792
        }
793
}
794

    
795
void pmtu_error_cb_th(char *msg, int msglen)
796
{
797
        debug("ML: pmtu_error callback called msg_size: %d\n",msglen);
798
        //TODO debug
799
        return;
800

    
801
    char *msgbufptr = NULL;
802
    int msgtype;
803
    int connectionID;
804
    pmtu pmtusize;
805
    pmtu new_pmtusize;
806
    int dead = 0;
807

    
808
    // check the packettype
809
    msgbufptr = &msg[0];
810

    
811
    // check the msgtype
812
    msgbufptr = &msg[1];
813
    memcpy(&msgtype, msgbufptr, 4);
814

    
815
    if (msgtype == 0) {
816

    
817
        // get the connectionID
818
        msgbufptr = &msg[5];
819
        memcpy(&connectionID, msgbufptr, 4);
820

    
821
        int msgtype_c = connectbuf[connectionID]->status;
822
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
823

    
824
        if (msgtype_c != msgtype) {
825
            dead = 1;
826
        }
827

    
828

    
829
    } else if (msgtype == 1) {
830

    
831
        // read the connectionID
832
        msgbufptr = &msg[9];
833
        memcpy(&connectionID, msgbufptr, 4);
834

    
835
        int msgtype_c = connectbuf[connectionID]->status;
836
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
837

    
838
        if (msgtype_c != msgtype) {
839
            dead = 1;
840
        }
841

    
842
    }
843
    // decrement the pmtu size
844
    new_pmtusize = pmtu_decrement(pmtusize);
845

    
846
//    connectbuf[connectionID]->pmtutrysize = new_pmtusize;
847

    
848
    if (new_pmtusize == ERROR) {
849
                error("ML:  Could not create connection with connectionID %i !\n",
850
                        connectionID);
851

    
852
                if(failed_Connection_cb != NULL)
853
                        (failed_Connection_cb) (connectionID, NULL);
854
                // set the message type to a non existent message
855
                msgtype = 2;
856
                // delete the connection entry
857
                 mlCloseConnection(connectionID);
858
        }
859

    
860
    if (msgtype == 0 && dead != 1) {
861

    
862
        // stop the timeout event
863
        // timeout_del(connectbuf[connectionID]->timeout);
864
        /*
865
         * libevent2
866
         */
867

    
868
        // event_del(connectbuf[connectionID]->timeout);
869

    
870

    
871
        // create and send a connection message
872
//         create_conn_msg(new_pmtusize, connectionID,
873
//                         &local_socketID, INVITE);
874

    
875
//        send_conn_msg(connectionID, new_pmtusize);
876

    
877
        // set a timeout event for the pmtu discovery
878
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
879
        // *)&connectionID);
880

    
881
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
882

    
883
        /*
884
         * libevent2
885
         */
886

    
887
        struct event *ev;
888
        ev = evtimer_new(base, pmtu_timeout_cb,
889
                         (void *) connectbuf[connectionID]);
890

    
891
        // connectbuf[connectionID]->timeout = ev;
892

    
893
        event_add(ev, &connectbuf[connectionID]->timeout_value);
894

    
895
    } else if (msgtype == 1 && dead != 1) {
896

    
897
        // stop the timeout event
898
        // timeout_del(connectbuf[connectionID]->timeout);
899

    
900
        /*
901
         * libevent2
902
         */
903
        // printf("still here 11 \n");
904
        // printf("ev %d \n",connectbuf[connectionID]->timeout);
905
        // event_del(connectbuf[connectionID]->timeout );
906
        // evtimer_del(connectbuf[connectionID]->timeout );
907

    
908

    
909
//         // create and send a connection message
910
//         create_conn_msg(new_pmtusize,
911
//                         connectbuf[connectionID]->connectionID,
912
//                         NULL, CONNECT);
913

    
914
        //send_conn_msg(connectionID, new_pmtusize);
915

    
916
        // set a timeout event for the pmtu discovery
917
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
918
        // *)&connectionID);
919
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
920

    
921
        /*
922
         * libevent2
923
         */
924
        // struct event *ev;
925
        // ev = evtimer_new(base,pmtu_timeout_cb, (void
926
        // *)connectbuf[connectionID]);
927
        // connectbuf[connectionID]->timeout = ev;
928
        // event_add(ev,&connectbuf[connectionID]->timeout_value);
929

    
930
    }
931
}
932

    
933
/*
934
 * what to do once a packet arrived if it is a conn packet send it to
935
 * recv_conn handler if it is a data packet send it to the recv_data
936
 * handler
937
 */
938

    
939
//done --
940
void recv_pkg(int fd, short event, void *arg)
941
{
942
        debug("ML: recv_pkg called\n");
943

    
944
        struct msg_header *msg_h;
945
        char msgbuf[MAX];
946
        char *bufptr = msgbuf;
947
        int ttl;
948
        struct sockaddr_in recv_addr;
949
        pmtu recvSize = MAX;
950
        int msg_size;
951

    
952
        recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
953

    
954

    
955
        // check if it is not just an ERROR message
956
        if(recvSize < 0)
957
                return;
958

    
959
        // @TODO check if this simplistic STUN message recognition really always works, probably not
960
        unsigned short stun_bind_response = 0x0101;
961
        unsigned short * msgspot = (unsigned short *) msgbuf;
962
        if (*msgspot == stun_bind_response) {
963
                debug("ML: recv_pkg: parse stun message called\n");
964
                recv_stun_msg(msgbuf, recvSize);
965
                return;
966
        }
967

    
968
        msg_h = (struct msg_header *) msgbuf;
969
        bufptr += MSG_HEADER_SIZE + msg_h->len_mon_packet_hdr;
970
        msg_size = recvSize - MSG_HEADER_SIZE - msg_h->len_mon_packet_hdr;
971

    
972

    
973
        if(get_Recv_pkt_inf_cb != NULL && msg_h->len_mon_packet_hdr != 0) {
974
                mon_pkt_inf msginfNow;
975
                msginfNow.monitoringHeaderLen = msg_h->len_mon_packet_hdr;
976
                msginfNow.monitoringHeader = msg_h->len_mon_packet_hdr ? &msgbuf[0] + MSG_HEADER_SIZE : NULL;
977
                //TODO rethink this ...
978
                if(msg_h->msg_type == ML_CON_MSG) {
979
                        struct conn_msg *c_msg = (struct conn_msg *) bufptr;
980
                        msginfNow.remote_socketID = &(c_msg->sock_id);
981
                }
982
                else if(connectbuf[msg_h->remote_con_id] == NULL) {
983
                        error("ML: received pkg called with non existent connection\n");
984
                        return;
985
                } else
986
                        msginfNow.remote_socketID = &(connectbuf[msg_h->remote_con_id]->external_socketID);
987
                msginfNow.buffer = bufptr;
988
                msginfNow.bufSize = recvSize;
989
                msginfNow.msgtype = msg_h->msg_type;
990
                msginfNow.ttl = ttl;
991
                msginfNow.dataID = msg_h->msg_seq_num;
992
                msginfNow.offset = msg_h->offset;
993
                msginfNow.datasize = msg_h->msg_length;
994
                gettimeofday(&msginfNow.arrival_time, NULL);
995
                (get_Recv_pkt_inf_cb) ((void *) &msginfNow);
996
        }
997

    
998

    
999
        switch(msg_h->msg_type) {
1000
                case ML_CON_MSG:
1001
                        debug("ML: received conn pkg\n");
1002
                        recv_conn_msg(msg_h, bufptr, msg_size);
1003
                        break;
1004
                default:
1005
                        if(msg_h->msg_type < 127) {
1006
                                debug("ML: received data pkg\n");
1007
                                recv_data_msg(msg_h, bufptr, msg_size);
1008
                                break;
1009
                        }
1010
                        debug("ML: unrecognised msg_type\n");
1011
                        break;
1012
        }
1013
}
1014

    
1015
/*
1016
 * compare the external IP address of two socketIDs
1017
 */
1018
int
1019
compare_external_address_socketIDs(socketID_handle sock1, socketID_handle sock2)
1020
{
1021
        if( sock1->external_addr.udpaddr.sin_addr.s_addr == sock2->external_addr.udpaddr.sin_addr.s_addr)
1022
                return 0;
1023
        return 1;
1024
}
1025

    
1026
/*
1027
 * the timeout of the NAT traversal
1028
 */
1029
void nat_traversal_timeout(int fd, short event, void *arg)
1030
{
1031
        if (NAT_traversal == false) {
1032
                debug("ML: NAT traversal request re-send\n");
1033
                send_stun_request(socketfd, &stun_server);
1034

    
1035
                /*
1036
                * enter a NAT traversal timeout that takes care of retransmission
1037
                */
1038
                struct event *ev1;
1039
                struct timeval timeout_value_NAT_traversal = { 1, 0 };
1040
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1041
                event_add(ev1, &timeout_value_NAT_traversal);
1042
                if(receive_SocketID_cb)
1043
                        (receive_SocketID_cb) (&local_socketID, 2);
1044
        }
1045
}
1046

    
1047
unsigned long resolve(const char *ipaddr)
1048
{
1049
        struct hostent *h = gethostbyname(ipaddr);
1050
        if (!h) {
1051
                error("Unable to resolve host name %s\n", ipaddr);
1052
        exit(-1);
1053
    }
1054
    unsigned long *addr = (unsigned long *) (h->h_addr);
1055
    return *addr;
1056
}
1057

    
1058

    
1059
/*
1060
 * returns a handle to the socketID struct the ipaddr can be a null
1061
 * pointer. Then all available ipaddr on the machine are choosen.
1062
 */
1063
void create_socket(const int port, const char *ipaddr)
1064
{
1065
        struct sockaddr_in udpaddr;
1066
        udpaddr.sin_family = AF_INET;
1067
        if (ipaddr == NULL) {
1068
                /*
1069
                * try to guess the local IP address
1070
                */
1071
                const char *ipaddr_iface = mlAutodetectIPAddress();
1072
                if (ipaddr_iface) {
1073
                        udpaddr.sin_addr.s_addr = inet_addr(ipaddr_iface);
1074
                } else {
1075
                        udpaddr.sin_addr.s_addr = INADDR_ANY;
1076
                }
1077
        } else {
1078
                udpaddr.sin_addr.s_addr = inet_addr(ipaddr);
1079
        }
1080
        udpaddr.sin_port = htons(port);
1081

    
1082
        socketaddrgen udpgen;
1083
        udpgen.udpaddr = udpaddr;
1084
        local_socketID.internal_addr = udpgen;
1085

    
1086
        socketfd = createSocket(port, ipaddr);
1087

    
1088
        struct event *ev;
1089
        ev = event_new(base, socketfd, EV_READ | EV_PERSIST, recv_pkg, NULL);
1090

    
1091
        event_add(ev, NULL);
1092

    
1093
        if (isStunDefined()) {
1094
                /*
1095
                * send the NAT traversal STUN request
1096
                */
1097
                 send_stun_request(socketfd, &stun_server);
1098

    
1099
                /*
1100
                * enter a NAT traversal timeout that takes care of retransmission
1101
                */
1102
                struct event *ev1;
1103
                struct timeval timeout_value_NAT_traversal = { 2, 0 };
1104
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1105
                event_add(ev1, &timeout_value_NAT_traversal);
1106

    
1107
                NAT_traversal = false;
1108
        } else {
1109
                /*
1110
                * Assume we have accessibility and copy internal address to external one
1111
                */
1112
                local_socketID.external_addr = local_socketID.internal_addr;
1113
                NAT_traversal = true; // @TODO: this is not really NAT traversal, but a flag that init is over
1114
                // callback to the upper layer indicating that the socketID is now
1115
                // ready to use
1116
                (receive_SocketID_cb) (&local_socketID, 0);
1117
        }
1118
}
1119

    
1120
/**************************** END OF INTERNALS ***********************/
1121

    
1122
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){
1123

    
1124
        base = (struct event_base *) arg;
1125
        recv_data_callback = recv_data_cb;
1126
        mlSetRecvTimeout(timeout_value);
1127
        if (stun_ipaddr) {
1128
                 mlSetStunServer(stun_port, stun_ipaddr);
1129
        } else {
1130

    
1131
        }
1132
        register_recv_localsocketID_cb(local_socketID_cb);
1133
        create_socket(port, ipaddr);
1134

    
1135
}
1136

    
1137
/* register callbacks  */
1138
void mlRegisterGetRecvPktInf(get_recv_pkt_inf_cb recv_pkt_inf_cb){
1139

    
1140
        if (recv_pkt_inf_cb == NULL)
1141
                error("Register get_recv_pkt_inf_cb failed: NULL ptr  \n");
1142
        else
1143
                get_Recv_pkt_inf_cb = recv_pkt_inf_cb;
1144

    
1145
}
1146

    
1147
void mlRegisterGetSendPktInf(get_send_pkt_inf_cb  send_pkt_inf_cb){
1148

    
1149
        if (send_pkt_inf_cb == NULL)
1150
                error("Register get_send_pkt_inf_cb: NULL ptr  \n");
1151
        else
1152
                get_Send_pkt_inf_cb = send_pkt_inf_cb;
1153

    
1154
}
1155

    
1156

    
1157
void mlRegisterSetMonitoringHeaderPktCb(set_monitoring_header_pkt_cb monitoring_header_pkt_cb ){
1158

    
1159
        if (monitoring_header_pkt_cb == NULL)
1160
                error("Register set_monitoring_header_pkt_cb: NULL ptr  \n");
1161
        else
1162
                set_Monitoring_header_pkt_cb = monitoring_header_pkt_cb;
1163

    
1164
}
1165

    
1166
void mlRegisterGetRecvDataInf(get_recv_data_inf_cb recv_data_inf_cb){
1167

    
1168
        if (recv_data_inf_cb == NULL)
1169
                error("Register get_recv_data_inf_cb: NULL ptr  \n");
1170
        else
1171
                get_Recv_data_inf_cb = recv_data_inf_cb;
1172

    
1173
}
1174

    
1175
void mlRegisterGetSendDataInf(get_send_data_inf_cb  send_data_inf_cb){
1176

    
1177
        if (send_data_inf_cb == NULL)
1178
                error("Register get_send_data_inf_cb: NULL ptr  \n");
1179
        else
1180
                get_Send_data_inf_cb = send_data_inf_cb;
1181

    
1182
}
1183

    
1184
void mlRegisterSetMonitoringHeaderDataCb(set_monitoring_header_data_cb monitoring_header_data_cb){
1185

    
1186
        if (monitoring_header_data_cb == NULL)
1187
                error("Register set_monitoring_header_data_cb : NULL ptr  \n");
1188
        else
1189
        set_Monitoring_header_data_cb = monitoring_header_data_cb;
1190

    
1191
}
1192

    
1193
void mlRegisterRecvConnectionCb(receive_connection_cb recv_conn_cb){
1194

    
1195
        if (recv_conn_cb == NULL)
1196
                error("Register receive_connection_cb: NULL ptr  \n");
1197
        else
1198
                receive_Connection_cb = recv_conn_cb;
1199

    
1200
}
1201

    
1202
void mlRegisterErrorConnectionCb(connection_failed_cb conn_failed){
1203

    
1204
        if (conn_failed == NULL)
1205
                error("Register connection_failed_cb: NULL ptr  \n");
1206
        else
1207
        failed_Connection_cb = conn_failed;
1208

    
1209
}
1210

    
1211
void mlRegisterRecvDataCb(receive_data_cb data_cb,unsigned char msgtype){
1212

    
1213
    if (msgtype > 126) {
1214

    
1215
            error
1216
            ("ML: Could not register recv_data callback. Msgtype is greater then 126 \n");
1217

    
1218
    }
1219

    
1220
    if (data_cb == NULL) {
1221

    
1222
            error("ML: Register receive data callback: NUll ptr \n ");
1223

    
1224
    } else {
1225

    
1226
        recvcbbuf[msgtype] = data_cb;
1227

    
1228
    }
1229

    
1230
}
1231

    
1232
void mlCloseSocket(socketID_handle socketID){
1233

    
1234
        free(socketID);
1235

    
1236
}
1237

    
1238
void keepalive_fn(evutil_socket_t fd, short what, void *arg) {
1239
        socketID_handle peer = arg;
1240

    
1241
        int con_id = mlConnectionExist(peer, false);
1242
        if (con_id < 0 || connectbuf[con_id]->defaultSendParams.keepalive <= 0) {
1243
                /* Connection fell from under us or keepalive was disabled */
1244
                free(arg);
1245
                return;
1246
        }
1247

    
1248
        /* do what we gotta do */
1249
        if ( connectbuf[con_id]->status == READY) {
1250
                char keepaliveMsg[32] = "";
1251
                sprintf(keepaliveMsg, "KEEPALIVE %d", connectbuf[con_id]->keepalive_seq++);
1252
                send_msg(con_id, MSG_TYPE_ML_KEEPALIVE, keepaliveMsg, 1 + strlen(keepaliveMsg), false, 
1253
                        &(connectbuf[con_id]->defaultSendParams));
1254
        }
1255

    
1256
        /* re-schedule */
1257
        struct timeval t = { 0,0 };
1258
        t.tv_sec = time(NULL) + connectbuf[con_id]->defaultSendParams.keepalive;
1259

    
1260
        event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1261
}
1262

    
1263
void setupKeepalive(int conn_id) {
1264
        /* Save the peer's address for us */
1265
        socketID_handle peer = malloc(sizeof(socket_ID));
1266
        memcpy(peer, &connectbuf[conn_id]->external_socketID, sizeof(socket_ID));
1267

    
1268
        struct timeval t = { 0,0 };
1269
        t.tv_sec = time(NULL) + connectbuf[conn_id]->defaultSendParams.keepalive;
1270

    
1271
        event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1272
}
1273

    
1274
/* connection functions */
1275
int mlOpenConnection(socketID_handle external_socketID,receive_connection_cb connection_cb,void *arg, const send_params defaultSendParams){
1276

    
1277
        int con_id;
1278
        if (external_socketID == NULL) {
1279
                error("ML: cannot open connection: one of the socketIDs is NULL\n");
1280
                return -1;
1281
        }
1282
        if (NAT_traversal == false) {
1283
                error("ML: cannot open connection: NAT traversal for socketID still in progress\n");
1284
                return -1;
1285
        }
1286
        if (connection_cb == NULL) {
1287
                error("ML: cannot open connection: connection_cb is NULL\n");
1288
                return -1;
1289
        }
1290

    
1291
        // check if that connection already exist
1292

    
1293
        con_id = mlConnectionExist(external_socketID, false);
1294
        if (con_id >= 0) {
1295
                // overwrite defaultSendParams
1296
                bool newKeepalive = 
1297
                        connectbuf[con_id]->defaultSendParams.keepalive == 0 && defaultSendParams.keepalive != 0;
1298
                connectbuf[con_id]->defaultSendParams = defaultSendParams;
1299
                if (newKeepalive) setupKeepalive(con_id);
1300
                // if so check if it is ready to use
1301
                if (connectbuf[con_id]->status == READY) {
1302
                                // if so use the callback immidiatley
1303
                                (connection_cb) (con_id, arg);
1304

    
1305
                // otherwise just write the connection cb and the arg pointer
1306
                // into the connection struct
1307
                } else {
1308
                        struct receive_connection_cb_list *temp;
1309
                        temp = malloc(sizeof(struct receive_connection_cb_list));
1310
                        temp->next = NULL;
1311
                        temp->connection_cb = connection_cb;
1312
                        temp->arg = arg;
1313
                        if(connectbuf[con_id]->connection_last != NULL) {
1314
                                connectbuf[con_id]->connection_last->next = temp;
1315
                                connectbuf[con_id]->connection_last = temp;
1316
                        } else
1317
                                connectbuf[con_id]->connection_last = connectbuf[con_id]->connection_head = temp;
1318
                }
1319
                return con_id;
1320
        }
1321
        // make entry in connection_establishment array
1322
        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
1323
                if (connectbuf[con_id] == NULL) {
1324
                        connectbuf[con_id] = (connect_data *) malloc(sizeof(connect_data));
1325
                        memset(connectbuf[con_id],0,sizeof(connect_data));
1326
                        connectbuf[con_id]->starttime = time(NULL);
1327
                        memcpy(&connectbuf[con_id]->external_socketID, external_socketID, sizeof(socket_ID));
1328
                        connectbuf[con_id]->pmtusize = MAX;
1329
                        connectbuf[con_id]->status = INVITE;
1330
                        connectbuf[con_id]->seqnr = 0;
1331
                        connectbuf[con_id]->internal_connect = !compare_external_address_socketIDs(external_socketID, &local_socketID);
1332
                        /*
1333
                        * timeout values for the pmtu discovery
1334
                        */
1335
                        connectbuf[con_id]->timeout_value.tv_sec = 15;
1336
                        connectbuf[con_id]->timeout_value.tv_usec = 0;
1337
                        connectbuf[con_id]->connectionID = con_id;
1338

    
1339
                        connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
1340
                        connectbuf[con_id]->connection_last->next = NULL;
1341
                        connectbuf[con_id]->connection_last->connection_cb = connection_cb;
1342
                        connectbuf[con_id]->connection_last->arg = arg;
1343
                        connectbuf[con_id]->external_connectionID = -1;
1344

    
1345
                        connectbuf[con_id]->defaultSendParams = defaultSendParams;
1346
                        if (defaultSendParams.keepalive) setupKeepalive(con_id);
1347
                        break;
1348
                }
1349
        } //end of for
1350

    
1351
        if (con_id == CONNECTBUFSIZE) {
1352
                error("ML: Could not open connection: connection buffer full\n");
1353
                return -1;
1354
        }
1355

    
1356
        // create and send a connection message
1357
        send_conn_msg(con_id, MAX, INVITE);
1358

    
1359
        struct event *ev;
1360
        ev = evtimer_new(base, pmtu_timeout_cb, (void *) (long)con_id);
1361
        event_add(ev, &connectbuf[con_id]->timeout_value);
1362

    
1363
        return con_id;
1364

    
1365
}
1366

    
1367
void mlCloseConnection(const int connectionID){
1368

    
1369
        // remove it from the connection array
1370
        if(connectbuf[connectionID]) {
1371
                if(connectbuf[connectionID]->ctrl_msg_buf)
1372
                        free(connectbuf[connectionID]->ctrl_msg_buf);
1373
                free(connectbuf[connectionID]);
1374
                connectbuf[connectionID] = NULL;
1375
        }
1376

    
1377
}
1378

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

    
1381
        if (connectionID < 0) {
1382
                error("ML: send data failed: connectionID does not exist\n");
1383
                return;
1384
        }
1385

    
1386
        if (connectbuf[connectionID] == NULL) {
1387
                error("ML: send data failed: connectionID does not exist\n");
1388
                return;
1389
        }
1390
        if (connectbuf[connectionID]->status != READY) {
1391
            error("ML: send data failed: connection is not active\n");
1392
            return;
1393
        }
1394

    
1395
        if (sParams == NULL) {
1396
                sParams = &(connectbuf[connectionID]->defaultSendParams);
1397
        }
1398

    
1399
        send_msg(connectionID, msgtype, sendbuf, bufsize, false, sParams);
1400

    
1401
}
1402

    
1403
/* transmit data functions  */
1404
int mlSendAllData(const int connectionID,send_all_data_container *container,int nr_entries,unsigned char msgtype,send_params *sParams){
1405

    
1406
    if (nr_entries < 1 || nr_entries > 5) {
1407

    
1408
        error
1409
            ("ML : sendALlData : nr_enties is not between 1 and 5 \n ");
1410
        return 0;
1411

    
1412
    } else {
1413

    
1414
        if (nr_entries == 1) {
1415

    
1416
                mlSendData(connectionID, container->buffer_1,
1417
                      container->length_1, msgtype, sParams);
1418

    
1419
            return 1;
1420

    
1421
        } else if (nr_entries == 2) {
1422

    
1423
            int buflen = container->length_1 + container->length_2;
1424
            char buf[buflen];
1425
            memcpy(buf, container->buffer_1, container->length_1);
1426
            memcpy(&buf[container->length_1], container->buffer_2,
1427
                   container->length_2);
1428
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1429

    
1430
            return 1;
1431

    
1432
        } else if (nr_entries == 3) {
1433

    
1434
            int buflen =
1435
                container->length_1 + container->length_2 +
1436
                container->length_3;
1437
            char buf[buflen];
1438
            memcpy(buf, container->buffer_1, container->length_1);
1439
            memcpy(&buf[container->length_1], container->buffer_2,
1440
                   container->length_2);
1441
            memcpy(&buf[container->length_2], container->buffer_3,
1442
                   container->length_3);
1443
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1444

    
1445

    
1446
            return 1;
1447

    
1448
        } else if (nr_entries == 4) {
1449

    
1450
            int buflen =
1451
                container->length_1 + container->length_2 +
1452
                container->length_3 + container->length_4;
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
            memcpy(&buf[container->length_2], container->buffer_3,
1458
                   container->length_3);
1459
            memcpy(&buf[container->length_3], container->buffer_4,
1460
                   container->length_4);
1461
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1462

    
1463
            return 1;
1464

    
1465
        } else {
1466

    
1467
            int buflen =
1468
                container->length_1 + container->length_2 +
1469
                container->length_3 + container->length_4 +
1470
                container->length_5;
1471
            char buf[buflen];
1472
            memcpy(buf, container->buffer_1, container->length_1);
1473
            memcpy(&buf[container->length_1], container->buffer_2,
1474
                   container->length_2);
1475
            memcpy(&buf[container->length_2], container->buffer_3,
1476
                   container->length_3);
1477
            memcpy(&buf[container->length_3], container->buffer_4,
1478
                   container->length_4);
1479
            memcpy(&buf[container->length_4], container->buffer_5,
1480
                   container->length_5);
1481
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1482

    
1483
            return 1;
1484
        }
1485

    
1486
    }
1487

    
1488
}
1489

    
1490
int mlRecvData(const int connectionID,char *recvbuf,int *bufsize,recv_params *rParams){
1491

    
1492
        //TODO yet to be converted
1493
        return 0;
1494
#if 0
1495
        if (rParams == NULL) {
1496
                error("ML: recv_data failed: recv_params is a NULL ptr\n");
1497
                return 0;
1498
    } else {
1499

1500
        info("ML: recv data called \n");
1501

1502
        int i = 0;
1503
        int returnValue = 0;
1504
        double timeout = (double) recv_timeout.tv_sec;
1505
        time_t endtime = time(NULL);
1506

1507
        for (i = 0; i < RECVDATABUFSIZE; i++) {
1508

1509
            if (recvdatabuf[i] != NULL) {
1510

1511
                if (recvdatabuf[i]->connectionID == connectionID) {
1512

1513
                    info("ML: recv data has entry  \n");
1514

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

1517
                    // check if the specified connection has data and it
1518
                    // is complete
1519
                    // check the data seqnr
1520
                    // if(connectionID == recvdatabuf[i]->connectionID &&
1521
                    // 1 == recvdatabuf[i]->status){
1522

1523
                    if (1 == recvdatabuf[i]->status) {
1524

1525
                        // printf("transmissionHandler: recv_data set is
1526
                        // complete \n" );
1527

1528
                        // printf("debud \n");
1529

1530
                        // exchange the pointers
1531
                        int buffersize = 0;
1532
                        buffersize = recvdatabuf[i]->bufsize;
1533
                        *bufsize = buffersize;
1534
                        // recvbuf = recvdatabuf[i]->recvbuf;
1535

1536
                        // printf("buffersize %d \n",buffersize);
1537
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1538
                               buffersize);
1539
                        // printf(" recvbuf %s \n",recvbuf );
1540

1541
//                         double nrMissFrags =
1542
//                             (double) recvdatabuf[i]->nrFragments /
1543
//                             (double) recvdatabuf[i]->recvFragments;
1544
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
1545

1546
//                        rParams->nrMissingFragments = nrMissingFragments;
1547
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
1548
                        rParams->msgtype = recvdatabuf[i]->msgtype;
1549
                        rParams->connectionID =
1550
                            recvdatabuf[i]->connectionID;
1551

1552
                        // break from the loop
1553
                        // printf(" recvbuf %s \n ",recvbuf);
1554

1555
                        // double nrMissFrags =
1556
                        // (double)recvdatabuf[i]->nrFragments /
1557
                        // (double)recvdatabuf[i]->recvFragments;
1558
                        // int nrMissingFragments =
1559
                        // (int)ceil(nrMissFrags);
1560

1561
                        if(get_Recv_data_inf_cb != NULL) {
1562
                                mon_data_inf recv_data_inf;
1563

1564
                                recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1565
                                recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1566
                                recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1567
                                recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1568
//                                 recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1569
//                                 recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1570
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
1571
                                recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1572
                                recv_data_inf.nrMissingFragments = nrMissingFragments;
1573
                                recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1574
                                recv_data_inf.priority = false;
1575
                                recv_data_inf.padding = false;
1576
                                recv_data_inf.confirmation = false;
1577
                                recv_data_inf.reliable = false;
1578

1579
                                // send data recv callback to monitoring module
1580

1581
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1582
                        }
1583

1584

1585
                        // free the allocated memory
1586
                        free(recvdatabuf[i]);
1587
                        recvdatabuf[i] = NULL;
1588

1589
                        returnValue = 1;
1590
                        break;
1591

1592
                    }
1593

1594
                    if (recvdatabuf[i] != NULL) {
1595

1596
                        if (timepass > timeout) {
1597

1598
                            info("ML: recv_data timeout called  \n");
1599

1600
                            // some data about the missing chunks should
1601
                            // be added here
1602
                            // exchange the pointers
1603
                            int buffersize = 0;
1604
                            buffersize = recvdatabuf[i]->bufsize;
1605
                            *bufsize = buffersize;
1606
                            // recvbuf = recvdatabuf[i]->recvbuf;
1607

1608
                            double nrMissFrags =
1609
                                (double) recvdatabuf[i]->nrFragments /
1610
                                (double) recvdatabuf[i]->recvFragments;
1611
                            int nrMissingFragments =
1612
                                (int) ceil(nrMissFrags);
1613

1614
                            // printf(" recvbuf %s \n",recvbuf );
1615

1616
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1617
                                   buffersize);
1618

1619
                            rParams->nrMissingFragments =
1620
                                nrMissingFragments;
1621
                            rParams->nrFragments =
1622
                                recvdatabuf[i]->nrFragments;
1623
                            rParams->msgtype = recvdatabuf[i]->msgtype;
1624
                            rParams->connectionID =
1625
                                recvdatabuf[i]->connectionID;
1626

1627
                                if(get_Recv_data_inf_cb != NULL) {
1628
                                        mon_data_inf recv_data_inf;
1629

1630
                                        recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1631
                                        recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1632
                                        recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1633
                                        recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1634
                                        recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1635
                                        recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1636
                                        gettimeofday(&recv_data_inf.arrival_time, NULL);
1637
                                        recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1638
                                        recv_data_inf.nrMissingFragments = nrMissingFragments;
1639
                                        recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1640
                                        recv_data_inf.priority = false;
1641
                                        recv_data_inf.padding = false;
1642
                                        recv_data_inf.confirmation = false;
1643
                                        recv_data_inf.reliable = false;
1644

1645
                                        // send data recv callback to monitoring module
1646

1647
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1648
                                }
1649

1650
                            // free the allocated memory
1651
                            free(recvdatabuf[i]);
1652
                            recvdatabuf[i] = NULL;
1653

1654
                            returnValue = 1;
1655
                            break;
1656

1657
                        }
1658
                    }
1659

1660
                }
1661

1662
            }
1663
            // printf("2 recvbuf %s \n ",recvbuf);
1664
        }
1665
        return returnValue;
1666
    }
1667
#endif
1668

    
1669
}
1670

    
1671
/* setter  */
1672
void mlSetStunServer(const int port,const char *ipaddr){
1673

    
1674
        stun_server.sin_family = AF_INET;
1675
        if (ipaddr == NULL)
1676
                stun_server.sin_addr.s_addr = htonl(INADDR_ANY);
1677
        else
1678
                stun_server.sin_addr.s_addr = resolve(ipaddr);
1679
        stun_server.sin_port = htons(port);
1680

    
1681
}
1682

    
1683
void mlSetRecvTimeout(struct timeval timeout_value){
1684

    
1685
        recv_timeout = timeout_value;
1686

    
1687
}
1688

    
1689
int mlGetStandardTTL(socketID_handle socketID,uint8_t *ttl){
1690

    
1691
        return getTTL(socketfd, ttl);
1692

    
1693
}
1694

    
1695
socketID_handle mlGetLocalSocketID(int *errorstatus){
1696

    
1697
        if (NAT_traversal == false) {
1698
                *errorstatus = 2;
1699
                return NULL;
1700
        }
1701

    
1702
        *errorstatus = 0;
1703
        return &local_socketID;
1704

    
1705
}
1706

    
1707
int mlGetExternalIP(char* external_addr){
1708

    
1709
        socketaddrgen udpgen;
1710
        struct sockaddr_in udpaddr;
1711

    
1712
        udpgen = local_socketID.external_addr;
1713
        udpaddr = udpgen.udpaddr;
1714

    
1715
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
1716
                        INET_ADDRSTRLEN);
1717

    
1718
        if (external_addr == NULL) {
1719

    
1720
        return -1;
1721

    
1722
        } else {
1723

    
1724
        return 0;
1725

    
1726
        }
1727

    
1728
}
1729

    
1730
int mlSocketIDToString(socketID_handle socketID,char* socketID_string, size_t len){
1731

    
1732
        char internal_addr[INET_ADDRSTRLEN];
1733
        char external_addr[INET_ADDRSTRLEN];
1734
        inet_ntop(AF_INET, &(socketID->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1735
        inet_ntop(AF_INET, &(socketID->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1736

    
1737
        snprintf(socketID_string,len,"%s:%d-%s:%d", internal_addr, ntohs(socketID->internal_addr.udpaddr.sin_port),
1738
                external_addr,        ntohs(socketID->external_addr.udpaddr.sin_port));
1739
        return 0;
1740

    
1741
}
1742

    
1743
int mlStringToSocketID(const char* socketID_string, socketID_handle socketID){
1744

    
1745
        //@TODO add checks against malformed string
1746
        char external_addr[INET_ADDRSTRLEN];
1747
        int external_port;
1748
        char internal_addr[INET_ADDRSTRLEN];
1749
        int internal_port;
1750

    
1751
        char *pch;
1752
        char *s = strdup(socketID_string);
1753

    
1754
        //replace ':' with a blank
1755
        pch=strchr(s,':');
1756
        while (pch!=NULL){
1757
                                *pch = ' ';
1758
                pch=strchr(pch+1,':');
1759
        }
1760
        pch=strchr(s,'-');
1761
        if(pch) *pch = ' ';
1762

    
1763
        sscanf(s,"%s %d %s %d", internal_addr, &internal_port,
1764
                external_addr, &external_port);
1765

    
1766
        if(inet_pton(AF_INET, internal_addr, &(socketID->internal_addr.udpaddr.sin_addr)) == 0)
1767
                return EINVAL;
1768
        socketID->internal_addr.udpaddr.sin_family = AF_INET;
1769
        socketID->internal_addr.udpaddr.sin_port = htons(internal_port);
1770

    
1771

    
1772
        if(inet_pton(AF_INET, external_addr, &(socketID->external_addr.udpaddr.sin_addr)) ==0)
1773
                return EINVAL;
1774
        socketID->external_addr.udpaddr.sin_family = AF_INET;
1775
        socketID->external_addr.udpaddr.sin_port = htons(external_port);
1776

    
1777
        free(s);
1778
        return 0;
1779

    
1780
}
1781

    
1782
int mlGetConnectionStatus(int connectionID){
1783

    
1784
        if(connectbuf[connectionID])
1785
                return connectbuf[connectionID]->status == READY;
1786
        return -1;
1787
    
1788
}
1789

    
1790

    
1791
int mlConnectionExist(socketID_handle socketID, bool ready){
1792

    
1793
    /*
1794
     * check if another connection for the external connectionID exist
1795
     * that was established \ within the last 2 seconds
1796
     */
1797
        int i;
1798
        for (i = 0; i < CONNECTBUFSIZE; i++)
1799
                if (connectbuf[i] != NULL)
1800
                        if (mlCompareSocketIDs(&(connectbuf[i]->external_socketID), socketID) == 0) {
1801
                                if (ready) return (connectbuf[i]->status == READY ? i : -1);;
1802
                                return i;
1803
                                }
1804

    
1805
    return -1;
1806

    
1807
}
1808

    
1809
//Added by Robert Birke as comodity functions
1810

    
1811
//int mlPrintSocketID(socketID_handle socketID) {
1812
//        char str[SOCKETID_STRING_SIZE];
1813
//        mlSocketIDToString(socketID, str, sizeof(str));
1814
//        printf(stderr,"int->%s<-ext\n",str);
1815
//}
1816

    
1817
/*
1818
 * hash code of a socketID
1819
 * TODO might think of a better way
1820
 */
1821
int mlHashSocketID(socketID_handle sock) {
1822
    return sock->internal_addr.udpaddr.sin_port +
1823
                          sock->external_addr.udpaddr.sin_port;
1824
}
1825

    
1826
int mlCompareSocketIDs(socketID_handle sock1, socketID_handle sock2) {
1827
        /*
1828
        * compare internal addr
1829
        */
1830
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr !=
1831
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
1832
                        return 1;
1833

    
1834
        if (sock1->internal_addr.udpaddr.sin_port !=
1835
                 sock2->internal_addr.udpaddr.sin_port)
1836
                        return 1;
1837

    
1838
        /*
1839
        * compare external addr
1840
        */
1841
        if (sock1->external_addr.udpaddr.sin_addr.s_addr !=
1842
            sock2->external_addr.udpaddr.sin_addr.s_addr)
1843
                        return 1;
1844

    
1845
        if (sock1->external_addr.udpaddr.sin_port !=
1846
                 sock2->external_addr.udpaddr.sin_port)
1847
                        return 1;
1848

    
1849
        return 0;
1850
}
1851

    
1852
int mlCompareSocketIDsByPort(socketID_handle sock1, socketID_handle sock2)
1853
{ 
1854
        if (sock1->internal_addr.udpaddr.sin_port !=
1855
                 sock2->internal_addr.udpaddr.sin_port)
1856
                        return 1;
1857

    
1858
        if (sock1->external_addr.udpaddr.sin_port !=
1859
                 sock2->external_addr.udpaddr.sin_port)
1860
                        return 1;
1861
        return 0;
1862
}
1863

    
1864
int mlGetPathMTU(int ConnectionId) {
1865
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
1866
                return -1;
1867
        if (connectbuf[ConnectionId] != NULL)
1868
                return connectbuf[ConnectionId]->pmtusize;
1869
        return -1;
1870
}