Statistics
| Branch: | Revision:

ml / ml.c @ 6f256447

History | View | Annotate | Download (50.9 KB)

1 a0a1f630 KristianBeckers
/*
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 07355669 TivadarSzemethy
35 da5dade7 MarcoBiazzini
#include <arpa/inet.h>
36
#include <netinet/in.h>
37
#include <sys/socket.h>
38
#include <fcntl.h>
39
#include <event2/event.h>
40
#include <stdlib.h>
41
#include <unistd.h>
42 a0a1f630 KristianBeckers
#include <stdio.h>
43
#include <stddef.h>
44 da5dade7 MarcoBiazzini
#include <stdint.h>
45
#include <string.h>
46 a0a1f630 KristianBeckers
#include <sys/types.h>
47
#include <arpa/inet.h>
48 da5dade7 MarcoBiazzini
#include <netdb.h>
49 a0a1f630 KristianBeckers
#include <errno.h>
50
#include <time.h>
51 da5dade7 MarcoBiazzini
#include <math.h>
52
#include "util/udpSocket.h"
53
#include "util/stun.h"
54
#include "transmissionHandler.h"
55 07355669 TivadarSzemethy
56 da5dade7 MarcoBiazzini
#define LOG_MODULE "[ml] "
57
#include "grapes_log.h"
58 380cf1b9 RobertBirke
59 da5dade7 MarcoBiazzini
/**************************** START OF INTERNALS ***********************/
60
61
/*
62
 * a pointer to a libevent instance
63
 */
64
struct event_base *base;
65
66
/*
67
 * define the nr of connections the messaging layer can handle
68
 */
69
#define CONNECTBUFSIZE 10000
70
/*
71
 * define the nr of data that can be received parallel
72
 */
73
#define RECVDATABUFSIZE 10000
74
/*
75
 * define an array for message multiplexing
76
 */
77
#define MSGMULTIPLEXSIZE 127
78
79
/*
80
 * global variables
81
 */
82
/*
83
 * define a buffer of pointers to connect structures
84
 */
85
connect_data *connectbuf[CONNECTBUFSIZE];
86
87
/*
88
 * define a pointer buffer with pointers to recv_data structures
89
 */
90
recvdata *recvdatabuf[RECVDATABUFSIZE];
91
92
/*
93
 * define a pointer buffer for message multiplexing
94
 */
95
receive_data_cb recvcbbuf[MSGMULTIPLEXSIZE];
96
97
/*
98
 * stun server address
99
 */
100
struct sockaddr_in stun_server;
101
102
/*
103
 * receive timeout
104
 */
105
struct timeval recv_timeout;
106
107
/*
108
 * boolean NAT traversal successful if true
109
 */
110
boolean NAT_traversal;
111
112
/*
113
 * file descriptor for local socket
114
 */
115
evutil_socket_t socketfd;
116
117
/*
118
 * local socketID
119
 */
120
socket_ID local_socketID;
121
122
socketID_handle loc_socketID = &local_socketID;
123
124
/*
125
 * callback function pointers
126
 */
127
/*
128
 * monitoring module callbacks
129
 */
130
get_recv_pkt_inf_cb get_Recv_pkt_inf_cb = NULL;
131
get_send_pkt_inf_cb get_Send_pkt_inf_cb = NULL;
132
set_monitoring_header_pkt_cb set_Monitoring_header_pkt_cb = NULL;
133
get_recv_data_inf_cb get_Recv_data_inf_cb = NULL;
134
get_send_data_inf_cb get_Send_data_inf_cb = NULL;
135
set_monitoring_header_data_cb set_Monitoring_header_data_cb = NULL;
136
/*
137
 * connection callbacks
138
 */
139
receive_connection_cb receive_Connection_cb = NULL;
140
connection_failed_cb failed_Connection_cb = NULL;
141
/*
142
 * local socketID callback
143
 */
144
receive_localsocketID_cb receive_SocketID_cb;
145
146
/*
147
 * boolean that defines if received data is transmitted to the upper layer
148
 * via callback or via upper layer polling
149
 */
150
boolean recv_data_callback;
151
152
/*
153
 * helper function to get rid of a warning
154
 */
155
int min(int a, int b) {
156
        if (a > b) return b;
157
        return a;
158
}
159
160
void register_recv_localsocketID_cb(receive_localsocketID_cb local_socketID_cb)
161
{
162
        if (local_socketID_cb == NULL)
163
                printf("Register receive_localsocketID_cb: NULL ptr \n");
164
        else
165
        receive_SocketID_cb = local_socketID_cb;
166
}
167
168
169
void keep_connection_alive(const int connectionID)
170
{
171
172
    // to be done with the NAT traversal
173
    // send a message over the wire
174
    printf("\n");
175
176
}
177
178
void unsetStunServer()
179
{
180
        stun_server.sin_addr.s_addr = 0;
181
}
182
183
bool isStunDefined()
184
{
185
        return stun_server.sin_addr.s_addr;
186
}
187
188
void send_msg(int con_id, int msg_type, char* msg, int msg_len, bool truncable, send_params * sParams) {
189
        socketaddrgen udpgen;
190
        bool retry;
191
        int pkt_len, offset;
192
        struct iovec iov[4];
193
194
        char h_pkt[MON_HEADER_SPACE];
195
        char h_data[MON_HEADER_SPACE];
196
197
        struct msg_header msg_h;
198
199
        iov[0].iov_base = &msg_h;
200
        iov[0].iov_len = MSG_HEADER_SIZE;
201
202
        msg_h.local_con_id = con_id;
203
        msg_h.remote_con_id = connectbuf[con_id]->external_connectionID;
204
        msg_h.msg_type = msg_type;
205
        msg_h.msg_seq_num = connectbuf[con_id]->seqnr++;
206
207
208
        iov[1].iov_len = iov[2].iov_len = 0;
209
        iov[1].iov_base = h_pkt;
210
        iov[2].iov_base = h_data;
211
212
213
        if (connectbuf[con_id]->internal_connect)
214
                udpgen = connectbuf[con_id]->external_socketID.internal_addr;
215
        else
216
                udpgen = connectbuf[con_id]->external_socketID.external_addr;
217
218
        do{
219
                offset = 0;
220
                retry = false;
221
                // Monitoring layer hook
222
                if(set_Monitoring_header_data_cb != NULL) {
223
                        iov[2].iov_len = ((set_Monitoring_header_data_cb) (&(connectbuf[con_id]->external_socketID), msg_type));
224
                }
225
                msg_h.len_mon_data_hdr = iov[2].iov_len;
226
227
                if(get_Send_data_inf_cb != NULL && iov[2].iov_len != 0) {
228
                        mon_data_inf sd_data_inf;
229
230
                        sd_data_inf.remote_socketID = &(connectbuf[con_id]->external_socketID);
231
                        sd_data_inf.buffer = msg;
232
                        sd_data_inf.bufSize = msg_len;
233
                        sd_data_inf.msgtype = msg_type;
234
                        sd_data_inf.monitoringDataHeader = iov[2].iov_base;
235
                        sd_data_inf.monitoringDataHeaderLen = iov[2].iov_len;
236
                        sd_data_inf.priority = sParams->priority;
237
                        sd_data_inf.padding = sParams->padding;
238
                        sd_data_inf.confirmation = sParams->confirmation;
239
                        sd_data_inf.reliable = sParams->reliable;
240
                        memset(&sd_data_inf.arrival_time, 0, sizeof(struct timeval));
241
242
                        (get_Send_data_inf_cb) ((void *) &sd_data_inf);
243
                }
244
245
                do {
246
                        if(set_Monitoring_header_pkt_cb != NULL) {
247
                                iov[1].iov_len = (set_Monitoring_header_pkt_cb) (&(connectbuf[con_id]->external_socketID), msg_type);
248
                        }
249
                        pkt_len = min(connectbuf[con_id]->pmtusize - iov[2].iov_len - iov[1].iov_len - iov[0].iov_len, msg_len - offset) ;
250
251
                        iov[3].iov_len = pkt_len;
252
                        iov[3].iov_base = msg + offset;
253
254
                        //fill header
255
                        msg_h.len_mon_packet_hdr = iov[1].iov_len;
256
                        msg_h.offset = offset;
257
                        msg_h.msg_length = truncable ? pkt_len : msg_len;
258
259
                        //monitoring layer hook
260
                        if(get_Send_pkt_inf_cb != NULL && iov[1].iov_len) {
261
                                mon_pkt_inf pkt_info;
262
263
                                pkt_info.remote_socketID = &(connectbuf[con_id]->external_socketID);
264
                                pkt_info.buffer = msg + offset;
265
                                pkt_info.bufSize = pkt_len;
266
                                pkt_info.msgtype = msg_type;
267
                                pkt_info.dataID = connectbuf[con_id]->seqnr;
268
                                pkt_info.offset = offset;
269
                                pkt_info.datasize = msg_len;
270
                                pkt_info.monitoringHeaderLen = iov[1].iov_len;
271
                                pkt_info.monitoringHeader = iov[1].iov_base;
272
                                pkt_info.ttl = -1;
273
                                memset(&(pkt_info.arrival_time),0,sizeof(struct timeval));
274
275
                                (get_Send_pkt_inf_cb) ((void *) &pkt_info);
276
                        }
277
278
279
                        switch(sendPacket(socketfd, iov, 4, &udpgen.udpaddr)) {
280
                                case MSGLEN:
281
                                        connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
282
                                        connectbuf[con_id]->delay = true;
283
                                        retry = true;
284
                                        offset = msg_len; // exit the while
285
                                        break;
286
                                case FAILURE:
287
                                        offset = msg_len; // exit the while
288
                                        break;
289
                                case OK:
290
                                        //update
291
                                        offset += pkt_len + iov[2].iov_len;
292
                                        //transmit data header only in the first packet
293
                                        iov[2].iov_len = 0;
294
                                        break;
295
                        }
296
                } while(offset != msg_len + msg_h.len_mon_data_hdr && !truncable);
297
        } while(retry);
298
}
299
300
void send_conn_msg(int con_id, int buf_size, int command_type)
301
{
302
        if(connectbuf[con_id]->ctrl_msg_buf == NULL)
303
                connectbuf[con_id]->ctrl_msg_buf = malloc(MAX);
304
305
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
306
                error("ML: can not allocate memory for connection message");
307
                return;
308
        }
