Statistics
| Branch: | Revision:

ml / transmissionHandler.c @ 85bc61b5

History | View | Annotate | Download (49.3 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
 * functions 
151
 */
152
/*
153
 * register callback functions 
154
 */
155

    
156
void register_get_recv_pkt_inf(get_recv_pkt_inf_cb recv_pkt_inf_cb)
157
{
158
        if (recv_pkt_inf_cb == NULL)
159
                printf("Register get_recv_pkt_inf_cb failed: NULL ptr  \n");
160
        else
161
                get_Recv_pkt_inf_cb = recv_pkt_inf_cb;
162
}
163

    
164
void register_get_send_pkt_inf(get_send_pkt_inf_cb send_pkt_inf_cb)
165
{
166
        if (send_pkt_inf_cb == NULL)
167
                printf("Register get_send_pkt_inf_cb: NULL ptr  \n");
168
        else
169
                get_Send_pkt_inf_cb = send_pkt_inf_cb;
170
}
171

    
172
void
173
register_set_monitoring_header_pkt_cb(set_monitoring_header_pkt_cb
174
                                      monitoring_header_pkt_cb)
175
{
176
        if (monitoring_header_pkt_cb == NULL)
177
                printf("Register set_monitoring_header_pkt_cb: NULL ptr  \n");
178
        else
179
                set_Monitoring_header_pkt_cb = monitoring_header_pkt_cb;
180
}
181

    
182
void register_get_recv_data_inf(get_recv_data_inf_cb recv_data_inf_cb)
183
{
184
        if (recv_data_inf_cb == NULL)
185
                printf("Register get_recv_data_inf_cb: NULL ptr  \n");
186
        else
187
                get_Recv_data_inf_cb = recv_data_inf_cb;
188
}
189

    
190
void register_get_send_data_inf(get_send_data_inf_cb send_data_inf_cb)
191
{
192
        if (send_data_inf_cb == NULL)
193
                printf("Register get_send_data_inf_cb: NULL ptr  \n");
194
        else
195
                get_Send_data_inf_cb = send_data_inf_cb;
196
}
197

    
198
void
199
register_set_monitoring_header_data_cb(set_monitoring_header_data_cb
200
                                       monitoring_header_data_cb)
201
{
202
        if (monitoring_header_data_cb == NULL)
203
                printf("Register set_monitoring_header_data_cb : NULL ptr  \n");
204
        else
205
        set_Monitoring_header_data_cb = monitoring_header_data_cb;
206
}
207

    
208
void register_recv_connection_cb(receive_connection_cb connection_cb)
209
{
210
        if (connection_cb == NULL)
211
                printf("Register receive_connection_cb: NULL ptr  \n");
212
        else
213
                receive_Connection_cb = connection_cb;
214
}
215

    
216
void
217
register_recv_localsocketID_cb(receive_localsocketID_cb local_socketID_cb)
218
{
219
        if (local_socketID_cb == NULL)
220
                printf("Register receive_localsocketID_cb: NULL ptr \n");
221
        else
222
        receive_SocketID_cb = local_socketID_cb;
223
}
224

    
225

    
226
void register_error_connection_cb(connection_failed_cb connection_fail)
227
{
228
        if (connection_fail == NULL)
229
                printf("Register connection_failed_cb: NULL ptr  \n");
230
        else
231
        failed_Connection_cb = connection_fail;
232
}
233

    
234

    
235
void register_recv_data_cb(receive_data_cb data_cb, unsigned char msgtype)
236
{
237

    
238
    if (msgtype > 126) {
239

    
240
        printf
241
            ("transmissionHandler: Could not register recv_data callback. Msgtype is greater then 126 \n");
242

    
243
    }
244

    
245
    if (data_cb == NULL) {
246

    
247
        printf("Register receive data callback: NUll ptr \n ");
248

    
249
    } else {
250

    
251
        recvcbbuf[msgtype] = data_cb;
252

    
253
    }
254
}
255

    
256
void
257
init_transmissionHandler(boolean recv_data_cb,
258
                         struct timeval timeout_value, const int port,
259
                         const char *ipaddr, const int stun_port,
260
                         const char *stun_ipaddr,
261
                         receive_localsocketID_cb local_socketID_cb,
262
                         void *arg)
263
{
264
        base = (struct event_base *) arg;
265
        recv_data_callback = recv_data_cb;
266
        setRecvTimeout(timeout_value);
267
        setStunServer(stun_port, stun_ipaddr);
268
        register_recv_localsocketID_cb(local_socketID_cb);
269
        create_socket(port, ipaddr);
270
}
271

    
272
/*
273
 * Sockets 
274
 */
275
/*
276
 * returns a handle to the socketID struct the ipaddr can be a null
277
 * pointer. Then all available ipaddr on the machine are choosen.
278
 */
279
void create_socket(const int port, const char *ipaddr)
280
{
281
        struct sockaddr_in udpaddr;
282
        udpaddr.sin_family = AF_INET;
283
        if (ipaddr == NULL)
284
                udpaddr.sin_addr.s_addr = INADDR_ANY;
285
        else
286
                udpaddr.sin_addr.s_addr = inet_addr(ipaddr);
287
        udpaddr.sin_port = htons(port);
288

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

    
313
        NAT_traversal = false;
314
}
315

    
316
void close_socket(socketID_handle socketID)
317
{
318
        free(socketID);
319
}
320

    
321
/*
322
 * Connections 
323
 */
324
// the first socketID is the from socketID, the second one is the to
325
// socketID
326

    
327
int
328
open_connection(socketID_handle external_socketID, receive_connection_cb connection_cb, void *arg)
329
{
330
        int con_id;
331
        if (external_socketID == NULL) {
332
                error("ML: cannot open connection: one of the socketIDs is NULL");
333
                return -1;
334
        } 
335
        if (NAT_traversal == false) {
336
                error("ML: cannot open connection: NAT traversal for socketID still in progress");
337
                return -1;
338
        }
339
        if (connection_cb == NULL) {
340
                error("ML: cannot open connection: connection_cb is NULL");
341
                return -1;
342
        }
343

    
344
        // check if that connection already exist
345

    
346
        con_id = connection_exist(external_socketID);
347
        if (con_id >= 0) {
348
                // if so check if it is ready to use        
349
                if (connectbuf[con_id]->status == READY) {
350
                                // if so use the callback immidiatley
351
                                (connection_cb) (con_id, arg);
352

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

    
387
                        connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
388
                        connectbuf[con_id]->connection_last->next = NULL;
389
                        connectbuf[con_id]->connection_last->connection_cb = connection_cb;
390
                        connectbuf[con_id]->connection_last->arg = arg;
391
                        connectbuf[con_id]->external_connectionID = -1;
392
                        break;
393
                }
394
        } //end of for
395

    
396
        if (con_id == CONNECTBUFSIZE) {
397
                error("ML: Could not open connection: connbuffer full");
398
                return -1;
399
        }
400

    
401
        // create and send a connection message
402
        send_conn_msg(con_id, MAX, INVITE);
403

    
404
        struct event *ev;
405
        ev = evtimer_new(base, pmtu_timeout_cb, (void *) con_id);
406
        event_add(ev, &connectbuf[con_id]->timeout_value);
407

    
408
        return con_id;
409
}
410

    
411
//done
412
void close_connection(const int connectionID)
413
{
414
        // remove it from the connection array
415
        if(connectbuf[connectionID]) {
416
                if(connectbuf[connectionID]->ctrl_msg_buf)
417
                        free(connectbuf[connectionID]->ctrl_msg_buf);
418
                free(connectbuf[connectionID]);
419
                connectbuf[connectionID] = NULL;
420
        }
421
}
422

    
423
void keep_connection_alive(const int connectionID)
424
{
425

    
426
    // to be done with the NAT traversal
427
    // send a message over the wire
428
    printf("\n");
429

    
430
}
431

    
432
int
433
send_all_data(const int connectionID, send_all_data_container * container,
434
              int nr_entries, unsigned char msgtype, send_params * sParams)
435
{
436

    
437

    
438

    
439
    if (nr_entries < 1 || nr_entries > 5) {
440

    
441
        printf
442
            ("send_all_data ERROR: nr_enties is not between 1 and 5 \n ");
443
        return 0;
444

    
445
    } else {
446

    
447
        if (nr_entries == 1) {
448

    
449
            send_data(connectionID, container->buffer_1,
450
                      container->length_1, msgtype, sParams);
451

    
452
            return 1;
453

    
454
        } else if (nr_entries == 2) {
455

    
456
            int buflen = container->length_1 + container->length_2;
457
            char buf[buflen];
458
            memcpy(buf, container->buffer_1, container->length_1);
459
            memcpy(&buf[container->length_1], container->buffer_2,
460
                   container->length_2);
461
            send_data(connectionID, buf, buflen, msgtype, sParams);
462

    
463
            return 1;
464

    
465
        } else if (nr_entries == 3) {
466

    
467
            int buflen =
468
                container->length_1 + container->length_2 +
469
                container->length_3;
470
            char buf[buflen];
471
            memcpy(buf, container->buffer_1, container->length_1);
472
            memcpy(&buf[container->length_1], container->buffer_2,
473
                   container->length_2);
474
            memcpy(&buf[container->length_2], container->buffer_3,
475
                   container->length_3);
476
            send_data(connectionID, buf, buflen, msgtype, sParams);
477

    
478

    
479
            return 1;
480

    
481
        } else if (nr_entries == 4) {
482

    
483
            int buflen =
484
                container->length_1 + container->length_2 +
485
                container->length_3 + container->length_4;
486
            char buf[buflen];
487
            memcpy(buf, container->buffer_1, container->length_1);
488
            memcpy(&buf[container->length_1], container->buffer_2,
489
                   container->length_2);
490
            memcpy(&buf[container->length_2], container->buffer_3,
491
                   container->length_3);
492
            memcpy(&buf[container->length_3], container->buffer_4,
493
                   container->length_4);
494
            send_data(connectionID, buf, buflen, msgtype, sParams);
495

    
496
            return 1;
497

    
498
        } else {
499

    
500
            int buflen =
501
                container->length_1 + container->length_2 +
502
                container->length_3 + container->length_4 +
503
                container->length_5;
504
            char buf[buflen];
505
            memcpy(buf, container->buffer_1, container->length_1);
506
            memcpy(&buf[container->length_1], container->buffer_2,
507
                   container->length_2);
508
            memcpy(&buf[container->length_2], container->buffer_3,
509
                   container->length_3);
510
            memcpy(&buf[container->length_3], container->buffer_4,
511
                   container->length_4);
512
            memcpy(&buf[container->length_4], container->buffer_5,
513
                   container->length_5);
514
            send_data(connectionID, buf, buflen, msgtype, sParams);
515

    
516
            return 1;
517
        }
518

    
519
    }
520

    
521

    
522
}
523

    
524
/*
525
 * send an entire block of data 
526
 */
527
void send_data(int con_id, char *sendbuf, int bufsize, int msgtype, send_params * sParams)
528
{
529
        if (sParams == NULL) {
530
                error("ML: send data failed: send_params is a NULL ptr");
531
                return;
532
        }
533

    
534
        if (con_id < 0) {
535
                error("ML: send data failed: connectionID does not exist");
536
                return;
537
        }
538

    
539
        if (connectbuf[con_id] == NULL) {
540
                error("ML: send data failed: connectionID does not exist");
541
                return;
542
        }
543
        if (connectbuf[con_id]->status != READY) {
544
            error("ML: send data failed: connection is not active");
545
            return;
546
        }
547

    
548
        send_msg(con_id, msgtype, sendbuf, bufsize, false, sParams);
549
}
550

    
551
/*
552
 * recv data with polling 
553
 */
554
int
555
recv_data(const int connectionID, char *recvbuf, int *bufsize,
556
          recv_params * rParams)
557
{
558
        //TODO yet to be converted
559
        return 0;
560
#if 0
561
        if (rParams == NULL) {
562
                error("ML: recv_data failed: recv_params is a NULL ptr");
563
                return 0;
564
    } else {
565

566
        printf("transmissionhandler: recv data called \n");
567

568
        int i = 0;
569
        int returnValue = 0;
570
        double timeout = (double) recv_timeout.tv_sec;
571
        time_t endtime = time(NULL);
572

573
        for (i = 0; i < RECVDATABUFSIZE; i++) {
574

575
            if (recvdatabuf[i] != NULL) {
576

577
                if (recvdatabuf[i]->connectionID == connectionID) {
578

579
                    printf("transmissionhandler: recv data has entry  \n");
580

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

583
                    // check if the specified connection has data and it
584
                    // is complete
585
                    // check the data seqnr
586
                    // if(connectionID == recvdatabuf[i]->connectionID &&
587
                    // 1 == recvdatabuf[i]->status){
588

589
                    if (1 == recvdatabuf[i]->status) {
590

591
                        // printf("transmissionHandler: recv_data set is
592
                        // complete \n" );
593

594
                        // printf("debud \n");
595

596
                        // exchange the pointers
597
                        int buffersize = 0;
598
                        buffersize = recvdatabuf[i]->bufsize;
599
                        *bufsize = buffersize;
600
                        // recvbuf = recvdatabuf[i]->recvbuf;
601

602
                        // printf("buffersize %d \n",buffersize);
603
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
604
                               buffersize);
605
                        // printf(" recvbuf %s \n",recvbuf );
606

607
//                         double nrMissFrags =
608
//                             (double) recvdatabuf[i]->nrFragments /
609
//                             (double) recvdatabuf[i]->recvFragments;
610
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
611

612
//                        rParams->nrMissingFragments = nrMissingFragments;
613
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
614
                        rParams->msgtype = recvdatabuf[i]->msgtype;
615
                        rParams->connectionID =
616
                            recvdatabuf[i]->connectionID;
617

618
                        // break from the loop
619
                        // printf(" recvbuf %s \n ",recvbuf);
620

621
                        // double nrMissFrags =
622
                        // (double)recvdatabuf[i]->nrFragments /
623
                        // (double)recvdatabuf[i]->recvFragments;
624
                        // int nrMissingFragments =
625
                        // (int)ceil(nrMissFrags);
626

627
                        if(get_Recv_data_inf_cb != NULL) {
628
                                mon_data_inf recv_data_inf;
629

630
                                recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
631
                                recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
632
                                recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
633
                                recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
634
//                                 recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
635
//                                 recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
636
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
637
                                recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
638
                                recv_data_inf.nrMissingFragments = nrMissingFragments;
639
                                recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
640
                                recv_data_inf.priority = false;
641
                                recv_data_inf.padding = false;
642
                                recv_data_inf.confirmation = false;
643
                                recv_data_inf.reliable = false;
644

645
                                // send data recv callback to monitoring module
646

647
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
648
                        }
649

650

651
                        // free the allocated memory
652
                        free(recvdatabuf[i]);
653
                        recvdatabuf[i] = NULL;
654

655
                        returnValue = 1;
656
                        break;
657

658
                    }
659

660
                    if (recvdatabuf[i] != NULL) {
661

662
                        if (timepass > timeout) {
663

664
                            printf("transmissionHandler: recv_data timeout called  \n");
665

666
                            // some data about the missing chunks should
667
                            // be added here
668
                            // exchange the pointers 
669
                            int buffersize = 0;
670
                            buffersize = recvdatabuf[i]->bufsize;
671
                            *bufsize = buffersize;
672
                            // recvbuf = recvdatabuf[i]->recvbuf;
673

674
                            double nrMissFrags =
675
                                (double) recvdatabuf[i]->nrFragments /
676
                                (double) recvdatabuf[i]->recvFragments;
677
                            int nrMissingFragments =
678
                                (int) ceil(nrMissFrags);
679

680
                            // printf(" recvbuf %s \n",recvbuf );
681

682
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
683
                                   buffersize);
684

685
                            rParams->nrMissingFragments =
686
                                nrMissingFragments;
687
                            rParams->nrFragments =
688
                                recvdatabuf[i]->nrFragments;
689
                            rParams->msgtype = recvdatabuf[i]->msgtype;
690
                            rParams->connectionID =
691
                                recvdatabuf[i]->connectionID;
692

693
                                if(get_Recv_data_inf_cb != NULL) {
694
                                        mon_data_inf recv_data_inf;
695

696
                                        recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
697
                                        recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
698
                                        recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
699
                                        recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
700
                                        recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
701
                                        recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
702
                                        gettimeofday(&recv_data_inf.arrival_time, NULL);
703
                                        recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
704
                                        recv_data_inf.nrMissingFragments = nrMissingFragments;
705
                                        recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
706
                                        recv_data_inf.priority = false;
707
                                        recv_data_inf.padding = false;
708
                                        recv_data_inf.confirmation = false;
709
                                        recv_data_inf.reliable = false;
710

711
                                        // send data recv callback to monitoring module
712

713
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
714
                                }
715

716
                            // free the allocated memory 
717
                            free(recvdatabuf[i]);
718
                            recvdatabuf[i] = NULL;
719

720
                            returnValue = 1;
721
                            break;
722

723
                        }
724
                    }
725

726
                }
727

728
            }
729
            // printf("2 recvbuf %s \n ",recvbuf);
730
        }
731
        return returnValue;
732
    }
