Statistics
| Branch: | Revision:

ml / ml.c @ db8c431a

History | View | Annotate | Download (60.4 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 "msg_types.h"
55
#include "util/udpSocket.h"
56
#include "util/stun.h"
57
#include "transmissionHandler.h"
58

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

    
62
/**************************** START OF INTERNALS ***********************/
63

    
64
/*
65
 * a pointer to a libevent instance
66
 */
67
struct event_base *base;
68

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

    
82

    
83
/*
84
 * timeout before thinking that the STUN server can't be connected
85
 */
86
#define NAT_TRAVERSAL_TIMEOUT { 1, 0 }
87

    
88
/*
89
 * timeout before thinking of an mtu problem (check MAX_TRIALS as well)
90
 */
91
#define PMTU_TIMEOUT { 0, 500000 }
92

    
93
/*
94
 * retry sending connection messages this many times before reducing pmtu
95
 */
96
#define MAX_TRIALS 3
97

    
98
/*
99
 * default timeout value between the first and the last received packet of a message
100
 */
101
#define RECV_TIMEOUT_DEFAULT { 2, 0 }
102

    
103
/*
104
 * global variables
105
 */
106
/*
107
 * define a buffer of pointers to connect structures
108
 */
109
connect_data *connectbuf[CONNECTBUFSIZE];
110

    
111
/*
112
 * define a pointer buffer with pointers to recv_data structures
113
 */
114
recvdata *recvdatabuf[RECVDATABUFSIZE];
115

    
116
/*
117
 * define a pointer buffer for message multiplexing
118
 */
119
receive_data_cb recvcbbuf[MSGMULTIPLEXSIZE];
120

    
121
/*
122
 * stun server address
123
 */
124
struct sockaddr_in stun_server;
125

    
126
/*
127
 * receive timeout
128
 */
129
static struct timeval recv_timeout = RECV_TIMEOUT_DEFAULT;
130

    
131
/*
132
 * boolean NAT traversal successful if true
133
 */
134
boolean NAT_traversal;
135

    
136
/*
137
 * file descriptor for local socket
138
 */
139
evutil_socket_t socketfd;
140

    
141
/*
142
 * local socketID
143
 */
144
socket_ID local_socketID;
145

    
146
socketID_handle loc_socketID = &local_socketID;
147

    
148
/*
149
 * callback function pointers
150
 */
151
/*
152
 * monitoring module callbacks
153
 */
154
get_recv_pkt_inf_cb get_Recv_pkt_inf_cb = NULL;
155
get_send_pkt_inf_cb get_Send_pkt_inf_cb = NULL;
156
set_monitoring_header_pkt_cb set_Monitoring_header_pkt_cb = NULL;
157
get_recv_data_inf_cb get_Recv_data_inf_cb = NULL;
158
get_send_data_inf_cb get_Send_data_inf_cb = NULL;
159
set_monitoring_header_data_cb set_Monitoring_header_data_cb = NULL;
160
/*
161
 * connection callbacks
162
 */
163
receive_connection_cb receive_Connection_cb = NULL;
164
connection_failed_cb failed_Connection_cb = NULL;
165
/*
166
 * local socketID callback
167
 */
168
receive_localsocketID_cb receive_SocketID_cb;
169

    
170
/*
171
 * boolean that defines if received data is transmitted to the upper layer
172
 * via callback or via upper layer polling
173
 */
174
boolean recv_data_callback;
175

    
176
/*
177
 * helper function to get rid of a warning
178
 */
179
int min(int a, int b) {
180
        if (a > b) return b;
181
        return a;
182
}
183

    
184
/*
185
 * convert a socketID to a string. It uses a static buffer, so either strdup is needed, or the string will get lost!
186
 */
187
const char *conid_to_string(int con_id)
188
{
189
        static char s[INET_ADDRSTRLEN+1+5+1+INET_ADDRSTRLEN+1+5+1];
190
        mlSocketIDToString(&connectbuf[con_id]->external_socketID, s, sizeof(s));
191
        return s;
192
}
193

    
194
void register_recv_localsocketID_cb(receive_localsocketID_cb local_socketID_cb)
195
{
196
        if (local_socketID_cb == NULL)
197
                error("ML : Register receive_localsocketID_cb: NULL ptr \n");
198
        else
199
        receive_SocketID_cb = local_socketID_cb;
200
}
201

    
202

    
203
//void keep_connection_alive(const int connectionID)
204
//{
205
//
206
//    // to be done with the NAT traversal
207
//    // send a message over the wire
208
//    printf("\n");
209
//
210
//}
211

    
212
void unsetStunServer()
213
{
214
        stun_server.sin_addr.s_addr = INADDR_NONE;
215
}
216

    
217
bool isStunDefined()
218
{
219
        return stun_server.sin_addr.s_addr != INADDR_NONE;
220
}
221

    
222
void send_msg(int con_id, int msg_type, char* msg, int msg_len, bool truncable, send_params * sParams) {
223
        socketaddrgen udpgen;
224
        bool retry;
225
        int pkt_len, offset;
226
        struct iovec iov[4];
227

    
228
        char h_pkt[MON_PKT_HEADER_SPACE];
229
        char h_data[MON_DATA_HEADER_SPACE];
230

    
231
        struct msg_header msg_h;
232

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

    
235
        iov[0].iov_base = &msg_h;
236
        iov[0].iov_len = MSG_HEADER_SIZE;
237

    
238
        msg_h.local_con_id = con_id;
239
        msg_h.remote_con_id = connectbuf[con_id]->external_connectionID;
240
        msg_h.msg_type = msg_type;
241
        msg_h.msg_seq_num = connectbuf[con_id]->seqnr++;
242

    
243

    
244
        iov[1].iov_len = iov[2].iov_len = 0;
245
        iov[1].iov_base = h_pkt;
246
        iov[2].iov_base = h_data;
247

    
248

    
249
        if (connectbuf[con_id]->internal_connect)
250
                udpgen = connectbuf[con_id]->external_socketID.internal_addr;
251
        else
252
                udpgen = connectbuf[con_id]->external_socketID.external_addr;
253

    
254
        do{
255
                offset = 0;
256
                retry = false;
257
                // Monitoring layer hook
258
                if(set_Monitoring_header_data_cb != NULL) {
259
                        iov[2].iov_len = ((set_Monitoring_header_data_cb) (&(connectbuf[con_id]->external_socketID), msg_type));
260
                }
261
                msg_h.len_mon_data_hdr = iov[2].iov_len;
262

    
263
                if(get_Send_data_inf_cb != NULL && iov[2].iov_len != 0) {
264
                        mon_data_inf sd_data_inf;
265

    
266
                        memset(h_data, 0, MON_DATA_HEADER_SPACE);
267

    
268
                        sd_data_inf.remote_socketID = &(connectbuf[con_id]->external_socketID);
269
                        sd_data_inf.buffer = msg;
270
                        sd_data_inf.bufSize = msg_len;
271
                        sd_data_inf.msgtype = msg_type;
272
                        sd_data_inf.monitoringDataHeader = iov[2].iov_base;
273
                        sd_data_inf.monitoringDataHeaderLen = iov[2].iov_len;
274
                        sd_data_inf.priority = sParams->priority;
275
                        sd_data_inf.padding = sParams->padding;
276
                        sd_data_inf.confirmation = sParams->confirmation;
277
                        sd_data_inf.reliable = sParams->reliable;
278
                        memset(&sd_data_inf.arrival_time, 0, sizeof(struct timeval));
279

    
280
                        (get_Send_data_inf_cb) ((void *) &sd_data_inf);
281
                }
282

    
283
                do {
284
                        if(set_Monitoring_header_pkt_cb != NULL) {
285
                                iov[1].iov_len = (set_Monitoring_header_pkt_cb) (&(connectbuf[con_id]->external_socketID), msg_type);
286
                        }
287
                        pkt_len = min(connectbuf[con_id]->pmtusize - iov[2].iov_len - iov[1].iov_len - iov[0].iov_len, msg_len - offset) ;
288

    
289
                        iov[3].iov_len = pkt_len;
290
                        iov[3].iov_base = msg + offset;
291

    
292
                        //fill header
293
                        msg_h.len_mon_packet_hdr = iov[1].iov_len;
294
                        msg_h.offset = offset;
295
                        msg_h.msg_length = truncable ? pkt_len : msg_len;
296

    
297
                        //monitoring layer hook
298
                        if(get_Send_pkt_inf_cb != NULL && iov[1].iov_len) {
299
                                mon_pkt_inf pkt_info;
300

    
301
                                memset(h_pkt,0,MON_PKT_HEADER_SPACE);
302

    
303
                                pkt_info.remote_socketID = &(connectbuf[con_id]->external_socketID);
304
                                pkt_info.buffer = msg + offset;
305
                                pkt_info.bufSize = pkt_len;
306
                                pkt_info.msgtype = msg_type;
307
                                pkt_info.dataID = connectbuf[con_id]->seqnr;
308
                                pkt_info.offset = offset;
309
                                pkt_info.datasize = msg_len;
310
                                pkt_info.monitoringHeaderLen = iov[1].iov_len;
311
                                pkt_info.monitoringHeader = iov[1].iov_base;
312
                                pkt_info.ttl = -1;
313
                                memset(&(pkt_info.arrival_time),0,sizeof(struct timeval));
314

    
315
                                (get_Send_pkt_inf_cb) ((void *) &pkt_info);
316
                        }
317

    
318
                        debug("ML: sending packet to %s with rconID:%d lconID:%d\n", conid_to_string(con_id), msg_h.remote_con_id, msg_h.local_con_id);
319
                        switch(sendPacket(socketfd, iov, 4, &udpgen.udpaddr)) {
320
                                case MSGLEN:
321
                                        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), msg_h.remote_con_id, msg_h.local_con_id, msg_len, offset);
322
                                        // TODO: pmtu decremented here, but not in the "truncable" packet. That is currently resent without changing the claimed pmtu. Might need to be changed.
323
                                        connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
324
                                        if (connectbuf[con_id]->pmtusize > 0) {
325
                                                connectbuf[con_id]->delay = true;
326
                                                retry = true;
327
                                        }
328
                                        offset = msg_len; // exit the while
329
                                        break;
330
                                case FAILURE:
331
                                        info("ML: sending message failed (to:%s conID:%d lconID:%d msgsize:%d offset:%d)\n", conid_to_string(con_id), msg_h.remote_con_id, msg_h.local_con_id, msg_len, offset);
332
                                        offset = msg_len; // exit the while
333
                                        break;
334
                                case OK:
335
                                        //update
336
                                        offset += pkt_len;
337
                                        //transmit data header only in the first packet
338
                                        iov[2].iov_len = 0;
339
                                        break;
340
                        }
341
                } while(offset != msg_len && !truncable);
342
        } while(retry);
