Statistics
| Branch: | Revision:

ml / transmissionHandler.c @ 86f87418

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

    
55
#define LOG_MODULE "[ml] "
56
#include "pulse_log.h"
57

    
58
/*
59
 * a pointer to a libevent instance 
60
 */
61
struct event_base *base;
62

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

    
76
/*
77
 * global variables 
78
 */
79
/*
80
 * define a buffer of pointers to connect structures 
81
 */
82
connect_data *connectbuf[CONNECTBUFSIZE];
83

    
84
/*
85
 * define a pointer buffer with pointers to recv_data structures 
86
 */
87
recvdata *recvdatabuf[RECVDATABUFSIZE];
88

    
89
/*
90
 * define a pointer buffer for message multiplexing 
91
 */
92
receive_data_cb recvcbbuf[MSGMULTIPLEXSIZE];
93

    
94
/*
95
 * stun server address 
96
 */
97
struct sockaddr_in stun_server;
98

    
99
/*
100
 * receive timeout 
101
 */
102
struct timeval recv_timeout;
103

    
104
/*
105
 * boolean NAT traversal successful if true 
106
 */
107
boolean NAT_traversal;
108

    
109
/*
110
 * file descriptor for local socket 
111
 */
112
evutil_socket_t socketfd;
113

    
114
/*
115
 * local socketID 
116
 */
117
socket_ID local_socketID;
118

    
119
socketID_handle loc_socketID = &local_socketID;
120

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

    
143
/*
144
 * boolean that defines if received data is transmitted to the upper layer 
145
 * via callback or via upper layer polling 
146
 */
147
boolean recv_data_callback;
148

    
149
/*
150
 * helper function to get rid of a warning
151
 */
152
int min(int a, int b) {
153
        if (a > b) return b;
154
        return a;
155
}
156

    
157
/*
158
 * functions 
159
 */
160
/*
161
 * register callback functions 
162
 */
163

    
164
void register_get_recv_pkt_inf(get_recv_pkt_inf_cb recv_pkt_inf_cb)
165
{
166
        if (recv_pkt_inf_cb == NULL)
167
                printf("Register get_recv_pkt_inf_cb failed: NULL ptr  \n");
168
        else
169
                get_Recv_pkt_inf_cb = recv_pkt_inf_cb;
170
}
171

    
172
void register_get_send_pkt_inf(get_send_pkt_inf_cb send_pkt_inf_cb)
173
{
174
        if (send_pkt_inf_cb == NULL)
175
                printf("Register get_send_pkt_inf_cb: NULL ptr  \n");
176
        else
177
                get_Send_pkt_inf_cb = send_pkt_inf_cb;
178
}
179

    
180
void
181
register_set_monitoring_header_pkt_cb(set_monitoring_header_pkt_cb
182
                                      monitoring_header_pkt_cb)
183
{
184
        if (monitoring_header_pkt_cb == NULL)
185
                printf("Register set_monitoring_header_pkt_cb: NULL ptr  \n");
186
        else
187
                set_Monitoring_header_pkt_cb = monitoring_header_pkt_cb;
188
}
189

    
190
void register_get_recv_data_inf(get_recv_data_inf_cb recv_data_inf_cb)
191
{
192
        if (recv_data_inf_cb == NULL)
193
                printf("Register get_recv_data_inf_cb: NULL ptr  \n");
194
        else
195
                get_Recv_data_inf_cb = recv_data_inf_cb;
196
}
197

    
198
void register_get_send_data_inf(get_send_data_inf_cb send_data_inf_cb)
199
{
200
        if (send_data_inf_cb == NULL)
201
                printf("Register get_send_data_inf_cb: NULL ptr  \n");
202
        else
203
                get_Send_data_inf_cb = send_data_inf_cb;
204
}
205

    
206
void
207
register_set_monitoring_header_data_cb(set_monitoring_header_data_cb
208
                                       monitoring_header_data_cb)
209
{
210
        if (monitoring_header_data_cb == NULL)
211
                printf("Register set_monitoring_header_data_cb : NULL ptr  \n");
212
        else
213
        set_Monitoring_header_data_cb = monitoring_header_data_cb;
214
}
215

    
216
void register_recv_connection_cb(receive_connection_cb connection_cb)
217
{
218
        if (connection_cb == NULL)
219
                printf("Register receive_connection_cb: NULL ptr  \n");
220
        else
221
                receive_Connection_cb = connection_cb;
222
}
223

    
224
void
225
register_recv_localsocketID_cb(receive_localsocketID_cb local_socketID_cb)
226
{
227
        if (local_socketID_cb == NULL)
228
                printf("Register receive_localsocketID_cb: NULL ptr \n");
229
        else
230
        receive_SocketID_cb = local_socketID_cb;
231
}
232

    
233

    
234
void register_error_connection_cb(connection_failed_cb connection_fail)
235
{
236
        if (connection_fail == NULL)
237
                printf("Register connection_failed_cb: NULL ptr  \n");
238
        else
239
        failed_Connection_cb = connection_fail;
240
}
241

    
242

    
243
void register_recv_data_cb(receive_data_cb data_cb, unsigned char msgtype)
244
{
245

    
246
    if (msgtype > 126) {
247

    
248
        printf
249
            ("transmissionHandler: Could not register recv_data callback. Msgtype is greater then 126 \n");
250

    
251
    }
252

    
253
    if (data_cb == NULL) {
254

    
255
        printf("Register receive data callback: NUll ptr \n ");
256

    
257
    } else {
258

    
259
        recvcbbuf[msgtype] = data_cb;
260

    
261
    }
262
}
263

    
264
void
265
init_transmissionHandler(boolean recv_data_cb,
266
                         struct timeval timeout_value, const int port,
267
                         const char *ipaddr, const int stun_port,
268
                         const char *stun_ipaddr,
269
                         receive_localsocketID_cb local_socketID_cb,
270
                         void *arg)
271
{
272
        base = (struct event_base *) arg;
273
        recv_data_callback = recv_data_cb;
274
        setRecvTimeout(timeout_value);
275
        setStunServer(stun_port, stun_ipaddr);
276
        register_recv_localsocketID_cb(local_socketID_cb);
277
        create_socket(port, ipaddr);
278
}
279

    
280
/*
281
 * Sockets 
282
 */
283
/*
284
 * returns a handle to the socketID struct the ipaddr can be a null
285
 * pointer. Then all available ipaddr on the machine are choosen.
286
 */
287
void create_socket(const int port, const char *ipaddr)
288
{
289
        struct sockaddr_in udpaddr;
290
        udpaddr.sin_family = AF_INET;
291
        if (ipaddr == NULL)
292
                udpaddr.sin_addr.s_addr = INADDR_ANY;
293
        else
294
                udpaddr.sin_addr.s_addr = inet_addr(ipaddr);
295
        udpaddr.sin_port = htons(port);
296

    
297
        socketaddrgen udpgen;
298
        udpgen.udpaddr = udpaddr;
299
        local_socketID.internal_addr = udpgen;
300
        
301
        socketfd = createSocket(port, ipaddr);
302
        
303
        struct event *ev;
304
        ev = event_new(base, socketfd, EV_READ | EV_PERSIST, recv_pkg, NULL);
305
        
306
        event_add(ev, NULL);
307
        
308
        /*
309
        * send the NAT traversal STUN request 
310
        */
311
        send_stun_request(socketfd, &stun_server);
312
        
313
        /*
314
        * enter a NAT traversal timeout that takes care of retransmission 
315
        */
316
        struct event *ev1;
317
        struct timeval timeout_value_NAT_traversal = { 2, 0 };
318
        ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
319
        event_add(ev1, &timeout_value_NAT_traversal);
320

    
321
        NAT_traversal = false;
322
}
323

    
324
void close_socket(socketID_handle socketID)
325
{
326
        free(socketID);
327
}
328

    
329
/*
330
 * Connections 
331
 */