733
#endif
734
}
735

    
736
void setStunServer(const int port, const char *ipaddr)
737
{
738
        stun_server.sin_family = AF_INET;
739
        if (ipaddr == NULL)
740
                stun_server.sin_addr.s_addr = htonl(INADDR_ANY);
741
        else
742
                stun_server.sin_addr.s_addr = resolve(ipaddr);
743
        stun_server.sin_port = htons(port);
744
}
745

    
746
void setRecvTimeout(struct timeval timeout_value) {
747
        recv_timeout = timeout_value;
748
}
749
 
750
void send_msg(int con_id, int msg_type, char* msg, int msg_len, bool truncable, send_params * sParams) {
751
        socketaddrgen udpgen;
752
        bool retry;
753
        int pkt_len, offset;
754
        struct iovec iov[4];
755

    
756
        char h_pkt[MON_HEADER_SPACE];
757
        char h_data[MON_HEADER_SPACE];
758

    
759
        struct msg_header msg_h;
760

    
761
        iov[0].iov_base = &msg_h;
762
        iov[0].iov_len = MSG_HEADER_SIZE;
763

    
764
        msg_h.local_con_id = con_id;
765
        msg_h.remote_con_id = connectbuf[con_id]->external_connectionID;
766
        msg_h.msg_type = msg_type;
767
        msg_h.msg_seq_num = connectbuf[con_id]->seqnr++;
768

    
769

    
770
        iov[1].iov_len = iov[2].iov_len = 0;
771
        iov[1].iov_base = h_pkt;
772
        iov[2].iov_base = h_data;
773

    
774

    
775
        if (connectbuf[con_id]->internal_connect)
776
                udpgen = connectbuf[con_id]->external_socketID.internal_addr;
777
        else
778
                udpgen = connectbuf[con_id]->external_socketID.external_addr;
779

    
780
        do{
781
                offset = 0;
782
                retry = false;
783
                // Monitoring layer hook
784
                if(set_Monitoring_header_data_cb != NULL) {
785
                        iov[2].iov_len = ((set_Monitoring_header_data_cb) (&(connectbuf[con_id]->external_socketID), msg_type));
786
                }
787
                msg_h.len_mon_data_hdr = iov[2].iov_len;
788

    
789
                if(get_Send_data_inf_cb != NULL && iov[2].iov_len != 0) {
790
                        mon_data_inf sd_data_inf;
791
                        
792
                        sd_data_inf.remote_socketID = &(connectbuf[con_id]->external_socketID);
793
                        sd_data_inf.buffer = msg;
794
                        sd_data_inf.bufSize = msg_len;
795
                        sd_data_inf.msgtype = msg_type;
796
                        sd_data_inf.monitoringDataHeader = iov[2].iov_base;
797
                        sd_data_inf.monitoringDataHeaderLen = iov[2].iov_len;
798
                        sd_data_inf.priority = sParams->priority;
799
                        sd_data_inf.padding = sParams->padding;
800
                        sd_data_inf.confirmation = sParams->confirmation;
801
                        sd_data_inf.reliable = sParams->reliable;
802
                        memset(&sd_data_inf.arrival_time, 0, sizeof(struct timeval));
803
        
804
                        (get_Send_data_inf_cb) ((void *) &sd_data_inf);
805
                }
806

    
807
                do {
808
                        if(set_Monitoring_header_pkt_cb != NULL) {
809
                                iov[1].iov_len = (set_Monitoring_header_pkt_cb) (&(connectbuf[con_id]->external_socketID), msg_type);
810
                        }
811
                        pkt_len = fmin(connectbuf[con_id]->pmtusize - iov[2].iov_len - iov[1].iov_len - iov[0].iov_len, msg_len - offset) ;
812

    
813
                        iov[3].iov_len = pkt_len;
814
                        iov[3].iov_base = msg + offset;
815

    
816
                        //fill header
817
                        msg_h.len_mon_packet_hdr = iov[1].iov_len;
818
                        msg_h.offset = offset;
819
                        msg_h.msg_length = truncable ? pkt_len : msg_len;
820
                        
821
                        //monitoring layer hook
822
                        if(get_Send_pkt_inf_cb != NULL && iov[1].iov_len) {
823
                                mon_pkt_inf pkt_info;
824

    
825
                                pkt_info.remote_socketID = &(connectbuf[con_id]->external_socketID);
826
                                pkt_info.buffer = msg + offset;
827
                                pkt_info.bufSize = pkt_len;
828
                                pkt_info.msgtype = msg_type;
829
                                pkt_info.dataID = connectbuf[con_id]->seqnr;
830
                                pkt_info.offset = offset;
831
                                pkt_info.datasize = msg_len;
832
                                pkt_info.monitoringHeaderLen = iov[1].iov_len;
833
                                pkt_info.monitoringHeader = iov[1].iov_base;
834
                                pkt_info.ttl = -1;
835
                                memset(&(pkt_info.arrival_time),0,sizeof(struct timeval));
836
        
837
                                (get_Send_pkt_inf_cb) ((void *) &pkt_info);
838
                        }
839

    
840

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

    
862
void send_conn_msg(int con_id, int buf_size, int command_type)
863
{
864
        send_params sparams;
865
        if(connectbuf[con_id]->ctrl_msg_buf == NULL)
866
                connectbuf[con_id]->ctrl_msg_buf = malloc(MAX);
867

    
868
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
869
                error("ML: can not allocate memory for connection message");
870
                return;
871
        }
872

    
873
        struct conn_msg *msg_header = (struct conn_msg*) connectbuf[con_id]->ctrl_msg_buf;
874

    
875
        msg_header->comand_type = command_type;
876
        msg_header->pmtu_size = connectbuf[con_id]->pmtusize;
877

    
878
        memcpy(&(msg_header->sock_id), loc_socketID, sizeof(socket_ID));
879

    
880
        send_msg(con_id, ML_CON_MSG, connectbuf[con_id]->ctrl_msg_buf, buf_size, true, &sparams);
881
}
882

    
883
void
884
recv_conn_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
885
{
886
        struct conn_msg *con_msg;
887
        int free_con_id, con_id;
888

    
889
        time_t now = time(NULL);
890
        double timediff = 0.0;
891

    
892
        // Monitoring layer hook
893
        if(get_Recv_data_inf_cb != NULL && msg_h->len_mon_data_hdr != 0) {
894
                // update pointer to the real data
895
                msgbuf += msg_h->len_mon_data_hdr;
896
                bufsize -= msg_h->len_mon_data_hdr;
897
                con_msg = (struct conn_msg *)msgbuf;
898

    
899
                mon_data_inf recv_data_inf;
900
                recv_data_inf.remote_socketID = &(con_msg->sock_id);
901
                recv_data_inf.buffer = msgbuf;
902
                recv_data_inf.bufSize = bufsize;
903
                recv_data_inf.msgtype = msg_h->msg_type;
904
                recv_data_inf.monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
905
                recv_data_inf.monitoringDataHeader = msg_h->len_mon_data_hdr ? msgbuf : NULL;
906
                gettimeofday(&recv_data_inf.arrival_time, NULL);
907
                recv_data_inf.firstPacketArrived = true;
908
                recv_data_inf.recvFragments = 1;
909
                recv_data_inf.priority = false;
910
                recv_data_inf.padding = false;
911
                recv_data_inf.confirmation = false;
912
                recv_data_inf.reliable = false;
913

    
914
                // send data recv callback to monitoring module
915
                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
916
        } else
917
                con_msg = (struct conn_msg *) msgbuf;
918

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

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

    
961
                        if(connectbuf[con_id]->status <= CONNECT) {
962
                                //update status and send back answer
963
                                connectbuf[con_id]->status = CONNECT;
964
                                send_conn_msg(con_id, con_msg->pmtu_size, CONNECT);
965
                        }
966
                        break;
967
                case CONNECT:
968
                        debug("ML: received CONNECT");
969

    
970
                        if(msg_h->remote_con_id != -1 && connectbuf[msg_h->remote_con_id] == NULL) {
971
                                error("ML: received CONNECT for unexistent connection");
972
                                return;
973
                        }
974

    
975
                        /*
976
                        * check if the connection status is not already 1 or 2 
977
                        */
978
                        if (connectbuf[msg_h->remote_con_id]->status == INVITE) {
979
                                // set the external connectionID
980
                                connectbuf[msg_h->remote_con_id]->external_connectionID = msg_h->local_con_id;
981
                                // change status con_msg the connection_data
982
                                connectbuf[msg_h->remote_con_id]->status = READY;
983
                                // change pmtusize in the connection_data
984
                                connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
985

    
986
                                // send the READY
987
                                send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
988

    
989
                                if (receive_Connection_cb != NULL)
990
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
991

    
992
                                // call all registered callbacks
993
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
994
                                        struct receive_connection_cb_list *temp;
995
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
996
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
997
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
998
                                        free(temp);
999
                                }
1000
                                connectbuf[msg_h->remote_con_id]->connection_head =
1001
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
1002
                        } else
1003
                                // send the READY
1004
                                send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
1005

    
1006
                        debug("ML: active connection established");
1007
                        break;
1008

    
1009
                        /*
1010
                        * if READY: find the entry in the connection array set the
1011
                        * connection active change the pmtu size 
1012
                        */
1013
                case READY:
1014
                        debug("ML: received READY");
1015
                        if(connectbuf[msg_h->remote_con_id] == NULL) {
1016
                                error("ML: received READY for unexistent connection");
1017
                                return;
1018
                        }
1019
                        /*
1020
                        * checks if the connection is not already established 
1021
                        */
1022
                        if (connectbuf[msg_h->remote_con_id]->status == CONNECT) {
1023
                                // change status of the connection
1024
                                connectbuf[msg_h->remote_con_id]->status = 2;
1025
                                // change pmtusize
1026
                                connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
1027

    
1028
                                if (receive_Connection_cb != NULL)
1029
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
1030
                        
1031
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
1032
                                        struct receive_connection_cb_list *temp;
1033
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
1034
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
1035
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
1036
                                        free(temp);
1037
                                }
1038
                                connectbuf[msg_h->remote_con_id]->connection_head =
1039
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
1040
                                debug("ML: passiv connection established");
1041
                        }
1042
                        break;
1043
        }