343
}
344

    
345
void pmtu_timeout_cb(int fd, short event, void *arg);
346

    
347
void reschedule_conn_msg(int con_id)
348
{
349
        if (connectbuf[con_id]->timeout_event) {
350
                /* delete old timout */        
351
                event_del(connectbuf[con_id]->timeout_event);
352
                event_free(connectbuf[con_id]->timeout_event);
353
        }
354
        connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
355
        evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
356
}
357

    
358
void send_conn_msg(int con_id, int buf_size, int command_type)
359
{
360
        if (buf_size < sizeof(struct conn_msg)) {
361
                error("ML: requested connection message size is too small\n");
362
                return;
363
        }
364

    
365
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
366
                connectbuf[con_id]->ctrl_msg_buf = malloc(buf_size);
367
                memset(connectbuf[con_id]->ctrl_msg_buf, 0, buf_size);
368
        }
369

    
370
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
371
                error("ML: can not allocate memory for connection message\n");
372
                return;
373
        }
374

    
375
        struct conn_msg *msg_header = (struct conn_msg*) connectbuf[con_id]->ctrl_msg_buf;
376

    
377
        msg_header->comand_type = command_type;
378
        msg_header->pmtu_size = connectbuf[con_id]->pmtusize;
379

    
380
        memcpy(&(msg_header->sock_id), loc_socketID, sizeof(socket_ID));
381

    
382
        send_msg(con_id, ML_CON_MSG, connectbuf[con_id]->ctrl_msg_buf, buf_size, true, &(connectbuf[con_id]->defaultSendParams));
383
}
384

    
385
void send_conn_msg_with_pmtu_discovery(int con_id, int buf_size, int command_type)
386
{
387
        struct timeval tout = PMTU_TIMEOUT;
388
        connectbuf[con_id]->timeout_value = tout;
389
        connectbuf[con_id]->trials = 1;
390
        send_conn_msg(con_id, buf_size, command_type);
391
        reschedule_conn_msg(con_id);
392
}
393

    
394
void resend_conn_msg(int con_id)
395
{
396
        connectbuf[con_id]->trials++;
397
        send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
398
        reschedule_conn_msg(con_id);
399
}
400

    
401
void recv_conn_msg(struct msg_header *msg_h, char *msgbuf, int msg_size, struct sockaddr_in *recv_addr)
402
{
403
        struct conn_msg *con_msg;
404
        int free_con_id, con_id;
405

    
406
        time_t now = time(NULL);
407
        double timediff = 0.0;
408
        char sock_id_str[1000];
409
        
410
        msgbuf += msg_h->len_mon_data_hdr;
411
        msg_size -= msg_h->len_mon_data_hdr;
412
        con_msg = (struct conn_msg *)msgbuf;
413
        
414
        //verify message validity
415
        if (msg_size < sizeof(struct conn_msg)) {
416
                char recv_addr_str[INET_ADDRSTRLEN];
417
                inet_ntop(AF_INET, &(recv_addr->sin_addr.s_addr), recv_addr_str, INET_ADDRSTRLEN);
418
                info("Invalid conn_msg received from %s\n", recv_addr_str);
419
                return;
420
        }
421

    
422
        //decode sock_id for debug messages
423
        mlSocketIDToString(&con_msg->sock_id,sock_id_str,999);
424

    
425
        // Monitoring layer hook
426
        if(get_Recv_data_inf_cb != NULL) {
427
                // update pointer to the real data
428
                mon_data_inf recv_data_inf;
429
                recv_data_inf.remote_socketID = &(con_msg->sock_id);
430
                recv_data_inf.buffer = msgbuf;
431
                recv_data_inf.bufSize = msg_size;
432
                recv_data_inf.msgtype = msg_h->msg_type;
433
                recv_data_inf.monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
434
                recv_data_inf.monitoringDataHeader = msg_h->len_mon_data_hdr ? msgbuf : NULL;
435
                gettimeofday(&recv_data_inf.arrival_time, NULL);
436
                recv_data_inf.firstPacketArrived = true;
437
                recv_data_inf.recvFragments = 1;
438
                recv_data_inf.priority = false;
439
                recv_data_inf.padding = false;
440
                recv_data_inf.confirmation = false;
441
                recv_data_inf.reliable = false;
442

    
443
                // send data recv callback to monitoring module
444
                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
445
        }
446

    
447
        // check the connection command type
448
        switch (con_msg->comand_type) {
449
                /*
450
                * if INVITE: enter a new socket make new entry in connect array
451
                * send an ok
452
                */
453
                case INVITE:
454
                        info("ML: received INVITE from %s (size:%d)\n", sock_id_str, msg_size);
455
                        /*
456
                        * check if another connection for the external connectionID exist
457
                        * that was established within the last 2 seconds
458
                        */
459
                        free_con_id = -1;
460
                        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
461
                                if (connectbuf[con_id] != NULL) {
462
                                        if (mlCompareSocketIDs(&(connectbuf[con_id]->external_socketID), &(con_msg->sock_id)) == 0) {
463
                                                //timediff = difftime(now, connectbuf[con_id]->starttime);        //TODO: why this timeout? Shouldn't the connection be closed instead if there is a timeout?
464
                                                //if (timediff < 2)
465
                                                //update remote connection ID
466
                                                if (connectbuf[con_id]->external_connectionID != msg_h->local_con_id) {
467
                                                        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);
468
                                                        connectbuf[con_id]->external_connectionID = msg_h->local_con_id;
469
                                                }
470
                                                break;
471
                                        }
472
                                } else if(free_con_id == -1)
473
                                        free_con_id = con_id;
474
                        }
475

    
476
                        if (con_id == CONNECTBUFSIZE) {
477
                                // create an entry in the connecttrybuf
478
                                if(free_con_id == -1) {
479
                                        error("ML: no new connect_buf available\n");
480
                                        return;
481
                                }
482
                                connectbuf[free_con_id] = (connect_data *) malloc(sizeof(connect_data));
483
                                memset(connectbuf[free_con_id],0,sizeof(connect_data));
484
                                connectbuf[free_con_id]->connection_head = connectbuf[free_con_id]->connection_last = NULL;
485
                                connectbuf[free_con_id]->starttime = time(NULL);
486
                                memcpy(&(connectbuf[free_con_id]->external_socketID), &(con_msg->sock_id), sizeof(socket_ID));
487
                                connectbuf[free_con_id]->pmtusize = con_msg->pmtu_size;        // bootstrap pmtu from the other's size. Not strictly needed, but a good hint
488
                                connectbuf[free_con_id]->timeout_event = NULL;
489
                                connectbuf[free_con_id]->external_connectionID = msg_h->local_con_id;
490
                                connectbuf[free_con_id]->internal_connect =
491
                                        !compare_external_address_socketIDs(&(con_msg->sock_id), loc_socketID);
492
                                con_id = free_con_id;
493
                        }
494

    
495
                        //if(connectbuf[con_id]->status <= CONNECT) { //TODO: anwer anyway. Why the outher would invite otherwise?
496
                                //update status and send back answer
497
                                connectbuf[con_id]->status = CONNECT;
498
                                send_conn_msg_with_pmtu_discovery(con_id, con_msg->pmtu_size, CONNECT);
499
                        //}
500
                        break;
501
                case CONNECT:
502
                        info("ML: received CONNECT from %s (size:%d)\n", sock_id_str, msg_size);
503

    
504
                        if(msg_h->remote_con_id != -1 && connectbuf[msg_h->remote_con_id] == NULL) {
505
                                error("ML: received CONNECT for inexistent connection rconID:%d\n",msg_h->remote_con_id);
506
                                return;
507
                        }
508

    
509
                        /*
510
                        * check if the connection status is not already 1 or 2
511
                        */
512
                        if (connectbuf[msg_h->remote_con_id]->status == INVITE) {
513
                                // set the external connectionID
514
                                connectbuf[msg_h->remote_con_id]->external_connectionID = msg_h->local_con_id;
515
                                // change status con_msg the connection_data
516
                                connectbuf[msg_h->remote_con_id]->status = READY;
517
                                // change pmtusize in the connection_data: not needed. receiving a CONNECT means our INVITE went through. So why change pmtu?
518
                                //connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
519

    
520
                                // send the READY
521
                                send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
522

    
523
                                if (receive_Connection_cb != NULL)
524
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
525

    
526
                                // call all registered callbacks
527
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
528
                                        struct receive_connection_cb_list *temp;
529
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
530
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
531
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
532
                                        free(temp);
533
                                }