332
// the first socketID is the from socketID, the second one is the to
333
// socketID
334

    
335
int
336
open_connection(socketID_handle external_socketID, receive_connection_cb connection_cb, void *arg)
337
{
338
        int con_id;
339
        if (external_socketID == NULL) {
340
                error("ML: cannot open connection: one of the socketIDs is NULL");
341
                return -1;
342
        } 
343
        if (NAT_traversal == false) {
344
                error("ML: cannot open connection: NAT traversal for socketID still in progress");
345
                return -1;
346
        }
347
        if (connection_cb == NULL) {
348
                error("ML: cannot open connection: connection_cb is NULL");
349
                return -1;
350
        }
351

    
352
        // check if that connection already exist
353

    
354
        con_id = connection_exist(external_socketID);
355
        if (con_id >= 0) {
356
                // if so check if it is ready to use        
357
                if (connectbuf[con_id]->status == READY) {
358
                                // if so use the callback immidiatley
359
                                (connection_cb) (con_id, arg);
360

    
361
                // otherwise just write the connection cb and the arg pointer
362
                // into the connection struct
363
                } else {
364
                        struct receive_connection_cb_list *temp;
365
                        temp = malloc(sizeof(struct receive_connection_cb_list));
366
                        temp->next = NULL;
367
                        temp->connection_cb = connection_cb;
368
                        temp->arg = arg;
369
                        if(connectbuf[con_id]->connection_last != NULL) {
370
                                connectbuf[con_id]->connection_last->next = temp;
371
                                connectbuf[con_id]->connection_last = temp;
372
                        } else
373
                                connectbuf[con_id]->connection_last = connectbuf[con_id]->connection_head = temp;
374
                }
375
                return con_id;
376
        }
377
        // make entry in connection_establishment array
378
        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
379
                if (connectbuf[con_id] == NULL) {
380
                        connectbuf[con_id] = (connect_data *) malloc(sizeof(connect_data));
381
                        memset(connectbuf[con_id],0,sizeof(connect_data));
382
                        connectbuf[con_id]->starttime = time(NULL);
383
                        memcpy(&connectbuf[con_id]->external_socketID, external_socketID, sizeof(socket_ID));
384
                        connectbuf[con_id]->pmtusize = MAX;
385
                        connectbuf[con_id]->status = INVITE;
386
                        connectbuf[con_id]->seqnr = 0;
387
                        connectbuf[con_id]->internal_connect = !compare_external_address_socketIDs(external_socketID, &local_socketID);
388
                        /*
389
                        * timeout values for the pmtu discovery 
390
                        */
391
                        connectbuf[con_id]->timeout_value.tv_sec = 15;
392
                        connectbuf[con_id]->timeout_value.tv_usec = 0;
393
                        connectbuf[con_id]->connectionID = con_id;
394

    
395
                        connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
396
                        connectbuf[con_id]->connection_last->next = NULL;
397
                        connectbuf[con_id]->connection_last->connection_cb = connection_cb;
398
                        connectbuf[con_id]->connection_last->arg = arg;
399
                        connectbuf[con_id]->external_connectionID = -1;
400
                        break;
401
                }
402
        } //end of for
403

    
404
        if (con_id == CONNECTBUFSIZE) {
405
                error("ML: Could not open connection: connbuffer full");
406
                return -1;
407
        }
408

    
409
        // create and send a connection message
410
        send_conn_msg(con_id, MAX, INVITE);
411

    
412
        struct event *ev;
413
        ev = evtimer_new(base, pmtu_timeout_cb, (void *) con_id);
414
        event_add(ev, &connectbuf[con_id]->timeout_value);
415

    
416
        return con_id;
417
}
418

    
419
//done
420
void close_connection(const int connectionID)
421
{
422
        // remove it from the connection array
423
        if(connectbuf[connectionID]) {
424
                if(connectbuf[connectionID]->ctrl_msg_buf)
425
                        free(connectbuf[connectionID]->ctrl_msg_buf);
426
                free(connectbuf[connectionID]);
427
                connectbuf[connectionID] = NULL;
428
        }
429
}
430

    
431
void keep_connection_alive(const int connectionID)
432
{
433

    
434
    // to be done with the NAT traversal
435
    // send a message over the wire
436
    printf("\n");
437

    
438
}
439

    
440
int
441
send_all_data(const int connectionID, send_all_data_container * container,
442
              int nr_entries, unsigned char msgtype, send_params * sParams)
443
{
444

    
445

    
446

    
447
    if (nr_entries < 1 || nr_entries > 5) {
448

    
449
        printf
450
            ("send_all_data ERROR: nr_enties is not between 1 and 5 \n ");
451
        return 0;
452

    
453
    } else {
454

    
455
        if (nr_entries == 1) {
456

    
457
            send_data(connectionID, container->buffer_1,
458
                      container->length_1, msgtype, sParams);
459

    
460
            return 1;
461

    
462
        } else if (nr_entries == 2) {
463

    
464
            int buflen = container->length_1 + container->length_2;
465
            char buf[buflen];
466
            memcpy(buf, container->buffer_1, container->length_1);
467
            memcpy(&buf[container->length_1], container->buffer_2,
468
                   container->length_2);
469
            send_data(connectionID, buf, buflen, msgtype, sParams);
470

    
471
            return 1;
472

    
473
        } else if (nr_entries == 3) {
474

    
475
            int buflen =
476
                container->length_1 + container->length_2 +
477
                container->length_3;
478
            char buf[buflen];
479
            memcpy(buf, container->buffer_1, container->length_1);
480
            memcpy(&buf[container->length_1], container->buffer_2,
481
                   container->length_2);
482
            memcpy(&buf[container->length_2], container->buffer_3,
483
                   container->length_3);
484
            send_data(connectionID, buf, buflen, msgtype, sParams);
485

    
486

    
487
            return 1;
488

    
489
        } else if (nr_entries == 4) {
490

    
491
            int buflen =
492
                container->length_1 + container->length_2 +
493
                container->length_3 + container->length_4;
494
            char buf[buflen];
495
            memcpy(buf, container->buffer_1, container->length_1);
496
            memcpy(&buf[container->length_1], container->buffer_2,
497
                   container->length_2);
498
            memcpy(&buf[container->length_2], container->buffer_3,
499
                   container->length_3);
500
            memcpy(&buf[container->length_3], container->buffer_4,
501
                   container->length_4);
502
            send_data(connectionID, buf, buflen, msgtype, sParams);
503

    
504
            return 1;
505

    
506
        } else {
507

    
508
            int buflen =
509
                container->length_1 + container->length_2 +
510
                container->length_3 + container->length_4 +
511
                container->length_5;
512
            char buf[buflen];
513
            memcpy(buf, container->buffer_1, container->length_1);
514
            memcpy(&buf[container->length_1], container->buffer_2,
515
                   container->length_2);
516
            memcpy(&buf[container->length_2], container->buffer_3,
517
                   container->length_3);
518
            memcpy(&buf[container->length_3], container->buffer_4,
519
                   container->length_4);
520
            memcpy(&buf[container->length_4], container->buffer_5,
521
                   container->length_5);
522
            send_data(connectionID, buf, buflen, msgtype, sParams);
523

    
524
            return 1;
525
        }
526

    
527
    }
528

    
529

    
530
}
531

    
532
/*
533
 * send an entire block of data 
534
 */