309
310
        struct conn_msg *msg_header = (struct conn_msg*) connectbuf[con_id]->ctrl_msg_buf;
311
312
        msg_header->comand_type = command_type;
313
        msg_header->pmtu_size = connectbuf[con_id]->pmtusize;
314
315
        memcpy(&(msg_header->sock_id), loc_socketID, sizeof(socket_ID));
316
317 6f256447 TivadarSzemethy
        send_msg(con_id, ML_CON_MSG, connectbuf[con_id]->ctrl_msg_buf, buf_size, true, &(connectbuf[con_id]->defaultSendParams));
318 da5dade7 MarcoBiazzini
}
319
320
void
321
recv_conn_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
322
{
323
        struct conn_msg *con_msg;
324
        int free_con_id, con_id;
325
326
        time_t now = time(NULL);
327
        double timediff = 0.0;
328
329
        // Monitoring layer hook
330
        if(get_Recv_data_inf_cb != NULL && msg_h->len_mon_data_hdr != 0) {
331
                // update pointer to the real data
332
                msgbuf += msg_h->len_mon_data_hdr;
333
                bufsize -= msg_h->len_mon_data_hdr;
334
                con_msg = (struct conn_msg *)msgbuf;
335
336
                mon_data_inf recv_data_inf;
337
                recv_data_inf.remote_socketID = &(con_msg->sock_id);
338
                recv_data_inf.buffer = msgbuf;
339
                recv_data_inf.bufSize = bufsize;
340
                recv_data_inf.msgtype = msg_h->msg_type;
341
                recv_data_inf.monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
342
                recv_data_inf.monitoringDataHeader = msg_h->len_mon_data_hdr ? msgbuf : NULL;
343
                gettimeofday(&recv_data_inf.arrival_time, NULL);
344
                recv_data_inf.firstPacketArrived = true;
345
                recv_data_inf.recvFragments = 1;
346
                recv_data_inf.priority = false;
347
                recv_data_inf.padding = false;
348
                recv_data_inf.confirmation = false;
349
                recv_data_inf.reliable = false;
350
351
                // send data recv callback to monitoring module
352
                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
353
        } else
354
                con_msg = (struct conn_msg *) msgbuf;
355
356
        // check the connection command type
357
        switch (con_msg->comand_type) {
358
                /*
359
                * if INVITE: enter a new socket make new entry in connect array
360
                * send an ok
361
                */
362
                case INVITE:
363
                        debug("ML: received INVITE");
364
                        /*
365
                        * check if another connection for the external connectionID exist
366
                        * that was established within the last 2 seconds
367
                        */
368
                        free_con_id = -1;
369
                        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
370
                                if (connectbuf[con_id] != NULL) {
371
                                        if (mlCompareSocketIDs(&(connectbuf[con_id]->external_socketID), &(con_msg->sock_id)) == 0) {
372
                                                timediff = difftime(now, connectbuf[con_id]->starttime);
373
                                                if (timediff < 2)
374
                                                        break;
375
                                        }
376
                                } else if(free_con_id == -1)
377
                                        free_con_id = con_id;
378
                        }
379
380
                        if (con_id == CONNECTBUFSIZE) {
381
                                // create an entry in the connecttrybuf
382
                                if(free_con_id == -1) {
383
                                        error("ML: no new connect_buf available");
384
                                        return;
385
                                }
386
                                connectbuf[free_con_id] = (connect_data *) malloc(sizeof(connect_data));
387
                                memset(connectbuf[free_con_id],0,sizeof(connect_data));
388
                                connectbuf[free_con_id]->connection_head = connectbuf[free_con_id]->connection_last = NULL;
389
                                connectbuf[free_con_id]->starttime = time(NULL);
390
                                memcpy(&(connectbuf[free_con_id]->external_socketID), &(con_msg->sock_id), sizeof(socket_ID));
391
                                connectbuf[free_con_id]->pmtusize = con_msg->pmtu_size;
392
                                connectbuf[free_con_id]->external_connectionID = msg_h->local_con_id;
393
                                connectbuf[free_con_id]->internal_connect =
394
                                        !compare_external_address_socketIDs(&(con_msg->sock_id), loc_socketID);
395
                                con_id = free_con_id;
396
                        }
397
398
                        if(connectbuf[con_id]->status <= CONNECT) {
399
                                //update status and send back answer
400
                                connectbuf[con_id]->status = CONNECT;
401
                                send_conn_msg(con_id, con_msg->pmtu_size, CONNECT);
402
                        }
403
                        break;
404
                case CONNECT:
405
                        debug("ML: received CONNECT");
406
407
                        if(msg_h->remote_con_id != -1 && connectbuf[msg_h->remote_con_id] == NULL) {
408
                                error("ML: received CONNECT for unexistent connection");
409
                                return;
410
                        }
411
412
                        /*
413
                        * check if the connection status is not already 1 or 2
414
                        */
415
                        if (connectbuf[msg_h->remote_con_id]->status == INVITE) {
416
                                // set the external connectionID
417
                                connectbuf[msg_h->remote_con_id]->external_connectionID = msg_h->local_con_id;
418
                                // change status con_msg the connection_data
419
                                connectbuf[msg_h->remote_con_id]->status = READY;
420
                                // change pmtusize in the connection_data
421
                                connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
422
423
                                // send the READY
424
                                send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
425
426
                                if (receive_Connection_cb != NULL)
427
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
428
429
                                // call all registered callbacks
430
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
431
                                        struct receive_connection_cb_list *temp;
432
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
433
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
434
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
435
                                        free(temp);
436
                                }
437
                                connectbuf[msg_h->remote_con_id]->connection_head =
438
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
439
                        } else
440
                                // send the READY
441
                                send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
442
443
                        debug("ML: active connection established");
444
                        break;
445
446
                        /*
447
                        * if READY: find the entry in the connection array set the
448
                        * connection active change the pmtu size
449
                        */
450
                case READY:
451
                        debug("ML: received READY");
452
                        if(connectbuf[msg_h->remote_con_id] == NULL) {
453
                                error("ML: received READY for unexistent connection");
454
                                return;
455
                        }
456
                        /*
457
                        * checks if the connection is not already established
458
                        */
459
                        if (connectbuf[msg_h->remote_con_id]->status == CONNECT) {
460
                                // change status of the connection
461
                                connectbuf[msg_h->remote_con_id]->status = 2;
462
                                // change pmtusize
463
                                connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
464
465
                                if (receive_Connection_cb != NULL)
466
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
467
468
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
469
                                        struct receive_connection_cb_list *temp;
470
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
471
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
472
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
473
                                        free(temp);
474
                                }
475
                                connectbuf[msg_h->remote_con_id]->connection_head =
476
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
477
                                debug("ML: passiv connection established");
478
                        }
479
                        break;
480
        }