534
                                connectbuf[msg_h->remote_con_id]->connection_head =
535
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
536
                        } else {
537
                                // send the READY
538
                                send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
539
                        }
540

    
541
                        debug("ML: active connection established\n");
542
                        break;
543

    
544
                        /*
545
                        * if READY: find the entry in the connection array set the
546
                        * connection active change the pmtu size
547
                        */
548
                case READY:
549
                        info("ML: received READY from %s (size:%d)\n", sock_id_str, msg_size);
550
                        if(connectbuf[msg_h->remote_con_id] == NULL) {
551
                                error("ML: received READY for inexistent connection\n");
552
                                return;
553
                        }
554
                        /*
555
                        * checks if the connection is not already established
556
                        */
557
                        if (connectbuf[msg_h->remote_con_id]->status == CONNECT) {
558
                                // change status of the connection
559
                                connectbuf[msg_h->remote_con_id]->status = READY;
560
                                // change pmtusize: not needed. pmtu doesn't have to be symmetric
561
                                //connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
562

    
563
                                if (receive_Connection_cb != NULL)
564
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
565

    
566
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
567
                                        struct receive_connection_cb_list *temp;
568
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
569
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
570
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
571
                                        free(temp);
572
                                }
573
                                connectbuf[msg_h->remote_con_id]->connection_head =
574
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
575
                                debug("ML: passive connection established\n");
576
                        }
577
                        break;
578
        }
579
}
580

    
581
void recv_stun_msg(char *msgbuf, int recvSize)
582
{
583
        /*
584
        * create empty stun message struct
585
        */
586
        StunMessage resp;
587
        memset(&resp, 0, sizeof(StunMessage));
588
        /*
589
        * parse the message
590
        */
591
        int returnValue = 0;
592
        returnValue = recv_stun_message(msgbuf, recvSize, &resp);
593

    
594
        if (returnValue == 0) {
595
                /*
596
                * read the reflexive Address into the local_socketID
597
                */
598
                struct sockaddr_in reflexiveAddr = {0};
599
                reflexiveAddr.sin_family = AF_INET;
600
                reflexiveAddr.sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
601
                reflexiveAddr.sin_port = htons(resp.mappedAddress.ipv4.port);
602
                socketaddrgen reflexiveAddres = {0};
603
                reflexiveAddres.udpaddr = reflexiveAddr;
604
                local_socketID.external_addr = reflexiveAddres;
605
                NAT_traversal = true;
606
                // callback to the upper layer indicating that the socketID is now
607
                // ready to use
608
                (receive_SocketID_cb) (&local_socketID, 0);
609
        }
610
}
611

    
612
//done
613
void recv_timeout_cb(int fd, short event, void *arg)
614
{
615
        int recv_id = (long) arg;
616
        debug("ML: recv_timeout_cb called. Timeout for id:%d\n",recv_id);
617

    
618
        if (recvdatabuf[recv_id] == NULL) {
619
                return;
620
        }
621

    
622

    
623
/*        if(recvdatabuf[recv_id]->status == ACTIVE) {
624
                //TODO make timeout at least a DEFINE
625
                struct timeval timeout = { 4, 0 };
626
                recvdatabuf[recv_id]->status = INACTIVE;
627
                event_base_once(base, -1, EV_TIMEOUT, recv_timeout_cb,
628
                        arg, &timeout);
629
                return;
630
        }
631
*/
632

    
633
        if(recvdatabuf[recv_id]->status == ACTIVE) {
634
                // Monitoring layer hook
635
                if(get_Recv_data_inf_cb != NULL) {
636
                        mon_data_inf recv_data_inf;
637

    
638
                        recv_data_inf.remote_socketID =
639
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
640
                        recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
641
                        recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
642
                        recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
643
                        recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
644
                        recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
645
                                recvdatabuf[recv_id]->recvbuf : NULL;
646
                        gettimeofday(&recv_data_inf.arrival_time, NULL);
647
                        recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
648
                        recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
649
                        recv_data_inf.priority = false;
650
                        recv_data_inf.padding = false;
651
                        recv_data_inf.confirmation = false;
652
                        recv_data_inf.reliable = false;
653

    
654
                        // send data recv callback to monitoring module
655

    
656
                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
657
                }
658

    
659
                // Get the right callback
660
                receive_data_cb receive_data_callback = recvcbbuf[recvdatabuf[recv_id]->msgtype];
661

    
662
                recv_params rParams;
663

    
664
                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
665
                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
666
                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
667
                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
668
                rParams.remote_socketID =
669
                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
670
                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
671

    
672
                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
673
                        recvdatabuf[recv_id]->msgtype, &rParams);
674

    
675
                //clean up
676
                if (recvdatabuf[recv_id]->timeout_event) {
677
                        event_del(recvdatabuf[recv_id]->timeout_event);
678
                        event_free(recvdatabuf[recv_id]->timeout_event);
679
                        recvdatabuf[recv_id]->timeout_event = NULL;
680
                }
681
                free(recvdatabuf[recv_id]->recvbuf);
682
                free(recvdatabuf[recv_id]);
683
                recvdatabuf[recv_id] = NULL;
684
        }
685
}
686

    
687
// process a single recv data message
688
void recv_data_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
689
{
690
        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);
691

    
692
        int recv_id, free_recv_id = -1;
693

    
694
        if(connectbuf[msg_h->remote_con_id] == NULL) {
695
                debug("ML: Received a message not related to any opened connection!\n");
696
                return;
697
        }
698

    
699
        // check if a recv_data exist and enter data
700
        for (recv_id = 0; recv_id < RECVDATABUFSIZE; recv_id++)
701
                if (recvdatabuf[recv_id] != NULL) {
702
                        if (msg_h->remote_con_id == recvdatabuf[recv_id]->connectionID &&
703
                                        msg_h->msg_seq_num == recvdatabuf[recv_id]->seqnr)
704
                                                break;
705
                } else
706
                        if(free_recv_id == -1)
707
                                free_recv_id = recv_id;
708

    
709

    
710
        if(recv_id == RECVDATABUFSIZE) {
711
                //no recv_data found: create one
712
                recv_id = free_recv_id;
713
                recvdatabuf[recv_id] = (recvdata *) malloc(sizeof(recvdata));
714
                memset(recvdatabuf[recv_id], 0, sizeof(recvdata));
715
                recvdatabuf[recv_id]->connectionID = msg_h->remote_con_id;
716
                recvdatabuf[recv_id]->seqnr = msg_h->msg_seq_num;
717
                recvdatabuf[recv_id]->monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
718
                recvdatabuf[recv_id]->bufsize = msg_h->msg_length + msg_h->len_mon_data_hdr;
719
                recvdatabuf[recv_id]->recvbuf = (char *) malloc(recvdatabuf[recv_id]->bufsize);
720
                recvdatabuf[recv_id]->arrivedBytes = 0;        //count this without the Mon headers
721
                /*
722
                * read the timeout data and set it
723
                */
724
                recvdatabuf[recv_id]->timeout_value = recv_timeout;
725
                recvdatabuf[recv_id]->timeout_event = NULL;
726
                recvdatabuf[recv_id]->recvID = recv_id;
727
                recvdatabuf[recv_id]->starttime = time(NULL);
728
                recvdatabuf[recv_id]->msgtype = msg_h->msg_type;
729

    
730
                // fill the buffer with zeros
731
                memset(recvdatabuf[recv_id]->recvbuf, 0, recvdatabuf[recv_id]->bufsize);
732
                debug(" new @ id:%d\n",recv_id);
733
        } else {        //message structure already exists, no need to create new
734
                debug(" found @ id:%d (arrived before this packet: bytes:%d fragments%d\n",recv_id, recvdatabuf[recv_id]->arrivedBytes, recvdatabuf[recv_id]->recvFragments);
735
        }
736

    
737
        //if first packet extract mon data header and advance pointer
738
        if (msg_h->offset == 0) {
739
                memcpy(recvdatabuf[recv_id]->recvbuf, msgbuf, msg_h->len_mon_data_hdr);
740
                msgbuf += msg_h->len_mon_data_hdr;
741
                bufsize -= msg_h->len_mon_data_hdr;
742
                recvdatabuf[recv_id]->firstPacketArrived = 1;
743
        }
744

    
745

    
746
        // increment fragmentnr
747
        recvdatabuf[recv_id]->recvFragments++;
748
        // increment the arrivedBytes
749
        recvdatabuf[recv_id]->arrivedBytes += bufsize;
750

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

    
754
        //TODO very basic checkif all fragments arrived: has to be reviewed
755
        if(recvdatabuf[recv_id]->arrivedBytes == recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen)
756
                recvdatabuf[recv_id]->status = COMPLETE; //buffer full -> msg completly arrived
757
        else
758
                recvdatabuf[recv_id]->status = ACTIVE;