535
void send_data(int con_id, char *sendbuf, int bufsize, int msgtype, send_params * sParams)
536
{
537
        if (sParams == NULL) {
538
                error("ML: send data failed: send_params is a NULL ptr");
539
                return;
540
        }
541

    
542
        if (con_id < 0) {
543
                error("ML: send data failed: connectionID does not exist");
544
                return;
545
        }
546

    
547
        if (connectbuf[con_id] == NULL) {
548
                error("ML: send data failed: connectionID does not exist");
549
                return;
550
        }
551
        if (connectbuf[con_id]->status != READY) {
552
            error("ML: send data failed: connection is not active");
553
            return;
554
        }
555

    
556
        send_msg(con_id, msgtype, sendbuf, bufsize, false, sParams);
557
}
558

    
559
/*
560
 * recv data with polling 
561
 */
562
int
563
recv_data(const int connectionID, char *recvbuf, int *bufsize,
564
          recv_params * rParams)
565
{
566
        //TODO yet to be converted
567
        return 0;
568
#if 0
569
        if (rParams == NULL) {
570
                error("ML: recv_data failed: recv_params is a NULL ptr");
571
                return 0;
572
    } else {
573

574
        printf("transmissionhandler: recv data called \n");
575

576
        int i = 0;
577
        int returnValue = 0;
578
        double timeout = (double) recv_timeout.tv_sec;
579
        time_t endtime = time(NULL);
580

581
        for (i = 0; i < RECVDATABUFSIZE; i++) {
582

583
            if (recvdatabuf[i] != NULL) {
584

585
                if (recvdatabuf[i]->connectionID == connectionID) {
586

587
                    printf("transmissionhandler: recv data has entry  \n");
588

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

591
                    // check if the specified connection has data and it
592
                    // is complete
593
                    // check the data seqnr
594
                    // if(connectionID == recvdatabuf[i]->connectionID &&
595
                    // 1 == recvdatabuf[i]->status){
596

597
                    if (1 == recvdatabuf[i]->status) {
598

599
                        // printf("transmissionHandler: recv_data set is
600
                        // complete \n" );
601

602
                        // printf("debud \n");
603

604
                        // exchange the pointers
605
                        int buffersize = 0;
606
                        buffersize = recvdatabuf[i]->bufsize;
607
                        *bufsize = buffersize;
608
                        // recvbuf = recvdatabuf[i]->recvbuf;
609

610
                        // printf("buffersize %d \n",buffersize);
611
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
612
                               buffersize);
613
                        // printf(" recvbuf %s \n",recvbuf );
614

615
//                         double nrMissFrags =
616
//                             (double) recvdatabuf[i]->nrFragments /
617
//                             (double) recvdatabuf[i]->recvFragments;
618
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
619

620
//                        rParams->nrMissingFragments = nrMissingFragments;
621
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
622
                        rParams->msgtype = recvdatabuf[i]->msgtype;
623
                        rParams->connectionID =
624
                            recvdatabuf[i]->connectionID;
625

626
                        // break from the loop
627
                        // printf(" recvbuf %s \n ",recvbuf);
628

629
                        // double nrMissFrags =
630
                        // (double)recvdatabuf[i]->nrFragments /
631
                        // (double)recvdatabuf[i]->recvFragments;
632
                        // int nrMissingFragments =
633
                        // (int)ceil(nrMissFrags);
634

635
                        if(get_Recv_data_inf_cb != NULL) {
636
                                mon_data_inf recv_data_inf;
637

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

653
                                // send data recv callback to monitoring module
654

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

658

659
                        // free the allocated memory
660
                        free(recvdatabuf[i]);
661
                        recvdatabuf[i] = NULL;
662

663
                        returnValue = 1;
664
                        break;
665

666
                    }
667

668
                    if (recvdatabuf[i] != NULL) {
669

670
                        if (timepass > timeout) {
671

672
                            printf("transmissionHandler: recv_data timeout called  \n");
673

674
                            // some data about the missing chunks should
675
                            // be added here
676
                            // exchange the pointers 
677
                            int buffersize = 0;
678
                            buffersize = recvdatabuf[i]->bufsize;
679
                            *bufsize = buffersize;
680
                            // recvbuf = recvdatabuf[i]->recvbuf;
681

682
                            double nrMissFrags =
683
                                (double) recvdatabuf[i]->nrFragments /
684
                                (double) recvdatabuf[i]->recvFragments;
685
                            int nrMissingFragments =
686
                                (int) ceil(nrMissFrags);
687

688
                            // printf(" recvbuf %s \n",recvbuf );
689

690
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
691
                                   buffersize);
692

693
                            rParams->nrMissingFragments =
694
                                nrMissingFragments;
695
                            rParams->nrFragments =
696
                                recvdatabuf[i]->nrFragments;
697
                            rParams->msgtype = recvdatabuf[i]->msgtype;
698
                            rParams->connectionID =
699
                                recvdatabuf[i]->connectionID;
700

701
                                if(get_Recv_data_inf_cb != NULL) {
702
                                        mon_data_inf recv_data_inf;
703

704
                                        recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
705
                                        recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
706
                                        recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
707
                                        recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
708
                                        recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
709
                                        recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
710
                                        gettimeofday(&recv_data_inf.arrival_time, NULL);
711
                                        recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
712
                                        recv_data_inf.nrMissingFragments = nrMissingFragments;
713
                                        recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
714
                                        recv_data_inf.priority = false;
715
                                        recv_data_inf.padding = false;
716
                                        recv_data_inf.confirmation = false;
717
                                        recv_data_inf.reliable = false;
718

719
                                        // send data recv callback to monitoring module
720

721
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
722
                                }
723

724
                            // free the allocated memory 
725
                            free(recvdatabuf[i]);
726
                            recvdatabuf[i] = NULL;
727

728
                            returnValue = 1;
729
                            break;
730

731
                        }
732
                    }
733

734
                }
735

736
            }
737
            // printf("2 recvbuf %s \n ",recvbuf);
738
        }
739
        return returnValue;
740
    }
741
#endif
742
}
743

    
744
void setStunServer(const int port, const char *ipaddr)
745
{
746
        stun_server.sin_family = AF_INET;
747
        if (ipaddr == NULL)
748
                stun_server.sin_addr.s_addr = htonl(INADDR_ANY);
749
        else
750
                stun_server.sin_addr.s_addr = resolve(ipaddr);
751
        stun_server.sin_port = htons(port);
752
}
753

    
754
void setRecvTimeout(struct timeval timeout_value) {
755
        recv_timeout = timeout_value;
756
}
757
 