481
}
482
483
void recv_stun_msg(char *msgbuf, int recvSize)
484
{
485
        /*
486
        * create empty stun message struct
487
        */
488
        StunMessage resp;
489
        memset(&resp, 0, sizeof(StunMessage));
490
        /*
491
        * parse the message
492
        */
493
        int returnValue = 0;
494
        returnValue = recv_stun_message(msgbuf, recvSize, &resp);
495
496
        if (returnValue == 0) {
497
                /*
498
                * read the reflexive Address into the local_socketID
499
                */
500
                struct sockaddr_in reflexiveAddr;
501
                reflexiveAddr.sin_family = AF_INET;
502
                reflexiveAddr.sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
503
                reflexiveAddr.sin_port = htons(resp.mappedAddress.ipv4.port);
504
                socketaddrgen reflexiveAddres;
505
                reflexiveAddres.udpaddr = reflexiveAddr;
506
                local_socketID.external_addr = reflexiveAddres;
507
                NAT_traversal = true;
508
                // callback to the upper layer indicating that the socketID is now
509
                // ready to use
510
                (receive_SocketID_cb) (&local_socketID, 0);
511
        }
512
}
513
514
//done
515
void recv_timeout_cb(int fd, short event, void *arg)
516
{
517
        int recv_id = (long) arg;
518
        debug("ML: recv_timeout_cb called");
519
520
        if (recvdatabuf[recv_id] == NULL) {
521
                return;
522
        }
523
524
525
        if(recvdatabuf[recv_id]->status == ACTIVE) {
526
                //TODO make timeout at least a DEFINE
527
                struct timeval timeout = { 4, 0 };
528
                recvdatabuf[recv_id]->status = INACTIVE;
529
                event_base_once(base, -1, EV_TIMEOUT, recv_timeout_cb,
530
                        arg, &timeout);
531
                return;
532
        }
533
534
        if(recvdatabuf[recv_id]->status == INACTIVE) {
535
                // Monitoring layer hook
536
                if(get_Recv_data_inf_cb != NULL) {
537
                        mon_data_inf recv_data_inf;
538
539
                        recv_data_inf.remote_socketID =
540
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
541
                        recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
542
                        recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
543
                        recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
544
                        recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
545
                        recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
546
                                recvdatabuf[recv_id]->recvbuf : NULL;
547
                        gettimeofday(&recv_data_inf.arrival_time, NULL);
548
                        recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
549
                        recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
550
                        recv_data_inf.priority = false;
551
                        recv_data_inf.padding = false;
552
                        recv_data_inf.confirmation = false;
553
                        recv_data_inf.reliable = false;
554
555
                        // send data recv callback to monitoring module
556
557
                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
558
                }
559
560
                // Get the right callback
561
                receive_data_cb receive_data_callback = recvcbbuf[recvdatabuf[recv_id]->msgtype];
562
563
                recv_params rParams;
564
565
                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
566
                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
567
                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
568
                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
569
                rParams.remote_socketID =
570
                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
571
                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
572
573
                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
574
                        recvdatabuf[recv_id]->msgtype, &rParams);
575
576
                //clean up
577
                free(recvdatabuf[recv_id]->recvbuf);
578
                free(recvdatabuf[recv_id]);
579
                recvdatabuf[recv_id] = NULL;
580
        }
581
}
582
583
// process a single recv data message
584
void recv_data_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
585
{
586
        debug("transmissionHandler: received data message called");
587
588
        int recv_id, free_recv_id = -1;
589
590
        if(connectbuf[msg_h->remote_con_id] == NULL) {
591
                debug("ML: Received a message not related to any opened connection!");
592
                return;
593
        }
594
595
        // check if a recv_data exist and enter data
596
        for (recv_id = 0; recv_id < RECVDATABUFSIZE; recv_id++)
597
                if (recvdatabuf[recv_id] != NULL) {
598
                        if (msg_h->remote_con_id == recvdatabuf[recv_id]->connectionID &&
599
                                        msg_h->msg_seq_num == recvdatabuf[recv_id]->seqnr)
600
                                                break;
601
                } else
602
                        if(free_recv_id == -1)
603
                                free_recv_id = recv_id;
604
605
606
        if(recv_id == RECVDATABUFSIZE) {
607
                //no recv_data found: create one
608
                recv_id = free_recv_id;
609
                recvdatabuf[recv_id] = (recvdata *) malloc(sizeof(recvdata));
610
                memset(recvdatabuf[recv_id], 0, sizeof(recvdata));
611
                recvdatabuf[recv_id]->connectionID = msg_h->remote_con_id;
612
                recvdatabuf[recv_id]->seqnr = msg_h->msg_seq_num;
613
                recvdatabuf[recv_id]->monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
614
                recvdatabuf[recv_id]->bufsize = msg_h->msg_length + msg_h->len_mon_data_hdr;
615
                recvdatabuf[recv_id]->recvbuf = (char *) malloc(recvdatabuf[recv_id]->bufsize);
616
                /*
617
                * read the timeout data and set it
618
                */
619
                recvdatabuf[recv_id]->timeout_value.tv_sec = recv_timeout.tv_sec;
620
                recvdatabuf[recv_id]->timeout_value.tv_usec = recv_timeout.tv_usec;
621
                recvdatabuf[recv_id]->recvID = recv_id;
622
                recvdatabuf[recv_id]->starttime = time(NULL);
623
                recvdatabuf[recv_id]->msgtype = msg_h->msg_type;
624
625
                // fill the buffer with zeros
626
                memset(recvdatabuf[recv_id]->recvbuf, 0, msg_h->msg_length);
627
        }
628
629
        if (msg_h->offset == 0)
630
                recvdatabuf[recv_id]->firstPacketArrived = 1;
631
632
633
        // increment fragmentnr
634
        recvdatabuf[recv_id]->recvFragments++;
635
        // increment the arrivedBytes
636
        recvdatabuf[recv_id]->arrivedBytes += bufsize;
637
638
        // enter the data into the buffer
639
        memcpy(recvdatabuf[recv_id]->recvbuf + msg_h->offset, msgbuf, bufsize);
640
641
        //TODO very basic checkif all fragments arrived: has to be reviewed
642
        if(recvdatabuf[recv_id]->arrivedBytes == recvdatabuf[recv_id]->bufsize)
643
                recvdatabuf[recv_id]->status = COMPLETE; //buffer full -> msg completly arrived
644
        else
645
                recvdatabuf[recv_id]->status = ACTIVE;
646
647
        if (recv_data_callback) {
648
                if(recvdatabuf[recv_id]->status == COMPLETE) {
649
                        // Monitoring layer hook
650
                        if(get_Recv_data_inf_cb != NULL) {
651
                                mon_data_inf recv_data_inf;
652
653
                                recv_data_inf.remote_socketID =
654
                                         &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
655
                                recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
656
                                recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
657
                                recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
658
                                recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
659
                                recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
660
                                        recvdatabuf[recv_id]->recvbuf : NULL;
661
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
662
                                recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
663
                                recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
664
                                recv_data_inf.priority = false;
665
                                recv_data_inf.padding = false;
666
                                recv_data_inf.confirmation = false;
667
                                recv_data_inf.reliable = false;
668
669
                                // send data recv callback to monitoring module
670
671
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
672
                        }
673
674
                        // Get the right callback
675
                        receive_data_cb receive_data_callback = recvcbbuf[msg_h->msg_type];
676
                        if (receive_data_callback) {
677
678
                                recv_params rParams;
679
680
                                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
681
                                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
682
                                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
683
                                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
684
                                rParams.remote_socketID =
685
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
686
                                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
687
688
                                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
689
                                        recvdatabuf[recv_id]->msgtype, (void *) &rParams);
690
                        } else {
691
                            fprintf(stderr,"ML: Warning: callback not initialized for this message type: %d!\n",msg_h->msg_type);
692
                        }
693
694
                        //clean up
695
                        free(recvdatabuf[recv_id]->recvbuf);
696
                        free(recvdatabuf[recv_id]);
697
                        recvdatabuf[recv_id] = NULL;
698
                } else { // not COMPLETE
699
                        //start time out
700
                        //TODO make timeout at least a DEFINE
701
                        struct timeval timeout = { 4, 0 };
702
                        event_base_once(base, -1, EV_TIMEOUT, &recv_timeout_cb, (void *) (long)recv_id, &timeout);
703
                }
704
        }