759

    
760
        if (recv_data_callback) {
761
                if(recvdatabuf[recv_id]->status == COMPLETE) {
762
                        // Monitoring layer hook
763
                        if(get_Recv_data_inf_cb != NULL) {
764
                                mon_data_inf recv_data_inf;
765

    
766
                                recv_data_inf.remote_socketID =
767
                                         &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
768
                                recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
769
                                recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
770
                                recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
771
                                recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
772
                                recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
773
                                        recvdatabuf[recv_id]->recvbuf : NULL;
774
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
775
                                recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
776
                                recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
777
                                recv_data_inf.priority = false;
778
                                recv_data_inf.padding = false;
779
                                recv_data_inf.confirmation = false;
780
                                recv_data_inf.reliable = false;
781

    
782
                                // send data recv callback to monitoring module
783

    
784
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
785
                        }
786

    
787
                        // Get the right callback
788
                        receive_data_cb receive_data_callback = recvcbbuf[msg_h->msg_type];
789
                        if (receive_data_callback) {
790

    
791
                                recv_params rParams;
792

    
793
                                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen - recvdatabuf[recv_id]->arrivedBytes;
794
                                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
795
                                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
796
                                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
797
                                rParams.remote_socketID =
798
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
799

    
800
                                char str[1000];
801
                                mlSocketIDToString(rParams.remote_socketID,str,999);
802
                                debug("ML: received message from conID:%d, %s\n",recvdatabuf[recv_id]->connectionID,str);
803
                                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
804

    
805
                                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
806
                                        recvdatabuf[recv_id]->msgtype, (void *) &rParams);
807
                        } else {
808
                            warn("ML: callback not initialized for this message type: %d!\n",msg_h->msg_type);
809
                        }
810

    
811
                        //clean up
812
                        if (recvdatabuf[recv_id]->timeout_event) {
813
                                debug("ML: freeing timeout for %d",recv_id);
814
                                event_del(recvdatabuf[recv_id]->timeout_event);
815
                                event_free(recvdatabuf[recv_id]->timeout_event);
816
                                recvdatabuf[recv_id]->timeout_event = NULL;
817
                        } else {
818
                                debug("ML: received in 1 packet\n",recv_id);
819
                        }
820
                        free(recvdatabuf[recv_id]->recvbuf);
821
                        free(recvdatabuf[recv_id]);
822
                        recvdatabuf[recv_id] = NULL;
823
                } else { // not COMPLETE
824
                        if (!recvdatabuf[recv_id]->timeout_event) {
825
                                //start time out
826
                                //TODO make timeout at least a DEFINE
827
                                recvdatabuf[recv_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &recv_timeout_cb, (void *) (long)recv_id);
828
                                evtimer_add(recvdatabuf[recv_id]->timeout_event, &recv_timeout);
829
                        }
830
                }
831
        }
832
}
833

    
834
//done
835
void pmtu_timeout_cb(int fd, short event, void *arg)
836
{
837

    
838
        int con_id = (long) arg;
839
        pmtu new_pmtusize;
840

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

    
843
        if(connectbuf[con_id] == NULL) {
844
                error("ML: pmtu timeout called on non existing con_id\n");
845
                return;
846
        }
847

    
848
        if(connectbuf[con_id]->status == READY) {
849
                // nothing to do anymore
850
                event_del(connectbuf[con_id]->timeout_event);
851
                event_free(connectbuf[con_id]->timeout_event);
852
                connectbuf[con_id]->timeout_event = NULL;
853
                return;
854
        }
855

    
856
        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);
857

    
858
        if(connectbuf[con_id]->delay || connectbuf[con_id]->trials == MAX_TRIALS - 1) {
859
                double delay = connectbuf[con_id]->timeout_value.tv_sec + connectbuf[con_id]->timeout_value.tv_usec / 1000000.0;
860
                delay = delay * 2;
861
                info("\tML: increasing pmtu timeout to %f sec\n", delay);
862
                connectbuf[con_id]->timeout_value.tv_sec = floor(delay);
863
                connectbuf[con_id]->timeout_value.tv_usec = fmod(delay, 1.0) * 1000000.0;
864
                if(connectbuf[con_id]->delay) {
865
                        connectbuf[con_id]->delay = false;
866
                        reschedule_conn_msg(con_id);
867
                }
868
        }
869

    
870
        if(connectbuf[con_id]->trials == MAX_TRIALS) {
871
                // decrement the pmtu size
872
                struct timeval tout = PMTU_TIMEOUT;
873
                info("\tML: decreasing pmtu estimate from %d to %d\n", connectbuf[con_id]->pmtusize, pmtu_decrement(connectbuf[con_id]->pmtusize));
874
                connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
875
                connectbuf[con_id]->timeout_value = tout; 
876
                connectbuf[con_id]->trials = 0;
877
        }
878

    
879
        //error in PMTU discovery?
880
        if (connectbuf[con_id]->pmtusize == ERROR) {
881
                if (connectbuf[con_id]->internal_connect == true) {
882
                        //as of now we tried directly connecting, now let's try trough the NAT
883
                        connectbuf[con_id]->internal_connect = false;
884
                        connectbuf[con_id]->pmtusize = MAX;
885
                } else {
886
                        //nothing to do we have to give up
887
                        error("ML: Could not create connection with connectionID %i!\n",con_id);
888
                        // envoke the callback for failed connection establishment
889
                        if(failed_Connection_cb != NULL)
890
                                (failed_Connection_cb) (con_id, NULL);
891
                        // delete the connection entry
892
                        mlCloseConnection(con_id);
893
                        return;
894
                }
895
        }
896

    
897
        //retry
898
        resend_conn_msg(con_id);
899
}
900

    
901

    
902
int schedule_pmtu_timeout(int con_id)
903
{
904
        if (! connectbuf[con_id]->timeout_event) {
905
                struct timeval tout = PMTU_TIMEOUT;
906
                connectbuf[con_id]->timeout_value = tout;
907
                connectbuf[con_id]->trials = 1;
908
                connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
909
                evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
910
        }
911
}
912

    
913
/*
914
 * decrements the mtu size
915
 */
916
pmtu pmtu_decrement(pmtu pmtusize)
917
{
918
        pmtu pmtu_return_size;
919
        switch(pmtusize) {
920
        case MAX:
921
                return DSL;
922
        case DSL:
923
                return DSLMEDIUM;
924
        case DSLMEDIUM:
925
                return DSLSLIM;
926
        case DSLSLIM:
927
                return BELOWDSL;
928
        case BELOWDSL:
929
                return MIN;
930
        case MIN:
931
                return ERROR;
932
        default:
933
                warn("ML: strange pmtu size encountered:%d, changing to some safe value:%d\n", pmtusize, MIN);
934
                return MIN;
935
        }
936
}
937

    
938
// called when an ICMP pmtu error message (type 3, code 4) is received
939
void pmtu_error_cb_th(char *msg, int msglen)
940
{
941
        debug("ML: pmtu_error callback called msg_size: %d\n",msglen);
942
        //TODO debug
943
        return;
944

    
945
    char *msgbufptr = NULL;
946
    int msgtype;
947
    int connectionID;
948
    pmtu pmtusize;
949
    pmtu new_pmtusize;
950
    int dead = 0;
951

    
952
    // check the packettype
953
    msgbufptr = &msg[0];
954

    
955
    // check the msgtype
956
    msgbufptr = &msg[1];
957
    memcpy(&msgtype, msgbufptr, 4);
958

    
959
    if (msgtype == 0) {
960

    
961
        // get the connectionID
962
        msgbufptr = &msg[5];
963
        memcpy(&connectionID, msgbufptr, 4);
964

    
965
        int msgtype_c = connectbuf[connectionID]->status;
966
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
967

    
968
        if (msgtype_c != msgtype) {
969
            dead = 1;
970
        }
971

    
972

    
973
    } else if (msgtype == 1) {
974

    
975
        // read the connectionID
976
        msgbufptr = &msg[9];
977
        memcpy(&connectionID, msgbufptr, 4);
978

    
979
        int msgtype_c = connectbuf[connectionID]->status;
980
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
981

    
982
        if (msgtype_c != msgtype) {
983
            dead = 1;
984
        }
985

    
986
    }
987
    // decrement the pmtu size
988
    new_pmtusize = pmtu_decrement(pmtusize);
989

    
990
//    connectbuf[connectionID]->pmtutrysize = new_pmtusize;
991

    
992
    if (new_pmtusize == ERROR) {
993
                error("ML:  Could not create connection with connectionID %i !\n",
994
                        connectionID);
995

    
996
                if(failed_Connection_cb != NULL)
997
                        (failed_Connection_cb) (connectionID, NULL);
998
                // set the message type to a non existent message
999
                msgtype = 2;
1000
                // delete the connection entry
1001
                 mlCloseConnection(connectionID);
1002
        }
1003

    
1004
    if (msgtype == 0 && dead != 1) {
1005

    
1006
        // stop the timeout event
1007
        // timeout_del(connectbuf[connectionID]->timeout);
1008
        /*
1009
         * libevent2
1010
         */
1011

    
1012
        // event_del(connectbuf[connectionID]->timeout);
1013

    
1014

    
1015
        // create and send a connection message
1016
//         create_conn_msg(new_pmtusize, connectionID,
1017
//                         &local_socketID, INVITE);
1018

    
1019
//        send_conn_msg(connectionID, new_pmtusize);
1020

    
1021
        // set a timeout event for the pmtu discovery
1022
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
1023
        // *)&connectionID);
1024

    
1025
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1026

    
1027
        /*
1028
         * libevent2
1029
         */
1030

    
1031
        struct event *ev;
1032
        ev = evtimer_new(base, pmtu_timeout_cb,
1033
                         (void *) connectbuf[connectionID]);
1034

    
1035
        // connectbuf[connectionID]->timeout = ev;
1036

    
1037
        event_add(ev, &connectbuf[connectionID]->timeout_value);
1038

    
1039
    } else if (msgtype == 1 && dead != 1) {
1040

    
1041
        // stop the timeout event
1042
        // timeout_del(connectbuf[connectionID]->timeout);
1043

    
1044
        /*
1045
         * libevent2
1046
         */
1047
        // info("still here 11 \n");
1048
        // printf("ev %d \n",connectbuf[connectionID]->timeout);
1049
        // event_del(connectbuf[connectionID]->timeout );
1050
        // evtimer_del(connectbuf[connectionID]->timeout );
1051

    
1052

    
1053
//         // create and send a connection message
1054
//         create_conn_msg(new_pmtusize,
1055
//                         connectbuf[connectionID]->connectionID,
1056
//                         NULL, CONNECT);
1057

    
1058
        //send_conn_msg(connectionID, new_pmtusize);
1059

    
1060
        // set a timeout event for the pmtu discovery
1061
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
1062
        // *)&connectionID);
1063
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1064

    
1065
        /*
1066
         * libevent2
1067
         */
1068
        // struct event *ev;
1069
        // ev = evtimer_new(base,pmtu_timeout_cb, (void
1070
        // *)connectbuf[connectionID]);
1071
        // connectbuf[connectionID]->timeout = ev;
1072
        // event_add(ev,&connectbuf[connectionID]->timeout_value);
1073

    
1074
    }
1075
}
1076

    
1077
/*
1078
 * what to do once a packet arrived if it is a conn packet send it to
1079
 * recv_conn handler if it is a data packet send it to the recv_data
1080
 * handler
1081
 */