758
void send_msg(int con_id, int msg_type, char* msg, int msg_len, bool truncable, send_params * sParams) {
759
        socketaddrgen udpgen;
760
        bool retry;
761
        int pkt_len, offset;
762
        struct iovec iov[4];
763

    
764
        char h_pkt[MON_HEADER_SPACE];
765
        char h_data[MON_HEADER_SPACE];
766

    
767
        struct msg_header msg_h;
768

    
769
        iov[0].iov_base = &msg_h;
770
        iov[0].iov_len = MSG_HEADER_SIZE;
771

    
772
        msg_h.local_con_id = con_id;
773
        msg_h.remote_con_id = connectbuf[con_id]->external_connectionID;
774
        msg_h.msg_type = msg_type;
775
        msg_h.msg_seq_num = connectbuf[con_id]->seqnr++;
776

    
777

    
778
        iov[1].iov_len = iov[2].iov_len = 0;
779
        iov[1].iov_base = h_pkt;
780
        iov[2].iov_base = h_data;
781

    
782

    
783
        if (connectbuf[con_id]->internal_connect)
784
                udpgen = connectbuf[con_id]->external_socketID.internal_addr;
785
        else
786
                udpgen = connectbuf[con_id]->external_socketID.external_addr;
787

    
788
        do{
789
                offset = 0;
790
                retry = false;
791
                // Monitoring layer hook
792
                if(set_Monitoring_header_data_cb != NULL) {
793
                        iov[2].iov_len = ((set_Monitoring_header_data_cb) (&(connectbuf[con_id]->external_socketID), msg_type));
794
                }
795
                msg_h.len_mon_data_hdr = iov[2].iov_len;
796

    
797
                if(get_Send_data_inf_cb != NULL && iov[2].iov_len != 0) {
798
                        mon_data_inf sd_data_inf;
799
                        
800
                        sd_data_inf.remote_socketID = &(connectbuf[con_id]->external_socketID);
801
                        sd_data_inf.buffer = msg;
802
                        sd_data_inf.bufSize = msg_len;
803
                        sd_data_inf.msgtype = msg_type;
804
                        sd_data_inf.monitoringDataHeader = iov[2].iov_base;
805
                        sd_data_inf.monitoringDataHeaderLen = iov[2].iov_len;
806
                        sd_data_inf.priority = sParams->priority;
807
                        sd_data_inf.padding = sParams->padding;
808
                        sd_data_inf.confirmation = sParams->confirmation;
809
                        sd_data_inf.reliable = sParams->reliable;
810
                        memset(&sd_data_inf.arrival_time, 0, sizeof(struct timeval));
811
        
812
                        (get_Send_data_inf_cb) ((void *) &sd_data_inf);
813
                }
814

    
815
                do {
816
                        if(set_Monitoring_header_pkt_cb != NULL) {
817
                                iov[1].iov_len = (set_Monitoring_header_pkt_cb) (&(connectbuf[con_id]->external_socketID), msg_type);
818
                        }
819
                        pkt_len = min(connectbuf[con_id]->pmtusize - iov[2].iov_len - iov[1].iov_len - iov[0].iov_len, msg_len - offset) ;
820

    
821
                        iov[3].iov_len = pkt_len;
822
                        iov[3].iov_base = msg + offset;
823

    
824
                        //fill header
825
                        msg_h.len_mon_packet_hdr = iov[1].iov_len;
826
                        msg_h.offset = offset;
827
                        msg_h.msg_length = truncable ? pkt_len : msg_len;
828
                        
829
                        //monitoring layer hook
830
                        if(get_Send_pkt_inf_cb != NULL && iov[1].iov_len) {
831
                                mon_pkt_inf pkt_info;
832

    
833
                                pkt_info.remote_socketID = &(connectbuf[con_id]->external_socketID);
834
                                pkt_info.buffer = msg + offset;
835
                                pkt_info.bufSize = pkt_len;
836
                                pkt_info.msgtype = msg_type;
837
                                pkt_info.dataID = connectbuf[con_id]->seqnr;
838
                                pkt_info.offset = offset;
839
                                pkt_info.datasize = msg_len;
840
                                pkt_info.monitoringHeaderLen = iov[1].iov_len;
841
                                pkt_info.monitoringHeader = iov[1].iov_base;
842
                                pkt_info.ttl = -1;
843
                                memset(&(pkt_info.arrival_time),0,sizeof(struct timeval));
844
        
845
                                (get_Send_pkt_inf_cb) ((void *) &pkt_info);
846
                        }
847

    
848

    
849
                        switch(sendPacket(socketfd, iov, 4, &udpgen.udpaddr)) {
850
                                case MSGLEN:
851
                                        connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
852
                                        connectbuf[con_id]->delay = true;
853
                                        retry = true;
854
                                        offset = msg_len; // exit the while
855
                                        break;
856
                                case FAILURE:
857
                                        offset = msg_len; // exit the while
858
                                        break;
859
                                case OK:
860
                                        //update
861
                                        offset += pkt_len + iov[2].iov_len;
862
                                        //transmit data header only in the first packet
863
                                        iov[2].iov_len = 0;
864
                                        break;
865
                        }
866
                } while(offset != msg_len + msg_h.len_mon_data_hdr && !truncable);
867
        } while(retry);
868
}
869

    
870
void send_conn_msg(int con_id, int buf_size, int command_type)
871
{
872
        send_params sparams;
873
        if(connectbuf[con_id]->ctrl_msg_buf == NULL)
874
                connectbuf[con_id]->ctrl_msg_buf = malloc(MAX);
875

    
876
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
877
                error("ML: can not allocate memory for connection message");
878
                return;
879
        }
880

    
881
        struct conn_msg *msg_header = (struct conn_msg*) connectbuf[con_id]->ctrl_msg_buf;
882

    
883
        msg_header->comand_type = command_type;
884
        msg_header->pmtu_size = connectbuf[con_id]->pmtusize;
885

    
886
        memcpy(&(msg_header->sock_id), loc_socketID, sizeof(socket_ID));
887

    
888
        send_msg(con_id, ML_CON_MSG, connectbuf[con_id]->ctrl_msg_buf, buf_size, true, &sparams);
889
}
890

    
891
void
892
recv_conn_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
893
{
894
        struct conn_msg *con_msg;
895
        int free_con_id, con_id;
896

    
897
        time_t now = time(NULL);
898
        double timediff = 0.0;
899

    
900
        // Monitoring layer hook
901
        if(get_Recv_data_inf_cb != NULL && msg_h->len_mon_data_hdr != 0) {
902
                // update pointer to the real data
903
                msgbuf += msg_h->len_mon_data_hdr;
904
                bufsize -= msg_h->len_mon_data_hdr;
905
                con_msg = (struct conn_msg *)msgbuf;
906

    
907
                mon_data_inf recv_data_inf;
908
                recv_data_inf.remote_socketID = &(con_msg->sock_id);
909
                recv_data_inf.buffer = msgbuf;
910
                recv_data_inf.bufSize = bufsize;
911
                recv_data_inf.msgtype = msg_h->msg_type;
912
                recv_data_inf.monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
913
                recv_data_inf.monitoringDataHeader = msg_h->len_mon_data_hdr ? msgbuf : NULL;
914
                gettimeofday(&recv_data_inf.arrival_time, NULL);
915
                recv_data_inf.firstPacketArrived = true;
916
                recv_data_inf.recvFragments = 1;
917
                recv_data_inf.priority = false;
918
                recv_data_inf.padding = false;
919
                recv_data_inf.confirmation = false;
920
                recv_data_inf.reliable = false;
921

    
922
                // send data recv callback to monitoring module
923
                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
924
        } else
925
                con_msg = (struct conn_msg *) msgbuf;
926

    
927
        // check the connection command type
928
        switch (con_msg->comand_type) {
929
                /*
930
                * if INVITE: enter a new socket make new entry in connect array
931
                * send an ok 
932
                */
933
                case INVITE:
934
                        debug("ML: received INVITE");
935
                        /*
936
                        * check if another connection for the external connectionID exist 
937
                        * that was established within the last 2 seconds 
938
                        */
939
                        free_con_id = -1;
940
                        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
941
                                if (connectbuf[con_id] != NULL) {
942
                                        if (compare_socketIDs(&(connectbuf[con_id]->external_socketID), &(con_msg->sock_id)) == 0) {
943
                                                timediff = difftime(now, connectbuf[con_id]->starttime);
944
                                                if (timediff < 2)
945
                                                        break;
946
                                        }
947
                                } else if(free_con_id == -1)
948
                                        free_con_id = con_id;
949
                        }
950

    
951
                        if (con_id == CONNECTBUFSIZE) {
952
                                // create an entry in the connecttrybuf
953
                                if(free_con_id == -1) {
954
                                        error("ML: no new connect_buf available");
955
                                        return;
956
                                }
957
                                connectbuf[free_con_id] = (connect_data *) malloc(sizeof(connect_data));
958
                                memset(connectbuf[free_con_id],0,sizeof(connect_data));
959
                                connectbuf[free_con_id]->connection_head = connectbuf[free_con_id]->connection_last = NULL;
960
                                connectbuf[free_con_id]->starttime = time(NULL);
961
                                memcpy(&(connectbuf[free_con_id]->external_socketID), &(con_msg->sock_id), sizeof(socket_ID));
962
                                connectbuf[free_con_id]->pmtusize = con_msg->pmtu_size;
963
                                connectbuf[free_con_id]->external_connectionID = msg_h->local_con_id;
964
                                connectbuf[free_con_id]->internal_connect =  
965
                                        !compare_external_address_socketIDs(&(con_msg->sock_id), loc_socketID);
966
                                con_id = free_con_id;
967
                        }
968

    
969
                        if(connectbuf[con_id]->status <= CONNECT) {
970
                                //update status and send back answer
971
                                connectbuf[con_id]->status = CONNECT;
972
                                send_conn_msg(con_id, con_msg->pmtu_size, CONNECT);
973
                        }
974
                        break;
975
                case CONNECT:
976
                        debug("ML: received CONNECT");
977

    
978
                        if(msg_h->remote_con_id != -1 && connectbuf[msg_h->remote_con_id] == NULL) {
979
                                error("ML: received CONNECT for unexistent connection");
980
                                return;
981
                        }
982

    
983
                        /*
984
                        * check if the connection status is not already 1 or 2 
985
                        */
986
                        if (connectbuf[msg_h->remote_con_id]->status == INVITE) {
987
                                // set the external connectionID
988
                                connectbuf[msg_h->remote_con_id]->external_connectionID = msg_h->local_con_id;
989
                                // change status con_msg the connection_data
990
                                connectbuf[msg_h->remote_con_id]->status = READY;
991
                                // change pmtusize in the connection_data
992
                                connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
993

    
994
                                // send the READY
995
                                send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
996

    
997
                                if (receive_Connection_cb != NULL)
998
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
999

    
1000
                                // call all registered callbacks
1001
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
1002
                                        struct receive_connection_cb_list *temp;
1003
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
1004
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
1005
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
1006
                                        free(temp);
1007
                                }
1008
                                connectbuf[msg_h->remote_con_id]->connection_head =
1009
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
1010
                        } else
