Statistics
| Branch: | Revision:

ml / ml.c @ 60b80a11

History | View | Annotate | Download (61.8 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
#ifndef WIN32
37
#include <netinet/in.h>
38
#include <sys/socket.h>
39
#endif
40
#include <fcntl.h>
41
#include <event2/event.h>
42
#include <stdlib.h>
43
#include <unistd.h>
44
#include <stdio.h>
45
#include <stddef.h>
46
#include <stdint.h>
47
#include <string.h>
48
#include <sys/types.h>
49
#include <arpa/inet.h>
50
#include <netdb.h>
51
#include <errno.h>
52
#include <time.h>
53
#include <math.h>
54
#include <assert.h>
55

    
56
#include "util/udpSocket.h"
57
#include "util/stun.h"
58
#include "transmissionHandler.h"
59

    
60
#define LOG_MODULE "[ml] "
61
#include "ml_log.h"
62

    
63
/**************************** START OF INTERNALS ***********************/
64

    
65

    
66
/*
67
 * reserved message type for internal puposes
68
 */
69
#define MSG_TYPE_ML_KEEPALIVE 0x126        //TODO: check that it is really interpreted as internal
70

    
71
/*
72
 * a pointer to a libevent instance
73
 */
74
struct event_base *base;
75

    
76
/*
77
 * define the nr of connections the messaging layer can handle
78
 */
79
#define CONNECTBUFSIZE 10000
80
/*
81
 * define the nr of data that can be received parallel
82
 */
83
#define RECVDATABUFSIZE 10000
84
/*
85
 * define an array for message multiplexing
86
 */
87
#define MSGMULTIPLEXSIZE 127
88

    
89

    
90
/*
91
 * timeout before thinking that the STUN server can't be connected
92
 */
93
#define NAT_TRAVERSAL_TIMEOUT { 1, 0 }
94

    
95
/*
96
 * timeout before thinking of an mtu problem (check MAX_TRIALS as well)
97
 */
98
#define PMTU_TIMEOUT { 0, 500000 }
99

    
100
/*
101
 * retry sending connection messages this many times before reducing pmtu
102
 */
103
#define MAX_TRIALS 3
104

    
105
/*
106
 * default timeout value between the first and the last received packet of a message
107
 */
108
#define RECV_TIMEOUT_DEFAULT { 2, 0 }
109

    
110
/*
111
 * global variables
112
 */
113
/*
114
 * define a buffer of pointers to connect structures
115
 */
116
connect_data *connectbuf[CONNECTBUFSIZE];
117

    
118
/*
119
 * define a pointer buffer with pointers to recv_data structures
120
 */
121
recvdata *recvdatabuf[RECVDATABUFSIZE];
122

    
123
/*
124
 * define a pointer buffer for message multiplexing
125
 */
126
receive_data_cb recvcbbuf[MSGMULTIPLEXSIZE];
127

    
128
/*
129
 * stun server address
130
 */
131
struct sockaddr_in stun_server;
132

    
133
/*
134
 * receive timeout
135
 */
136
static struct timeval recv_timeout = RECV_TIMEOUT_DEFAULT;
137

    
138
/*
139
 * boolean NAT traversal successful if true
140
 */
141
boolean NAT_traversal;
142

    
143
/*
144
 * file descriptor for local socket
145
 */
146
evutil_socket_t socketfd;
147

    
148
/*
149
 * local socketID
150
 */
151
socket_ID local_socketID;
152

    
153
socketID_handle loc_socketID = &local_socketID;
154

    
155
/*
156
 * callback function pointers
157
 */
158
/*
159
 * monitoring module callbacks
160
 */
161
get_recv_pkt_inf_cb get_Recv_pkt_inf_cb = NULL;
162
get_send_pkt_inf_cb get_Send_pkt_inf_cb = NULL;
163
set_monitoring_header_pkt_cb set_Monitoring_header_pkt_cb = NULL;
164
get_recv_data_inf_cb get_Recv_data_inf_cb = NULL;
165
get_send_data_inf_cb get_Send_data_inf_cb = NULL;
166
set_monitoring_header_data_cb set_Monitoring_header_data_cb = NULL;
167
/*
168
 * connection callbacks
169
 */
170
receive_connection_cb receive_Connection_cb = NULL;
171
connection_failed_cb failed_Connection_cb = NULL;
172
/*
173
 * local socketID callback
174
 */
175
receive_localsocketID_cb receive_SocketID_cb;
176

    
177
/*
178
 * boolean that defines if received data is transmitted to the upper layer
179
 * via callback or via upper layer polling
180
 */
181
boolean recv_data_callback;
182

    
183
/*
184
 * helper function to get rid of a warning
185
 */
186
int min(int a, int b) {
187
        if (a > b) return b;
188
        return a;
189
}
190

    
191
/*
192
 * convert a socketID to a string. It uses a static buffer, so either strdup is needed, or the string will get lost!
193
 */
194
const char *conid_to_string(int con_id)
195
{
196
        static char s[INET_ADDRSTRLEN+1+5+1+INET_ADDRSTRLEN+1+5+1];
197
        mlSocketIDToString(&connectbuf[con_id]->external_socketID, s, sizeof(s));
198
        return s;
199
}
200

    
201
void register_recv_localsocketID_cb(receive_localsocketID_cb local_socketID_cb)
202
{
203
        if (local_socketID_cb == NULL) {
204
                error("ML : Register receive_localsocketID_cb: NULL ptr \n");
205
        } else {
206
                receive_SocketID_cb = local_socketID_cb;
207
        }
208
}
209

    
210

    
211
//void keep_connection_alive(const int connectionID)
212
//{
213
//
214
//    // to be done with the NAT traversal
215
//    // send a message over the wire
216
//    printf("\n");
217
//
218
//}
219

    
220
void unsetStunServer()
221
{
222
        stun_server.sin_addr.s_addr = INADDR_NONE;
223
}
224

    
225
bool isStunDefined()
226
{
227
        return stun_server.sin_addr.s_addr != INADDR_NONE;
228
}
229

    
230
void send_msg(int con_id, int msg_type, char* msg, int msg_len, bool truncable, send_params * sParams) {
231
        socketaddrgen udpgen;
232
        bool retry;
233
        int pkt_len, offset;
234
        struct iovec iov[4];
235

    
236
        char h_pkt[MON_PKT_HEADER_SPACE];
237
        char h_data[MON_DATA_HEADER_SPACE];
238

    
239
        struct msg_header msg_h;
240

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

    
243
        iov[0].iov_base = &msg_h;
244
        iov[0].iov_len = MSG_HEADER_SIZE;
245

    
246
        msg_h.local_con_id = htonl(con_id);
247
        msg_h.remote_con_id = htonl(connectbuf[con_id]->external_connectionID);
248
        msg_h.msg_type = msg_type;
249
        msg_h.msg_seq_num = htonl(connectbuf[con_id]->seqnr++);
250

    
251

    
252
        iov[1].iov_len = iov[2].iov_len = 0;
253
        iov[1].iov_base = h_pkt;
254
        iov[2].iov_base = h_data;
255

    
256

    
257
        if (connectbuf[con_id]->internal_connect)
258
                udpgen = connectbuf[con_id]->external_socketID.internal_addr;
259
        else
260
                udpgen = connectbuf[con_id]->external_socketID.external_addr;
261

    
262
        do{
263
                offset = 0;
264
                retry = false;
265
                // Monitoring layer hook
266
                if(set_Monitoring_header_data_cb != NULL) {
267
                        iov[2].iov_len = ((set_Monitoring_header_data_cb) (&(connectbuf[con_id]->external_socketID), msg_type));
268
                }
269
                msg_h.len_mon_data_hdr = iov[2].iov_len;
270

    
271
                if(get_Send_data_inf_cb != NULL && iov[2].iov_len != 0) {
272
                        mon_data_inf sd_data_inf;
273

    
274
                        memset(h_data, 0, MON_DATA_HEADER_SPACE);
275

    
276
                        sd_data_inf.remote_socketID = &(connectbuf[con_id]->external_socketID);
277
                        sd_data_inf.buffer = msg;
278
                        sd_data_inf.bufSize = msg_len;
279
                        sd_data_inf.msgtype = msg_type;
280
                        sd_data_inf.monitoringDataHeader = iov[2].iov_base;
281
                        sd_data_inf.monitoringDataHeaderLen = iov[2].iov_len;
282
                        sd_data_inf.priority = sParams->priority;
283
                        sd_data_inf.padding = sParams->padding;
284
                        sd_data_inf.confirmation = sParams->confirmation;
285
                        sd_data_inf.reliable = sParams->reliable;
286
                        memset(&sd_data_inf.arrival_time, 0, sizeof(struct timeval));
287

    
288
                        (get_Send_data_inf_cb) ((void *) &sd_data_inf);
289
                }
290

    
291
                do {
292
                        if(set_Monitoring_header_pkt_cb != NULL) {
293
                                iov[1].iov_len = (set_Monitoring_header_pkt_cb) (&(connectbuf[con_id]->external_socketID), msg_type);
294
                        }
295
                        pkt_len = min(connectbuf[con_id]->pmtusize - iov[2].iov_len - iov[1].iov_len - iov[0].iov_len, msg_len - offset) ;
296

    
297
                        iov[3].iov_len = pkt_len;
298
                        iov[3].iov_base = msg + offset;
299

    
300
                        //fill header
301
                        msg_h.len_mon_packet_hdr = iov[1].iov_len;
302
                        msg_h.offset = htonl(offset);
303
                        msg_h.msg_length = htonl(truncable ? pkt_len : msg_len);
304

    
305
                        //monitoring layer hook
306
                        if(get_Send_pkt_inf_cb != NULL && iov[1].iov_len) {
307
                                mon_pkt_inf pkt_info;
308

    
309
                                memset(h_pkt,0,MON_PKT_HEADER_SPACE);
310

    
311
                                pkt_info.remote_socketID = &(connectbuf[con_id]->external_socketID);
312
                                pkt_info.buffer = msg + offset;
313
                                pkt_info.bufSize = pkt_len;
314
                                pkt_info.msgtype = msg_type;
315
                                pkt_info.dataID = connectbuf[con_id]->seqnr;
316
                                pkt_info.offset = offset;
317
                                pkt_info.datasize = msg_len;
318
                                pkt_info.monitoringHeaderLen = iov[1].iov_len;
319
                                pkt_info.monitoringHeader = iov[1].iov_base;
320
                                pkt_info.ttl = -1;
321
                                memset(&(pkt_info.arrival_time),0,sizeof(struct timeval));
322

    
323
                                (get_Send_pkt_inf_cb) ((void *) &pkt_info);
324
                        }
325

    
326
                        debug("ML: sending packet to %s with rconID:%d lconID:%d\n", conid_to_string(con_id), ntohl(msg_h.remote_con_id), ntohl(msg_h.local_con_id));
327
                        switch(sendPacket(socketfd, iov, 4, &udpgen.udpaddr)) {
328
                                case MSGLEN:
329
                                        info("ML: sending message failed, reducing MTU from %d to %d (to:%s conID:%d lconID:%d msgsize:%d offset:%d)\n", connectbuf[con_id]->pmtusize, pmtu_decrement(connectbuf[con_id]->pmtusize), conid_to_string(con_id), ntohl(msg_h.remote_con_id), ntohl(msg_h.local_con_id), msg_len, offset);
330
                                        // TODO: pmtu decremented here, but not in the "truncable" packet. That is currently resent without changing the claimed pmtu. Might need to be changed.
331
                                        connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
332
                                        if (connectbuf[con_id]->pmtusize > 0) {
333
                                                connectbuf[con_id]->delay = true;
334
                                                retry = true;
335
                                        }
336
                                        offset = msg_len; // exit the while
337
                                        break;
338
                                case FAILURE:
339
                                        info("ML: sending message failed (to:%s conID:%d lconID:%d msgsize:%d offset:%d)\n", conid_to_string(con_id), ntohl(msg_h.remote_con_id), ntohl(msg_h.local_con_id), msg_len, offset);
340
                                        offset = msg_len; // exit the while
341
                                        break;
342
                                case THROTTLE:
343
                                    //    debug("THROTTLE on output"); 
344
                                        offset = msg_len; // exit the while
345
                                        break;
346
                                case OK:
347
                                        //update
348
                                        offset += pkt_len;
349
                                        //transmit data header only in the first packet
350
                                        iov[2].iov_len = 0;
351
                                        break;
352
                        }
353
                } while(offset != msg_len && !truncable);
354
        } while(retry);
355
}
356

    
357
void pmtu_timeout_cb(int fd, short event, void *arg);
358

    
359
void reschedule_conn_msg(int con_id)
360
{
361
        if (connectbuf[con_id]->timeout_event) {
362
                /* delete old timout */        
363
                event_del(connectbuf[con_id]->timeout_event);
364
                event_free(connectbuf[con_id]->timeout_event);
365
        }
366
        connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
367
        evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
368
}
369

    
370
void send_conn_msg(int con_id, int buf_size, int command_type)
371
{
372
        if (buf_size < sizeof(struct conn_msg)) {
373
                error("ML: requested connection message size is too small\n");
374
                return;
375
        }
376

    
377
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
378
                connectbuf[con_id]->ctrl_msg_buf = malloc(buf_size);
379
                memset(connectbuf[con_id]->ctrl_msg_buf, 0, buf_size);
380
        }
381

    
382
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
383
                error("ML: can not allocate memory for connection message\n");
384
                return;
385
        }