705
}
706
707
//done
708
void pmtu_timeout_cb(int fd, short event, void *arg)
709
{
710
        debug("ML: pmtu timeout called");
711
712
        int con_id = (long) arg;
713
        pmtu new_pmtusize;
714
        struct timeval timeout;
715
716
        if(connectbuf[con_id] == NULL) {
717
                error("ML: pmtu timeout called on non existing con_id");
718
                return;
719
        }
720
721
        if(connectbuf[con_id]->status == READY) {
722
                // nothing to do anymore
723
                return;
724
        }
725
726
        timeout = connectbuf[con_id]->timeout_value;
727
728
        if(connectbuf[con_id]->delay || connectbuf[con_id]->trials == MAX_TRIALS - 1) {
729
                double delay = timeout.tv_sec + timeout.tv_usec / 1000000.0;
730
                delay = delay * 5;
731
                timeout.tv_sec = floor(delay);
732
                timeout.tv_usec = fmod(delay, 1.0) * 1000000.0;
733
                if(connectbuf[con_id]->delay) {
734
                        connectbuf[con_id]->delay = false;
735
                        goto reschedule;
736
                }
737
        }
738
739
        if(connectbuf[con_id]->trials == MAX_TRIALS) {
740
                // decrement the pmtu size
741
                connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
742
                connectbuf[con_id]->trials = 0;
743
        }
744
745
        //error in PMTU discovery?
746
        if (connectbuf[con_id]->pmtusize == ERROR) {
747
                if (connectbuf[con_id]->internal_connect == true) {
748
                        //as of now we tried directly connecting, now let's try trough the NAT
749
                        connectbuf[con_id]->internal_connect = false;
750
                        connectbuf[con_id]->pmtusize = MAX;
751
                } else {
752
                        //nothing to do we have to give up
753
                        error("ML: Could not create connection with connectionID %i!",con_id);
754
                        // envoke the callback for failed connection establishment
755
                        if(failed_Connection_cb != NULL)
756
                                (failed_Connection_cb) (con_id, NULL);
757
                        // delete the connection entry
758
                        mlCloseConnection(con_id);
759
                        return;
760
                }
761
        }
762
763
        //retry with new pmtu size
764
        connectbuf[con_id]->trials++;
765
        send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
766
767
reschedule:
768
        /* reschedule */
769
        event_base_once(base, -1, EV_TIMEOUT, pmtu_timeout_cb, (void *) (long)con_id, &timeout);
770
}
771
772
/*
773
 * decrements the mtu size
774
 */
775
pmtu pmtu_decrement(pmtu pmtusize)
776
{
777
        pmtu pmtu_return_size;
778
        switch(pmtusize) {
779
        case MAX:
780
                return DSL;
781
        case DSL:
782
                return DSLMEDIUM;
783
        case DSLMEDIUM:
784
                return DSLSLIM;
785
        case DSLSLIM:
786
                return BELOWDSL;
787
        case BELOWDSL:
788
                return MIN;
789
        default:
790
                return ERROR;
791
        }
792
}
793
794
void pmtu_error_cb_th(char *msg, int msglen)
795
{
796
        debug("ML: pmtu_error callback called msg_size: %d",msglen);
797
        //TODO debug
798
        return;
799
800
    char *msgbufptr = NULL;
801
    int msgtype;
802
    int connectionID;
803
    pmtu pmtusize;
804
    pmtu new_pmtusize;
805
    int dead = 0;
806
807
    // check the packettype
808
    msgbufptr = &msg[0];
809
810
    // check the msgtype
811
    msgbufptr = &msg[1];
812
    memcpy(&msgtype, msgbufptr, 4);
813
814
    if (msgtype == 0) {
815
816
        // get the connectionID
817
        msgbufptr = &msg[5];
818
        memcpy(&connectionID, msgbufptr, 4);
819
820
        int msgtype_c = connectbuf[connectionID]->status;
821
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
822
823
        if (msgtype_c != msgtype) {
824
            dead = 1;
825
        }
826
827
828
    } else if (msgtype == 1) {
829
830
        // read the connectionID
831
        msgbufptr = &msg[9];
832
        memcpy(&connectionID, msgbufptr, 4);
833
834
        int msgtype_c = connectbuf[connectionID]->status;
835
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
836
837
        if (msgtype_c != msgtype) {
838
            dead = 1;
839
        }
840
841
    }
842
    // decrement the pmtu size
843
    new_pmtusize = pmtu_decrement(pmtusize);
844
845
//    connectbuf[connectionID]->pmtutrysize = new_pmtusize;
846
847
    if (new_pmtusize == ERROR) {
848
                fprintf(stderr,
849
                        "transmissionHandler:  Could not create connection with connectionID %i !\n",
850
                        connectionID);
851
852
                if(failed_Connection_cb != NULL)
853
                        (failed_Connection_cb) (connectionID, NULL);
854
                // set the message type to a non existent message
855
                msgtype = 2;
856
                // delete the connection entry
857
                 mlCloseConnection(connectionID);
858
        }
859
860
    if (msgtype == 0 && dead != 1) {
861
862
        // stop the timeout event
863
        // timeout_del(connectbuf[connectionID]->timeout);
864
        /*
865
         * libevent2
866
         */
867
868
        // event_del(connectbuf[connectionID]->timeout);
869
870
871
        // create and send a connection message
872
//         create_conn_msg(new_pmtusize, connectionID,
873
//                         &local_socketID, INVITE);
874
875
//        send_conn_msg(connectionID, new_pmtusize);
876
877
        // set a timeout event for the pmtu discovery
878
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
879
        // *)&connectionID);
880
881
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
882
883
        /*
884
         * libevent2
885
         */
886
887
        struct event *ev;
888
        ev = evtimer_new(base, pmtu_timeout_cb,
889
                         (void *) connectbuf[connectionID]);
890
891
        // connectbuf[connectionID]->timeout = ev;
892
893
        event_add(ev, &connectbuf[connectionID]->timeout_value);
894 07355669 TivadarSzemethy
895 da5dade7 MarcoBiazzini
    } else if (msgtype == 1 && dead != 1) {
896 d18d76c2 TivadarSzemethy
897 da5dade7 MarcoBiazzini
        // stop the timeout event
898
        // timeout_del(connectbuf[connectionID]->timeout);
899
900
        /*
901
         * libevent2
902
         */
903
        // printf("still here 11 \n");
904
        // printf("ev %d \n",connectbuf[connectionID]->timeout);
905
        // event_del(connectbuf[connectionID]->timeout );
906
        // evtimer_del(connectbuf[connectionID]->timeout );
907
908
909
//         // create and send a connection message
910
//         create_conn_msg(new_pmtusize,
911
//                         connectbuf[connectionID]->connectionID,
912
//                         NULL, CONNECT);
913
914
        //send_conn_msg(connectionID, new_pmtusize);
915
916
        // set a timeout event for the pmtu discovery
917
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
918
        // *)&connectionID);
919
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
920
921
        /*
922
         * libevent2
923
         */
924
        // struct event *ev;
925
        // ev = evtimer_new(base,pmtu_timeout_cb, (void
926
        // *)connectbuf[connectionID]);
927
        // connectbuf[connectionID]->timeout = ev;
928
        // event_add(ev,&connectbuf[connectionID]->timeout_value);
929
930
    }
931
}
932
933
/*
934
 * what to do once a packet arrived if it is a conn packet send it to
935
 * recv_conn handler if it is a data packet send it to the recv_data
936
 * handler
937
 */
938
939
//done --
940
void recv_pkg(int fd, short event, void *arg)
941
{
942
        debug("ML: recv_pkg called");
943
944
        struct msg_header *msg_h;
945
        char msgbuf[MAX];
946
        char *bufptr = msgbuf;
947
        int ttl;
948
        struct sockaddr_in recv_addr;
949
        pmtu recvSize = MAX;
950
        int msg_size;
951
952
        recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
953
954
955
        // check if it is not just an ERROR message
956
        if(recvSize < 0)
957
                return;
958
959
        // @TODO check if this simplistic STUN message recognition really always works, probably not
960
        unsigned short stun_bind_response = 0x0101;
961
        unsigned short * msgspot = (unsigned short *) msgbuf;
962
        if (*msgspot == stun_bind_response) {
963
                debug("ML: recv_pkg: parse stun message called");
964
                recv_stun_msg(msgbuf, recvSize);
965
                return;
966
        }
967
968
        msg_h = (struct msg_header *) msgbuf;
969
        bufptr += MSG_HEADER_SIZE + msg_h->len_mon_packet_hdr;
970
        msg_size = recvSize - MSG_HEADER_SIZE - msg_h->len_mon_packet_hdr;
971
972
973
        if(get_Recv_pkt_inf_cb != NULL && msg_h->len_mon_packet_hdr != 0) {
974
                mon_pkt_inf msginfNow;
975
                msginfNow.monitoringHeaderLen = msg_h->len_mon_packet_hdr;
976
                msginfNow.monitoringHeader = msg_h->len_mon_packet_hdr ? &msgbuf[0] + MSG_HEADER_SIZE : NULL;
977
                //TODO rethink this ...
978
                if(msg_h->msg_type == ML_CON_MSG) {
979
                        struct conn_msg *c_msg = (struct conn_msg *) bufptr;
980
                        msginfNow.remote_socketID = &(c_msg->sock_id);
981
                }
982
                else if(connectbuf[msg_h->remote_con_id] == NULL) {
983
                        error("ML: received pkg called with non existent connection");
984
                        return;
985
                } else
986
                        msginfNow.remote_socketID = &(connectbuf[msg_h->remote_con_id]->external_socketID);
987
                msginfNow.buffer = bufptr;
988
                msginfNow.bufSize = recvSize;
989
                msginfNow.msgtype = msg_h->msg_type;
990
                msginfNow.ttl = ttl;
991
                msginfNow.dataID = msg_h->msg_seq_num;
992
                msginfNow.offset = msg_h->offset;
993
                msginfNow.datasize = msg_h->msg_length;
994
                gettimeofday(&msginfNow.arrival_time, NULL);
995
                (get_Recv_pkt_inf_cb) ((void *) &msginfNow);
996
        }
997
998
999
        switch(msg_h->msg_type) {
1000
                case ML_CON_MSG:
1001
                        debug("ML: received conn pkg");
1002
                        recv_conn_msg(msg_h, bufptr, msg_size);
1003
                        break;
1004
                default:
1005
                        if(msg_h->msg_type < 127) {
1006
                                debug("ML: received data pkg");
1007
                                recv_data_msg(msg_h, bufptr, msg_size);
1008
                                break;
1009
                        }
1010
                        debug("ML: unrecognised msg_type");
1011
                        break;
1012
        }
1013
}
1014
1015
/*
1016
 * compare the external IP address of two socketIDs
1017
 */