1082

    
1083
//done --
1084
void recv_pkg(int fd, short event, void *arg)
1085
{
1086
        debug("ML: recv_pkg called\n");
1087

    
1088
        struct msg_header *msg_h;
1089
        char msgbuf[MAX];
1090
        pmtu recvSize = MAX;
1091
        char *bufptr = msgbuf;
1092
        int ttl;
1093
        struct sockaddr_in recv_addr;
1094
        int msg_size;
1095

    
1096
        recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
1097

    
1098

    
1099
        // check if it is not just an ERROR message
1100
        if(recvSize < 0)
1101
                return;
1102

    
1103
        // @TODO check if this simplistic STUN message recognition really always works, probably not
1104
        unsigned short stun_bind_response = 0x0101;
1105
        unsigned short * msgspot = (unsigned short *) msgbuf;
1106
        if (*msgspot == stun_bind_response) {
1107
                debug("ML: recv_pkg: parse stun message called\n");
1108
                recv_stun_msg(msgbuf, recvSize);
1109
                return;
1110
        }
1111

    
1112
        msg_h = (struct msg_header *) msgbuf;
1113

    
1114
        //verify minimum size
1115
        if (recvSize < sizeof(struct msg_header)) {
1116
          info("UDP packet too small, can't be an ML packet");
1117
          return;
1118
        }
1119

    
1120
        //TODO add more verifications
1121

    
1122
        bufptr += MSG_HEADER_SIZE + msg_h->len_mon_packet_hdr;
1123
        msg_size = recvSize - MSG_HEADER_SIZE - msg_h->len_mon_packet_hdr;
1124

    
1125
        //verify more fields
1126
        if (msg_size < 0) {
1127
          info("Corrupted UDP packet received");
1128
          return;
1129
        }
1130

    
1131
        if(get_Recv_pkt_inf_cb != NULL) {
1132
                mon_pkt_inf msginfNow;
1133
                msginfNow.monitoringHeaderLen = msg_h->len_mon_packet_hdr;
1134
                msginfNow.monitoringHeader = msg_h->len_mon_packet_hdr ? &msgbuf[0] + MSG_HEADER_SIZE : NULL;
1135
                //TODO rethink this ...
1136
                if(msg_h->msg_type == ML_CON_MSG) {
1137
                        struct conn_msg *c_msg = (struct conn_msg *) bufptr;
1138
                        msginfNow.remote_socketID = &(c_msg->sock_id);
1139
                }
1140
                else if(connectbuf[msg_h->remote_con_id] == NULL) {
1141
                        error("ML: received pkg called with non existent connection\n");
1142
                        return;
1143
                } else
1144
                        msginfNow.remote_socketID = &(connectbuf[msg_h->remote_con_id]->external_socketID);
1145
                msginfNow.buffer = bufptr;
1146
                msginfNow.bufSize = recvSize;
1147
                msginfNow.msgtype = msg_h->msg_type;
1148
                msginfNow.ttl = ttl;
1149
                msginfNow.dataID = msg_h->msg_seq_num;
1150
                msginfNow.offset = msg_h->offset;
1151
                msginfNow.datasize = msg_h->msg_length;
1152
                gettimeofday(&msginfNow.arrival_time, NULL);
1153
                (get_Recv_pkt_inf_cb) ((void *) &msginfNow);
1154
        }
1155

    
1156

    
1157
        switch(msg_h->msg_type) {
1158
                case ML_CON_MSG:
1159
                        debug("ML: received conn pkg\n");
1160
                        recv_conn_msg(msg_h, bufptr, msg_size, &recv_addr);
1161
                        break;
1162
                default:
1163
                        if(msg_h->msg_type < 127) {
1164
                                debug("ML: received data pkg\n");
1165
                                recv_data_msg(msg_h, bufptr, msg_size);
1166
                                break;
1167
                        }
1168
                        debug("ML: unrecognised msg_type\n");
1169
                        break;
1170
        }
1171
}
1172

    
1173
/*
1174
 * compare the external IP address of two socketIDs
1175
 */
1176
int
1177
compare_external_address_socketIDs(socketID_handle sock1, socketID_handle sock2)
1178
{
1179
        if( sock1->external_addr.udpaddr.sin_addr.s_addr == sock2->external_addr.udpaddr.sin_addr.s_addr)
1180
                return 0;
1181
        return 1;
1182
}
1183

    
1184
void try_stun();
1185

    
1186
/*
1187
 * the timeout of the NAT traversal
1188
 */
1189
void nat_traversal_timeout(int fd, short event, void *arg)
1190
{
1191
        if (NAT_traversal == false) {
1192
                debug("ML: NAT traversal request re-send\n");
1193
                if(receive_SocketID_cb)
1194
                        (receive_SocketID_cb) (&local_socketID, 2);
1195
                try_stun();
1196
        }
1197
}
1198

    
1199
//return IP address, or INADDR_NONE if can't resolve
1200
unsigned long resolve(const char *ipaddr)
1201
{
1202
        struct hostent *h = gethostbyname(ipaddr);
1203
        if (!h) {
1204
                error("ML: Unable to resolve host name %s\n", ipaddr);
1205
                return INADDR_NONE;
1206
        }
1207
        unsigned long *addr = (unsigned long *) (h->h_addr);
1208
        return *addr;
1209
}
1210

    
1211

    
1212
/*
1213
 * returns the file descriptor, or <0 on error. The ipaddr can be a null
1214
 * pointer. Then all available ipaddr on the machine are choosen.
1215
 */
1216
int create_socket(const int port, const char *ipaddr)
1217
{
1218
        struct sockaddr_in udpaddr = {0};
1219
        udpaddr.sin_family = AF_INET;
1220
        if (ipaddr == NULL) {
1221
                /*
1222
                * try to guess the local IP address
1223
                */
1224
                const char *ipaddr_iface = mlAutodetectIPAddress();
1225
                if (ipaddr_iface) {
1226
                        udpaddr.sin_addr.s_addr = inet_addr(ipaddr_iface);
1227
                } else {
1228
                        udpaddr.sin_addr.s_addr = INADDR_ANY;
1229
                }
1230
        } else {
1231
                udpaddr.sin_addr.s_addr = inet_addr(ipaddr);
1232
        }
1233
        udpaddr.sin_port = htons(port);
1234

    
1235
        socketaddrgen udpgen;
1236
        memset(&udpgen,0,sizeof(socketaddrgen));        //this will be sent over the net, so set it to 0
1237
        udpgen.udpaddr = udpaddr;
1238
        local_socketID.internal_addr = udpgen;
1239

    
1240
        socketfd = createSocket(port, ipaddr);
1241
        if (socketfd < 0){
1242
                return socketfd;
1243
        }
1244

    
1245
        struct event *ev;
1246
        ev = event_new(base, socketfd, EV_READ | EV_PERSIST, recv_pkg, NULL);
1247

    
1248
        event_add(ev, NULL);
1249

    
1250
        try_stun();
1251

    
1252
        return socketfd;
1253
}
1254

    
1255
/*
1256
 * try to figure out external IP using STUN, if defined
1257
 */