386

    
387
        struct conn_msg *msg_header = (struct conn_msg*) connectbuf[con_id]->ctrl_msg_buf;
388

    
389
        msg_header->comand_type = command_type;
390
        msg_header->pmtu_size = connectbuf[con_id]->pmtusize;
391

    
392
        memcpy(&(msg_header->sock_id), loc_socketID, sizeof(socket_ID));
393

    
394
        send_msg(con_id, ML_CON_MSG, connectbuf[con_id]->ctrl_msg_buf, buf_size, true, &(connectbuf[con_id]->defaultSendParams));
395
}
396

    
397
void send_conn_msg_with_pmtu_discovery(int con_id, int buf_size, int command_type)
398
{
399
        struct timeval tout = PMTU_TIMEOUT;
400
        connectbuf[con_id]->timeout_value = tout;
401
        connectbuf[con_id]->trials = 1;
402
        send_conn_msg(con_id, buf_size, command_type);
403
        reschedule_conn_msg(con_id);
404
}
405

    
406
void resend_conn_msg(int con_id)
407
{
408
        connectbuf[con_id]->trials++;
409
        send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
410
        reschedule_conn_msg(con_id);
411
}
412

    
413
void recv_conn_msg(struct msg_header *msg_h, char *msgbuf, int msg_size, struct sockaddr_in *recv_addr)
414
{
415
        struct conn_msg *con_msg;
416
        int free_con_id, con_id;
417

    
418
        time_t now = time(NULL);
419
        double timediff = 0.0;
420
        char sock_id_str[1000];
421
        
422
        msgbuf += msg_h->len_mon_data_hdr;
423
        msg_size -= msg_h->len_mon_data_hdr;
424
        con_msg = (struct conn_msg *)msgbuf;
425
        
426
        //verify message validity
427
        if (msg_size < sizeof(struct conn_msg)) {
428
                char recv_addr_str[INET_ADDRSTRLEN];
429
                inet_ntop(AF_INET, &(recv_addr->sin_addr.s_addr), recv_addr_str, INET_ADDRSTRLEN);
430
                info("Invalid conn_msg received from %s\n", recv_addr_str);
431
                return;
432
        }
433

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

    
437
        if (con_msg->sock_id.internal_addr.udpaddr.sin_addr.s_addr != recv_addr->sin_addr.s_addr &&
438
            con_msg->sock_id.external_addr.udpaddr.sin_addr.s_addr != recv_addr->sin_addr.s_addr   ) {
439
                char recv_addr_str[INET_ADDRSTRLEN];
440
                inet_ntop(AF_INET, &(recv_addr->sin_addr.s_addr), recv_addr_str, INET_ADDRSTRLEN);
441
                info("Conn msg received from %s, but claims to be from %s", recv_addr_str, sock_id_str);
442
                return;
443
        }
444

    
445
        // Monitoring layer hook
446
        if(get_Recv_data_inf_cb != NULL) {
447
                // update pointer to the real data
448
                mon_data_inf recv_data_inf;
449
                recv_data_inf.remote_socketID = &(con_msg->sock_id);
450
                recv_data_inf.buffer = msgbuf;
451
                recv_data_inf.bufSize = msg_size;
452
                recv_data_inf.msgtype = msg_h->msg_type;
453
                recv_data_inf.monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
454
                recv_data_inf.monitoringDataHeader = msg_h->len_mon_data_hdr ? msgbuf : NULL;
455
                gettimeofday(&recv_data_inf.arrival_time, NULL);
456
                recv_data_inf.firstPacketArrived = true;
457
                recv_data_inf.recvFragments = 1;
458
                recv_data_inf.priority = false;
459
                recv_data_inf.padding = false;
460
                recv_data_inf.confirmation = false;
461
                recv_data_inf.reliable = false;
462

    
463
                // send data recv callback to monitoring module
464
                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
465
        }
466

    
467
        // check the connection command type
468
        switch (con_msg->comand_type) {
469
                /*
470
                * if INVITE: enter a new socket make new entry in connect array
471
                * send an ok
472
                */
473
                case INVITE:
474
                        info("ML: received INVITE from %s (size:%d)\n", sock_id_str, msg_size);
475
                        /*
476
                        * check if another connection for the external connectionID exist
477
                        * that was established within the last 2 seconds
478
                        */
479
                        free_con_id = -1;
480
                        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
481
                                if (connectbuf[con_id] != NULL) {
482
                                        if (mlCompareSocketIDs(&(connectbuf[con_id]->external_socketID), &(con_msg->sock_id)) == 0) {
483
                                                //timediff = difftime(now, connectbuf[con_id]->starttime);        //TODO: why this timeout? Shouldn't the connection be closed instead if there is a timeout?
484
                                                //if (timediff < 2)
485
                                                //update remote connection ID
486
                                                if (connectbuf[con_id]->external_connectionID != msg_h->local_con_id) {
487
                                                        warn("ML: updating remote connection ID for %s: from %d to %d\n",sock_id_str, connectbuf[con_id]->external_connectionID, msg_h->local_con_id);
488
                                                        connectbuf[con_id]->external_connectionID = msg_h->local_con_id;
489
                                                }
490
                                                break;
491
                                        }
492
                                } else if(free_con_id == -1)
493
                                        free_con_id = con_id;
494
                        }
495

    
496
                        if (con_id == CONNECTBUFSIZE) {
497
                                // create an entry in the connecttrybuf
498
                                if(free_con_id == -1) {
499
                                        error("ML: no new connect_buf available\n");
500
                                        return;
501
                                }
502
                                connectbuf[free_con_id] = (connect_data *) malloc(sizeof(connect_data));
503
                                memset(connectbuf[free_con_id],0,sizeof(connect_data));
504
                                connectbuf[free_con_id]->connection_head = connectbuf[free_con_id]->connection_last = NULL;
505
                                connectbuf[free_con_id]->starttime = time(NULL);
506
                                memcpy(&(connectbuf[free_con_id]->external_socketID), &(con_msg->sock_id), sizeof(socket_ID));
507
                                connectbuf[free_con_id]->pmtusize = con_msg->pmtu_size;        // bootstrap pmtu from the other's size. Not strictly needed, but a good hint
508
                                connectbuf[free_con_id]->timeout_event = NULL;
509
                                connectbuf[free_con_id]->external_connectionID = msg_h->local_con_id;
510
                                connectbuf[free_con_id]->internal_connect =
511
                                        !compare_external_address_socketIDs(&(con_msg->sock_id), loc_socketID);
512
                                con_id = free_con_id;
513
                        }
514

    
515
                        //if(connectbuf[con_id]->status <= CONNECT) { //TODO: anwer anyway. Why the outher would invite otherwise?
516
                                //update status and send back answer
517
                                connectbuf[con_id]->status = CONNECT;
518
                                send_conn_msg_with_pmtu_discovery(con_id, con_msg->pmtu_size, CONNECT);
519
                        //}
520
                        break;
521
                case CONNECT:
522
                        info("ML: received CONNECT from %s (size:%d)\n", sock_id_str, msg_size);
523

    
524
                        if(msg_h->remote_con_id != -1 && connectbuf[msg_h->remote_con_id] == NULL) {
525
                                error("ML: received CONNECT for inexistent connection rconID:%d\n",msg_h->remote_con_id);
526
                                return;
527
                        }
528

    
529
                        /*
530
                        * check if the connection status is not already 1 or 2
531
                        */
532
                        if (connectbuf[msg_h->remote_con_id]->status == INVITE) {
533
                                // set the external connectionID
534
                                connectbuf[msg_h->remote_con_id]->external_connectionID = msg_h->local_con_id;
535
                                // change status con_msg the connection_data
536
                                connectbuf[msg_h->remote_con_id]->status = READY;
537
                                // change pmtusize in the connection_data: not needed. receiving a CONNECT means our INVITE went through. So why change pmtu?
538
                                //connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
539

    
540
                                // send the READY
541
                                send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
542

    
543
                                if (receive_Connection_cb != NULL)
544
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
545

    
546
                                // call all registered callbacks
547
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
548
                                        struct receive_connection_cb_list *temp;
549
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
550
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
551
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
552
                                        free(temp);
553
                                }
554
                                connectbuf[msg_h->remote_con_id]->connection_head =
555
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
556
                        } else {
557
                                // send the READY
558
                                send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
559
                        }