1011
                                // send the READY
1012
                                send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
1013

    
1014
                        debug("ML: active connection established");
1015
                        break;
1016

    
1017
                        /*
1018
                        * if READY: find the entry in the connection array set the
1019
                        * connection active change the pmtu size 
1020
                        */
1021
                case READY:
1022
                        debug("ML: received READY");
1023
                        if(connectbuf[msg_h->remote_con_id] == NULL) {
1024
                                error("ML: received READY for unexistent connection");
1025
                                return;
1026
                        }
1027
                        /*
1028
                        * checks if the connection is not already established 
1029
                        */
1030
                        if (connectbuf[msg_h->remote_con_id]->status == CONNECT) {
1031
                                // change status of the connection
1032
                                connectbuf[msg_h->remote_con_id]->status = 2;
1033
                                // change pmtusize
1034
                                connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
1035

    
1036
                                if (receive_Connection_cb != NULL)
1037
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
1038
                        
1039
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
1040
                                        struct receive_connection_cb_list *temp;
1041
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
1042
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
1043
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
1044
                                        free(temp);
1045
                                }
1046
                                connectbuf[msg_h->remote_con_id]->connection_head =
1047
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
1048
                                debug("ML: passiv connection established");
1049
                        }
1050
                        break;
1051
        }
1052
}
1053

    
1054
/*
1055
 * what to do once a packet arrived if it is a conn packet send it to
1056
 * recv_conn handler if it is a data packet send it to the recv_data
1057
 * handler 
1058
 */