1258
void try_stun()
1259
{
1260
        if (isStunDefined()) {
1261
                /*
1262
                * send the NAT traversal STUN request
1263
                */
1264
                 send_stun_request(socketfd, &stun_server);
1265

    
1266
                /*
1267
                * enter a NAT traversal timeout that takes care of retransmission
1268
                */
1269
                struct event *ev1;
1270
                struct timeval timeout_value_NAT_traversal = NAT_TRAVERSAL_TIMEOUT;
1271
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1272
                event_add(ev1, &timeout_value_NAT_traversal);
1273

    
1274
                NAT_traversal = false;
1275
        } else {
1276
                /*
1277
                * Assume we have accessibility and copy internal address to external one
1278
                */
1279
                local_socketID.external_addr = local_socketID.internal_addr;
1280
                NAT_traversal = true; // @TODO: this is not really NAT traversal, but a flag that init is over
1281
                // callback to the upper layer indicating that the socketID is now
1282
                // ready to use
1283
                if(receive_SocketID_cb)
1284
                        (receive_SocketID_cb) (&local_socketID, 0); //success
1285
        }
1286
}
1287

    
1288
/**************************** END OF INTERNAL ***********************/
1289

    
1290
/**************************** MONL functions *************************/
1291

    
1292
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){
1293

    
1294
        base = (struct event_base *) arg;
1295
        recv_data_callback = recv_data_cb;
1296
        mlSetRecvTimeout(timeout_value);
1297
        if (stun_ipaddr) {
1298
                 mlSetStunServer(stun_port, stun_ipaddr);
1299
        } else {
1300

    
1301
        }
1302
        register_recv_localsocketID_cb(local_socketID_cb);
1303
        return create_socket(port, ipaddr);
1304
}
1305

    
1306
/* register callbacks  */
1307
void mlRegisterGetRecvPktInf(get_recv_pkt_inf_cb recv_pkt_inf_cb){
1308

    
1309
        if (recv_pkt_inf_cb == NULL)
1310
                error("ML: Register get_recv_pkt_inf_cb failed: NULL ptr  \n");
1311
        else
1312
                get_Recv_pkt_inf_cb = recv_pkt_inf_cb;
1313

    
1314
}
1315

    
1316
void mlRegisterGetSendPktInf(get_send_pkt_inf_cb  send_pkt_inf_cb){
1317

    
1318
        if (send_pkt_inf_cb == NULL)
1319
                error("ML: Register get_send_pkt_inf_cb: NULL ptr  \n");
1320
        else
1321
                get_Send_pkt_inf_cb = send_pkt_inf_cb;
1322

    
1323
}
1324

    
1325

    
1326
void mlRegisterSetMonitoringHeaderPktCb(set_monitoring_header_pkt_cb monitoring_header_pkt_cb ){
1327

    
1328
        if (monitoring_header_pkt_cb == NULL)
1329
                error("ML: Register set_monitoring_header_pkt_cb: NULL ptr  \n");
1330
        else
1331
                set_Monitoring_header_pkt_cb = monitoring_header_pkt_cb;
1332

    
1333
}
1334

    
1335
void mlRegisterGetRecvDataInf(get_recv_data_inf_cb recv_data_inf_cb){
1336

    
1337
        if (recv_data_inf_cb == NULL)
1338
                error("ML: Register get_recv_data_inf_cb: NULL ptr  \n");
1339
        else
1340
                get_Recv_data_inf_cb = recv_data_inf_cb;
1341

    
1342
}
1343

    
1344
void mlRegisterGetSendDataInf(get_send_data_inf_cb  send_data_inf_cb){
1345

    
1346
        if (send_data_inf_cb == NULL)
1347
                error("ML: Register get_send_data_inf_cb: NULL ptr  \n");
1348
        else
1349
                get_Send_data_inf_cb = send_data_inf_cb;
1350

    
1351
}
1352

    
1353
void mlRegisterSetMonitoringHeaderDataCb(set_monitoring_header_data_cb monitoring_header_data_cb){
1354

    
1355
        if (monitoring_header_data_cb == NULL)
1356
                error("ML: Register set_monitoring_header_data_cb : NULL ptr  \n");
1357
        else
1358
        set_Monitoring_header_data_cb = monitoring_header_data_cb;
1359

    
1360
}
1361

    
1362
void mlSetRecvTimeout(struct timeval timeout_value){
1363

    
1364
        recv_timeout = timeout_value;
1365

    
1366
}
1367

    
1368
int mlGetStandardTTL(socketID_handle socketID,uint8_t *ttl){
1369

    
1370
        return getTTL(socketfd, ttl);
1371

    
1372
}
1373

    
1374
socketID_handle mlGetLocalSocketID(int *errorstatus){
1375

    
1376
        if (NAT_traversal == false) {
1377
                *errorstatus = 2;
1378
                return NULL;
1379
        }
1380

    
1381
        *errorstatus = 0;
1382
        return &local_socketID;
1383

    
1384
}
1385

    
1386

    
1387
/**************************** END of MONL functions *************************/
1388

    
1389
/**************************** GENERAL functions *************************/
1390

    
1391
void mlRegisterRecvConnectionCb(receive_connection_cb recv_conn_cb){
1392

    
1393
        if (recv_conn_cb == NULL)
1394
                error("ML: Register receive_connection_cb: NULL ptr  \n");
1395
        else
1396
                receive_Connection_cb = recv_conn_cb;
1397

    
1398
}
1399

    
1400
void mlRegisterErrorConnectionCb(connection_failed_cb conn_failed){
1401

    
1402
        if (conn_failed == NULL)
1403
                error("ML: Register connection_failed_cb: NULL ptr  \n");
1404
        else
1405
        failed_Connection_cb = conn_failed;
1406

    
1407
}
1408

    
1409
void mlRegisterRecvDataCb(receive_data_cb data_cb,unsigned char msgtype){
1410

    
1411
    if (msgtype > 126) {
1412

    
1413
            error
1414
            ("ML: Could not register recv_data callback. Msgtype is greater then 126 \n");
1415

    
1416
    }
1417

    
1418
    if (data_cb == NULL) {
1419

    
1420
            error("ML: Register receive data callback: NUll ptr \n ");
1421

    
1422
    } else {
1423

    
1424
        recvcbbuf[msgtype] = data_cb;
1425

    
1426
    }
1427

    
1428
}
1429

    
1430
void mlCloseSocket(socketID_handle socketID){
1431

    
1432
        free(socketID);
1433

    
1434
}
1435

    
1436
void keepalive_fn(evutil_socket_t fd, short what, void *arg) {
1437
        socketID_handle peer = arg;
1438

    
1439
        int con_id = mlConnectionExist(peer, false);
1440
        if (con_id < 0 || connectbuf[con_id]->defaultSendParams.keepalive <= 0) {
1441
                /* Connection fell from under us or keepalive was disabled */
1442
                free(arg);
1443
                return;
1444
        }
1445

    
1446
        /* do what we gotta do */
1447
        if ( connectbuf[con_id]->status == READY) {
1448
                char keepaliveMsg[32] = "";
1449
                sprintf(keepaliveMsg, "KEEPALIVE %d", connectbuf[con_id]->keepalive_seq++);
1450
                send_msg(con_id, MSG_TYPE_ML_KEEPALIVE, keepaliveMsg, 1 + strlen(keepaliveMsg), false, 
1451
                        &(connectbuf[con_id]->defaultSendParams));
1452
        }
1453

    
1454
        /* re-schedule */
1455
        struct timeval t = { 0,0 };
1456
        t.tv_sec = connectbuf[con_id]->defaultSendParams.keepalive;
1457
        if (connectbuf[con_id]->defaultSendParams.keepalive) 
1458
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1459
}
1460

    
1461
void setupKeepalive(int conn_id) {
1462
        /* Save the peer's address for us */
1463
        socketID_handle peer = malloc(sizeof(socket_ID));
1464
        memcpy(peer, &connectbuf[conn_id]->external_socketID, sizeof(socket_ID));
1465

    
1466
        struct timeval t = { 0,0 };
1467
        t.tv_sec = connectbuf[conn_id]->defaultSendParams.keepalive;
1468

    
1469
        if (connectbuf[conn_id]->defaultSendParams.keepalive) 
1470
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1471
}
1472

    
1473
/* connection functions */
1474
int mlOpenConnection(socketID_handle external_socketID,receive_connection_cb connection_cb,void *arg, const send_params defaultSendParams){
1475

    
1476
        int con_id;
1477
        if (external_socketID == NULL) {
1478
                error("ML: cannot open connection: one of the socketIDs is NULL\n");
1479
                return -1;
1480
        }
1481
        if (NAT_traversal == false) {
1482
                error("ML: cannot open connection: NAT traversal for socketID still in progress\n");
1483
                return -1;
1484
        }
1485
        if (connection_cb == NULL) {
1486
                error("ML: cannot open connection: connection_cb is NULL\n");
1487
                return -1;
1488
        }
1489

    
1490
        // check if that connection already exist
1491

    
1492
        con_id = mlConnectionExist(external_socketID, false);
1493
        if (con_id >= 0) {
1494
                // overwrite defaultSendParams
1495
                bool newKeepalive = 
1496
                        connectbuf[con_id]->defaultSendParams.keepalive == 0 && defaultSendParams.keepalive != 0;
1497
                connectbuf[con_id]->defaultSendParams = defaultSendParams;
1498
                if (newKeepalive) setupKeepalive(con_id);
1499
                // if so check if it is ready to use
1500
                if (connectbuf[con_id]->status == READY) {
1501
                                // if so use the callback immediately
1502
                                (connection_cb) (con_id, arg);
1503

    
1504
                // otherwise just write the connection cb and the arg pointer
1505
                // into the connection struct
1506
                } else {
1507
                        struct receive_connection_cb_list *temp;
1508
                        temp = malloc(sizeof(struct receive_connection_cb_list));
1509
                        temp->next = NULL;
1510
                        temp->connection_cb = connection_cb;
1511
                        temp->arg = arg;
1512
                        if(connectbuf[con_id]->connection_last != NULL) {
1513
                                connectbuf[con_id]->connection_last->next = temp;
1514
                                connectbuf[con_id]->connection_last = temp;
1515
                        } else
1516
                                connectbuf[con_id]->connection_last = connectbuf[con_id]->connection_head = temp;
1517
                }
1518
                return con_id;
1519
        }
1520
        // make entry in connection_establishment array
1521
        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
1522
                if (connectbuf[con_id] == NULL) {
1523
                        connectbuf[con_id] = (connect_data *) malloc(sizeof(connect_data));
1524
                        memset(connectbuf[con_id],0,sizeof(connect_data));
1525
                        connectbuf[con_id]->starttime = time(NULL);
1526
                        memcpy(&connectbuf[con_id]->external_socketID, external_socketID, sizeof(socket_ID));
1527
                        connectbuf[con_id]->pmtusize = DSLSLIM;
1528
                        connectbuf[con_id]->timeout_event = NULL;
1529
                        connectbuf[con_id]->status = INVITE;
1530
                        connectbuf[con_id]->seqnr = 0;
1531
                        connectbuf[con_id]->internal_connect = !compare_external_address_socketIDs(external_socketID, &local_socketID);
1532
                        connectbuf[con_id]->connectionID = con_id;
1533

    
1534
                        connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
1535
                        connectbuf[con_id]->connection_last->next = NULL;
1536
                        connectbuf[con_id]->connection_last->connection_cb = connection_cb;
1537
                        connectbuf[con_id]->connection_last->arg = arg;
1538
                        connectbuf[con_id]->external_connectionID = -1;
1539

    
1540
                        connectbuf[con_id]->defaultSendParams = defaultSendParams;
1541
                        if (defaultSendParams.keepalive) setupKeepalive(con_id);
1542
                        break;
1543
                }
1544
        } //end of for