560

    
561
                        debug("ML: active connection established\n");
562
                        break;
563

    
564
                        /*
565
                        * if READY: find the entry in the connection array set the
566
                        * connection active change the pmtu size
567
                        */
568
                case READY:
569
                        info("ML: received READY from %s (size:%d)\n", sock_id_str, msg_size);
570
                        if(connectbuf[msg_h->remote_con_id] == NULL) {
571
                                error("ML: received READY for inexistent connection\n");
572
                                return;
573
                        }
574
                        /*
575
                        * checks if the connection is not already established
576
                        */
577
                        if (connectbuf[msg_h->remote_con_id]->status == CONNECT) {
578
                                // change status of the connection
579
                                connectbuf[msg_h->remote_con_id]->status = READY;
580
                                // change pmtusize: not needed. pmtu doesn't have to be symmetric
581
                                //connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
582

    
583
                                if (receive_Connection_cb != NULL)
584
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
585

    
586
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
587
                                        struct receive_connection_cb_list *temp;
588
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
589
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
590
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
591
                                        free(temp);
592
                                }
593
                                connectbuf[msg_h->remote_con_id]->connection_head =
594
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
595
                                debug("ML: passive connection established\n");
596
                        }
597
                        break;
598
        }
599
}
600

    
601
void recv_stun_msg(char *msgbuf, int recvSize)
602
{
603
        /*
604
        * create empty stun message struct
605
        */
606
        StunMessage resp;
607
        memset(&resp, 0, sizeof(StunMessage));
608
        /*
609
        * parse the message
610
        */
611
        int returnValue = 0;
612
        returnValue = recv_stun_message(msgbuf, recvSize, &resp);
613

    
614
        if (returnValue == 0) {
615
                /*
616
                * read the reflexive Address into the local_socketID
617
                */
618
                struct sockaddr_in reflexiveAddr = {0};
619
                reflexiveAddr.sin_family = AF_INET;
620
                reflexiveAddr.sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
621
                reflexiveAddr.sin_port = htons(resp.mappedAddress.ipv4.port);
622
                socketaddrgen reflexiveAddres = {0};
623
                reflexiveAddres.udpaddr = reflexiveAddr;
624
                local_socketID.external_addr = reflexiveAddres;
625
                NAT_traversal = true;
626
                // callback to the upper layer indicating that the socketID is now
627
                // ready to use
628
                (receive_SocketID_cb) (&local_socketID, 0);
629
        }
630
}
631

    
632
//done
633
void recv_timeout_cb(int fd, short event, void *arg)
634
{
635
        int recv_id = (long) arg;
636
        debug("ML: recv_timeout_cb called. Timeout for id:%d\n",recv_id);
637

    
638
        if (recvdatabuf[recv_id] == NULL) {
639
                return;
640
        }
641

    
642

    
643
/*        if(recvdatabuf[recv_id]->status == ACTIVE) {
644
                //TODO make timeout at least a DEFINE
645
                struct timeval timeout = { 4, 0 };
646
                recvdatabuf[recv_id]->status = INACTIVE;
647
                event_base_once(base, -1, EV_TIMEOUT, recv_timeout_cb,
648
                        arg, &timeout);
649
                return;
650
        }
651
*/
652

    
653
        if(recvdatabuf[recv_id]->status == ACTIVE) {
654
                // Monitoring layer hook
655
                if(get_Recv_data_inf_cb != NULL) {
656
                        mon_data_inf recv_data_inf;
657

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

    
674
                        // send data recv callback to monitoring module
675

    
676
//                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
677
                }
678

    
679
                // Get the right callback
680
                receive_data_cb receive_data_callback = recvcbbuf[recvdatabuf[recv_id]->msgtype];
681

    
682
                recv_params rParams;
683

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

    
692
//                 (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
693
//                         recvdatabuf[recv_id]->msgtype, &rParams);
694

    
695
                //clean up
696
                if (recvdatabuf[recv_id]->timeout_event) {
697
                        event_del(recvdatabuf[recv_id]->timeout_event);
698
                        event_free(recvdatabuf[recv_id]->timeout_event);
699
                        recvdatabuf[recv_id]->timeout_event = NULL;
700
                }
701
                free(recvdatabuf[recv_id]->recvbuf);
702
                free(recvdatabuf[recv_id]);
703
                recvdatabuf[recv_id] = NULL;
704
        }
705
}
706

    
707
// process a single recv data message
708
void recv_data_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
709
{
710
        debug("ML: received packet of size %d with rconID:%d lconID:%d type:%d offset:%d\n",bufsize,msg_h->remote_con_id,msg_h->local_con_id,msg_h->msg_type,msg_h->offset);
711

    
712
        int recv_id, free_recv_id = -1;
713

    
714
        if(connectbuf[msg_h->remote_con_id] == NULL) {
715
                debug("ML: Received a message not related to any opened connection!\n");
716
                return;
717
        }
718

    
719
        // check if a recv_data exist and enter data
720
        for (recv_id = 0; recv_id < RECVDATABUFSIZE; recv_id++)
721
                if (recvdatabuf[recv_id] != NULL) {
722
                        if (msg_h->remote_con_id == recvdatabuf[recv_id]->connectionID &&
723
                                        msg_h->msg_seq_num == recvdatabuf[recv_id]->seqnr)
724
                                                break;
725
                } else
726
                        if(free_recv_id == -1)
727
                                free_recv_id = recv_id;
728

    
729

    
730
        if(recv_id == RECVDATABUFSIZE) {
731
                //no recv_data found: create one
732
                recv_id = free_recv_id;
733
                recvdatabuf[recv_id] = (recvdata *) malloc(sizeof(recvdata));
734
                memset(recvdatabuf[recv_id], 0, sizeof(recvdata));
735
                recvdatabuf[recv_id]->connectionID = msg_h->remote_con_id;
736
                recvdatabuf[recv_id]->seqnr = msg_h->msg_seq_num;
737
                recvdatabuf[recv_id]->monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
738
                recvdatabuf[recv_id]->bufsize = msg_h->msg_length + msg_h->len_mon_data_hdr;
739
                recvdatabuf[recv_id]->recvbuf = (char *) malloc(recvdatabuf[recv_id]->bufsize);
740
                recvdatabuf[recv_id]->arrivedBytes = 0;        //count this without the Mon headers
741
                /*
742
                * read the timeout data and set it
743
                */
744
                recvdatabuf[recv_id]->timeout_value = recv_timeout;
745
                recvdatabuf[recv_id]->timeout_event = NULL;
746
                recvdatabuf[recv_id]->recvID = recv_id;
747
                recvdatabuf[recv_id]->starttime = time(NULL);
748
                recvdatabuf[recv_id]->msgtype = msg_h->msg_type;
749

    
750
                // fill the buffer with zeros
751
                memset(recvdatabuf[recv_id]->recvbuf, 0, recvdatabuf[recv_id]->bufsize);
752
                debug(" new @ id:%d\n",recv_id);
753
        } else {        //message structure already exists, no need to create new
754
                debug(" found @ id:%d (arrived before this packet: bytes:%d fragments%d\n",recv_id, recvdatabuf[recv_id]->arrivedBytes, recvdatabuf[recv_id]->recvFragments);
755
        }
756

    
757
        //if first packet extract mon data header and advance pointer
758
        if (msg_h->offset == 0) {
759
                memcpy(recvdatabuf[recv_id]->recvbuf, msgbuf, msg_h->len_mon_data_hdr);
760
                msgbuf += msg_h->len_mon_data_hdr;
761
                bufsize -= msg_h->len_mon_data_hdr;
762
                recvdatabuf[recv_id]->firstPacketArrived = 1;
763
        }
764

    
765

    
766
        // increment fragmentnr
767
        recvdatabuf[recv_id]->recvFragments++;
768
        // increment the arrivedBytes
769
        recvdatabuf[recv_id]->arrivedBytes += bufsize;
770

    
771
        // enter the data into the buffer
772
        memcpy(recvdatabuf[recv_id]->recvbuf + msg_h->len_mon_data_hdr + msg_h->offset, msgbuf, bufsize);
773

    
774
        //TODO very basic checkif all fragments arrived: has to be reviewed
775
        if(recvdatabuf[recv_id]->arrivedBytes == recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen)
776
                recvdatabuf[recv_id]->status = COMPLETE; //buffer full -> msg completly arrived
777
        else
778
                recvdatabuf[recv_id]->status = ACTIVE;
779

    
780
        if (recv_data_callback) {
781
                if(recvdatabuf[recv_id]->status == COMPLETE) {
782
                        // Monitoring layer hook
783
                        if(get_Recv_data_inf_cb != NULL) {
784
                                mon_data_inf recv_data_inf;
785

    
786
                                recv_data_inf.remote_socketID =
787
                                         &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
788
                                recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
789
                                recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
790
                                recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
791
                                recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
792
                                recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
793
                                        recvdatabuf[recv_id]->recvbuf : NULL;
794
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
795
                                recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
796
                                recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
797
                                recv_data_inf.priority = false;
798
                                recv_data_inf.padding = false;
799
                                recv_data_inf.confirmation = false;
800
                                recv_data_inf.reliable = false;
801

    
802
                                // send data recv callback to monitoring module
803

    
804
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
805
                        }
806

    
807
                        // Get the right callback
808
                        receive_data_cb receive_data_callback = recvcbbuf[msg_h->msg_type];
809
                        if (receive_data_callback) {
810

    
811
                                recv_params rParams;
812

    
813
                                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen - recvdatabuf[recv_id]->arrivedBytes;
814
                                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
815
                                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
816
                                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
817
                                rParams.remote_socketID =
818
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
819

    
820
                                char str[1000];
821
                                mlSocketIDToString(rParams.remote_socketID,str,999);
822
                                debug("ML: received message from conID:%d, %s\n",recvdatabuf[recv_id]->connectionID,str);
823
                                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
824

    
825
                                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
826
                                        recvdatabuf[recv_id]->msgtype, (void *) &rParams);
827
                        } else {
828
                            warn("ML: callback not initialized for this message type: %d!\n",msg_h->msg_type);
829
                        }
830

    
831
                        //clean up
832
                        if (recvdatabuf[recv_id]->timeout_event) {
833
                                debug("ML: freeing timeout for %d",recv_id);
834
                                event_del(recvdatabuf[recv_id]->timeout_event);
835
                                event_free(recvdatabuf[recv_id]->timeout_event);
836
                                recvdatabuf[recv_id]->timeout_event = NULL;
837
                        } else {
838
                                debug("ML: received in 1 packet\n",recv_id);
839
                        }
840
                        free(recvdatabuf[recv_id]->recvbuf);
841
                        free(recvdatabuf[recv_id]);
842
                        recvdatabuf[recv_id] = NULL;
843
                } else { // not COMPLETE
844
                        if (!recvdatabuf[recv_id]->timeout_event) {
845
                                //start time out
846
                                //TODO make timeout at least a DEFINE
847
                                recvdatabuf[recv_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &recv_timeout_cb, (void *) (long)recv_id);
848
                                evtimer_add(recvdatabuf[recv_id]->timeout_event, &recv_timeout);
849
                        }
850
                }
851
        }