1018
int
1019
compare_external_address_socketIDs(socketID_handle sock1, socketID_handle sock2)
1020
{
1021
        if( sock1->external_addr.udpaddr.sin_addr.s_addr == sock2->external_addr.udpaddr.sin_addr.s_addr)
1022
                return 0;
1023
        return 1;
1024
}
1025
1026
/*
1027
 * the timeout of the NAT traversal
1028
 */
1029
void nat_traversal_timeout(int fd, short event, void *arg)
1030
{
1031
        if (NAT_traversal == false) {
1032
                debug("ML: NAT traversal request resend");
1033
                send_stun_request(socketfd, &stun_server);
1034
1035
                /*
1036
                * enter a NAT traversal timeout that takes care of retransmission
1037
                */
1038
                struct event *ev1;
1039
                struct timeval timeout_value_NAT_traversal = { 1, 0 };
1040
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1041
                event_add(ev1, &timeout_value_NAT_traversal);
1042
                if(receive_SocketID_cb)
1043
                        (receive_SocketID_cb) (&local_socketID, 2);
1044
        }
1045
}
1046
1047
unsigned long resolve(const char *ipaddr)
1048
{
1049
        struct hostent *h = gethostbyname(ipaddr);
1050
        if (!h) {
1051
                error("Unable to resolve hostname %s\n", ipaddr);
1052
        exit(-1);
1053
    }
1054
    unsigned long *addr = (unsigned long *) (h->h_addr);
1055
    return *addr;
1056
}
1057
1058
1059
/*
1060
 * returns a handle to the socketID struct the ipaddr can be a null
1061
 * pointer. Then all available ipaddr on the machine are choosen.
1062
 */