1545

    
1546
        if (con_id == CONNECTBUFSIZE) {
1547
                error("ML: Could not open connection: connection buffer full\n");
1548
                return -1;
1549
        }
1550

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

    
1555
        return con_id;
1556

    
1557
}
1558

    
1559
void mlCloseConnection(const int connectionID){
1560

    
1561
        // remove it from the connection array
1562
        if(connectbuf[connectionID]) {
1563
                if(connectbuf[connectionID]->ctrl_msg_buf) {
1564
                        free(connectbuf[connectionID]->ctrl_msg_buf);
1565
                }
1566
                // remove related events
1567
                if (connectbuf[connectionID]->timeout_event) {
1568
                        event_del(connectbuf[connectionID]->timeout_event);
1569
                        event_free(connectbuf[connectionID]->timeout_event);
1570
                        connectbuf[connectionID]->timeout_event = NULL;
1571
                }
1572
                free(connectbuf[connectionID]);
1573
                connectbuf[connectionID] = NULL;
1574
        }
1575

    
1576
}
1577

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

    
1580
        if (connectionID < 0) {
1581
                error("ML: send data failed: connectionID does not exist\n");
1582
                return;
1583
        }
1584

    
1585
        if (connectbuf[connectionID] == NULL) {
1586
                error("ML: send data failed: connectionID does not exist\n");
1587
                return;
1588
        }
1589
        if (connectbuf[connectionID]->status != READY) {
1590
            error("ML: send data failed: connection is not active\n");
1591
            return;
1592
        }
1593

    
1594
        if (sParams == NULL) {
1595
                sParams = &(connectbuf[connectionID]->defaultSendParams);
1596
        }
1597

    
1598
        send_msg(connectionID, msgtype, sendbuf, bufsize, false, sParams);
1599

    
1600
}
1601

    
1602
/* transmit data functions  */
1603
int mlSendAllData(const int connectionID,send_all_data_container *container,int nr_entries,unsigned char msgtype,send_params *sParams){
1604

    
1605
    if (nr_entries < 1 || nr_entries > 5) {
1606

    
1607
        error
1608
            ("ML : sendALlData : nr_enties is not between 1 and 5 \n ");
1609
        return 0;
1610

    
1611
    } else {
1612

    
1613
        if (nr_entries == 1) {
1614

    
1615
                mlSendData(connectionID, container->buffer_1,
1616
                      container->length_1, msgtype, sParams);
1617

    
1618
            return 1;
1619

    
1620
        } else if (nr_entries == 2) {
1621

    
1622
            int buflen = container->length_1 + container->length_2;
1623
            char buf[buflen];
1624
            memcpy(buf, container->buffer_1, container->length_1);
1625
            memcpy(&buf[container->length_1], container->buffer_2,
1626
                   container->length_2);
1627
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1628

    
1629
            return 1;
1630

    
1631
        } else if (nr_entries == 3) {
1632

    
1633
            int buflen =
1634
                container->length_1 + container->length_2 +
1635
                container->length_3;
1636
            char buf[buflen];
1637
            memcpy(buf, container->buffer_1, container->length_1);
1638
            memcpy(&buf[container->length_1], container->buffer_2,
1639
                   container->length_2);
1640
            memcpy(&buf[container->length_2], container->buffer_3,
1641
                   container->length_3);
1642
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1643

    
1644

    
1645
            return 1;
1646

    
1647
        } else if (nr_entries == 4) {
1648

    
1649
            int buflen =
1650
                container->length_1 + container->length_2 +
1651
                container->length_3 + container->length_4;
1652
            char buf[buflen];
1653
            memcpy(buf, container->buffer_1, container->length_1);
1654
            memcpy(&buf[container->length_1], container->buffer_2,
1655
                   container->length_2);
1656
            memcpy(&buf[container->length_2], container->buffer_3,
1657
                   container->length_3);
1658
            memcpy(&buf[container->length_3], container->buffer_4,
1659
                   container->length_4);
1660
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1661

    
1662
            return 1;
1663

    
1664
        } else {
1665

    
1666
            int buflen =
1667
                container->length_1 + container->length_2 +
1668
                container->length_3 + container->length_4 +
1669
                container->length_5;
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
            memcpy(&buf[container->length_3], container->buffer_4,
1677
                   container->length_4);
1678
            memcpy(&buf[container->length_4], container->buffer_5,
1679
                   container->length_5);
1680
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1681

    
1682
            return 1;
1683
        }
1684

    
1685
    }
1686

    
1687
}
1688

    
1689
int mlRecvData(const int connectionID,char *recvbuf,int *bufsize,recv_params *rParams){
1690

    
1691
        //TODO yet to be converted
1692
        return 0;
1693
#if 0
1694
        if (rParams == NULL) {
1695
                error("ML: recv_data failed: recv_params is a NULL ptr\n");
1696
                return 0;
1697
    } else {
1698

1699
        info("ML: recv data called \n");
1700

1701
        int i = 0;
1702
        int returnValue = 0;
1703
        double timeout = (double) recv_timeout.tv_sec;
1704
        time_t endtime = time(NULL);
1705

1706
        for (i = 0; i < RECVDATABUFSIZE; i++) {
1707

1708
            if (recvdatabuf[i] != NULL) {
1709

1710
                if (recvdatabuf[i]->connectionID == connectionID) {
1711

1712
                    info("ML: recv data has entry  \n");
1713

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

1716
                    // check if the specified connection has data and it
1717
                    // is complete
1718
                    // check the data seqnr
1719
                    // if(connectionID == recvdatabuf[i]->connectionID &&
1720
                    // 1 == recvdatabuf[i]->status){
1721

1722
                    if (1 == recvdatabuf[i]->status) {
1723

1724
                        // info("transmissionHandler: recv_data set is
1725
                        // complete \n" );
1726

1727
                        // debug("debud \n");
1728

1729
                        // exchange the pointers
1730
                        int buffersize = 0;
1731
                        buffersize = recvdatabuf[i]->bufsize;
1732
                        *bufsize = buffersize;
1733
                        // recvbuf = recvdatabuf[i]->recvbuf;
1734

1735
                        // info("buffersize %d \n",buffersize);
1736
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1737
                               buffersize);
1738
                        // debug(" recvbuf %s \n",recvbuf );
1739

1740
//                         double nrMissFrags =
1741
//                             (double) recvdatabuf[i]->nrFragments /
1742
//                             (double) recvdatabuf[i]->recvFragments;
1743
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
1744

1745
//                        rParams->nrMissingFragments = nrMissingFragments;
1746
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
1747
                        rParams->msgtype = recvdatabuf[i]->msgtype;
1748
                        rParams->connectionID =
1749
                            recvdatabuf[i]->connectionID;
1750

1751
                        // break from the loop
1752
                        // debug(" recvbuf %s \n ",recvbuf);
1753

1754
                        // double nrMissFrags =
1755
                        // (double)recvdatabuf[i]->nrFragments /
1756
                        // (double)recvdatabuf[i]->recvFragments;
1757
                        // int nrMissingFragments =
1758
                        // (int)ceil(nrMissFrags);
1759

1760
                        if(get_Recv_data_inf_cb != NULL) {
1761
                                mon_data_inf recv_data_inf;
1762

1763
                                recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1764
                                recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1765
                                recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1766
                                recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1767
//                                 recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1768
//                                 recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1769
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
1770
                                recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1771
                                recv_data_inf.nrMissingFragments = nrMissingFragments;
1772
                                recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1773
                                recv_data_inf.priority = false;
1774
                                recv_data_inf.padding = false;
1775
                                recv_data_inf.confirmation = false;
1776
                                recv_data_inf.reliable = false;
1777

1778
                                // send data recv callback to monitoring module
1779

1780
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1781
                        }
1782

1783

1784
                        // free the allocated memory
1785
                        free(recvdatabuf[i]);
1786
                        recvdatabuf[i] = NULL;
1787

1788
                        returnValue = 1;
1789
                        break;
1790

1791
                    }
1792

1793
                    if (recvdatabuf[i] != NULL) {
1794

1795
                        if (timepass > timeout) {
1796

1797
                            info("ML: recv_data timeout called  \n");
1798

1799
                            // some data about the missing chunks should
1800
                            // be added here
1801
                            // exchange the pointers
1802
                            int buffersize = 0;
1803
                            buffersize = recvdatabuf[i]->bufsize;
1804
                            *bufsize = buffersize;
1805
                            // recvbuf = recvdatabuf[i]->recvbuf;
1806

1807
                            double nrMissFrags =
1808
                                (double) recvdatabuf[i]->nrFragments /
1809
                                (double) recvdatabuf[i]->recvFragments;
1810
                            int nrMissingFragments =
1811
                                (int) ceil(nrMissFrags);
1812

1813
                            // debug(" recvbuf %s \n",recvbuf );
1814

1815
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1816
                                   buffersize);
1817

1818
                            rParams->nrMissingFragments =
1819
                                nrMissingFragments;
1820
                            rParams->nrFragments =
1821
                                recvdatabuf[i]->nrFragments;
1822
                            rParams->msgtype = recvdatabuf[i]->msgtype;
1823
                            rParams->connectionID =
1824
                                recvdatabuf[i]->connectionID;
1825

1826
                                if(get_Recv_data_inf_cb != NULL) {
1827
                                        mon_data_inf recv_data_inf;
1828

1829
                                        recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1830
                                        recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1831
                                        recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1832
                                        recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1833
                                        recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1834
                                        recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1835
                                        gettimeofday(&recv_data_inf.arrival_time, NULL);
1836
                                        recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1837
                                        recv_data_inf.nrMissingFragments = nrMissingFragments;
1838
                                        recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1839
                                        recv_data_inf.priority = false;
1840
                                        recv_data_inf.padding = false;
1841
                                        recv_data_inf.confirmation = false;
1842
                                        recv_data_inf.reliable = false;
1843

1844
                                        // send data recv callback to monitoring module
1845

1846
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1847
                                }
1848

1849
                            // free the allocated memory
1850
                            free(recvdatabuf[i]);
1851
                            recvdatabuf[i] = NULL;
1852

1853
                            returnValue = 1;
1854
                            break;
1855

1856
                        }
1857
                    }
1858

1859
                }
1860

1861
            }
1862
            // debug("2 recvbuf %s \n ",recvbuf);
1863
        }