852
}
853

    
854
//done
855
void pmtu_timeout_cb(int fd, short event, void *arg)
856
{
857

    
858
        int con_id = (long) arg;
859
        pmtu new_pmtusize;
860

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

    
863
        if(connectbuf[con_id] == NULL) {
864
                error("ML: pmtu timeout called on non existing con_id\n");
865
                return;
866
        }
867

    
868
        if(connectbuf[con_id]->status == READY) {
869
                // nothing to do anymore
870
                event_del(connectbuf[con_id]->timeout_event);
871
                event_free(connectbuf[con_id]->timeout_event);
872
                connectbuf[con_id]->timeout_event = NULL;
873
                return;
874
        }
875

    
876
        info("ML: pmtu timeout while connecting(to:%s lcon:%d status:%d size:%d trial:%d tout:%ld.%06ld)\n",conid_to_string(con_id), con_id, connectbuf[con_id]->status, connectbuf[con_id]->pmtusize, connectbuf[con_id]->trials, connectbuf[con_id]->timeout_value.tv_sec, connectbuf[con_id]->timeout_value.tv_usec);
877

    
878
        if(connectbuf[con_id]->delay || connectbuf[con_id]->trials == MAX_TRIALS - 1) {
879
                double delay = connectbuf[con_id]->timeout_value.tv_sec + connectbuf[con_id]->timeout_value.tv_usec / 1000000.0;
880
                delay = delay * 2;
881
                info("\tML: increasing pmtu timeout to %f sec\n", delay);
882
                connectbuf[con_id]->timeout_value.tv_sec = floor(delay);
883
                connectbuf[con_id]->timeout_value.tv_usec = fmod(delay, 1.0) * 1000000.0;
884
                if(connectbuf[con_id]->delay) {
885
                        connectbuf[con_id]->delay = false;
886
                        reschedule_conn_msg(con_id);
887
                }
888
        }
889

    
890
        if(connectbuf[con_id]->trials == MAX_TRIALS) {
891
                // decrement the pmtu size
892
                struct timeval tout = PMTU_TIMEOUT;
893
                info("\tML: decreasing pmtu estimate from %d to %d\n", connectbuf[con_id]->pmtusize, pmtu_decrement(connectbuf[con_id]->pmtusize));
894
                connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
895
                connectbuf[con_id]->timeout_value = tout; 
896
                connectbuf[con_id]->trials = 0;
897
        }
898

    
899
        //error in PMTU discovery?
900
        if (connectbuf[con_id]->pmtusize == ERROR) {
901
                if (connectbuf[con_id]->internal_connect == true) {
902
                        //as of now we tried directly connecting, now let's try trough the NAT
903
                        connectbuf[con_id]->internal_connect = false;
904
                        connectbuf[con_id]->pmtusize = DSLSLIM;
905
                } else {
906
                        //nothing to do we have to give up
907
                        error("ML: Could not create connection with connectionID %i!\n",con_id);
908
                        // envoke the callback for failed connection establishment
909
                        if(failed_Connection_cb != NULL)
910
                                (failed_Connection_cb) (con_id, NULL);
911
                        // delete the connection entry
912
                        mlCloseConnection(con_id);
913
                        return;
914
                }
915
        }
916

    
917
        //retry
918
        resend_conn_msg(con_id);
919
}
920

    
921

    
922
int schedule_pmtu_timeout(int con_id)
923
{
924
        if (! connectbuf[con_id]->timeout_event) {
925
                struct timeval tout = PMTU_TIMEOUT;
926
                connectbuf[con_id]->timeout_value = tout;
927
                connectbuf[con_id]->trials = 1;
928
                connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
929
                evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
930
        }
931
}
932

    
933
/*
934
 * decrements the mtu size
935
 */
936
pmtu pmtu_decrement(pmtu pmtusize)
937
{
938
        pmtu pmtu_return_size;
939
        switch(pmtusize) {
940
        case MAX:
941
                //return DSL;
942
                return DSLSLIM;        //shortcut to use less vales
943
        case DSL:
944
                return DSLMEDIUM;
945
        case DSLMEDIUM:
946
                return DSLSLIM;
947
        case DSLSLIM:
948
                //return BELOWDSL;
949
                return MIN;        //shortcut to use less vales
950
        case BELOWDSL:
951
                return MIN;
952
        case MIN:
953
                return ERROR;
954
        default:
955
                warn("ML: strange pmtu size encountered:%d, changing to some safe value:%d\n", pmtusize, MIN);
956
                return MIN;
957
        }
958
}
959

    
960
// called when an ICMP pmtu error message (type 3, code 4) is received
961
void pmtu_error_cb_th(char *msg, int msglen)
962
{
963
        debug("ML: pmtu_error callback called msg_size: %d\n",msglen);
964
        //TODO debug
965
        return;
966

    
967
    char *msgbufptr = NULL;
968
    int msgtype;
969
    int connectionID;
970
    pmtu pmtusize;
971
    pmtu new_pmtusize;
972
    int dead = 0;
973

    
974
    // check the packettype
975
    msgbufptr = &msg[0];
976

    
977
    // check the msgtype
978
    msgbufptr = &msg[1];
979
    memcpy(&msgtype, msgbufptr, 4);
980

    
981
    if (msgtype == 0) {
982

    
983
        // get the connectionID
984
        msgbufptr = &msg[5];
985
        memcpy(&connectionID, msgbufptr, 4);
986

    
987
        int msgtype_c = connectbuf[connectionID]->status;
988
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
989

    
990
        if (msgtype_c != msgtype) {
991
            dead = 1;
992
        }
993

    
994

    
995
    } else if (msgtype == 1) {
996

    
997
        // read the connectionID
998
        msgbufptr = &msg[9];
999
        memcpy(&connectionID, msgbufptr, 4);
1000

    
1001
        int msgtype_c = connectbuf[connectionID]->status;
1002
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
1003

    
1004
        if (msgtype_c != msgtype) {
1005
            dead = 1;
1006
        }
1007

    
1008
    }
1009
    // decrement the pmtu size
1010
    new_pmtusize = pmtu_decrement(pmtusize);
1011

    
1012
//    connectbuf[connectionID]->pmtutrysize = new_pmtusize;
1013

    
1014
    if (new_pmtusize == ERROR) {
1015
                error("ML:  Could not create connection with connectionID %i !\n",
1016
                        connectionID);
1017

    
1018
                if(failed_Connection_cb != NULL)
1019
                        (failed_Connection_cb) (connectionID, NULL);
1020
                // set the message type to a non existent message
1021
                msgtype = 2;
1022
                // delete the connection entry
1023
                 mlCloseConnection(connectionID);
1024
        }
1025

    
1026
    if (msgtype == 0 && dead != 1) {
1027

    
1028
        // stop the timeout event
1029
        // timeout_del(connectbuf[connectionID]->timeout);
1030
        /*
1031
         * libevent2
1032
         */
1033

    
1034
        // event_del(connectbuf[connectionID]->timeout);
1035

    
1036

    
1037
        // create and send a connection message
1038
//         create_conn_msg(new_pmtusize, connectionID,
1039
//                         &local_socketID, INVITE);
1040

    
1041
//        send_conn_msg(connectionID, new_pmtusize);
1042

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

    
1047
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1048

    
1049
        /*
1050
         * libevent2
1051
         */
1052

    
1053
        struct event *ev;
1054
        ev = evtimer_new(base, pmtu_timeout_cb,
1055
                         (void *) connectbuf[connectionID]);
1056

    
1057
        // connectbuf[connectionID]->timeout = ev;
1058

    
1059
        event_add(ev, &connectbuf[connectionID]->timeout_value);
1060

    
1061
    } else if (msgtype == 1 && dead != 1) {
1062

    
1063
        // stop the timeout event
1064
        // timeout_del(connectbuf[connectionID]->timeout);
1065

    
1066
        /*
1067
         * libevent2
1068
         */
1069
        // info("still here 11 \n");
1070
        // printf("ev %d \n",connectbuf[connectionID]->timeout);
1071
        // event_del(connectbuf[connectionID]->timeout );
1072
        // evtimer_del(connectbuf[connectionID]->timeout );
1073

    
1074

    
1075
//         // create and send a connection message
1076
//         create_conn_msg(new_pmtusize,
1077
//                         connectbuf[connectionID]->connectionID,
1078
//                         NULL, CONNECT);
1079

    
1080
        //send_conn_msg(connectionID, new_pmtusize);
1081

    
1082
        // set a timeout event for the pmtu discovery
1083
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
1084
        // *)&connectionID);
1085
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1086

    
1087
        /*
1088
         * libevent2
1089
         */
1090
        // struct event *ev;
1091
        // ev = evtimer_new(base,pmtu_timeout_cb, (void
1092
        // *)connectbuf[connectionID]);
1093
        // connectbuf[connectionID]->timeout = ev;
1094
        // event_add(ev,&connectbuf[connectionID]->timeout_value);
1095

    
1096
    }
1097
}
1098

    
1099
/*
1100
 * what to do once a packet arrived if it is a conn packet send it to
1101
 * recv_conn handler if it is a data packet send it to the recv_data
1102
 * handler
1103
 */