1044
}
1045

    
1046
/*
1047
 * what to do once a packet arrived if it is a conn packet send it to
1048
 * recv_conn handler if it is a data packet send it to the recv_data
1049
 * handler 
1050
 */
1051

    
1052
//done --
1053
void recv_pkg(int fd, short event, void *arg)
1054
{
1055
        debug("ML: recv_pkg called");
1056

    
1057
        struct msg_header *msg_h;
1058
        char msgbuf[MAX];
1059
        char *bufptr = msgbuf;
1060
        int ttl;
1061
        struct sockaddr_in recv_addr;
1062
        pmtu recvSize = MAX;
1063
        int msg_size;
1064

    
1065
        recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
1066

    
1067

    
1068
        // check if it is not just an ERROR message
1069
        if(recvSize < 0)
1070
                return;
1071

    
1072
        // @TODO check if this simplistic STUN message recognition really always works, probably not
1073
        unsigned short stun_bind_response = 0x0101;
1074
        unsigned short * msgspot = (unsigned short *) msgbuf;
1075
        if (*msgspot == stun_bind_response) {
1076
                debug("ML: recv_pkg: parse stun message called");
1077
                recv_stun_msg(msgbuf, recvSize);
1078
                return;
1079
        }
1080

    
1081
        msg_h = (struct msg_header *) msgbuf;
1082
        bufptr += MSG_HEADER_SIZE + msg_h->len_mon_packet_hdr;
1083
        msg_size = recvSize - MSG_HEADER_SIZE - msg_h->len_mon_packet_hdr;
1084

    
1085

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

    
1111

    
1112
        switch(msg_h->msg_type) {
1113
                case ML_CON_MSG:
1114
                        debug("ML: received conn pkg");
1115
                        recv_conn_msg(msg_h, bufptr, msg_size);
1116
                        break;
1117
                default:
1118
                        if(msg_h->msg_type < 127) {
1119
                                debug("ML: received data pkg");
1120
                                recv_data_msg(msg_h, bufptr, msg_size);
1121
                                break;
1122
                        }
1123
                        debug("ML: unrecognised msg_type");
1124
                        break;
1125
        }
1126
}
1127

    
1128
void recv_stun_msg(char *msgbuf, int recvSize)
1129
{
1130
        /*
1131
        * create empty stun message struct 
1132
        */
1133
        StunMessage resp;
1134
        memset(&resp, 0, sizeof(StunMessage));
1135
        /*
1136
        * parse the message 
1137
        */
1138
        int returnValue = 0;
1139
        returnValue = recv_stun_message(msgbuf, recvSize, &resp);
1140

    
1141
        if (returnValue == 0) {
1142
                /*
1143
                * read the reflexive Address into the local_socketID 
1144
                */
1145
                struct sockaddr_in reflexiveAddr;
1146
                reflexiveAddr.sin_family = AF_INET;
1147
                reflexiveAddr.sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
1148
                reflexiveAddr.sin_port = htons(resp.mappedAddress.ipv4.port);
1149
                socketaddrgen reflexiveAddres;
1150
                reflexiveAddres.udpaddr = reflexiveAddr;
1151
                local_socketID.external_addr = reflexiveAddres;
1152
                NAT_traversal = true;
1153
                // callback to the upper layer indicating that the socketID is now
1154
                // ready to use
1155
                (receive_SocketID_cb) (&local_socketID, 0);
1156
        }
1157
}
1158

    
1159
// process a single recv data message
1160
void recv_data_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
1161
{
1162
        debug("transmissionHandler: received data message called");
1163

    
1164
        int recv_id, free_recv_id = -1;
1165

    
1166
        if(connectbuf[msg_h->remote_con_id] == NULL) {
1167
                debug("ML: Received a message not related to any opened connection!");
1168
                return;
1169
        }
1170

    
1171
        // check if a recv_data exist and enter data
1172
        for (recv_id = 0; recv_id < RECVDATABUFSIZE; recv_id++)
1173
                if (recvdatabuf[recv_id] != NULL) {
1174
                        if (msg_h->remote_con_id == recvdatabuf[recv_id]->connectionID && 
1175
                                        msg_h->msg_seq_num == recvdatabuf[recv_id]->seqnr)
1176
                                                break;
1177
                } else
1178
                        if(free_recv_id == -1)
1179
                                free_recv_id = recv_id;
1180

    
1181

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

    
1201
                // fill the buffer with zeros
1202
                memset(recvdatabuf[recv_id]->recvbuf, 0, msg_h->msg_length);
1203
        }