1063
void create_socket(const int port, const char *ipaddr)
1064
{
1065
        struct sockaddr_in udpaddr;
1066
        udpaddr.sin_family = AF_INET;
1067
        if (ipaddr == NULL) {
1068
                /*
1069
                * try to guess the local IP address
1070
                */
1071
                const char *ipaddr_iface = mlAutodetectIPAddress();
1072
                if (ipaddr_iface) {
1073
                        udpaddr.sin_addr.s_addr = inet_addr(ipaddr_iface);
1074
                } else {
1075
                        udpaddr.sin_addr.s_addr = INADDR_ANY;
1076
                }
1077
        } else {
1078
                udpaddr.sin_addr.s_addr = inet_addr(ipaddr);
1079
        }
1080
        udpaddr.sin_port = htons(port);
1081
1082
        socketaddrgen udpgen;
1083
        udpgen.udpaddr = udpaddr;
1084
        local_socketID.internal_addr = udpgen;
1085
1086
        socketfd = createSocket(port, ipaddr);
1087
1088
        struct event *ev;
1089
        ev = event_new(base, socketfd, EV_READ | EV_PERSIST, recv_pkg, NULL);
1090
1091
        event_add(ev, NULL);
1092
1093
        if (isStunDefined()) {
1094
                /*
1095
                * send the NAT traversal STUN request
1096
                */
1097
                 send_stun_request(socketfd, &stun_server);
1098
1099
                /*
1100
                * enter a NAT traversal timeout that takes care of retransmission
1101
                */
1102
                struct event *ev1;
1103
                struct timeval timeout_value_NAT_traversal = { 2, 0 };
1104
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1105
                event_add(ev1, &timeout_value_NAT_traversal);
1106
1107
                NAT_traversal = false;
1108
        } else {
1109
                /*
1110
                * Assume we have accessibility and copy internal address to external one
1111
                */
1112
                local_socketID.external_addr = local_socketID.internal_addr;
1113
                NAT_traversal = true; // @TODO: this is not really NAT traversal, but a flag that init is over
1114
                // callback to the upper layer indicating that the socketID is now
1115
                // ready to use
1116
                (receive_SocketID_cb) (&local_socketID, 0);
1117
        }
1118
}
1119
1120
/**************************** END OF INTERNALS ***********************/
1121
1122
void mlInit(bool recv_data_cb,struct timeval timeout_value,const int port,const char *ipaddr,const int stun_port,const char *stun_ipaddr,receive_localsocketID_cb local_socketID_cb,void *arg){
1123
1124
        base = (struct event_base *) arg;
1125
        recv_data_callback = recv_data_cb;
1126
        mlSetRecvTimeout(timeout_value);
1127
        if (stun_ipaddr) {
1128
                 mlSetStunServer(stun_port, stun_ipaddr);
1129
        } else {
1130
1131
        }
1132
        register_recv_localsocketID_cb(local_socketID_cb);
1133
        create_socket(port, ipaddr);
1134 a0a1f630 KristianBeckers
1135
}
1136
1137
/* register callbacks  */
1138 da5dade7 MarcoBiazzini
void mlRegisterGetRecvPktInf(get_recv_pkt_inf_cb recv_pkt_inf_cb){
1139 a0a1f630 KristianBeckers
1140 da5dade7 MarcoBiazzini
        if (recv_pkt_inf_cb == NULL)
1141
                printf("Register get_recv_pkt_inf_cb failed: NULL ptr  \n");
1142
        else
1143
                get_Recv_pkt_inf_cb = recv_pkt_inf_cb;
1144 a0a1f630 KristianBeckers
1145
}
1146
1147 9f15e9f6 MarcoBiazzini
void mlRegisterGetSendPktInf(get_send_pkt_inf_cb  send_pkt_inf_cb){
1148 8601bccf RobertBirke
1149 da5dade7 MarcoBiazzini
        if (send_pkt_inf_cb == NULL)
1150
                printf("Register get_send_pkt_inf_cb: NULL ptr  \n");
1151
        else
1152
                get_Send_pkt_inf_cb = send_pkt_inf_cb;
1153 8601bccf RobertBirke
1154
}
1155
1156
1157 da5dade7 MarcoBiazzini
void mlRegisterSetMonitoringHeaderPktCb(set_monitoring_header_pkt_cb monitoring_header_pkt_cb ){
1158 a0a1f630 KristianBeckers
1159 da5dade7 MarcoBiazzini
        if (monitoring_header_pkt_cb == NULL)
1160
                printf("Register set_monitoring_header_pkt_cb: NULL ptr  \n");
1161
        else
1162
                set_Monitoring_header_pkt_cb = monitoring_header_pkt_cb;
1163 a0a1f630 KristianBeckers
1164
}
1165
1166 da5dade7 MarcoBiazzini
void mlRegisterGetRecvDataInf(get_recv_data_inf_cb recv_data_inf_cb){
1167 a0a1f630 KristianBeckers
1168 da5dade7 MarcoBiazzini
        if (recv_data_inf_cb == NULL)
1169
                printf("Register get_recv_data_inf_cb: NULL ptr  \n");
1170
        else
1171
                get_Recv_data_inf_cb = recv_data_inf_cb;
1172 a0a1f630 KristianBeckers
1173
}
1174
1175 da5dade7 MarcoBiazzini
void mlRegisterGetSendDataInf(get_send_data_inf_cb  send_data_inf_cb){
1176 a0a1f630 KristianBeckers
1177 da5dade7 MarcoBiazzini
        if (send_data_inf_cb == NULL)
1178
                printf("Register get_send_data_inf_cb: NULL ptr  \n");
1179
        else
1180
                get_Send_data_inf_cb = send_data_inf_cb;
1181 a0a1f630 KristianBeckers
1182
}
1183
1184 da5dade7 MarcoBiazzini
void mlRegisterSetMonitoringHeaderDataCb(set_monitoring_header_data_cb monitoring_header_data_cb){
1185 a0a1f630 KristianBeckers
1186 da5dade7 MarcoBiazzini
        if (monitoring_header_data_cb == NULL)
1187
                printf("Register set_monitoring_header_data_cb : NULL ptr  \n");
1188
        else
1189
        set_Monitoring_header_data_cb = monitoring_header_data_cb;
1190 a0a1f630 KristianBeckers
1191
}
1192
1193 da5dade7 MarcoBiazzini
void mlRegisterRecvConnectionCb(receive_connection_cb recv_conn_cb){
1194 a0a1f630 KristianBeckers
1195 da5dade7 MarcoBiazzini
        if (recv_conn_cb == NULL)
1196
                printf("Register receive_connection_cb: NULL ptr  \n");
1197
        else
1198
                receive_Connection_cb = recv_conn_cb;
1199 a0a1f630 KristianBeckers
1200
}
1201
1202 da5dade7 MarcoBiazzini
void mlRegisterErrorConnectionCb(connection_failed_cb conn_failed){
1203 a0a1f630 KristianBeckers
1204 da5dade7 MarcoBiazzini
        if (conn_failed == NULL)
1205
                printf("Register connection_failed_cb: NULL ptr  \n");
1206
        else
1207
        failed_Connection_cb = conn_failed;
1208 a0a1f630 KristianBeckers
1209
}
1210
1211 da5dade7 MarcoBiazzini
void mlRegisterRecvDataCb(receive_data_cb data_cb,unsigned char msgtype){
1212
1213
    if (msgtype > 126) {
1214 a0a1f630 KristianBeckers
1215 da5dade7 MarcoBiazzini
        printf
1216
            ("transmissionHandler: Could not register recv_data callback. Msgtype is greater then 126 \n");
1217
1218
    }
1219
1220
    if (data_cb == NULL) {
1221
1222
        printf("Register receive data callback: NUll ptr \n ");
1223
1224
    } else {
1225
1226
        recvcbbuf[msgtype] = data_cb;
1227
1228
    }
1229 a0a1f630 KristianBeckers
1230
}
1231
1232 da5dade7 MarcoBiazzini
void mlCloseSocket(socketID_handle socketID){
1233 a0a1f630 KristianBeckers
1234 da5dade7 MarcoBiazzini
        free(socketID);
1235 a0a1f630 KristianBeckers
1236
}
1237
1238
/* connection functions */
1239 6f256447 TivadarSzemethy
int mlOpenConnection(socketID_handle external_socketID,receive_connection_cb connection_cb,void *arg, const send_params defaultSendParams){
1240 da5dade7 MarcoBiazzini
1241
        int con_id;
1242
        if (external_socketID == NULL) {
1243
                error("ML: cannot open connection: one of the socketIDs is NULL");
1244
                return -1;
1245
        }
1246
        if (NAT_traversal == false) {
1247
                error("ML: cannot open connection: NAT traversal for socketID still in progress");
1248
                return -1;
1249
        }
1250
        if (connection_cb == NULL) {
1251
                error("ML: cannot open connection: connection_cb is NULL");
1252
                return -1;
1253
        }
1254
1255
        // check if that connection already exist
1256
1257
        con_id = mlConnectionExist(external_socketID, false);
1258
        if (con_id >= 0) {
1259 6f256447 TivadarSzemethy
                // overwrite defaultSendParams
1260
                connectbuf[con_id]->defaultSendParams = defaultSendParams;
1261 da5dade7 MarcoBiazzini
                // if so check if it is ready to use
1262
                if (connectbuf[con_id]->status == READY) {
1263
                                // if so use the callback immidiatley
1264
                                (connection_cb) (con_id, arg);
1265
1266
                // otherwise just write the connection cb and the arg pointer
1267
                // into the connection struct
1268
                } else {
1269
                        struct receive_connection_cb_list *temp;
1270
                        temp = malloc(sizeof(struct receive_connection_cb_list));
1271
                        temp->next = NULL;
1272
                        temp->connection_cb = connection_cb;
1273
                        temp->arg = arg;
1274
                        if(connectbuf[con_id]->connection_last != NULL) {
1275
                                connectbuf[con_id]->connection_last->next = temp;
1276
                                connectbuf[con_id]->connection_last = temp;
1277
                        } else
1278
                                connectbuf[con_id]->connection_last = connectbuf[con_id]->connection_head = temp;
1279
                }
1280
                return con_id;
1281
        }
1282
        // make entry in connection_establishment array
1283
        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
1284
                if (connectbuf[con_id] == NULL) {
1285
                        connectbuf[con_id] = (connect_data *) malloc(sizeof(connect_data));
1286
                        memset(connectbuf[con_id],0,sizeof(connect_data));
1287
                        connectbuf[con_id]->starttime = time(NULL);
1288
                        memcpy(&connectbuf[con_id]->external_socketID, external_socketID, sizeof(socket_ID));
1289
                        connectbuf[con_id]->pmtusize = MAX;
1290
                        connectbuf[con_id]->status = INVITE;
1291
                        connectbuf[con_id]->seqnr = 0;
1292
                        connectbuf[con_id]->internal_connect = !compare_external_address_socketIDs(external_socketID, &local_socketID);
1293
                        /*
1294
                        * timeout values for the pmtu discovery
1295
                        */
1296
                        connectbuf[con_id]->timeout_value.tv_sec = 15;
1297
                        connectbuf[con_id]->timeout_value.tv_usec = 0;
1298
                        connectbuf[con_id]->connectionID = con_id;
1299
1300
                        connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
1301
                        connectbuf[con_id]->connection_last->next = NULL;
1302
                        connectbuf[con_id]->connection_last->connection_cb = connection_cb;
1303
                        connectbuf[con_id]->connection_last->arg = arg;
1304
                        connectbuf[con_id]->external_connectionID = -1;
1305 6f256447 TivadarSzemethy
                        connectbuf[con_id]->defaultSendParams = defaultSendParams;
1306 da5dade7 MarcoBiazzini
                        break;
1307
                }
1308
        } //end of for
1309
1310
        if (con_id == CONNECTBUFSIZE) {
1311
                error("ML: Could not open connection: connbuffer full");
1312
                return -1;
1313
        }
1314
1315
        // create and send a connection message
1316
        send_conn_msg(con_id, MAX, INVITE);
1317
1318
        struct event *ev;
1319
        ev = evtimer_new(base, pmtu_timeout_cb, (void *) (long)con_id);
1320
        event_add(ev, &connectbuf[con_id]->timeout_value);
1321
1322
        return con_id;