1059

    
1060
//done --
1061
void recv_pkg(int fd, short event, void *arg)
1062
{
1063
        debug("ML: recv_pkg called");
1064

    
1065
        struct msg_header *msg_h;
1066
        char msgbuf[MAX];
1067
        char *bufptr = msgbuf;
1068
        int ttl;
1069
        struct sockaddr_in recv_addr;
1070
        pmtu recvSize = MAX;
1071
        int msg_size;
1072

    
1073
        recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
1074

    
1075

    
1076
        // check if it is not just an ERROR message
1077
        if(recvSize < 0)
1078
                return;
1079

    
1080
        // @TODO check if this simplistic STUN message recognition really always works, probably not
1081
        unsigned short stun_bind_response = 0x0101;
1082
        unsigned short * msgspot = (unsigned short *) msgbuf;
1083
        if (*msgspot == stun_bind_response) {
1084
                debug("ML: recv_pkg: parse stun message called");
1085
                recv_stun_msg(msgbuf, recvSize);
1086
                return;
1087
        }
1088

    
1089
        msg_h = (struct msg_header *) msgbuf;
1090
        bufptr += MSG_HEADER_SIZE + msg_h->len_mon_packet_hdr;
1091
        msg_size = recvSize - MSG_HEADER_SIZE - msg_h->len_mon_packet_hdr;
1092

    
1093

    
1094
        if(get_Recv_pkt_inf_cb != NULL && msg_h->len_mon_packet_hdr != 0) {
1095
                mon_pkt_inf msginfNow;
1096
                msginfNow.monitoringHeaderLen = msg_h->len_mon_packet_hdr;
1097
                msginfNow.monitoringHeader = msg_h->len_mon_packet_hdr ? &msgbuf[0] + MSG_HEADER_SIZE : NULL;
1098
                //TODO rethink this ...
1099
                if(msg_h->msg_type == ML_CON_MSG) {
1100
                        struct conn_msg *c_msg = (struct conn_msg *) bufptr;
1101
                        msginfNow.remote_socketID = &(c_msg->sock_id);
1102
                }
1103
                else if(connectbuf[msg_h->remote_con_id] == NULL) {
1104
                        error("ML: received pkg called with non existent connection");
1105
                        return;
1106
                } else
1107
                        msginfNow.remote_socketID = &(connectbuf[msg_h->remote_con_id]->external_socketID);
1108
                msginfNow.buffer = bufptr;
1109
                msginfNow.bufSize = recvSize;
1110
                msginfNow.msgtype = msg_h->msg_type;
1111
                msginfNow.ttl = ttl;
1112
                msginfNow.dataID = msg_h->msg_seq_num;
1113
                msginfNow.offset = msg_h->offset;
1114
                msginfNow.datasize = msg_h->msg_length;
1115
                gettimeofday(&msginfNow.arrival_time, NULL);
1116
                (get_Recv_pkt_inf_cb) ((void *) &msginfNow);
1117
        }
1118

    
1119

    
1120
        switch(msg_h->msg_type) {
1121
                case ML_CON_MSG:
1122
                        debug("ML: received conn pkg");
1123
                        recv_conn_msg(msg_h, bufptr, msg_size);
1124
                        break;
1125
                default:
1126
                        if(msg_h->msg_type < 127) {
1127
                                debug("ML: received data pkg");
1128
                                recv_data_msg(msg_h, bufptr, msg_size);
1129
                                break;
1130
                        }
1131
                        debug("ML: unrecognised msg_type");
1132
                        break;
1133
        }
1134
}
1135

    
1136
void recv_stun_msg(char *msgbuf, int recvSize)
1137
{
1138
        /*
1139
        * create empty stun message struct 
1140
        */
1141
        StunMessage resp;
1142
        memset(&resp, 0, sizeof(StunMessage));
1143
        /*
1144
        * parse the message 
1145
        */
1146
        int returnValue = 0;
1147
        returnValue = recv_stun_message(msgbuf, recvSize, &resp);
1148

    
1149
        if (returnValue == 0) {
1150
                /*
1151
                * read the reflexive Address into the local_socketID 
1152
                */
1153
                struct sockaddr_in reflexiveAddr;
1154
                reflexiveAddr.sin_family = AF_INET;
1155
                reflexiveAddr.sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
1156
                reflexiveAddr.sin_port = htons(resp.mappedAddress.ipv4.port);
1157
                socketaddrgen reflexiveAddres;
1158
                reflexiveAddres.udpaddr = reflexiveAddr;
1159
                local_socketID.external_addr = reflexiveAddres;
1160
                NAT_traversal = true;
1161
                // callback to the upper layer indicating that the socketID is now
1162
                // ready to use
1163
                (receive_SocketID_cb) (&local_socketID, 0);
1164
        }
1165
}
1166

    
1167
// process a single recv data message
1168
void recv_data_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
1169
{
1170
        debug("transmissionHandler: received data message called");
1171

    
1172
        int recv_id, free_recv_id = -1;
1173

    
1174
        if(connectbuf[msg_h->remote_con_id] == NULL) {
1175
                debug("ML: Received a message not related to any opened connection!");
1176
                return;
1177
        }
1178

    
1179
        // check if a recv_data exist and enter data
1180
        for (recv_id = 0; recv_id < RECVDATABUFSIZE; recv_id++)
1181
                if (recvdatabuf[recv_id] != NULL) {
1182
                        if (msg_h->remote_con_id == recvdatabuf[recv_id]->connectionID && 
1183
                                        msg_h->msg_seq_num == recvdatabuf[recv_id]->seqnr)
1184
                                                break;
1185
                } else
1186
                        if(free_recv_id == -1)
1187
                                free_recv_id = recv_id;
1188

    
1189

    
1190
        if(recv_id == RECVDATABUFSIZE) { 
1191
                //no recv_data found: create one
1192
                recv_id = free_recv_id;
1193
                recvdatabuf[recv_id] = (recvdata *) malloc(sizeof(recvdata));
1194
                memset(recvdatabuf[recv_id], 0, sizeof(recvdata));
1195
                recvdatabuf[recv_id]->connectionID = msg_h->remote_con_id;
1196
                recvdatabuf[recv_id]->seqnr = msg_h->msg_seq_num;
1197
                recvdatabuf[recv_id]->monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
1198
                recvdatabuf[recv_id]->bufsize = msg_h->msg_length + msg_h->len_mon_data_hdr;
1199
                recvdatabuf[recv_id]->recvbuf = (char *) malloc(recvdatabuf[recv_id]->bufsize);
1200
                /*
1201
                * read the timeout data and set it 
1202
                */
1203
                recvdatabuf[recv_id]->timeout_value.tv_sec = recv_timeout.tv_sec;
1204
                recvdatabuf[recv_id]->timeout_value.tv_usec = recv_timeout.tv_usec;
1205
                recvdatabuf[recv_id]->recvID = recv_id;
1206
                recvdatabuf[recv_id]->starttime = time(NULL);
1207
                recvdatabuf[recv_id]->msgtype = msg_h->msg_type;
1208

    
1209
                // fill the buffer with zeros
1210
                memset(recvdatabuf[recv_id]->recvbuf, 0, msg_h->msg_length);
1211
        }
1212

    
1213
        if (msg_h->offset == 0)
1214
                recvdatabuf[recv_id]->firstPacketArrived = 1;
1215

    
1216

    
1217
        // increment fragmentnr
1218
        recvdatabuf[recv_id]->recvFragments++;
1219
        // increment the arrivedBytes
1220
        recvdatabuf[recv_id]->arrivedBytes += bufsize;
1221

    
1222
        // enter the data into the buffer
1223
        memcpy(recvdatabuf[recv_id]->recvbuf + msg_h->offset, msgbuf, bufsize);
1224
        
1225
        //TODO very basic checkif all fragments arrived: has to be reviewed
1226
        if(recvdatabuf[recv_id]->arrivedBytes == recvdatabuf[recv_id]->bufsize)
1227
                recvdatabuf[recv_id]->status = COMPLETE; //buffer full -> msg completly arrived
1228
        else
1229
                recvdatabuf[recv_id]->status = ACTIVE;
1230

    
1231
        if (recv_data_callback) {
1232
                if(recvdatabuf[recv_id]->status == COMPLETE) {
1233
                        // Monitoring layer hook
1234
                        if(get_Recv_data_inf_cb != NULL) {
1235
                                mon_data_inf recv_data_inf;
1236
        
1237
                                recv_data_inf.remote_socketID =
1238
                                         &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
1239
                                recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
1240
                                recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
1241
                                recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
1242
                                recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
1243
                                recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
1244
                                        recvdatabuf[recv_id]->recvbuf : NULL;
1245
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
1246
                                recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
1247
                                recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
1248
                                recv_data_inf.priority = false;
1249
                                recv_data_inf.padding = false;
1250
                                recv_data_inf.confirmation = false;
1251
                                recv_data_inf.reliable = false;
1252

    
1253
                                // send data recv callback to monitoring module
1254

    
1255
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1256
                        }
1257

    
1258
                        // Get the right callback
1259
                        receive_data_cb receive_data_callback = recvcbbuf[msg_h->msg_type];
1260
        
1261
                        recv_params rParams;
1262
        
1263
                        rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
1264
                        rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
1265
                        rParams.msgtype = recvdatabuf[recv_id]->msgtype;
1266
                        rParams.connectionID = recvdatabuf[recv_id]->connectionID;
1267
                        rParams.remote_socketID = 
1268
                                &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
1269
                        rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
1270
        
1271
                        (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
1272
                                recvdatabuf[recv_id]->msgtype, (void *) &rParams);
1273
        
1274
                        //clean up
1275
                        free(recvdatabuf[recv_id]->recvbuf);
1276
                        free(recvdatabuf[recv_id]);
1277
                        recvdatabuf[recv_id] = NULL;
1278
                } else { // not COMPLETE
1279
                        //start time out
1280
                        //TODO make timeout at least a DEFINE
1281
                        struct timeval timeout = { 4, 0 };
1282
                        event_base_once(base, -1, EV_TIMEOUT, &recv_timeout_cb, (void *) recv_id, &timeout);
1283
                }
1284
        }
1285
}
1286

    
1287
//done
1288
void recv_timeout_cb(int fd, short event, void *arg)
1289
{
1290
        int recv_id = (int) arg;
1291
        debug("ML: recv_timeout_cb called");
1292

    
1293
        if (recvdatabuf[recv_id] == NULL) {
1294
                return;
1295
        }
1296

    
1297

    
1298
        if(recvdatabuf[recv_id]->status == ACTIVE) {
1299
                //TODO make timeout at least a DEFINE
1300
                struct timeval timeout = { 4, 0 };
1301
                recvdatabuf[recv_id]->status = INACTIVE;
1302
                event_base_once(base, -1, EV_TIMEOUT, recv_timeout_cb,
1303
                        arg, &timeout);
1304
                return;
1305
        }
1306

    
1307
        if(recvdatabuf[recv_id]->status == INACTIVE) {
1308
                // Monitoring layer hook
1309
                if(get_Recv_data_inf_cb != NULL) {
1310
                        mon_data_inf recv_data_inf;
1311

    
1312
                        recv_data_inf.remote_socketID =
1313
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
1314
                        recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
1315
                        recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
1316
                        recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
1317
                        recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
1318
                        recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
1319
                                recvdatabuf[recv_id]->recvbuf : NULL;
1320
                        gettimeofday(&recv_data_inf.arrival_time, NULL);
1321
                        recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
1322
                        recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
1323
                        recv_data_inf.priority = false;
1324
                        recv_data_inf.padding = false;
1325
                        recv_data_inf.confirmation = false;
1326
                        recv_data_inf.reliable = false;
1327

    
1328
                        // send data recv callback to monitoring module
1329

    
1330
                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1331
                }
1332

    
1333
                // Get the right callback
1334
                receive_data_cb receive_data_callback = recvcbbuf[recvdatabuf[recv_id]->msgtype];
1335

    
1336
                recv_params rParams;
1337

    
1338
                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
1339
                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
1340
                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
1341
                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
1342
                rParams.remote_socketID = 
1343
                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
1344
                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
1345

    
1346
                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
1347
                        recvdatabuf[recv_id]->msgtype, &rParams);
1348

    
1349
                //clean up
1350
                free(recvdatabuf[recv_id]->recvbuf);
1351
                free(recvdatabuf[recv_id]);
1352
                recvdatabuf[recv_id] = NULL;
1353
        }