1864
        return returnValue;
1865
    }
1866
#endif
1867

    
1868
}
1869

    
1870
int mlSocketIDToString(socketID_handle socketID,char* socketID_string, size_t len){
1871

    
1872
        char internal_addr[INET_ADDRSTRLEN];
1873
        char external_addr[INET_ADDRSTRLEN];
1874
        inet_ntop(AF_INET, &(socketID->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1875
        inet_ntop(AF_INET, &(socketID->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1876

    
1877
        snprintf(socketID_string,len,"%s:%d-%s:%d", internal_addr, ntohs(socketID->internal_addr.udpaddr.sin_port),
1878
                external_addr,        ntohs(socketID->external_addr.udpaddr.sin_port));
1879
        return 0;
1880

    
1881
}
1882

    
1883
int mlStringToSocketID(const char* socketID_string, socketID_handle socketID){
1884

    
1885
        //@TODO add checks against malformed string
1886
        char external_addr[INET_ADDRSTRLEN];
1887
        int external_port;
1888
        char internal_addr[INET_ADDRSTRLEN];
1889
        int internal_port;
1890

    
1891
        char *pch;
1892
        char *s = strdup(socketID_string);
1893

    
1894
        //replace ':' with a blank
1895
        pch=strchr(s,':');
1896
        while (pch!=NULL){
1897
                                *pch = ' ';
1898
                pch=strchr(pch+1,':');
1899
        }
1900
        pch=strchr(s,'-');
1901
        if(pch) *pch = ' ';
1902

    
1903
        sscanf(s,"%s %d %s %d", internal_addr, &internal_port,
1904
                external_addr, &external_port);
1905

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

    
1909
        if(inet_pton(AF_INET, internal_addr, &(socketID->internal_addr.udpaddr.sin_addr)) == 0)
1910
                return EINVAL;
1911
        socketID->internal_addr.udpaddr.sin_family = AF_INET;
1912
        socketID->internal_addr.udpaddr.sin_port = htons(internal_port);
1913

    
1914

    
1915
        if(inet_pton(AF_INET, external_addr, &(socketID->external_addr.udpaddr.sin_addr)) ==0)
1916
                return EINVAL;
1917
        socketID->external_addr.udpaddr.sin_family = AF_INET;
1918
        socketID->external_addr.udpaddr.sin_port = htons(external_port);
1919

    
1920
        free(s);
1921
        return 0;
1922

    
1923
}
1924

    
1925
int mlGetConnectionStatus(int connectionID){
1926

    
1927
        if(connectbuf[connectionID])
1928
                return connectbuf[connectionID]->status == READY;
1929
        return -1;
1930
    
1931
}
1932

    
1933

    
1934
int mlConnectionExist(socketID_handle socketID, bool ready){
1935

    
1936
    /*
1937
     * check if another connection for the external connectionID exist
1938
     * that was established \ within the last 2 seconds
1939
     */
1940
        int i;
1941
        for (i = 0; i < CONNECTBUFSIZE; i++)
1942
                if (connectbuf[i] != NULL)
1943
                        if (mlCompareSocketIDs(&(connectbuf[i]->external_socketID), socketID) == 0) {
1944
                                if (ready) return (connectbuf[i]->status == READY ? i : -1);;
1945
                                return i;
1946
                                }
1947

    
1948
    return -1;
1949

    
1950
}
1951

    
1952
//Added by Robert Birke as comodity functions
1953

    
1954
//int mlPrintSocketID(socketID_handle socketID) {
1955
//        char str[SOCKETID_STRING_SIZE];
1956
//        mlSocketIDToString(socketID, str, sizeof(str));
1957
//        printf(stderr,"int->%s<-ext\n",str);
1958
//}
1959

    
1960
/*
1961
 * hash code of a socketID
1962
 * TODO might think of a better way
1963
 */
1964
int mlHashSocketID(socketID_handle sock) {
1965
    return sock->internal_addr.udpaddr.sin_port +
1966
                          sock->external_addr.udpaddr.sin_port;
1967
}
1968

    
1969
int mlCompareSocketIDs(socketID_handle sock1, socketID_handle sock2) {
1970
        /*
1971
        * compare internal addr
1972
        */
1973
        if(sock1 == NULL || sock2 == NULL)
1974
                return 1;
1975

    
1976
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr !=
1977
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
1978
                        return 1;
1979

    
1980
        if (sock1->internal_addr.udpaddr.sin_port !=
1981
                 sock2->internal_addr.udpaddr.sin_port)
1982
                        return 1;
1983

    
1984
        /*
1985
        * compare external addr
1986
        */
1987
        if (sock1->external_addr.udpaddr.sin_addr.s_addr !=
1988
            sock2->external_addr.udpaddr.sin_addr.s_addr)
1989
                        return 1;
1990

    
1991
        if (sock1->external_addr.udpaddr.sin_port !=
1992
                 sock2->external_addr.udpaddr.sin_port)
1993
                        return 1;
1994

    
1995
        return 0;
1996
}
1997

    
1998
int mlCompareSocketIDsByPort(socketID_handle sock1, socketID_handle sock2)
1999
{
2000
        if(sock1 == NULL || sock2 == NULL)
2001
                return 1;
2002
 
2003
        if (sock1->internal_addr.udpaddr.sin_port !=
2004
                 sock2->internal_addr.udpaddr.sin_port)
2005
                        return 1;
2006

    
2007
        if (sock1->external_addr.udpaddr.sin_port !=
2008
                 sock2->external_addr.udpaddr.sin_port)
2009
                        return 1;
2010
        return 0;
2011
}
2012

    
2013
int mlGetPathMTU(int ConnectionId) {
2014
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
2015
                return -1;
2016
        if (connectbuf[ConnectionId] != NULL)
2017
                return connectbuf[ConnectionId]->pmtusize;
2018
        return -1;
2019
}
2020

    
2021
/**************************** END of GENERAL functions *************************/
2022

    
2023
/**************************** NAT functions *************************/
2024

    
2025
/* setter  */
2026
void mlSetStunServer(const int port,const char *ipaddr){
2027

    
2028
        stun_server.sin_family = AF_INET;
2029
        if (ipaddr == NULL)
2030
                stun_server.sin_addr.s_addr = htonl(INADDR_NONE);
2031
        else
2032
                stun_server.sin_addr.s_addr = resolve(ipaddr);
2033
        stun_server.sin_port = htons(port);
2034

    
2035
}
2036

    
2037
int mlGetExternalIP(char* external_addr){
2038

    
2039
        socketaddrgen udpgen;
2040
        struct sockaddr_in udpaddr;
2041

    
2042
        udpgen = local_socketID.external_addr;
2043
        udpaddr = udpgen.udpaddr;
2044

    
2045
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
2046
                        INET_ADDRSTRLEN);
2047

    
2048
        if (external_addr == NULL) {
2049

    
2050
        return -1;
2051

    
2052
        } else {
2053

    
2054
        return 0;
2055

    
2056
        }
2057

    
2058
}
2059

    
2060
/**************************** END of NAT functions *************************/