1323
1324
}
1325 a0a1f630 KristianBeckers
1326 da5dade7 MarcoBiazzini
void mlCloseConnection(const int connectionID){
1327
1328
        // remove it from the connection array
1329
        if(connectbuf[connectionID]) {
1330
                if(connectbuf[connectionID]->ctrl_msg_buf)
1331
                        free(connectbuf[connectionID]->ctrl_msg_buf);
1332
                free(connectbuf[connectionID]);
1333
                connectbuf[connectionID] = NULL;
1334
        }
1335 a0a1f630 KristianBeckers
1336
}
1337
1338 da5dade7 MarcoBiazzini
void mlSendData(const int connectionID,char *sendbuf,int bufsize,unsigned char msgtype,send_params *sParams){
1339
1340
        if (connectionID < 0) {
1341
                error("ML: send data failed: connectionID does not exist");
1342
                return;
1343
        }
1344
1345
        if (connectbuf[connectionID] == NULL) {
1346
                error("ML: send data failed: connectionID does not exist");
1347
                return;
1348
        }
1349
        if (connectbuf[connectionID]->status != READY) {
1350
            error("ML: send data failed: connection is not active");
1351
            return;
1352
        }
1353 a0a1f630 KristianBeckers
1354 6f256447 TivadarSzemethy
        if (sParams == NULL) {
1355
                sParams = &(connectbuf[connectionID]->defaultSendParams);
1356
        }
1357
1358 da5dade7 MarcoBiazzini
        send_msg(connectionID, msgtype, sendbuf, bufsize, false, sParams);
1359 a0a1f630 KristianBeckers
1360
}
1361
1362
/* transmit data functions  */
1363 da5dade7 MarcoBiazzini
int mlSendAllData(const int connectionID,send_all_data_container *container,int nr_entries,unsigned char msgtype,send_params *sParams){
1364 2a178954 KristianBeckers
1365 da5dade7 MarcoBiazzini
    if (nr_entries < 1 || nr_entries > 5) {
1366
1367
        printf
1368
            ("send_all_data ERROR: nr_enties is not between 1 and 5 \n ");
1369
        return 0;
1370
1371
    } else {
1372
1373
        if (nr_entries == 1) {
1374
1375
                mlSendData(connectionID, container->buffer_1,
1376
                      container->length_1, msgtype, sParams);
1377
1378
            return 1;
1379
1380
        } else if (nr_entries == 2) {
1381
1382
            int buflen = container->length_1 + container->length_2;
1383
            char buf[buflen];
1384
            memcpy(buf, container->buffer_1, container->length_1);
1385
            memcpy(&buf[container->length_1], container->buffer_2,
1386
                   container->length_2);
1387
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1388
1389
            return 1;
1390
1391
        } else if (nr_entries == 3) {
1392
1393
            int buflen =
1394
                container->length_1 + container->length_2 +
1395
                container->length_3;
1396
            char buf[buflen];
1397
            memcpy(buf, container->buffer_1, container->length_1);
1398
            memcpy(&buf[container->length_1], container->buffer_2,
1399
                   container->length_2);
1400
            memcpy(&buf[container->length_2], container->buffer_3,
1401
                   container->length_3);
1402
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1403
1404
1405
            return 1;
1406
1407
        } else if (nr_entries == 4) {
1408
1409
            int buflen =
1410
                container->length_1 + container->length_2 +
1411
                container->length_3 + container->length_4;
1412
            char buf[buflen];
1413
            memcpy(buf, container->buffer_1, container->length_1);
1414
            memcpy(&buf[container->length_1], container->buffer_2,
1415
                   container->length_2);
1416
            memcpy(&buf[container->length_2], container->buffer_3,
1417
                   container->length_3);
1418
            memcpy(&buf[container->length_3], container->buffer_4,
1419
                   container->length_4);
1420
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1421
1422
            return 1;
1423
1424
        } else {
1425
1426
            int buflen =
1427
                container->length_1 + container->length_2 +
1428
                container->length_3 + container->length_4 +
1429
                container->length_5;
1430
            char buf[buflen];
1431
            memcpy(buf, container->buffer_1, container->length_1);
1432
            memcpy(&buf[container->length_1], container->buffer_2,
1433
                   container->length_2);
1434
            memcpy(&buf[container->length_2], container->buffer_3,
1435
                   container->length_3);
1436
            memcpy(&buf[container->length_3], container->buffer_4,
1437
                   container->length_4);
1438
            memcpy(&buf[container->length_4], container->buffer_5,
1439
                   container->length_5);
1440
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1441
1442
            return 1;
1443
        }
1444
1445
    }
1446 a0a1f630 KristianBeckers
1447
}
1448
1449 da5dade7 MarcoBiazzini
int mlRecvData(const int connectionID,char *recvbuf,int *bufsize,recv_params *rParams){
1450
1451
        //TODO yet to be converted
1452
        return 0;
1453
#if 0
1454
        if (rParams == NULL) {
1455
                error("ML: recv_data failed: recv_params is a NULL ptr");
1456
                return 0;
1457
    } else {
1458

1459
        printf("transmissionhandler: recv data called \n");
1460

1461
        int i = 0;
1462
        int returnValue = 0;
1463
        double timeout = (double) recv_timeout.tv_sec;
1464
        time_t endtime = time(NULL);
1465

1466
        for (i = 0; i < RECVDATABUFSIZE; i++) {
1467

1468
            if (recvdatabuf[i] != NULL) {
1469

1470
                if (recvdatabuf[i]->connectionID == connectionID) {
1471

1472
                    printf("transmissionhandler: recv data has entry  \n");
1473

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

1476
                    // check if the specified connection has data and it
1477
                    // is complete
1478
                    // check the data seqnr
1479
                    // if(connectionID == recvdatabuf[i]->connectionID &&
1480
                    // 1 == recvdatabuf[i]->status){
1481

1482
                    if (1 == recvdatabuf[i]->status) {
1483

1484
                        // printf("transmissionHandler: recv_data set is
1485
                        // complete \n" );
1486

1487
                        // printf("debud \n");
1488

1489
                        // exchange the pointers
1490
                        int buffersize = 0;
1491
                        buffersize = recvdatabuf[i]->bufsize;
1492
                        *bufsize = buffersize;
1493
                        // recvbuf = recvdatabuf[i]->recvbuf;
1494

1495
                        // printf("buffersize %d \n",buffersize);
1496
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1497
                               buffersize);
1498
                        // printf(" recvbuf %s \n",recvbuf );
1499

1500
//                         double nrMissFrags =
1501
//                             (double) recvdatabuf[i]->nrFragments /
1502
//                             (double) recvdatabuf[i]->recvFragments;
1503
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
1504

1505
//                        rParams->nrMissingFragments = nrMissingFragments;
1506
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
1507
                        rParams->msgtype = recvdatabuf[i]->msgtype;
1508
                        rParams->connectionID =
1509
                            recvdatabuf[i]->connectionID;
1510

1511
                        // break from the loop
1512
                        // printf(" recvbuf %s \n ",recvbuf);
1513

1514
                        // double nrMissFrags =
1515
                        // (double)recvdatabuf[i]->nrFragments /
1516
                        // (double)recvdatabuf[i]->recvFragments;
1517
                        // int nrMissingFragments =
1518
                        // (int)ceil(nrMissFrags);
1519 a0a1f630 KristianBeckers

1520 da5dade7 MarcoBiazzini
                        if(get_Recv_data_inf_cb != NULL) {
1521
                                mon_data_inf recv_data_inf;
1522

1523
                                recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1524
                                recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1525
                                recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1526
                                recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1527
//                                 recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1528
//                                 recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1529
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
1530
                                recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1531
                                recv_data_inf.nrMissingFragments = nrMissingFragments;
1532
                                recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1533
                                recv_data_inf.priority = false;
1534
                                recv_data_inf.padding = false;
1535
                                recv_data_inf.confirmation = false;
1536
                                recv_data_inf.reliable = false;
1537

1538
                                // send data recv callback to monitoring module
1539

1540
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1541
                        }
1542

1543

1544
                        // free the allocated memory
1545
                        free(recvdatabuf[i]);
1546
                        recvdatabuf[i] = NULL;
1547

1548
                        returnValue = 1;
1549
                        break;
1550

1551
                    }
1552

1553
                    if (recvdatabuf[i] != NULL) {
1554

1555
                        if (timepass > timeout) {
1556

1557
                            printf("transmissionHandler: recv_data timeout called  \n");
1558

1559
                            // some data about the missing chunks should
1560
                            // be added here
1561
                            // exchange the pointers
1562
                            int buffersize = 0;
1563
                            buffersize = recvdatabuf[i]->bufsize;
1564
                            *bufsize = buffersize;
1565
                            // recvbuf = recvdatabuf[i]->recvbuf;
1566

1567
                            double nrMissFrags =
1568
                                (double) recvdatabuf[i]->nrFragments /
1569
                                (double) recvdatabuf[i]->recvFragments;
1570
                            int nrMissingFragments =
1571
                                (int) ceil(nrMissFrags);
1572

1573
                            // printf(" recvbuf %s \n",recvbuf );
1574

1575
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1576
                                   buffersize);
1577

1578
                            rParams->nrMissingFragments =
1579
                                nrMissingFragments;
1580
                            rParams->nrFragments =
1581
                                recvdatabuf[i]->nrFragments;
1582
                            rParams->msgtype = recvdatabuf[i]->msgtype;
1583
                            rParams->connectionID =
1584
                                recvdatabuf[i]->connectionID;
1585

1586
                                if(get_Recv_data_inf_cb != NULL) {
1587
                                        mon_data_inf recv_data_inf;
1588

1589
                                        recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1590
                                        recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1591
                                        recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1592
                                        recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1593
                                        recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1594
                                        recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1595
                                        gettimeofday(&recv_data_inf.arrival_time, NULL);
1596
                                        recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1597
                                        recv_data_inf.nrMissingFragments = nrMissingFragments;
1598
                                        recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1599
                                        recv_data_inf.priority = false;
1600
                                        recv_data_inf.padding = false;
1601
                                        recv_data_inf.confirmation = false;
1602
                                        recv_data_inf.reliable = false;
1603

1604
                                        // send data recv callback to monitoring module
1605

1606
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1607
                                }
1608

1609
                            // free the allocated memory
1610
                            free(recvdatabuf[i]);
1611
                            recvdatabuf[i] = NULL;
1612

1613
                            returnValue = 1;
1614
                            break;
1615

1616
                        }
1617
                    }
1618

1619
                }
1620

1621
            }
1622
            // printf("2 recvbuf %s \n ",recvbuf);
1623
        }
1624
        return returnValue;
1625
    }