1104

    
1105
//done --
1106
void recv_pkg(int fd, short event, void *arg)
1107
{
1108
        debug("ML: recv_pkg called\n");
1109

    
1110
        struct msg_header *msg_h;
1111
        char msgbuf[MAX];
1112
        pmtu recvSize = MAX;
1113
        char *bufptr = msgbuf;
1114
        int ttl;
1115
        struct sockaddr_in recv_addr;
1116
        int msg_size;
1117

    
1118
        recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
1119

    
1120

    
1121
        // check if it is not just an ERROR message
1122
        if(recvSize < 0)
1123
                return;
1124

    
1125
        // @TODO check if this simplistic STUN message recognition really always works, probably not
1126
        unsigned short stun_bind_response = 0x0101;
1127
        unsigned short * msgspot = (unsigned short *) msgbuf;
1128
        if (*msgspot == stun_bind_response) {
1129
                debug("ML: recv_pkg: parse stun message called\n");
1130
                recv_stun_msg(msgbuf, recvSize);
1131
                return;
1132
        }
1133

    
1134
        msg_h = (struct msg_header *) msgbuf;
1135

    
1136
        /* convert header from network to host order */
1137
        msg_h->offset = ntohl(msg_h->offset);
1138
        msg_h->msg_length = ntohl(msg_h->msg_length);
1139
        msg_h->local_con_id = ntohl(msg_h->local_con_id);
1140
        msg_h->remote_con_id = ntohl(msg_h->remote_con_id);
1141
        msg_h->msg_seq_num = ntohl(msg_h->msg_seq_num);
1142

    
1143
        //verify minimum size
1144
        if (recvSize < sizeof(struct msg_header)) {
1145
          info("UDP packet too small, can't be an ML packet");
1146
          return;
1147
        }
1148

    
1149
        //TODO add more verifications
1150

    
1151
        bufptr += MSG_HEADER_SIZE + msg_h->len_mon_packet_hdr;
1152
        msg_size = recvSize - MSG_HEADER_SIZE - msg_h->len_mon_packet_hdr;
1153

    
1154
        //verify more fields
1155
        if (msg_size < 0) {
1156
          info("Corrupted UDP packet received");
1157
          return;
1158
        }
1159

    
1160
        if(get_Recv_pkt_inf_cb != NULL) {
1161
                mon_pkt_inf msginfNow;
1162
                msginfNow.monitoringHeaderLen = msg_h->len_mon_packet_hdr;
1163
                msginfNow.monitoringHeader = msg_h->len_mon_packet_hdr ? &msgbuf[0] + MSG_HEADER_SIZE : NULL;
1164
                //TODO rethink this ...
1165
                if(msg_h->msg_type == ML_CON_MSG) {
1166
                        struct conn_msg *c_msg = (struct conn_msg *) bufptr;
1167
                        msginfNow.remote_socketID = &(c_msg->sock_id);
1168
                }
1169
                else if(connectbuf[msg_h->remote_con_id] == NULL) {
1170
                        error("ML: received pkg called with non existent connection\n");
1171
                        return;
1172
                } else
1173
                        msginfNow.remote_socketID = &(connectbuf[msg_h->remote_con_id]->external_socketID);
1174
                msginfNow.buffer = bufptr;
1175
                msginfNow.bufSize = recvSize;
1176
                msginfNow.msgtype = msg_h->msg_type;
1177
                msginfNow.ttl = ttl;
1178
                msginfNow.dataID = msg_h->msg_seq_num;
1179
                msginfNow.offset = msg_h->offset;
1180
                msginfNow.datasize = msg_h->msg_length;
1181
                gettimeofday(&msginfNow.arrival_time, NULL);
1182
                (get_Recv_pkt_inf_cb) ((void *) &msginfNow);
1183
        }
1184

    
1185

    
1186
        switch(msg_h->msg_type) {
1187
                case ML_CON_MSG:
1188
                        debug("ML: received conn pkg\n");
1189
                        recv_conn_msg(msg_h, bufptr, msg_size, &recv_addr);
1190
                        break;
1191
                default:
1192
                        if(msg_h->msg_type < 127) {
1193
                                debug("ML: received data pkg\n");
1194
                                recv_data_msg(msg_h, bufptr, msg_size);
1195
                                break;
1196
                        }
1197
                        debug("ML: unrecognised msg_type\n");
1198
                        break;
1199
        }
1200
}
1201

    
1202
/*
1203
 * compare the external IP address of two socketIDs
1204
 */
1205
int
1206
compare_external_address_socketIDs(socketID_handle sock1, socketID_handle sock2)
1207
{
1208
        if( sock1->external_addr.udpaddr.sin_addr.s_addr == sock2->external_addr.udpaddr.sin_addr.s_addr)
1209
                return 0;
1210
        return 1;
1211
}
1212

    
1213
void try_stun();
1214

    
1215
/*
1216
 * the timeout of the NAT traversal
1217
 */
1218
void nat_traversal_timeout(int fd, short event, void *arg)
1219
{
1220
        if (NAT_traversal == false) {
1221
                debug("ML: NAT traversal request re-send\n");
1222
                if(receive_SocketID_cb)
1223
                        (receive_SocketID_cb) (&local_socketID, 2);
1224
                try_stun();
1225
        }
1226
}
1227

    
1228
//return IP address, or INADDR_NONE if can't resolve
1229
unsigned long resolve(const char *ipaddr)
1230
{
1231
        struct hostent *h = gethostbyname(ipaddr);
1232
        if (!h) {
1233
                error("ML: Unable to resolve host name %s\n", ipaddr);
1234
                return INADDR_NONE;
1235
        }
1236
        unsigned long *addr = (unsigned long *) (h->h_addr);
1237
        return *addr;
1238
}
1239

    
1240

    
1241
/*
1242
 * returns the file descriptor, or <0 on error. The ipaddr can be a null
1243
 * pointer. Then all available ipaddr on the machine are choosen.
1244
 */
1245
int create_socket(const int port, const char *ipaddr)
1246
{
1247
        struct sockaddr_in udpaddr = {0};
1248
        udpaddr.sin_family = AF_INET;
1249
        if (ipaddr == NULL) {
1250
                /*
1251
                * try to guess the local IP address
1252
                */
1253
                const char *ipaddr_iface = mlAutodetectIPAddress();
1254
                if (ipaddr_iface) {
1255
                        udpaddr.sin_addr.s_addr = inet_addr(ipaddr_iface);
1256
                } else {
1257
                        udpaddr.sin_addr.s_addr = INADDR_ANY;
1258
                }
1259
        } else {
1260
                udpaddr.sin_addr.s_addr = inet_addr(ipaddr);
1261
        }
1262
        udpaddr.sin_port = htons(port);
1263

    
1264
        socketaddrgen udpgen;
1265
        memset(&udpgen,0,sizeof(socketaddrgen));        //this will be sent over the net, so set it to 0
1266
        udpgen.udpaddr = udpaddr;
1267
        local_socketID.internal_addr = udpgen;
1268

    
1269
        socketfd = createSocket(port, ipaddr);
1270
        if (socketfd < 0){
1271
                return socketfd;
1272
        }
1273

    
1274
        struct event *ev;
1275
        ev = event_new(base, socketfd, EV_READ | EV_PERSIST, recv_pkg, NULL);
1276

    
1277
        event_add(ev, NULL);
1278

    
1279
        try_stun();
1280

    
1281
        return socketfd;
1282
}
1283

    
1284
/*
1285
 * try to figure out external IP using STUN, if defined
1286
 */