1354
}
1355

    
1356
//done
1357
void pmtu_timeout_cb(int fd, short event, void *arg)
1358
{
1359
        debug("ML: pmtu timeout called");
1360

    
1361
        int con_id = (int) arg;
1362
        pmtu new_pmtusize;
1363
        struct timeval timeout;
1364
        
1365
        if(connectbuf[con_id] == NULL) {
1366
                error("ML: pmtu timeout called on non existing con_id");
1367
                return;
1368
        }
1369

    
1370
        if(connectbuf[con_id]->status == READY) {
1371
                // nothing to do anymore
1372
                return;
1373
        }
1374

    
1375
        timeout = connectbuf[con_id]->timeout_value;
1376

    
1377
        if(connectbuf[con_id]->delay || connectbuf[con_id]->trials == MAX_TRIALS - 1) {
1378
                double delay = timeout.tv_sec + timeout.tv_usec / 1000000.0;
1379
                delay = delay * 5;
1380
                timeout.tv_sec = floor(delay);
1381
                timeout.tv_usec = fmod(delay, 1.0) * 1000000.0;
1382
                if(connectbuf[con_id]->delay) {
1383
                        connectbuf[con_id]->delay = false;
1384
                        goto reschedule;
1385
                }
1386
        }
1387

    
1388
        if(connectbuf[con_id]->trials == MAX_TRIALS) {
1389
                // decrement the pmtu size
1390
                connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
1391
                connectbuf[con_id]->trials = 0;
1392
        }
1393

    
1394
        //error in PMTU discovery?
1395
        if (connectbuf[con_id]->pmtusize == ERROR) {
1396
                if (connectbuf[con_id]->internal_connect == true) {
1397
                        //as of now we tried directly connecting, now let's try trough the NAT
1398
                        connectbuf[con_id]->internal_connect = false;
1399
                        connectbuf[con_id]->pmtusize = MAX;
1400
                } else {
1401
                        //nothing to do we have to give up
1402
                        error("ML: Could not create connection with connectionID %i!",con_id);
1403
                        // envoke the callback for failed connection establishment
1404
                        if(failed_Connection_cb != NULL)
1405
                                (failed_Connection_cb) (con_id, NULL);
1406
                        // delete the connection entry
1407
                        close_connection(con_id);
1408
                        return;
1409
                }
1410
        }
1411

    
1412
        //retry with new pmtu size
1413
        connectbuf[con_id]->trials++;
1414
        send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
1415

    
1416
reschedule:
1417
        /* reschedule */
1418
        event_base_once(base, -1, EV_TIMEOUT, pmtu_timeout_cb, (void *) con_id, &timeout);
1419
}
1420

    
1421
/*
1422
 * decrements the mtu size
1423
 */
1424
pmtu pmtu_decrement(pmtu pmtusize)
1425
{
1426
        pmtu pmtu_return_size;
1427
        switch(pmtusize) {
1428
        case MAX:
1429
                return DSL;
1430
        case DSL:
1431
                return DSLMEDIUM;
1432
        case DSLMEDIUM:
1433
                return DSLSLIM;
1434
        case DSLSLIM:
1435
                return BELOWDSL;
1436
        case BELOWDSL:
1437
                return MIN;
1438
        default:
1439
                return ERROR;
1440
        }
1441
}
1442

    
1443
void pmtu_error_cb_th(char *msg, int msglen)
1444
{
1445
        debug("ML: pmtu_error callback called msg_size: %d",msglen);
1446
        //TODO debug
1447
        return;
1448

    
1449
    char *msgbufptr = NULL;
1450
    int msgtype;
1451
    int connectionID;
1452
    pmtu pmtusize;
1453
    pmtu new_pmtusize;
1454
    int dead = 0;
1455

    
1456
    // check the packettype
1457
    msgbufptr = &msg[0];
1458

    
1459
    // check the msgtype
1460
    msgbufptr = &msg[1];
1461
    memcpy(&msgtype, msgbufptr, 4);
1462

    
1463
    if (msgtype == 0) {
1464

    
1465
        // get the connectionID
1466
        msgbufptr = &msg[5];
1467
        memcpy(&connectionID, msgbufptr, 4);
1468

    
1469
        int msgtype_c = connectbuf[connectionID]->status;
1470
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
1471

    
1472
        if (msgtype_c != msgtype) {
1473
            dead = 1;
1474
        }
1475

    
1476

    
1477
    } else if (msgtype == 1) {
1478

    
1479
        // read the connectionID
1480
        msgbufptr = &msg[9];
1481
        memcpy(&connectionID, msgbufptr, 4);
1482

    
1483
        int msgtype_c = connectbuf[connectionID]->status;
1484
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
1485

    
1486
        if (msgtype_c != msgtype) {
1487
            dead = 1;
1488
        }
1489

    
1490
    }
1491
    // decrement the pmtu size 
1492
    new_pmtusize = pmtu_decrement(pmtusize);
1493

    
1494
//    connectbuf[connectionID]->pmtutrysize = new_pmtusize;
1495

    
1496
    if (new_pmtusize == ERROR) {
1497
                fprintf(stderr,
1498
                        "transmissionHandler:  Could not create connection with connectionID %i !\n",
1499
                        connectionID);
1500
                
1501
                if(failed_Connection_cb != NULL)
1502
                        (failed_Connection_cb) (connectionID, NULL);
1503
                // set the message type to a non existent message 
1504
                msgtype = 2;
1505
                // delete the connection entry
1506
                 close_connection(connectionID);
1507
        }
1508

    
1509
    if (msgtype == 0 && dead != 1) {
1510

    
1511
        // stop the timeout event
1512
        // timeout_del(connectbuf[connectionID]->timeout);
1513
        /*
1514
         * libevent2 
1515
         */
1516

    
1517
        // event_del(connectbuf[connectionID]->timeout);
1518

    
1519

    
1520
        // create and send a connection message
1521
//         create_conn_msg(new_pmtusize, connectionID, 
1522
//                         &local_socketID, INVITE);
1523

    
1524
//        send_conn_msg(connectionID, new_pmtusize);
1525

    
1526
        // set a timeout event for the pmtu discovery 
1527
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void 
1528
        // *)&connectionID);
1529

    
1530
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1531

    
1532
        /*
1533
         * libevent2 
1534
         */
1535

    
1536
        struct event *ev;
1537
        ev = evtimer_new(base, pmtu_timeout_cb,
1538
                         (void *) connectbuf[connectionID]);
1539

    
1540
        // connectbuf[connectionID]->timeout = ev;
1541

    
1542
        event_add(ev, &connectbuf[connectionID]->timeout_value);
1543

    
1544
    } else if (msgtype == 1 && dead != 1) {
1545

    
1546
        // stop the timeout event
1547
        // timeout_del(connectbuf[connectionID]->timeout);
1548

    
1549
        /*
1550
         * libevent2 
1551
         */
1552
        // printf("still here 11 \n");
1553
        // printf("ev %d \n",connectbuf[connectionID]->timeout);
1554
        // event_del(connectbuf[connectionID]->timeout );
1555
        // evtimer_del(connectbuf[connectionID]->timeout );
1556

    
1557

    
1558
//         // create and send a connection message
1559
//         create_conn_msg(new_pmtusize,
1560
//                         connectbuf[connectionID]->connectionID,
1561
//                         NULL, CONNECT);
1562

    
1563
        //send_conn_msg(connectionID, new_pmtusize);
1564

    
1565
        // set a timeout event for the pmtu discovery 
1566
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void 
1567
        // *)&connectionID);
1568
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1569

    
1570
        /*
1571
         * libevent2 
1572
         */
1573
        // struct event *ev;
1574
        // ev = evtimer_new(base,pmtu_timeout_cb, (void
1575
        // *)connectbuf[connectionID]);
1576
        // connectbuf[connectionID]->timeout = ev;
1577
        // event_add(ev,&connectbuf[connectionID]->timeout_value);
1578

    
1579
    }
1580
}
1581

    
1582
/*
1583
 * compare the external IP address of two socketIDs 
1584
 */