1204

    
1205
        if (msg_h->offset == 0)
1206
                recvdatabuf[recv_id]->firstPacketArrived = 1;
1207

    
1208

    
1209
        // increment fragmentnr
1210
        recvdatabuf[recv_id]->recvFragments++;
1211
        // increment the arrivedBytes
1212
        recvdatabuf[recv_id]->arrivedBytes += bufsize;
1213

    
1214
        // enter the data into the buffer
1215
        memcpy(recvdatabuf[recv_id]->recvbuf + msg_h->offset, msgbuf, bufsize);
1216
        
1217
        //TODO very basic checkif all fragments arrived: has to be reviewed
1218
        if(recvdatabuf[recv_id]->arrivedBytes == recvdatabuf[recv_id]->bufsize)
1219
                recvdatabuf[recv_id]->status = COMPLETE; //buffer full -> msg completly arrived
1220
        else
1221
                recvdatabuf[recv_id]->status = ACTIVE;
1222

    
1223
        if (recv_data_callback) {
1224
                if(recvdatabuf[recv_id]->status == COMPLETE) {
1225
                        // Monitoring layer hook
1226
                        if(get_Recv_data_inf_cb != NULL) {
1227
                                mon_data_inf recv_data_inf;
1228
        
1229
                                recv_data_inf.remote_socketID =
1230
                                         &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
1231
                                recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
1232
                                recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
1233
                                recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
1234
                                recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
1235
                                recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
1236
                                        recvdatabuf[recv_id]->recvbuf : NULL;
1237
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
1238
                                recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
1239
                                recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
1240
                                recv_data_inf.priority = false;
1241
                                recv_data_inf.padding = false;
1242
                                recv_data_inf.confirmation = false;
1243
                                recv_data_inf.reliable = false;
1244

    
1245
                                // send data recv callback to monitoring module
1246

    
1247
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1248
                        }
1249

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

    
1279
//done
1280
void recv_timeout_cb(int fd, short event, void *arg)
1281
{
1282
        int recv_id = (int) arg;
1283
        debug("ML: recv_timeout_cb called");
1284

    
1285
        if (recvdatabuf[recv_id] == NULL) {
1286
                return;
1287
        }
1288

    
1289

    
1290
        if(recvdatabuf[recv_id]->status == ACTIVE) {
1291
                //TODO make timeout at least a DEFINE
1292
                struct timeval timeout = { 4, 0 };
1293
                recvdatabuf[recv_id]->status = INACTIVE;
1294
                event_base_once(base, -1, EV_TIMEOUT, recv_timeout_cb,
1295
                        arg, &timeout);
1296
                return;
1297
        }
1298

    
1299
        if(recvdatabuf[recv_id]->status == INACTIVE) {
1300
                // Monitoring layer hook
1301
                if(get_Recv_data_inf_cb != NULL) {
1302
                        mon_data_inf recv_data_inf;
1303

    
1304
                        recv_data_inf.remote_socketID =
1305
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
1306
                        recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
1307
                        recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
1308
                        recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
1309
                        recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
1310
                        recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
1311
                                recvdatabuf[recv_id]->recvbuf : NULL;
1312
                        gettimeofday(&recv_data_inf.arrival_time, NULL);
1313
                        recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
1314
                        recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
1315
                        recv_data_inf.priority = false;
1316
                        recv_data_inf.padding = false;
1317
                        recv_data_inf.confirmation = false;
1318
                        recv_data_inf.reliable = false;
1319

    
1320
                        // send data recv callback to monitoring module
1321

    
1322
                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1323
                }
1324

    
1325
                // Get the right callback
1326
                receive_data_cb receive_data_callback = recvcbbuf[recvdatabuf[recv_id]->msgtype];
1327

    
1328
                recv_params rParams;
1329

    
1330
                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
1331
                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
1332
                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
1333
                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
1334
                rParams.remote_socketID = 
1335
                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
1336
                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
1337

    
1338
                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
1339
                        recvdatabuf[recv_id]->msgtype, (void *) &rParams);
1340

    
1341
                //clean up
1342
                free(recvdatabuf[recv_id]->recvbuf);
1343
                free(recvdatabuf[recv_id]);
1344
                recvdatabuf[recv_id] = NULL;
1345
        }
1346
}
1347

    
1348
//done
1349
void pmtu_timeout_cb(int fd, short event, void *arg)
1350
{
1351
        debug("ML: pmtu timeout called");
1352

    
1353
        int con_id = (int) arg;
1354
        pmtu new_pmtusize;
1355
        struct timeval timeout;
1356
        
1357
        if(connectbuf[con_id] == NULL) {
1358
                error("ML: pmtu timeout called on non existing con_id");
1359
                return;
1360
        }
1361

    
1362
        if(connectbuf[con_id]->status == READY) {
1363
                // nothing to do anymore
1364
                return;
1365
        }
1366

    
1367
        timeout = connectbuf[con_id]->timeout_value;
1368

    
1369
        if(connectbuf[con_id]->delay || connectbuf[con_id]->trials == MAX_TRIALS - 1) {
1370
                double delay = timeout.tv_sec + timeout.tv_usec / 1000000.0;
1371
                delay = delay * 5;
1372
                timeout.tv_sec = floor(delay);
1373
                timeout.tv_usec = fmod(delay, 1.0) * 1000000.0;
1374
                if(connectbuf[con_id]->delay) {
1375
                        connectbuf[con_id]->delay = false;
1376
                        goto reschedule;
1377
                }
1378
        }
1379

    
1380
        if(connectbuf[con_id]->trials == MAX_TRIALS) {
1381
                // decrement the pmtu size
1382
                connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
1383
                connectbuf[con_id]->trials = 0;
1384
        }
1385

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

    
1404
        //retry with new pmtu size
1405
        connectbuf[con_id]->trials++;
1406
        send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
1407

    
1408
reschedule:
1409
        /* reschedule */
1410
        event_base_once(base, -1, EV_TIMEOUT, pmtu_timeout_cb, (void *) con_id, &timeout);
1411
}
1412

    
1413
/*
1414
 * decrements the mtu size
1415
 */
1416
pmtu pmtu_decrement(pmtu pmtusize)
1417
{
1418
        pmtu pmtu_return_size;
1419
        switch(pmtusize) {
1420
        case MAX:
1421
                return DSL;
1422
        case DSL:
1423
                return DSLMEDIUM;
1424
        case DSLMEDIUM:
1425
                return DSLSLIM;
1426
        case DSLSLIM:
1427
                return BELOWDSL;
1428
        case BELOWDSL:
1429
                return MIN;
1430
        default:
1431
                return ERROR;
1432
        }
1433
}
1434

    
1435
void pmtu_error_cb_th(char *msg, int msglen)
1436
{
1437
        debug("ML: pmtu_error callback called msg_size: %d",msglen);
1438
        //TODO debug
1439
        return;
1440

    
1441
    char *msgbufptr = NULL;
1442
    int msgtype;
1443
    int connectionID;
1444
    pmtu pmtusize;
1445
    pmtu new_pmtusize;
1446
    int dead = 0;
1447

    
1448
    // check the packettype
1449
    msgbufptr = &msg[0];
1450

    
1451
    // check the msgtype
1452
    msgbufptr = &msg[1];
1453
    memcpy(&msgtype, msgbufptr, 4);
1454

    
1455
    if (msgtype == 0) {
1456

    
1457
        // get the connectionID
1458
        msgbufptr = &msg[5];
1459
        memcpy(&connectionID, msgbufptr, 4);
1460

    
1461
        int msgtype_c = connectbuf[connectionID]->status;
1462
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
1463

    
1464
        if (msgtype_c != msgtype) {
1465
            dead = 1;
1466
        }
1467

    
1468

    
1469
    } else if (msgtype == 1) {
1470

    
1471
        // read the connectionID
1472
        msgbufptr = &msg[9];
1473
        memcpy(&connectionID, msgbufptr, 4);
1474

    
1475
        int msgtype_c = connectbuf[connectionID]->status;
1476
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
1477

    
1478
        if (msgtype_c != msgtype) {
1479
            dead = 1;
1480
        }
1481

    
1482
    }
1483
    // decrement the pmtu size 
1484
    new_pmtusize = pmtu_decrement(pmtusize);
1485

    
1486
//    connectbuf[connectionID]->pmtutrysize = new_pmtusize;
1487

    
1488
    if (new_pmtusize == ERROR) {
1489
                fprintf(stderr,
1490
                        "transmissionHandler:  Could not create connection with connectionID %i !\n",
1491
                        connectionID);
1492
                
1493
                if(failed_Connection_cb != NULL)
1494
                        (failed_Connection_cb) (connectionID, NULL);
1495
                // set the message type to a non existent message 
1496
                msgtype = 2;
1497
                // delete the connection entry
1498
                 close_connection(connectionID);
1499
        }
1500

    
1501
    if (msgtype == 0 && dead != 1) {
1502

    
1503
        // stop the timeout event
1504
        // timeout_del(connectbuf[connectionID]->timeout);
1505
        /*
1506
         * libevent2 
1507
         */
1508

    
1509
        // event_del(connectbuf[connectionID]->timeout);
1510

    
1511

    
1512
        // create and send a connection message
1513
//         create_conn_msg(new_pmtusize, connectionID, 
1514
//                         &local_socketID, INVITE);
1515

    
1516
//        send_conn_msg(connectionID, new_pmtusize);
1517

    
1518
        // set a timeout event for the pmtu discovery 
1519
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void 
1520
        // *)&connectionID);
1521

    
1522
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1523

    
1524
        /*
1525
         * libevent2 
1526
         */
1527

    
1528
        struct event *ev;
1529
        ev = evtimer_new(base, pmtu_timeout_cb,
1530
                         (void *) connectbuf[connectionID]);
1531

    
1532
        // connectbuf[connectionID]->timeout = ev;
1533

    
1534
        event_add(ev, &connectbuf[connectionID]->timeout_value);
1535

    
1536
    } else if (msgtype == 1 && dead != 1) {
1537

    
1538
        // stop the timeout event
1539
        // timeout_del(connectbuf[connectionID]->timeout);
1540

    
1541
        /*
1542
         * libevent2 
1543
         */
1544
        // printf("still here 11 \n");
1545
        // printf("ev %d \n",connectbuf[connectionID]->timeout);
1546
        // event_del(connectbuf[connectionID]->timeout );
1547
        // evtimer_del(connectbuf[connectionID]->timeout );
1548

    
1549

    
1550
//         // create and send a connection message
1551
//         create_conn_msg(new_pmtusize,
1552
//                         connectbuf[connectionID]->connectionID,
1553
//                         NULL, CONNECT);
1554

    
1555
        //send_conn_msg(connectionID, new_pmtusize);
1556

    
1557
        // set a timeout event for the pmtu discovery 
1558
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void 
1559
        // *)&connectionID);
1560
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1561

    
1562
        /*
1563
         * libevent2 
1564
         */
1565
        // struct event *ev;
1566
        // ev = evtimer_new(base,pmtu_timeout_cb, (void
1567
        // *)connectbuf[connectionID]);
1568
        // connectbuf[connectionID]->timeout = ev;
1569
        // event_add(ev,&connectbuf[connectionID]->timeout_value);
1570

    
1571
    }
1572
}
1573

    
1574
/*
1575
 * compare the external IP address of two socketIDs 
1576
 */
1577
int
1578
compare_external_address_socketIDs(socketID_handle sock1, socketID_handle sock2)
1579
{
1580
        if( sock1->external_addr.udpaddr.sin_addr.s_addr == sock2->external_addr.udpaddr.sin_addr.s_addr)
1581
                return 0;
1582
        return 1;
1583
}
1584

    
1585

    
1586
/*
1587
 * hash code of a socketID
1588
 * TODO might think of a better way
1589
 */
1590
int hash_socketID(socketID_handle sock)
1591
{
1592
    return sock->internal_addr.udpaddr.sin_port +
1593
                          sock->external_addr.udpaddr.sin_port;
1594
}
1595

    
1596
/*
1597
 * compares 2 socketIDs: returns 0 if they are equl otherwise 1 
1598
 */
1599
int compare_socketIDs(socketID_handle sock1, socketID_handle sock2)
1600
{
1601
        /*
1602
        * compare internal addr 
1603
        */
1604
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr != 
1605
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
1606
                        return 1;
1607

    
1608
        if (sock1->internal_addr.udpaddr.sin_port !=
1609
                 sock2->internal_addr.udpaddr.sin_port)
1610
                        return 1;
1611

    
1612
        /*
1613
        * compare external addr 
1614
        */
1615
        if (sock1->external_addr.udpaddr.sin_addr.s_addr != 
1616
            sock2->external_addr.udpaddr.sin_addr.s_addr)
1617
                        return 1;
1618

    
1619
        if (sock1->external_addr.udpaddr.sin_port !=
1620
                 sock2->external_addr.udpaddr.sin_port)
1621
                        return 1;
1622

    
1623
        return 0;
1624
}
1625

    
1626
/*
1627
 * the timeout of the NAT traversal 
1628
 */
1629
void nat_traversal_timeout(int fd, short event, void *arg)
1630
{
1631
        if (NAT_traversal == false) {
1632
                debug("ML: NAT traversal request resend");
1633
                send_stun_request(socketfd, &stun_server);
1634

    
1635
                /*
1636
                * enter a NAT traversal timeout that takes care of retransmission 
1637
                */
1638
                struct event *ev1;
1639
                struct timeval timeout_value_NAT_traversal = { 1, 0 };
1640
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1641
                event_add(ev1, &timeout_value_NAT_traversal);
1642
                if(receive_SocketID_cb)
1643
                        (receive_SocketID_cb) (&local_socketID, 2);
1644
        }
1645
}
1646

    
1647
int get_standard_ttl(socketID_handle socketID, uint8_t *ttl)
1648
{
1649
        return getTTL(socketfd, ttl);
1650
}
1651

    
1652
socketID_handle get_local_socketID(int *error_status)
1653
{
1654
        if (NAT_traversal == false) {
1655
                *error_status = 2;
1656
                return NULL;
1657
        }
1658

    
1659
        *error_status = 0;
1660
        return &local_socketID;
1661
}
1662

    
1663
int get_external_IP(char *external_addr)
1664
{
1665
        socketaddrgen udpgen;
1666
        struct sockaddr_in udpaddr;
1667

    
1668
        udpgen = local_socketID.external_addr;
1669
        udpaddr = udpgen.udpaddr;
1670

    
1671
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
1672
                        INET_ADDRSTRLEN);
1673
        
1674
        if (external_addr == NULL) {
1675
        
1676
        return -1;
1677
        
1678
        } else {
1679
        
1680
        return 0;
1681
        
1682
        }
1683
        
1684
}
1685

    
1686
int print_socketID(socketID_handle sock)
1687
{
1688
        char str[SOCKETID_STRING_SIZE];
1689
        socketID_to_String(sock, str, sizeof(str));
1690
        printf("int->%s<-ext\n",str);
1691
}
1692

    
1693
int socketID_to_String(socketID_handle sock, char *sock_string, size_t len)
1694
{
1695
        char internal_addr[INET_ADDRSTRLEN];
1696
        char external_addr[INET_ADDRSTRLEN];
1697
        inet_ntop(AF_INET, &(sock->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1698
        inet_ntop(AF_INET, &(sock->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1699
        
1700
        snprintf(sock_string,len,"%s:%d-%s:%d", internal_addr, ntohs(sock->internal_addr.udpaddr.sin_port),
1701
                external_addr,        ntohs(sock->external_addr.udpaddr.sin_port));
1702
        return 0;
1703
}
1704

    
1705
int string_to_socketID(char* socketID_string, socketID_handle sock)
1706
{
1707
        //@TODO add checks against malformed string
1708
        char external_addr[INET_ADDRSTRLEN];
1709
        int external_port;
1710
        char internal_addr[INET_ADDRSTRLEN];
1711
        int internal_port;
1712

    
1713
        char *pch;
1714

    
1715
        //replace ':' with a blank
1716
        pch=strchr(socketID_string,':');
1717
        while (pch!=NULL){
1718
                                *pch = ' ';
1719
                pch=strchr(pch+1,':');
1720
        }
1721
        pch=strchr(socketID_string,'-');
1722
        if(pch) *pch = ' ';
1723

    
1724
        sscanf(socketID_string,"%s %d %s %d", internal_addr, &internal_port,
1725
                external_addr, &external_port);
1726

    
1727
        if(inet_pton(AF_INET, internal_addr, &(sock->internal_addr.udpaddr.sin_addr)) == 0)
1728
                return EINVAL;
1729
        sock->internal_addr.udpaddr.sin_family = AF_INET;
1730
        sock->internal_addr.udpaddr.sin_port = htons(internal_port);
1731
        
1732

    
1733
        if(inet_pton(AF_INET, external_addr, &(sock->external_addr.udpaddr.sin_addr)) ==0)
1734
                return EINVAL;
1735
        sock->external_addr.udpaddr.sin_family = AF_INET;
1736
        sock->external_addr.udpaddr.sin_port = htons(external_port);
1737

    
1738
        return 0;
1739
}
1740

    
1741

    
1742
int get_connection_status(int con_id)
1743
{
1744
        if(connectbuf[con_id])
1745
                return connectbuf[con_id]->status == READY;
1746
        return -1;
1747
}
1748

    
1749

    
1750
int connection_exist(socketID_handle socketID) {
1751
    /*
1752
     * check if another connection for the external connectionID exist
1753
     * that was established \ within the last 2 seconds
1754
     */
1755
        int i;
1756
        for (i = 0; i < CONNECTBUFSIZE; i++)
1757
                if (connectbuf[i] != NULL)
1758
                        if (compare_socketIDs(&(connectbuf[i]->external_socketID), socketID) == 0)
1759
                                return i;
1760

    
1761
    return -1;
1762
}
1763

    
1764
int get_path_mtu(int ConnectionId) {
1765
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
1766
                return -1;
1767
        if (connectbuf[ConnectionId] != NULL)
1768
                return connectbuf[ConnectionId]->pmtusize;
1769
        return -1;
1770
}
1771

    
1772
unsigned long resolve(const char *ipaddr)
1773
{
1774
        struct hostent *h = gethostbyname(ipaddr);
1775
        if (!h) {
1776
                error("Unable to resolve hostname %s\n", ipaddr);
1777
        exit(-1);
1778
    }
1779
    unsigned long *addr = (unsigned long *) (h->h_addr);
1780
    return *addr;
1781
}