1287
void try_stun()
1288
{
1289
        if (isStunDefined()) {
1290
                /*
1291
                * send the NAT traversal STUN request
1292
                */
1293
                 send_stun_request(socketfd, &stun_server);
1294

    
1295
                /*
1296
                * enter a NAT traversal timeout that takes care of retransmission
1297
                */
1298
                struct event *ev1;
1299
                struct timeval timeout_value_NAT_traversal = NAT_TRAVERSAL_TIMEOUT;
1300
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1301
                event_add(ev1, &timeout_value_NAT_traversal);
1302

    
1303
                NAT_traversal = false;
1304
        } else {
1305
                /*
1306
                * Assume we have accessibility and copy internal address to external one
1307
                */
1308
                local_socketID.external_addr = local_socketID.internal_addr;
1309
                NAT_traversal = true; // @TODO: this is not really NAT traversal, but a flag that init is over
1310
                // callback to the upper layer indicating that the socketID is now
1311
                // ready to use
1312
                if(receive_SocketID_cb)
1313
                        (receive_SocketID_cb) (&local_socketID, 0); //success
1314
        }
1315
}
1316

    
1317
/**************************** END OF INTERNAL ***********************/
1318

    
1319
/**************************** MONL functions *************************/
1320

    
1321
int 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){
1322

    
1323
        base = (struct event_base *) arg;
1324
        recv_data_callback = recv_data_cb;
1325
        mlSetRecvTimeout(timeout_value);
1326
        if (stun_ipaddr) {
1327
                 mlSetStunServer(stun_port, stun_ipaddr);
1328
        } else {
1329

    
1330
        }
1331
        register_recv_localsocketID_cb(local_socketID_cb);
1332
        return create_socket(port, ipaddr);
1333
}
1334

    
1335
void mlSetThrottle(int bucketsize, int drainrate) {
1336
        setOutputRateParams(bucketsize, drainrate);
1337
}
1338
     
1339

    
1340
/* register callbacks  */
1341
void mlRegisterGetRecvPktInf(get_recv_pkt_inf_cb recv_pkt_inf_cb){
1342

    
1343
        if (recv_pkt_inf_cb == NULL) {
1344
                error("ML: Register get_recv_pkt_inf_cb failed: NULL ptr  \n");
1345
        } else {
1346
                get_Recv_pkt_inf_cb = recv_pkt_inf_cb;
1347
        }
1348
}
1349

    
1350
void mlRegisterGetSendPktInf(get_send_pkt_inf_cb  send_pkt_inf_cb){
1351

    
1352
        if (send_pkt_inf_cb == NULL) {
1353
                error("ML: Register get_send_pkt_inf_cb: NULL ptr  \n");
1354
        } else {
1355
                get_Send_pkt_inf_cb = send_pkt_inf_cb;
1356
        }
1357
}
1358

    
1359

    
1360
void mlRegisterSetMonitoringHeaderPktCb(set_monitoring_header_pkt_cb monitoring_header_pkt_cb ){
1361

    
1362
        if (monitoring_header_pkt_cb == NULL) {
1363
                error("ML: Register set_monitoring_header_pkt_cb: NULL ptr  \n");
1364
        } else {
1365
                set_Monitoring_header_pkt_cb = monitoring_header_pkt_cb;
1366
        }
1367
}
1368

    
1369
void mlRegisterGetRecvDataInf(get_recv_data_inf_cb recv_data_inf_cb){
1370

    
1371
        if (recv_data_inf_cb == NULL) {
1372
                error("ML: Register get_recv_data_inf_cb: NULL ptr  \n");
1373
        } else {
1374
                get_Recv_data_inf_cb = recv_data_inf_cb;
1375
        }
1376
}
1377

    
1378
void mlRegisterGetSendDataInf(get_send_data_inf_cb  send_data_inf_cb){
1379

    
1380
        if (send_data_inf_cb == NULL) {
1381
                error("ML: Register get_send_data_inf_cb: NULL ptr  \n");
1382
        } else {
1383
                get_Send_data_inf_cb = send_data_inf_cb;
1384
        }
1385
}
1386

    
1387
void mlRegisterSetMonitoringHeaderDataCb(set_monitoring_header_data_cb monitoring_header_data_cb){
1388

    
1389
        if (monitoring_header_data_cb == NULL) {
1390
                error("ML: Register set_monitoring_header_data_cb : NULL ptr  \n");
1391
        } else {
1392
                set_Monitoring_header_data_cb = monitoring_header_data_cb;
1393
        }
1394
}
1395

    
1396
void mlSetRecvTimeout(struct timeval timeout_value){
1397

    
1398
        recv_timeout = timeout_value;
1399

    
1400
}
1401

    
1402
int mlGetStandardTTL(socketID_handle socketID,uint8_t *ttl){
1403

    
1404
        return getTTL(socketfd, ttl);
1405

    
1406
}
1407

    
1408
socketID_handle mlGetLocalSocketID(int *errorstatus){
1409

    
1410
        if (NAT_traversal == false) {
1411
                *errorstatus = 2;
1412
                return NULL;
1413
        }
1414

    
1415
        *errorstatus = 0;
1416
        return &local_socketID;
1417

    
1418
}
1419

    
1420

    
1421
/**************************** END of MONL functions *************************/
1422

    
1423
/**************************** GENERAL functions *************************/
1424

    
1425
void mlRegisterRecvConnectionCb(receive_connection_cb recv_conn_cb){
1426

    
1427
        if (recv_conn_cb == NULL) {
1428
                error("ML: Register receive_connection_cb: NULL ptr  \n");
1429
        }else {
1430
                receive_Connection_cb = recv_conn_cb;
1431
        }
1432
}
1433

    
1434
void mlRegisterErrorConnectionCb(connection_failed_cb conn_failed){
1435

    
1436
        if (conn_failed == NULL) {
1437
                error("ML: Register connection_failed_cb: NULL ptr  \n");
1438
        } else {
1439
                failed_Connection_cb = conn_failed;
1440
        }
1441
}
1442

    
1443
void mlRegisterRecvDataCb(receive_data_cb data_cb,unsigned char msgtype){
1444

    
1445
    if (msgtype > 126) {
1446

    
1447
            error
1448
            ("ML: Could not register recv_data callback. Msgtype is greater then 126 \n");
1449

    
1450
    }
1451

    
1452
    if (data_cb == NULL) {
1453

    
1454
            error("ML: Register receive data callback: NUll ptr \n ");
1455

    
1456
    } else {
1457

    
1458
        recvcbbuf[msgtype] = data_cb;
1459

    
1460
    }
1461

    
1462
}
1463

    
1464
void mlCloseSocket(socketID_handle socketID){
1465

    
1466
        free(socketID);
1467

    
1468
}
1469

    
1470
void keepalive_fn(evutil_socket_t fd, short what, void *arg) {
1471
        socketID_handle peer = arg;
1472

    
1473
        int con_id = mlConnectionExist(peer, false);
1474
        if (con_id < 0 || connectbuf[con_id]->defaultSendParams.keepalive <= 0) {
1475
                /* Connection fell from under us or keepalive was disabled */
1476
                free(arg);
1477
                return;
1478
        }
1479

    
1480
        /* do what we gotta do */
1481
        if ( connectbuf[con_id]->status == READY) {
1482
                char keepaliveMsg[32] = "";
1483
                sprintf(keepaliveMsg, "KEEPALIVE %d", connectbuf[con_id]->keepalive_seq++);
1484
                send_msg(con_id, MSG_TYPE_ML_KEEPALIVE, keepaliveMsg, 1 + strlen(keepaliveMsg), false, 
1485
                        &(connectbuf[con_id]->defaultSendParams));
1486
        }
1487

    
1488
        /* re-schedule */
1489
        struct timeval t = { 0,0 };
1490
        t.tv_sec = connectbuf[con_id]->defaultSendParams.keepalive;
1491
        if (connectbuf[con_id]->defaultSendParams.keepalive) 
1492
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1493
}
1494

    
1495
void setupKeepalive(int conn_id) {
1496
        /* Save the peer's address for us */
1497
        socketID_handle peer = malloc(sizeof(socket_ID));
1498
        memcpy(peer, &connectbuf[conn_id]->external_socketID, sizeof(socket_ID));
1499

    
1500
        struct timeval t = { 0,0 };
1501
        t.tv_sec = connectbuf[conn_id]->defaultSendParams.keepalive;
1502

    
1503
        if (connectbuf[conn_id]->defaultSendParams.keepalive) 
1504
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1505
}
1506

    
1507
/* connection functions */
1508
int mlOpenConnection(socketID_handle external_socketID,receive_connection_cb connection_cb,void *arg, const send_params defaultSendParams){
1509

    
1510
        int con_id;
1511
        if (external_socketID == NULL) {
1512
                error("ML: cannot open connection: one of the socketIDs is NULL\n");
1513
                return -1;
1514
        }
1515
        if (NAT_traversal == false) {
1516
                error("ML: cannot open connection: NAT traversal for socketID still in progress\n");
1517
                return -1;
1518
        }
1519
        if (connection_cb == NULL) {
1520
                error("ML: cannot open connection: connection_cb is NULL\n");
1521
                return -1;
1522
        }
1523

    
1524
        // check if that connection already exist
1525

    
1526
        con_id = mlConnectionExist(external_socketID, false);
1527
        if (con_id >= 0) {
1528
                // overwrite defaultSendParams
1529
                bool newKeepalive = 
1530
                        connectbuf[con_id]->defaultSendParams.keepalive == 0 && defaultSendParams.keepalive != 0;
1531
                connectbuf[con_id]->defaultSendParams = defaultSendParams;
1532
                if (newKeepalive) setupKeepalive(con_id);
1533
                // if so check if it is ready to use
1534
                if (connectbuf[con_id]->status == READY) {
1535
                                // if so use the callback immediately
1536
                                (connection_cb) (con_id, arg);
1537

    
1538
                // otherwise just write the connection cb and the arg pointer
1539
                // into the connection struct
1540
                } else {
1541
                        struct receive_connection_cb_list *temp;
1542
                        temp = malloc(sizeof(struct receive_connection_cb_list));
1543
                        temp->next = NULL;
1544
                        temp->connection_cb = connection_cb;
1545
                        temp->arg = arg;
1546
                        if(connectbuf[con_id]->connection_last != NULL) {
1547
                                connectbuf[con_id]->connection_last->next = temp;
1548
                                connectbuf[con_id]->connection_last = temp;
1549
                        } else
1550
                                connectbuf[con_id]->connection_last = connectbuf[con_id]->connection_head = temp;
1551
                }
1552
                return con_id;
1553
        }
1554
        // make entry in connection_establishment array
1555
        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
1556
                if (connectbuf[con_id] == NULL) {
1557
                        connectbuf[con_id] = (connect_data *) malloc(sizeof(connect_data));
1558
                        memset(connectbuf[con_id],0,sizeof(connect_data));
1559
                        connectbuf[con_id]->starttime = time(NULL);
1560
                        memcpy(&connectbuf[con_id]->external_socketID, external_socketID, sizeof(socket_ID));
1561
                        connectbuf[con_id]->pmtusize = DSLSLIM;
1562
                        connectbuf[con_id]->timeout_event = NULL;
1563
                        connectbuf[con_id]->status = INVITE;
1564
                        connectbuf[con_id]->seqnr = 0;
1565
                        connectbuf[con_id]->internal_connect = !compare_external_address_socketIDs(external_socketID, &local_socketID);
1566
                        connectbuf[con_id]->connectionID = con_id;
1567

    
1568
                        connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
1569
                        connectbuf[con_id]->connection_last->next = NULL;
1570
                        connectbuf[con_id]->connection_last->connection_cb = connection_cb;
1571
                        connectbuf[con_id]->connection_last->arg = arg;
1572
                        connectbuf[con_id]->external_connectionID = -1;
1573

    
1574
                        connectbuf[con_id]->defaultSendParams = defaultSendParams;
1575
                        if (defaultSendParams.keepalive) setupKeepalive(con_id);
1576
                        break;
1577
                }
1578
        } //end of for