1585
int
1586
compare_external_address_socketIDs(socketID_handle sock1, socketID_handle sock2)
1587
{
1588
        if( sock1->external_addr.udpaddr.sin_addr.s_addr == sock2->external_addr.udpaddr.sin_addr.s_addr)
1589
                return 0;
1590
        return 1;
1591
}
1592

    
1593

    
1594
/*
1595
 * hash code of a socketID
1596
 * TODO might think of a better way
1597
 */
1598
int hash_socketID(socketID_handle sock)
1599
{
1600
    return sock->internal_addr.udpaddr.sin_port +
1601
                          sock->external_addr.udpaddr.sin_port;
1602
}
1603

    
1604
/*
1605
 * compares 2 socketIDs: returns 0 if they are equl otherwise 1 
1606
 */
1607
int compare_socketIDs(socketID_handle sock1, socketID_handle sock2)
1608
{
1609
        /*
1610
        * compare internal addr 
1611
        */
1612
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr != 
1613
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
1614
                        return 1;
1615

    
1616
        if (sock1->internal_addr.udpaddr.sin_port !=
1617
                 sock2->internal_addr.udpaddr.sin_port)
1618
                        return 1;
1619

    
1620
        /*
1621
        * compare external addr 
1622
        */
1623
        if (sock1->external_addr.udpaddr.sin_addr.s_addr != 
1624
            sock2->external_addr.udpaddr.sin_addr.s_addr)
1625
                        return 1;
1626

    
1627
        if (sock1->external_addr.udpaddr.sin_port !=
1628
                 sock2->external_addr.udpaddr.sin_port)
1629
                        return 1;
1630

    
1631
        return 0;
1632
}
1633

    
1634
/*
1635
 * the timeout of the NAT traversal 
1636
 */
1637
void nat_traversal_timeout(int fd, short event, void *arg)
1638
{
1639
        if (NAT_traversal == false) {
1640
                debug("ML: NAT traversal request resend");
1641
                send_stun_request(socketfd, &stun_server);
1642

    
1643
                /*
1644
                * enter a NAT traversal timeout that takes care of retransmission 
1645
                */
1646
                struct event *ev1;
1647
                struct timeval timeout_value_NAT_traversal = { 1, 0 };
1648
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1649
                event_add(ev1, &timeout_value_NAT_traversal);
1650
                if(receive_SocketID_cb)
1651
                        (receive_SocketID_cb) (&local_socketID, 2);
1652
        }
1653
}
1654

    
1655
int get_standard_ttl(socketID_handle socketID, uint8_t *ttl)
1656
{
1657
        return getTTL(socketfd, ttl);
1658
}
1659

    
1660
socketID_handle get_local_socketID(int *error_status)
1661
{
1662
        if (NAT_traversal == false) {
1663
                *error_status = 2;
1664
                return NULL;
1665
        }
1666

    
1667
        *error_status = 0;
1668
        return &local_socketID;
1669
}
1670

    
1671
int get_external_IP(char *external_addr)
1672
{
1673
        socketaddrgen udpgen;
1674
        struct sockaddr_in udpaddr;
1675

    
1676
        udpgen = local_socketID.external_addr;
1677
        udpaddr = udpgen.udpaddr;
1678

    
1679
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
1680
                        INET_ADDRSTRLEN);
1681
        
1682
        if (external_addr == NULL) {
1683
        
1684
        return -1;
1685
        
1686
        } else {
1687
        
1688
        return 0;
1689
        
1690
        }
1691
        
1692
}
1693

    
1694
int print_socketID(socketID_handle sock)
1695
{
1696
        char str[SOCKETID_STRING_SIZE];
1697
        socketID_to_String(sock, str, sizeof(str));
1698
        printf("int->%s<-ext\n",str);
1699
}
1700

    
1701
int socketID_to_String(socketID_handle sock, char *sock_string, size_t len)
1702
{
1703
        char internal_addr[INET_ADDRSTRLEN];
1704
        char external_addr[INET_ADDRSTRLEN];
1705
        inet_ntop(AF_INET, &(sock->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1706
        inet_ntop(AF_INET, &(sock->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1707
        
1708
        snprintf(sock_string,len,"%s:%d-%s:%d", internal_addr, ntohs(sock->internal_addr.udpaddr.sin_port),
1709
                external_addr,        ntohs(sock->external_addr.udpaddr.sin_port));
1710
        return 0;
1711
}
1712

    
1713
int string_to_socketID(char* socketID_string, socketID_handle sock)
1714
{
1715
        //@TODO add checks against malformed string
1716
        char external_addr[INET_ADDRSTRLEN];
1717
        int external_port;
1718
        char internal_addr[INET_ADDRSTRLEN];
1719
        int internal_port;
1720

    
1721
        char *pch;
1722

    
1723
        //replace ':' with a blank
1724
        pch=strchr(socketID_string,':');
1725
        while (pch!=NULL){
1726
                                *pch = ' ';
1727
                pch=strchr(pch+1,':');
1728
        }
1729
        pch=strchr(socketID_string,'-');
1730
        if(pch) *pch = ' ';
1731

    
1732
        sscanf(socketID_string,"%s %d %s %d", internal_addr, &internal_port,
1733
                external_addr, &external_port);
1734

    
1735
        if(inet_pton(AF_INET, internal_addr, &(sock->internal_addr.udpaddr.sin_addr)) == 0)
1736
                return EINVAL;
1737
        sock->internal_addr.udpaddr.sin_family = AF_INET;
1738
        sock->internal_addr.udpaddr.sin_port = htons(internal_port);
1739
        
1740

    
1741
        if(inet_pton(AF_INET, external_addr, &(sock->external_addr.udpaddr.sin_addr)) ==0)
1742
                return EINVAL;
1743
        sock->external_addr.udpaddr.sin_family = AF_INET;
1744
        sock->external_addr.udpaddr.sin_port = htons(external_port);
1745

    
1746
        return 0;
1747
}
1748

    
1749

    
1750
int get_connection_status(int con_id)
1751
{
1752
        if(connectbuf[con_id])
1753
                return connectbuf[con_id]->status == READY;
1754
        return -1;
1755
}
1756

    
1757

    
1758
int connection_exist(socketID_handle socketID) {
1759
    /*
1760
     * check if another connection for the external connectionID exist
1761
     * that was established \ within the last 2 seconds
1762
     */
1763
        int i;
1764
        for (i = 0; i < CONNECTBUFSIZE; i++)
1765
                if (connectbuf[i] != NULL)
1766
                        if (compare_socketIDs(&(connectbuf[i]->external_socketID), socketID) == 0)
1767
                                return i;
1768

    
1769
    return -1;
1770
}
1771

    
1772
int get_path_mtu(int ConnectionId) {
1773
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
1774
                return -1;
1775
        if (connectbuf[ConnectionId] != NULL)
1776
                return connectbuf[ConnectionId]->pmtusize;
1777
        return -1;
1778
}
1779

    
1780
unsigned long resolve(const char *ipaddr)
1781
{
1782
        struct hostent *h = gethostbyname(ipaddr);
1783
        if (!h) {
1784
                error("Unable to resolve hostname %s\n", ipaddr);
1785
        exit(-1);
1786
    }
1787
    unsigned long *addr = (unsigned long *) (h->h_addr);
1788
    return *addr;
1789
}