1626
#endif
1627 a0a1f630 KristianBeckers
1628
}
1629
1630
/* setter  */
1631 da5dade7 MarcoBiazzini
void mlSetStunServer(const int port,const char *ipaddr){
1632 a0a1f630 KristianBeckers
1633 da5dade7 MarcoBiazzini
        stun_server.sin_family = AF_INET;
1634
        if (ipaddr == NULL)
1635
                stun_server.sin_addr.s_addr = htonl(INADDR_ANY);
1636
        else
1637
                stun_server.sin_addr.s_addr = resolve(ipaddr);
1638
        stun_server.sin_port = htons(port);
1639 a0a1f630 KristianBeckers
1640
}
1641
1642 da5dade7 MarcoBiazzini
void mlSetRecvTimeout(struct timeval timeout_value){
1643 a0a1f630 KristianBeckers
1644 da5dade7 MarcoBiazzini
        recv_timeout = timeout_value;
1645 a0a1f630 KristianBeckers
1646
}
1647
1648 da5dade7 MarcoBiazzini
int mlGetStandardTTL(socketID_handle socketID,uint8_t *ttl){
1649 a0a1f630 KristianBeckers
1650 da5dade7 MarcoBiazzini
        return getTTL(socketfd, ttl);
1651 a0a1f630 KristianBeckers
1652 07355669 TivadarSzemethy
}
1653 2a178954 KristianBeckers
1654 da5dade7 MarcoBiazzini
socketID_handle mlGetLocalSocketID(int *errorstatus){
1655 2a178954 KristianBeckers
1656 da5dade7 MarcoBiazzini
        if (NAT_traversal == false) {
1657
                *errorstatus = 2;
1658
                return NULL;
1659
        }
1660
1661
        *errorstatus = 0;
1662
        return &local_socketID;
1663 2a178954 KristianBeckers
1664
}
1665
1666 da5dade7 MarcoBiazzini
int mlGetExternalIP(char* external_addr){
1667
1668
        socketaddrgen udpgen;
1669
        struct sockaddr_in udpaddr;
1670
1671
        udpgen = local_socketID.external_addr;
1672
        udpaddr = udpgen.udpaddr;
1673
1674
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
1675
                        INET_ADDRSTRLEN);
1676 2a178954 KristianBeckers
1677 da5dade7 MarcoBiazzini
        if (external_addr == NULL) {
1678
1679
        return -1;
1680
1681
        } else {
1682
1683
        return 0;
1684
1685
        }
1686 2a178954 KristianBeckers
1687
}
1688
1689 da5dade7 MarcoBiazzini
int mlSocketIDToString(socketID_handle socketID,char* socketID_string, size_t len){
1690
1691
        char internal_addr[INET_ADDRSTRLEN];
1692
        char external_addr[INET_ADDRSTRLEN];
1693
        inet_ntop(AF_INET, &(socketID->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1694
        inet_ntop(AF_INET, &(socketID->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1695 2a178954 KristianBeckers
1696 da5dade7 MarcoBiazzini
        snprintf(socketID_string,len,"%s:%d-%s:%d", internal_addr, ntohs(socketID->internal_addr.udpaddr.sin_port),
1697
                external_addr,        ntohs(socketID->external_addr.udpaddr.sin_port));
1698
        return 0;
1699 2a178954 KristianBeckers
1700
}
1701
1702 da5dade7 MarcoBiazzini
int mlStringToSocketID(const char* socketID_string, socketID_handle socketID){
1703
1704
        //@TODO add checks against malformed string
1705
        char external_addr[INET_ADDRSTRLEN];
1706
        int external_port;
1707
        char internal_addr[INET_ADDRSTRLEN];
1708
        int internal_port;
1709 2a178954 KristianBeckers
1710 da5dade7 MarcoBiazzini
        char *pch;
1711
        char *s = strdup(socketID_string);
1712
1713
        //replace ':' with a blank
1714
        pch=strchr(s,':');
1715
        while (pch!=NULL){
1716
                                *pch = ' ';
1717
                pch=strchr(pch+1,':');
1718
        }
1719
        pch=strchr(s,'-');
1720
        if(pch) *pch = ' ';
1721
1722
        sscanf(s,"%s %d %s %d", internal_addr, &internal_port,
1723
                external_addr, &external_port);
1724
1725
        if(inet_pton(AF_INET, internal_addr, &(socketID->internal_addr.udpaddr.sin_addr)) == 0)
1726
                return EINVAL;
1727
        socketID->internal_addr.udpaddr.sin_family = AF_INET;
1728
        socketID->internal_addr.udpaddr.sin_port = htons(internal_port);
1729
1730
1731
        if(inet_pton(AF_INET, external_addr, &(socketID->external_addr.udpaddr.sin_addr)) ==0)
1732
                return EINVAL;
1733
        socketID->external_addr.udpaddr.sin_family = AF_INET;
1734
        socketID->external_addr.udpaddr.sin_port = htons(external_port);
1735
1736
        free(s);
1737
        return 0;
1738 2a178954 KristianBeckers
1739
}
1740
1741 da5dade7 MarcoBiazzini
int mlGetConnectionStatus(int connectionID){
1742 2a178954 KristianBeckers
1743 da5dade7 MarcoBiazzini
        if(connectbuf[connectionID])
1744
                return connectbuf[connectionID]->status == READY;
1745
        return -1;
1746 2a178954 KristianBeckers
    
1747
}
1748
1749
1750 da5dade7 MarcoBiazzini
int mlConnectionExist(socketID_handle socketID, bool ready){
1751
1752
    /*
1753
     * check if another connection for the external connectionID exist
1754
     * that was established \ within the last 2 seconds
1755
     */
1756
        int i;
1757
        for (i = 0; i < CONNECTBUFSIZE; i++)
1758
                if (connectbuf[i] != NULL)
1759
                        if (mlCompareSocketIDs(&(connectbuf[i]->external_socketID), socketID) == 0) {
1760
                                if (ready) return (connectbuf[i]->status == READY ? i : -1);;
1761
                                return i;
1762
                                }
1763 2a178954 KristianBeckers
1764 da5dade7 MarcoBiazzini
    return -1;
1765 2a178954 KristianBeckers
1766
}
1767 2c702104 RobertBirke
1768
//Added by Robert Birke as comodity functions
1769
1770 da5dade7 MarcoBiazzini
int mlPrintSocketID(socketID_handle socketID) {
1771
        char str[SOCKETID_STRING_SIZE];
1772
        mlSocketIDToString(socketID, str, sizeof(str));
1773
        printf("int->%s<-ext\n",str);
1774 2c702104 RobertBirke
}
1775 da5dade7 MarcoBiazzini
1776
/*
1777
 * hash code of a socketID
1778
 * TODO might think of a better way
1779
 */
1780
int mlHashSocketID(socketID_handle sock) {
1781
    return sock->internal_addr.udpaddr.sin_port +
1782
                          sock->external_addr.udpaddr.sin_port;
1783 2c702104 RobertBirke
}
1784
1785 da5dade7 MarcoBiazzini
int mlCompareSocketIDs(socketID_handle sock1, socketID_handle sock2) {
1786
        /*
1787
        * compare internal addr
1788
        */
1789
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr !=
1790
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
1791
                        return 1;
1792
1793
        if (sock1->internal_addr.udpaddr.sin_port !=
1794
                 sock2->internal_addr.udpaddr.sin_port)
1795
                        return 1;
1796
1797
        /*
1798
        * compare external addr
1799
        */
1800
        if (sock1->external_addr.udpaddr.sin_addr.s_addr !=
1801
            sock2->external_addr.udpaddr.sin_addr.s_addr)
1802
                        return 1;
1803
1804
        if (sock1->external_addr.udpaddr.sin_port !=
1805
                 sock2->external_addr.udpaddr.sin_port)
1806
                        return 1;
1807
1808
        return 0;
1809 2c702104 RobertBirke
}
1810
1811 da5dade7 MarcoBiazzini
int mlCompareSocketIDsByPort(socketID_handle sock1, socketID_handle sock2)
1812 380cf1b9 RobertBirke
{ 
1813 2c702104 RobertBirke
        if (sock1->internal_addr.udpaddr.sin_port !=
1814
                 sock2->internal_addr.udpaddr.sin_port)
1815
                        return 1;
1816
1817
        if (sock1->external_addr.udpaddr.sin_port !=
1818
                 sock2->external_addr.udpaddr.sin_port)
1819
                        return 1;
1820
        return 0;
1821 380cf1b9 RobertBirke
}
1822 bcf9c2dd RobertBirke
1823 da5dade7 MarcoBiazzini
int mlGetPathMTU(int ConnectionId) {
1824
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
1825
                return -1;
1826
        if (connectbuf[ConnectionId] != NULL)
1827
                return connectbuf[ConnectionId]->pmtusize;
1828
        return -1;
1829 bcf9c2dd RobertBirke
}