1579

    
1580
        if (con_id == CONNECTBUFSIZE) {
1581
                error("ML: Could not open connection: connection buffer full\n");
1582
                return -1;
1583
        }
1584

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

    
1589
        return con_id;
1590

    
1591
}
1592

    
1593
void mlCloseConnection(const int connectionID){
1594

    
1595
        // remove it from the connection array
1596
        if(connectbuf[connectionID]) {
1597
                if(connectbuf[connectionID]->ctrl_msg_buf) {
1598
                        free(connectbuf[connectionID]->ctrl_msg_buf);
1599
                }
1600
                // remove related events
1601
                if (connectbuf[connectionID]->timeout_event) {
1602
                        event_del(connectbuf[connectionID]->timeout_event);
1603
                        event_free(connectbuf[connectionID]->timeout_event);
1604
                        connectbuf[connectionID]->timeout_event = NULL;
1605
                }
1606
                free(connectbuf[connectionID]);
1607
                connectbuf[connectionID] = NULL;
1608
        }
1609

    
1610
}
1611

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

    
1614
        if (connectionID < 0) {
1615
                error("ML: send data failed: connectionID does not exist\n");
1616
                return;
1617
        }
1618

    
1619
        if (connectbuf[connectionID] == NULL) {
1620
                error("ML: send data failed: connectionID does not exist\n");
1621
                return;
1622
        }
1623
        if (connectbuf[connectionID]->status != READY) {
1624
            error("ML: send data failed: connection is not active\n");
1625
            return;
1626
        }
1627

    
1628
        if (sParams == NULL) {
1629
                sParams = &(connectbuf[connectionID]->defaultSendParams);
1630
        }
1631

    
1632
        send_msg(connectionID, msgtype, sendbuf, bufsize, false, sParams);
1633

    
1634
}
1635

    
1636
/* transmit data functions  */
1637
int mlSendAllData(const int connectionID,send_all_data_container *container,int nr_entries,unsigned char msgtype,send_params *sParams){
1638

    
1639
    if (nr_entries < 1 || nr_entries > 5) {
1640

    
1641
        error
1642
            ("ML : sendALlData : nr_enties is not between 1 and 5 \n ");
1643
        return 0;
1644

    
1645
    } else {
1646

    
1647
        if (nr_entries == 1) {
1648

    
1649
                mlSendData(connectionID, container->buffer_1,
1650
                      container->length_1, msgtype, sParams);
1651

    
1652
            return 1;
1653

    
1654
        } else if (nr_entries == 2) {
1655

    
1656
            int buflen = container->length_1 + container->length_2;
1657
            char buf[buflen];
1658
            memcpy(buf, container->buffer_1, container->length_1);
1659
            memcpy(&buf[container->length_1], container->buffer_2,
1660
                   container->length_2);
1661
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1662

    
1663
            return 1;
1664

    
1665
        } else if (nr_entries == 3) {
1666

    
1667
            int buflen =
1668
                container->length_1 + container->length_2 +
1669
                container->length_3;
1670
            char buf[buflen];
1671
            memcpy(buf, container->buffer_1, container->length_1);
1672
            memcpy(&buf[container->length_1], container->buffer_2,
1673
                   container->length_2);
1674
            memcpy(&buf[container->length_2], container->buffer_3,
1675
                   container->length_3);
1676
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1677

    
1678

    
1679
            return 1;
1680

    
1681
        } else if (nr_entries == 4) {
1682

    
1683
            int buflen =
1684
                container->length_1 + container->length_2 +
1685
                container->length_3 + container->length_4;
1686
            char buf[buflen];
1687
            memcpy(buf, container->buffer_1, container->length_1);
1688
            memcpy(&buf[container->length_1], container->buffer_2,
1689
                   container->length_2);
1690
            memcpy(&buf[container->length_2], container->buffer_3,
1691
                   container->length_3);
1692
            memcpy(&buf[container->length_3], container->buffer_4,
1693
                   container->length_4);
1694
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1695

    
1696
            return 1;
1697

    
1698
        } else {
1699

    
1700
            int buflen =
1701
                container->length_1 + container->length_2 +
1702
                container->length_3 + container->length_4 +
1703
                container->length_5;
1704
            char buf[buflen];
1705
            memcpy(buf, container->buffer_1, container->length_1);
1706
            memcpy(&buf[container->length_1], container->buffer_2,
1707
                   container->length_2);
1708
            memcpy(&buf[container->length_2], container->buffer_3,
1709
                   container->length_3);
1710
            memcpy(&buf[container->length_3], container->buffer_4,
1711
                   container->length_4);
1712
            memcpy(&buf[container->length_4], container->buffer_5,
1713
                   container->length_5);
1714
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1715

    
1716
            return 1;
1717
        }
1718

    
1719
    }
1720

    
1721
}
1722

    
1723
int mlRecvData(const int connectionID,char *recvbuf,int *bufsize,recv_params *rParams){
1724

    
1725
        //TODO yet to be converted
1726
        return 0;
1727
#if 0
1728
        if (rParams == NULL) {
1729
                error("ML: recv_data failed: recv_params is a NULL ptr\n");
1730
                return 0;
1731
    } else {
1732

1733
        info("ML: recv data called \n");
1734

1735
        int i = 0;
1736
        int returnValue = 0;
1737
        double timeout = (double) recv_timeout.tv_sec;
1738
        time_t endtime = time(NULL);
1739

1740
        for (i = 0; i < RECVDATABUFSIZE; i++) {
1741

1742
            if (recvdatabuf[i] != NULL) {
1743

1744
                if (recvdatabuf[i]->connectionID == connectionID) {
1745

1746
                    info("ML: recv data has entry  \n");
1747

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

1750
                    // check if the specified connection has data and it
1751
                    // is complete
1752
                    // check the data seqnr
1753
                    // if(connectionID == recvdatabuf[i]->connectionID &&
1754
                    // 1 == recvdatabuf[i]->status){
1755

1756
                    if (1 == recvdatabuf[i]->status) {
1757

1758
                        // info("transmissionHandler: recv_data set is
1759
                        // complete \n" );
1760

1761
                        // debug("debud \n");
1762

1763
                        // exchange the pointers
1764
                        int buffersize = 0;
1765
                        buffersize = recvdatabuf[i]->bufsize;
1766
                        *bufsize = buffersize;
1767
                        // recvbuf = recvdatabuf[i]->recvbuf;
1768

1769
                        // info("buffersize %d \n",buffersize);
1770
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1771
                               buffersize);
1772
                        // debug(" recvbuf %s \n",recvbuf );
1773

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

1779
//                        rParams->nrMissingFragments = nrMissingFragments;
1780
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
1781
                        rParams->msgtype = recvdatabuf[i]->msgtype;
1782
                        rParams->connectionID =
1783
                            recvdatabuf[i]->connectionID;
1784

1785
                        // break from the loop
1786
                        // debug(" recvbuf %s \n ",recvbuf);
1787

1788
                        // double nrMissFrags =
1789
                        // (double)recvdatabuf[i]->nrFragments /
1790
                        // (double)recvdatabuf[i]->recvFragments;
1791
                        // int nrMissingFragments =
1792
                        // (int)ceil(nrMissFrags);
1793

1794
                        if(get_Recv_data_inf_cb != NULL) {
1795
                                mon_data_inf recv_data_inf;
1796

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

1812
                                // send data recv callback to monitoring module
1813

1814
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1815
                        }
1816

1817

1818
                        // free the allocated memory
1819
                        free(recvdatabuf[i]);
1820
                        recvdatabuf[i] = NULL;
1821

1822
                        returnValue = 1;
1823
                        break;
1824

1825
                    }
1826

1827
                    if (recvdatabuf[i] != NULL) {
1828

1829
                        if (timepass > timeout) {
1830

1831
                            info("ML: recv_data timeout called  \n");
1832

1833
                            // some data about the missing chunks should
1834
                            // be added here
1835
                            // exchange the pointers
1836
                            int buffersize = 0;
1837
                            buffersize = recvdatabuf[i]->bufsize;
1838
                            *bufsize = buffersize;
1839
                            // recvbuf = recvdatabuf[i]->recvbuf;
1840

1841
                            double nrMissFrags =
1842
                                (double) recvdatabuf[i]->nrFragments /
1843
                                (double) recvdatabuf[i]->recvFragments;
1844
                            int nrMissingFragments =
1845
                                (int) ceil(nrMissFrags);
1846

1847
                            // debug(" recvbuf %s \n",recvbuf );
1848

1849
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1850
                                   buffersize);
1851

1852
                            rParams->nrMissingFragments =
1853
                                nrMissingFragments;
1854
                            rParams->nrFragments =
1855
                                recvdatabuf[i]->nrFragments;
1856
                            rParams->msgtype = recvdatabuf[i]->msgtype;
1857
                            rParams->connectionID =
1858
                                recvdatabuf[i]->connectionID;
1859

1860
                                if(get_Recv_data_inf_cb != NULL) {
1861
                                        mon_data_inf recv_data_inf;
1862

1863
                                        recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1864
                                        recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1865
                                        recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1866
                                        recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1867
                                        recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1868
                                        recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1869
                                        gettimeofday(&recv_data_inf.arrival_time, NULL);
1870
                                        recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1871
                                        recv_data_inf.nrMissingFragments = nrMissingFragments;
1872
                                        recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1873
                                        recv_data_inf.priority = false;
1874
                                        recv_data_inf.padding = false;
1875
                                        recv_data_inf.confirmation = false;
1876
                                        recv_data_inf.reliable = false;
1877

1878
                                        // send data recv callback to monitoring module
1879

1880
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1881
                                }
1882

1883
                            // free the allocated memory
1884
                            free(recvdatabuf[i]);
1885
                            recvdatabuf[i] = NULL;
1886

1887
                            returnValue = 1;
1888
                            break;
1889

1890
                        }
1891
                    }
1892

1893
                }
1894

1895
            }
1896
            // debug("2 recvbuf %s \n ",recvbuf);
1897
        }
1898
        return returnValue;
1899
    }
1900
#endif
1901

    
1902
}
1903

    
1904
int mlSocketIDToString(socketID_handle socketID,char* socketID_string, size_t len){
1905

    
1906
        char internal_addr[INET_ADDRSTRLEN];
1907
        char external_addr[INET_ADDRSTRLEN];
1908

    
1909
        assert(socketID);
1910

    
1911
        inet_ntop(AF_INET, &(socketID->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1912
        inet_ntop(AF_INET, &(socketID->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1913

    
1914
        snprintf(socketID_string,len,"%s:%d-%s:%d", internal_addr, ntohs(socketID->internal_addr.udpaddr.sin_port),
1915
                external_addr,        ntohs(socketID->external_addr.udpaddr.sin_port));
1916
        return 0;
1917

    
1918
}
1919

    
1920
int mlStringToSocketID(const char* socketID_string, socketID_handle socketID){
1921

    
1922
        //@TODO add checks against malformed string
1923
        char external_addr[INET_ADDRSTRLEN];
1924
        int external_port;
1925
        char internal_addr[INET_ADDRSTRLEN];
1926
        int internal_port;
1927

    
1928
        char *pch;
1929
        char *s = strdup(socketID_string);
1930

    
1931
        //replace ':' with a blank
1932
        pch=strchr(s,':');
1933
        while (pch!=NULL){
1934
                                *pch = ' ';
1935
                pch=strchr(pch+1,':');
1936
        }
1937
        pch=strchr(s,'-');
1938
        if(pch) *pch = ' ';
1939

    
1940
        sscanf(s,"%s %d %s %d", internal_addr, &internal_port,
1941
                external_addr, &external_port);
1942

    
1943
        //set structure to 0, we initialize each byte, since it will be sent on the net later
1944
        memset(socketID, 0, sizeof(struct _socket_ID));
1945

    
1946
        if(inet_pton(AF_INET, internal_addr, &(socketID->internal_addr.udpaddr.sin_addr)) == 0)
1947
                return EINVAL;
1948
        socketID->internal_addr.udpaddr.sin_family = AF_INET;
1949
        socketID->internal_addr.udpaddr.sin_port = htons(internal_port);
1950

    
1951

    
1952
        if(inet_pton(AF_INET, external_addr, &(socketID->external_addr.udpaddr.sin_addr)) ==0)
1953
                return EINVAL;
1954
        socketID->external_addr.udpaddr.sin_family = AF_INET;
1955
        socketID->external_addr.udpaddr.sin_port = htons(external_port);
1956

    
1957
        free(s);
1958
        return 0;
1959

    
1960
}
1961

    
1962
int mlGetConnectionStatus(int connectionID){
1963

    
1964
        if(connectbuf[connectionID])
1965
                return connectbuf[connectionID]->status == READY;
1966
        return -1;
1967
    
1968
}
1969

    
1970

    
1971
int mlConnectionExist(socketID_handle socketID, bool ready){
1972

    
1973
    /*
1974
     * check if another connection for the external connectionID exist
1975
     * that was established \ within the last 2 seconds
1976
     */
1977
        int i;
1978
        for (i = 0; i < CONNECTBUFSIZE; i++)
1979
                if (connectbuf[i] != NULL)
1980
                        if (mlCompareSocketIDs(&(connectbuf[i]->external_socketID), socketID) == 0) {
1981
                                if (ready) return (connectbuf[i]->status == READY ? i : -1);;
1982
                                return i;
1983
                                }
1984

    
1985
    return -1;
1986

    
1987
}
1988

    
1989
//Added by Robert Birke as comodity functions
1990

    
1991
//int mlPrintSocketID(socketID_handle socketID) {
1992
//        char str[SOCKETID_STRING_SIZE];
1993
//        mlSocketIDToString(socketID, str, sizeof(str));
1994
//        printf(stderr,"int->%s<-ext\n",str);
1995
//}
1996

    
1997
/*
1998
 * hash code of a socketID
1999
 * TODO might think of a better way
2000
 */
2001
int mlHashSocketID(socketID_handle sock) {
2002
        //assert(sock);
2003
   return sock->internal_addr.udpaddr.sin_port +
2004
                        sock->external_addr.udpaddr.sin_port;
2005
}
2006

    
2007
int mlCompareSocketIDs(socketID_handle sock1, socketID_handle sock2) {
2008

    
2009
        assert(sock1 && sock2);
2010

    
2011
        /*
2012
        * compare internal addr
2013
        */
2014
        if(sock1 == NULL || sock2 == NULL)
2015
                return 1;
2016

    
2017
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr !=
2018
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
2019
                        return 1;
2020

    
2021
        if (sock1->internal_addr.udpaddr.sin_port !=
2022
                 sock2->internal_addr.udpaddr.sin_port)
2023
                        return 1;
2024

    
2025
        /*
2026
        * compare external addr
2027
        */
2028
        if (sock1->external_addr.udpaddr.sin_addr.s_addr !=
2029
            sock2->external_addr.udpaddr.sin_addr.s_addr)
2030
                        return 1;
2031

    
2032
        if (sock1->external_addr.udpaddr.sin_port !=
2033
                 sock2->external_addr.udpaddr.sin_port)
2034
                        return 1;
2035

    
2036
        return 0;
2037
}
2038

    
2039
int mlCompareSocketIDsByPort(socketID_handle sock1, socketID_handle sock2)
2040
{
2041
        if(sock1 == NULL || sock2 == NULL)
2042
                return 1;
2043
 
2044
        if (sock1->internal_addr.udpaddr.sin_port !=
2045
                 sock2->internal_addr.udpaddr.sin_port)
2046
                        return 1;
2047

    
2048
        if (sock1->external_addr.udpaddr.sin_port !=
2049
                 sock2->external_addr.udpaddr.sin_port)
2050
                        return 1;
2051
        return 0;
2052
}
2053

    
2054
int mlGetPathMTU(int ConnectionId) {
2055
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
2056
                return -1;
2057
        if (connectbuf[ConnectionId] != NULL)
2058
                return connectbuf[ConnectionId]->pmtusize;
2059
        return -1;
2060
}
2061

    
2062
/**************************** END of GENERAL functions *************************/
2063

    
2064
/**************************** NAT functions *************************/
2065

    
2066
/* setter  */
2067
void mlSetStunServer(const int port,const char *ipaddr){
2068

    
2069
        stun_server.sin_family = AF_INET;
2070
        if (ipaddr == NULL)
2071
                stun_server.sin_addr.s_addr = htonl(INADDR_NONE);
2072
        else
2073
                stun_server.sin_addr.s_addr = resolve(ipaddr);
2074
        stun_server.sin_port = htons(port);
2075

    
2076
}
2077

    
2078
int mlGetExternalIP(char* external_addr){
2079

    
2080
        socketaddrgen udpgen;
2081
        struct sockaddr_in udpaddr;
2082

    
2083
        udpgen = local_socketID.external_addr;
2084
        udpaddr = udpgen.udpaddr;
2085

    
2086
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
2087
                        INET_ADDRSTRLEN);
2088

    
2089
        if (external_addr == NULL) {
2090

    
2091
        return -1;
2092

    
2093
        } else {
2094

    
2095
        return 0;
2096

    
2097
        }
2098

    
2099
}
2100

    
2101
/**************************** END of NAT functions *************************/