Statistics
| Branch: | Revision:

ml / ml.c @ b324d3d1

History | View | Annotate | Download (62.8 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 <stdlib.h>
36
#include <unistd.h>
37 a0a1f630 KristianBeckers
#include <stdio.h>
38
#include <stddef.h>
39 da5dade7 MarcoBiazzini
#include <stdint.h>
40
#include <string.h>
41 a0a1f630 KristianBeckers
#include <sys/types.h>
42 7b67b6a1 ArpadBakay
#include <event2/event.h>
43 a0a1f630 KristianBeckers
#include <time.h>
44 da5dade7 MarcoBiazzini
#include <math.h>
45 8fed9f23 CsabaKiraly
#include <assert.h>
46 7b67b6a1 ArpadBakay
#include <errno.h>
47
48
#ifndef WIN32
49
#include <arpa/inet.h>
50
#include <netdb.h>
51
#include <netinet/in.h>
52
#include <sys/socket.h>
53
#include <fcntl.h>
54
#else
55
56
#include <winsock2.h>
57
#include <ws2tcpip.h>
58
#endif
59 8fed9f23 CsabaKiraly
60 da5dade7 MarcoBiazzini
#include "util/udpSocket.h"
61
#include "util/stun.h"
62
#include "transmissionHandler.h"
63 07355669 TivadarSzemethy
64 da5dade7 MarcoBiazzini
#define LOG_MODULE "[ml] "
65 11fce711 MarcoBiazzini
#include "ml_log.h"
66 380cf1b9 RobertBirke
67 da5dade7 MarcoBiazzini
/**************************** START OF INTERNALS ***********************/
68
69 9bf9c247 CsabaKiraly
70
/*
71
 * reserved message type for internal puposes
72
 */
73
#define MSG_TYPE_ML_KEEPALIVE 0x126        //TODO: check that it is really interpreted as internal
74
75 da5dade7 MarcoBiazzini
/*
76
 * a pointer to a libevent instance
77
 */
78
struct event_base *base;
79
80
/*
81
 * define the nr of connections the messaging layer can handle
82
 */
83
#define CONNECTBUFSIZE 10000
84
/*
85
 * define the nr of data that can be received parallel
86
 */
87
#define RECVDATABUFSIZE 10000
88
/*
89
 * define an array for message multiplexing
90
 */
91
#define MSGMULTIPLEXSIZE 127
92
93 7ed37922 CsabaKiraly
94
/*
95
 * timeout before thinking that the STUN server can't be connected
96
 */
97
#define NAT_TRAVERSAL_TIMEOUT { 1, 0 }
98
99 da5dade7 MarcoBiazzini
/*
100 d5b9b14d CsabaKiraly
 * timeout before thinking of an mtu problem (check MAX_TRIALS as well)
101
 */
102 9eaed17c CsabaKiraly
#define PMTU_TIMEOUT { 0, 500000 }
103 d5b9b14d CsabaKiraly
104
/*
105
 * retry sending connection messages this many times before reducing pmtu
106
 */
107
#define MAX_TRIALS 3
108
109
/*
110 68d98e77 CsabaKiraly
 * default timeout value between the first and the last received packet of a message
111
 */
112
#define RECV_TIMEOUT_DEFAULT { 2, 0 }
113
114
/*
115 da5dade7 MarcoBiazzini
 * global variables
116
 */
117
/*
118
 * define a buffer of pointers to connect structures
119
 */
120
connect_data *connectbuf[CONNECTBUFSIZE];
121
122
/*
123
 * define a pointer buffer with pointers to recv_data structures
124
 */
125
recvdata *recvdatabuf[RECVDATABUFSIZE];
126
127
/*
128
 * define a pointer buffer for message multiplexing
129
 */
130
receive_data_cb recvcbbuf[MSGMULTIPLEXSIZE];
131
132
/*
133
 * stun server address
134
 */
135
struct sockaddr_in stun_server;
136
137
/*
138
 * receive timeout
139
 */
140 68d98e77 CsabaKiraly
static struct timeval recv_timeout = RECV_TIMEOUT_DEFAULT;
141 da5dade7 MarcoBiazzini
142
/*
143
 * boolean NAT traversal successful if true
144
 */
145
boolean NAT_traversal;
146
147
/*
148
 * file descriptor for local socket
149
 */
150
evutil_socket_t socketfd;
151
152
/*
153
 * local socketID
154
 */
155
socket_ID local_socketID;
156
157
socketID_handle loc_socketID = &local_socketID;
158
159
/*
160
 * callback function pointers
161
 */
162
/*
163
 * monitoring module callbacks
164
 */
165
get_recv_pkt_inf_cb get_Recv_pkt_inf_cb = NULL;
166
get_send_pkt_inf_cb get_Send_pkt_inf_cb = NULL;
167
set_monitoring_header_pkt_cb set_Monitoring_header_pkt_cb = NULL;
168
get_recv_data_inf_cb get_Recv_data_inf_cb = NULL;
169
get_send_data_inf_cb get_Send_data_inf_cb = NULL;
170
set_monitoring_header_data_cb set_Monitoring_header_data_cb = NULL;
171
/*
172
 * connection callbacks
173
 */
174
receive_connection_cb receive_Connection_cb = NULL;
175
connection_failed_cb failed_Connection_cb = NULL;
176
/*
177
 * local socketID callback
178
 */
179
receive_localsocketID_cb receive_SocketID_cb;
180
181
/*
182
 * boolean that defines if received data is transmitted to the upper layer
183
 * via callback or via upper layer polling
184
 */
185
boolean recv_data_callback;
186
187
/*
188
 * helper function to get rid of a warning
189
 */
190 7b67b6a1 ArpadBakay
#ifndef WIN32
191 da5dade7 MarcoBiazzini
int min(int a, int b) {
192
        if (a > b) return b;
193
        return a;
194
}
195 7b67b6a1 ArpadBakay
#endif
196 da5dade7 MarcoBiazzini
197 cdcc1fe1 CsabaKiraly
/*
198
 * convert a socketID to a string. It uses a static buffer, so either strdup is needed, or the string will get lost!
199
 */
200
const char *conid_to_string(int con_id)
201
{
202
        static char s[INET_ADDRSTRLEN+1+5+1+INET_ADDRSTRLEN+1+5+1];
203
        mlSocketIDToString(&connectbuf[con_id]->external_socketID, s, sizeof(s));
204
        return s;
205
}
206
207 da5dade7 MarcoBiazzini
void register_recv_localsocketID_cb(receive_localsocketID_cb local_socketID_cb)
208
{
209 028bda1f CsabaKiraly
        if (local_socketID_cb == NULL) {
210 11fce711 MarcoBiazzini
                error("ML : Register receive_localsocketID_cb: NULL ptr \n");
211 028bda1f CsabaKiraly
        } else {
212
                receive_SocketID_cb = local_socketID_cb;
213
        }
214 da5dade7 MarcoBiazzini
}
215
216
217 11fce711 MarcoBiazzini
//void keep_connection_alive(const int connectionID)
218
//{
219
//
220
//    // to be done with the NAT traversal
221
//    // send a message over the wire
222
//    printf("\n");
223
//
224
//}
225 da5dade7 MarcoBiazzini
226
void unsetStunServer()
227
{
228 ea1436ee CsabaKiraly
        stun_server.sin_addr.s_addr = INADDR_NONE;
229 da5dade7 MarcoBiazzini
}
230
231
bool isStunDefined()
232
{
233 ea1436ee CsabaKiraly
        return stun_server.sin_addr.s_addr != INADDR_NONE;
234 da5dade7 MarcoBiazzini
}
235
236
void send_msg(int con_id, int msg_type, char* msg, int msg_len, bool truncable, send_params * sParams) {
237
        socketaddrgen udpgen;
238
        bool retry;
239
        int pkt_len, offset;
240
        struct iovec iov[4];
241
242 c6898c39 RobertBirke
        char h_pkt[MON_PKT_HEADER_SPACE];
243
        char h_data[MON_DATA_HEADER_SPACE];
244 da5dade7 MarcoBiazzini
245
        struct msg_header msg_h;
246
247 cdcc1fe1 CsabaKiraly
        debug("ML: send_msg to %s conID:%d extID:%d\n", conid_to_string(con_id), con_id, connectbuf[con_id]->external_connectionID);
248 f081b938 CsabaKiraly
249 da5dade7 MarcoBiazzini
        iov[0].iov_base = &msg_h;
250
        iov[0].iov_len = MSG_HEADER_SIZE;
251
252 4132f78a RobertBirke
        msg_h.local_con_id = htonl(con_id);
253
        msg_h.remote_con_id = htonl(connectbuf[con_id]->external_connectionID);
254 da5dade7 MarcoBiazzini
        msg_h.msg_type = msg_type;
255 4132f78a RobertBirke
        msg_h.msg_seq_num = htonl(connectbuf[con_id]->seqnr++);
256 da5dade7 MarcoBiazzini
257
258
        iov[1].iov_len = iov[2].iov_len = 0;
259
        iov[1].iov_base = h_pkt;
260
        iov[2].iov_base = h_data;
261
262
263
        if (connectbuf[con_id]->internal_connect)
264
                udpgen = connectbuf[con_id]->external_socketID.internal_addr;
265
        else
266
                udpgen = connectbuf[con_id]->external_socketID.external_addr;
267
268
        do{
269
                offset = 0;
270
                retry = false;
271
                // Monitoring layer hook
272
                if(set_Monitoring_header_data_cb != NULL) {
273
                        iov[2].iov_len = ((set_Monitoring_header_data_cb) (&(connectbuf[con_id]->external_socketID), msg_type));
274
                }
275
                msg_h.len_mon_data_hdr = iov[2].iov_len;
276
277
                if(get_Send_data_inf_cb != NULL && iov[2].iov_len != 0) {
278
                        mon_data_inf sd_data_inf;
279
280 c6898c39 RobertBirke
                        memset(h_data, 0, MON_DATA_HEADER_SPACE);
281
282 da5dade7 MarcoBiazzini
                        sd_data_inf.remote_socketID = &(connectbuf[con_id]->external_socketID);
283
                        sd_data_inf.buffer = msg;
284
                        sd_data_inf.bufSize = msg_len;
285
                        sd_data_inf.msgtype = msg_type;
286
                        sd_data_inf.monitoringDataHeader = iov[2].iov_base;
287
                        sd_data_inf.monitoringDataHeaderLen = iov[2].iov_len;
288
                        sd_data_inf.priority = sParams->priority;
289
                        sd_data_inf.padding = sParams->padding;
290
                        sd_data_inf.confirmation = sParams->confirmation;
291
                        sd_data_inf.reliable = sParams->reliable;
292
                        memset(&sd_data_inf.arrival_time, 0, sizeof(struct timeval));
293
294
                        (get_Send_data_inf_cb) ((void *) &sd_data_inf);
295
                }
296
297
                do {
298
                        if(set_Monitoring_header_pkt_cb != NULL) {
299
                                iov[1].iov_len = (set_Monitoring_header_pkt_cb) (&(connectbuf[con_id]->external_socketID), msg_type);
300
                        }
301 1f8ebe96 RobertBirke
                        pkt_len = min(connectbuf[con_id]->pmtusize - iov[2].iov_len - iov[1].iov_len - iov[0].iov_len, msg_len - offset) ;
302 da5dade7 MarcoBiazzini
303
                        iov[3].iov_len = pkt_len;
304
                        iov[3].iov_base = msg + offset;
305
306
                        //fill header
307
                        msg_h.len_mon_packet_hdr = iov[1].iov_len;
308 4132f78a RobertBirke
                        msg_h.offset = htonl(offset);
309
                        msg_h.msg_length = htonl(truncable ? pkt_len : msg_len);
310 da5dade7 MarcoBiazzini
311
                        //monitoring layer hook
312
                        if(get_Send_pkt_inf_cb != NULL && iov[1].iov_len) {
313
                                mon_pkt_inf pkt_info;
314
315 c6898c39 RobertBirke
                                memset(h_pkt,0,MON_PKT_HEADER_SPACE);
316
317 da5dade7 MarcoBiazzini
                                pkt_info.remote_socketID = &(connectbuf[con_id]->external_socketID);
318
                                pkt_info.buffer = msg + offset;
319
                                pkt_info.bufSize = pkt_len;
320
                                pkt_info.msgtype = msg_type;
321
                                pkt_info.dataID = connectbuf[con_id]->seqnr;
322
                                pkt_info.offset = offset;
323
                                pkt_info.datasize = msg_len;
324
                                pkt_info.monitoringHeaderLen = iov[1].iov_len;
325
                                pkt_info.monitoringHeader = iov[1].iov_base;
326
                                pkt_info.ttl = -1;
327
                                memset(&(pkt_info.arrival_time),0,sizeof(struct timeval));
328
329
                                (get_Send_pkt_inf_cb) ((void *) &pkt_info);
330
                        }
331
332 4132f78a RobertBirke
                        debug("ML: sending packet to %s with rconID:%d lconID:%d\n", conid_to_string(con_id), ntohl(msg_h.remote_con_id), ntohl(msg_h.local_con_id));
333 da5dade7 MarcoBiazzini
                        switch(sendPacket(socketfd, iov, 4, &udpgen.udpaddr)) {
334
                                case MSGLEN:
335 4132f78a RobertBirke
                                        info("ML: sending message failed, reducing MTU from %d to %d (to:%s conID:%d lconID:%d msgsize:%d offset:%d)\n", connectbuf[con_id]->pmtusize, pmtu_decrement(connectbuf[con_id]->pmtusize), conid_to_string(con_id), ntohl(msg_h.remote_con_id), ntohl(msg_h.local_con_id), msg_len, offset);
336 ac550b87 CsabaKiraly
                                        // TODO: pmtu decremented here, but not in the "truncable" packet. That is currently resent without changing the claimed pmtu. Might need to be changed.
337 da5dade7 MarcoBiazzini
                                        connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
338 ac550b87 CsabaKiraly
                                        if (connectbuf[con_id]->pmtusize > 0) {
339
                                                connectbuf[con_id]->delay = true;
340
                                                retry = true;
341
                                        }
342 9ac85ab6 CsabaKiraly
                                        offset = msg_len; // exit the while
343 da5dade7 MarcoBiazzini
                                        break;
344
                                case FAILURE:
345 4132f78a RobertBirke
                                        info("ML: sending message failed (to:%s conID:%d lconID:%d msgsize:%d offset:%d)\n", conid_to_string(con_id), ntohl(msg_h.remote_con_id), ntohl(msg_h.local_con_id), msg_len, offset);
346 9ac85ab6 CsabaKiraly
                                        offset = msg_len; // exit the while
347 da5dade7 MarcoBiazzini
                                        break;
348 08a4230a ArpadBakay
                                case THROTTLE:
349
                                    //    debug("THROTTLE on output"); 
350
                                        offset = msg_len; // exit the while
351
                                        break;
352 da5dade7 MarcoBiazzini
                                case OK:
353
                                        //update
354 1f8ebe96 RobertBirke
                                        offset += pkt_len;
355 da5dade7 MarcoBiazzini
                                        //transmit data header only in the first packet
356
                                        iov[2].iov_len = 0;
357
                                        break;
358
                        }
359 1f8ebe96 RobertBirke
                } while(offset != msg_len && !truncable);
360 da5dade7 MarcoBiazzini
        } while(retry);
361
}
362
363 d5b9b14d CsabaKiraly
void pmtu_timeout_cb(int fd, short event, void *arg);
364
365
void reschedule_conn_msg(int con_id)
366
{
367
        if (connectbuf[con_id]->timeout_event) {
368
                /* delete old timout */        
369
                event_del(connectbuf[con_id]->timeout_event);
370
                event_free(connectbuf[con_id]->timeout_event);
371
        }
372
        connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
373
        evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
374
}
375
376 da5dade7 MarcoBiazzini
void send_conn_msg(int con_id, int buf_size, int command_type)
377
{
378 ff683f7d CsabaKiraly
        if (buf_size < sizeof(struct conn_msg)) {
379
                error("ML: requested connection message size is too small\n");
380
                return;
381
        }
382
383
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
384 993886fe CsabaKiraly
                connectbuf[con_id]->ctrl_msg_buf = malloc(buf_size);
385 ff683f7d CsabaKiraly
                memset(connectbuf[con_id]->ctrl_msg_buf, 0, buf_size);
386
        }
387 da5dade7 MarcoBiazzini
388
        if(connectbuf[con_id]->ctrl_msg_buf == NULL) {
389 11fce711 MarcoBiazzini
                error("ML: can not allocate memory for connection message\n");
390 da5dade7 MarcoBiazzini
                return;
391
        }
392
393
        struct conn_msg *msg_header = (struct conn_msg*) connectbuf[con_id]->ctrl_msg_buf;
394
395
        msg_header->comand_type = command_type;
396
        msg_header->pmtu_size = connectbuf[con_id]->pmtusize;
397
398
        memcpy(&(msg_header->sock_id), loc_socketID, sizeof(socket_ID));
399 7b67b6a1 ArpadBakay
  {
400
                        char buf[SOCKETID_STRING_SIZE];
401
                        mlSocketIDToString(&((struct conn_msg*)connectbuf[con_id]->ctrl_msg_buf)->sock_id,buf,sizeof(buf));
402
                        debug("Local socket_address sent in INVITE: %s, sizeof msg %d\n", buf, sizeof(struct conn_msg));
403
   }
404 6f256447 TivadarSzemethy
        send_msg(con_id, ML_CON_MSG, connectbuf[con_id]->ctrl_msg_buf, buf_size, true, &(connectbuf[con_id]->defaultSendParams));
405 da5dade7 MarcoBiazzini
}
406
407 d5b9b14d CsabaKiraly
void send_conn_msg_with_pmtu_discovery(int con_id, int buf_size, int command_type)
408
{
409
        struct timeval tout = PMTU_TIMEOUT;
410
        connectbuf[con_id]->timeout_value = tout;
411
        connectbuf[con_id]->trials = 1;
412
        send_conn_msg(con_id, buf_size, command_type);
413
        reschedule_conn_msg(con_id);
414
}
415
416
void resend_conn_msg(int con_id)
417
{
418
        connectbuf[con_id]->trials++;
419
        send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
420
        reschedule_conn_msg(con_id);
421
}
422
423 ffb63fbb CsabaKiraly
void recv_conn_msg(struct msg_header *msg_h, char *msgbuf, int msg_size, struct sockaddr_in *recv_addr)
424 da5dade7 MarcoBiazzini
{
425
        struct conn_msg *con_msg;
426
        int free_con_id, con_id;
427
428
        time_t now = time(NULL);
429
        double timediff = 0.0;
430 d12ca510 CsabaKiraly
        char sock_id_str[1000];
431 1f8ebe96 RobertBirke
        
432
        msgbuf += msg_h->len_mon_data_hdr;
433
        msg_size -= msg_h->len_mon_data_hdr;
434
        con_msg = (struct conn_msg *)msgbuf;
435
        
436 db8c431a CsabaKiraly
        //verify message validity
437
        if (msg_size < sizeof(struct conn_msg)) {
438
                char recv_addr_str[INET_ADDRSTRLEN];
439
                inet_ntop(AF_INET, &(recv_addr->sin_addr.s_addr), recv_addr_str, INET_ADDRSTRLEN);
440
                info("Invalid conn_msg received from %s\n", recv_addr_str);
441
                return;
442
        }
443
444 d12ca510 CsabaKiraly
        //decode sock_id for debug messages
445
        mlSocketIDToString(&con_msg->sock_id,sock_id_str,999);
446
447 1ee167ea CsabaKiraly
        if (con_msg->sock_id.internal_addr.udpaddr.sin_addr.s_addr != recv_addr->sin_addr.s_addr &&
448
            con_msg->sock_id.external_addr.udpaddr.sin_addr.s_addr != recv_addr->sin_addr.s_addr   ) {
449
                char recv_addr_str[INET_ADDRSTRLEN];
450
                inet_ntop(AF_INET, &(recv_addr->sin_addr.s_addr), recv_addr_str, INET_ADDRSTRLEN);
451
                info("Conn msg received from %s, but claims to be from %s", recv_addr_str, sock_id_str);
452
                return;
453
        }
454
455 da5dade7 MarcoBiazzini
        // Monitoring layer hook
456 e17edb88 RobertBirke
        if(get_Recv_data_inf_cb != NULL) {
457 da5dade7 MarcoBiazzini
                // update pointer to the real data
458
                mon_data_inf recv_data_inf;
459
                recv_data_inf.remote_socketID = &(con_msg->sock_id);
460
                recv_data_inf.buffer = msgbuf;
461 8a9424d2 CsabaKiraly
                recv_data_inf.bufSize = msg_size;
462 da5dade7 MarcoBiazzini
                recv_data_inf.msgtype = msg_h->msg_type;
463
                recv_data_inf.monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
464
                recv_data_inf.monitoringDataHeader = msg_h->len_mon_data_hdr ? msgbuf : NULL;
465
                gettimeofday(&recv_data_inf.arrival_time, NULL);
466
                recv_data_inf.firstPacketArrived = true;
467
                recv_data_inf.recvFragments = 1;
468
                recv_data_inf.priority = false;
469
                recv_data_inf.padding = false;
470
                recv_data_inf.confirmation = false;
471
                recv_data_inf.reliable = false;
472
473
                // send data recv callback to monitoring module
474
                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
475 f081b938 CsabaKiraly
        }
476
477 da5dade7 MarcoBiazzini
        // check the connection command type
478
        switch (con_msg->comand_type) {
479
                /*
480
                * if INVITE: enter a new socket make new entry in connect array
481
                * send an ok
482
                */
483
                case INVITE:
484 d12ca510 CsabaKiraly
                        info("ML: received INVITE from %s (size:%d)\n", sock_id_str, msg_size);
485 da5dade7 MarcoBiazzini
                        /*
486
                        * check if another connection for the external connectionID exist
487
                        * that was established within the last 2 seconds
488
                        */
489
                        free_con_id = -1;
490
                        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
491
                                if (connectbuf[con_id] != NULL) {
492
                                        if (mlCompareSocketIDs(&(connectbuf[con_id]->external_socketID), &(con_msg->sock_id)) == 0) {
493 f081b938 CsabaKiraly
                                                //timediff = difftime(now, connectbuf[con_id]->starttime);        //TODO: why this timeout? Shouldn't the connection be closed instead if there is a timeout?
494
                                                //if (timediff < 2)
495
                                                //update remote connection ID
496
                                                if (connectbuf[con_id]->external_connectionID != msg_h->local_con_id) {
497 d12ca510 CsabaKiraly
                                                        warn("ML: updating remote connection ID for %s: from %d to %d\n",sock_id_str, connectbuf[con_id]->external_connectionID, msg_h->local_con_id);
498 f081b938 CsabaKiraly
                                                        connectbuf[con_id]->external_connectionID = msg_h->local_con_id;
499
                                                }
500
                                                break;
501 da5dade7 MarcoBiazzini
                                        }
502
                                } else if(free_con_id == -1)
503
                                        free_con_id = con_id;
504
                        }
505
506
                        if (con_id == CONNECTBUFSIZE) {
507
                                // create an entry in the connecttrybuf
508
                                if(free_con_id == -1) {
509 11fce711 MarcoBiazzini
                                        error("ML: no new connect_buf available\n");
510 da5dade7 MarcoBiazzini
                                        return;
511
                                }
512
                                connectbuf[free_con_id] = (connect_data *) malloc(sizeof(connect_data));
513
                                memset(connectbuf[free_con_id],0,sizeof(connect_data));
514
                                connectbuf[free_con_id]->connection_head = connectbuf[free_con_id]->connection_last = NULL;
515
                                connectbuf[free_con_id]->starttime = time(NULL);
516
                                memcpy(&(connectbuf[free_con_id]->external_socketID), &(con_msg->sock_id), sizeof(socket_ID));
517 b324d3d1 RobertBirke
                //Workaround to support reuse of socketID
518
                                connectbuf[free_con_id]->external_socketID.internal_addr.udpaddr.sin_family=AF_INET;
519
                                connectbuf[free_con_id]->external_socketID.external_addr.udpaddr.sin_family=AF_INET;
520 d5b9b14d CsabaKiraly
                                connectbuf[free_con_id]->pmtusize = con_msg->pmtu_size;        // bootstrap pmtu from the other's size. Not strictly needed, but a good hint
521 e56673ab CsabaKiraly
                                connectbuf[free_con_id]->timeout_event = NULL;
522 da5dade7 MarcoBiazzini
                                connectbuf[free_con_id]->external_connectionID = msg_h->local_con_id;
523
                                connectbuf[free_con_id]->internal_connect =
524
                                        !compare_external_address_socketIDs(&(con_msg->sock_id), loc_socketID);
525
                                con_id = free_con_id;
526
                        }
527
528 f081b938 CsabaKiraly
                        //if(connectbuf[con_id]->status <= CONNECT) { //TODO: anwer anyway. Why the outher would invite otherwise?
529 da5dade7 MarcoBiazzini
                                //update status and send back answer
530
                                connectbuf[con_id]->status = CONNECT;
531 d5b9b14d CsabaKiraly
                                send_conn_msg_with_pmtu_discovery(con_id, con_msg->pmtu_size, CONNECT);
532 f081b938 CsabaKiraly
                        //}
533 da5dade7 MarcoBiazzini
                        break;
534
                case CONNECT:
535 d12ca510 CsabaKiraly
                        info("ML: received CONNECT from %s (size:%d)\n", sock_id_str, msg_size);
536 da5dade7 MarcoBiazzini
537
                        if(msg_h->remote_con_id != -1 && connectbuf[msg_h->remote_con_id] == NULL) {
538 f081b938 CsabaKiraly
                                error("ML: received CONNECT for inexistent connection rconID:%d\n",msg_h->remote_con_id);
539 da5dade7 MarcoBiazzini
                                return;
540
                        }
541
542
                        /*
543
                        * check if the connection status is not already 1 or 2
544
                        */
545
                        if (connectbuf[msg_h->remote_con_id]->status == INVITE) {
546
                                // set the external connectionID
547
                                connectbuf[msg_h->remote_con_id]->external_connectionID = msg_h->local_con_id;
548
                                // change status con_msg the connection_data
549
                                connectbuf[msg_h->remote_con_id]->status = READY;
550 d5b9b14d CsabaKiraly
                                // change pmtusize in the connection_data: not needed. receiving a CONNECT means our INVITE went through. So why change pmtu?
551
                                //connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
552 da5dade7 MarcoBiazzini
553
                                // send the READY
554 d5b9b14d CsabaKiraly
                                send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
555 da5dade7 MarcoBiazzini
556
                                if (receive_Connection_cb != NULL)
557
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
558
559
                                // call all registered callbacks
560
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
561
                                        struct receive_connection_cb_list *temp;
562
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
563
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
564
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
565
                                        free(temp);
566
                                }
567
                                connectbuf[msg_h->remote_con_id]->connection_head =
568
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
569 d5b9b14d CsabaKiraly
                        } else {
570 da5dade7 MarcoBiazzini
                                // send the READY
571 d5b9b14d CsabaKiraly
                                send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
572
                        }
573 da5dade7 MarcoBiazzini
574 11fce711 MarcoBiazzini
                        debug("ML: active connection established\n");
575 da5dade7 MarcoBiazzini
                        break;
576
577
                        /*
578
                        * if READY: find the entry in the connection array set the
579
                        * connection active change the pmtu size
580
                        */
581
                case READY:
582 d12ca510 CsabaKiraly
                        info("ML: received READY from %s (size:%d)\n", sock_id_str, msg_size);
583 da5dade7 MarcoBiazzini
                        if(connectbuf[msg_h->remote_con_id] == NULL) {
584 11fce711 MarcoBiazzini
                                error("ML: received READY for inexistent connection\n");
585 da5dade7 MarcoBiazzini
                                return;
586
                        }
587
                        /*
588
                        * checks if the connection is not already established
589
                        */
590
                        if (connectbuf[msg_h->remote_con_id]->status == CONNECT) {
591
                                // change status of the connection
592 d5b9b14d CsabaKiraly
                                connectbuf[msg_h->remote_con_id]->status = READY;
593
                                // change pmtusize: not needed. pmtu doesn't have to be symmetric
594
                                //connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
595 da5dade7 MarcoBiazzini
596
                                if (receive_Connection_cb != NULL)
597
                                        (receive_Connection_cb) (msg_h->remote_con_id, NULL);
598
599
                                while(connectbuf[msg_h->remote_con_id]->connection_head != NULL) {
600
                                        struct receive_connection_cb_list *temp;
601
                                        temp = connectbuf[msg_h->remote_con_id]->connection_head;
602
                                        (temp->connection_cb) (msg_h->remote_con_id, temp->arg);
603
                                        connectbuf[msg_h->remote_con_id]->connection_head = temp->next;
604
                                        free(temp);
605
                                }
606
                                connectbuf[msg_h->remote_con_id]->connection_head =
607
                                        connectbuf[msg_h->remote_con_id]->connection_last = NULL;
608 11fce711 MarcoBiazzini
                                debug("ML: passive connection established\n");
609 da5dade7 MarcoBiazzini
                        }
610
                        break;
611
        }
612
}
613
614
void recv_stun_msg(char *msgbuf, int recvSize)
615
{
616
        /*
617
        * create empty stun message struct
618
        */
619
        StunMessage resp;
620
        memset(&resp, 0, sizeof(StunMessage));
621
        /*
622
        * parse the message
623
        */
624
        int returnValue = 0;
625
        returnValue = recv_stun_message(msgbuf, recvSize, &resp);
626
627
        if (returnValue == 0) {
628
                /*
629
                * read the reflexive Address into the local_socketID
630
                */
631 c220a4cb CsabaKiraly
                struct sockaddr_in reflexiveAddr = {0};
632 da5dade7 MarcoBiazzini
                reflexiveAddr.sin_family = AF_INET;
633
                reflexiveAddr.sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
634
                reflexiveAddr.sin_port = htons(resp.mappedAddress.ipv4.port);
635 c220a4cb CsabaKiraly
                socketaddrgen reflexiveAddres = {0};
636 da5dade7 MarcoBiazzini
                reflexiveAddres.udpaddr = reflexiveAddr;
637
                local_socketID.external_addr = reflexiveAddres;
638
                NAT_traversal = true;
639
                // callback to the upper layer indicating that the socketID is now
640
                // ready to use
641 7b67b6a1 ArpadBakay
                {
642
                        char buf[SOCKETID_STRING_SIZE];
643
                        mlSocketIDToString(&local_socketID,buf,sizeof(buf));
644
                         debug("received local socket_address: %s\n", buf);
645
                }
646 da5dade7 MarcoBiazzini
                (receive_SocketID_cb) (&local_socketID, 0);
647
        }
648
}
649
650
//done
651
void recv_timeout_cb(int fd, short event, void *arg)
652
{
653
        int recv_id = (long) arg;
654 ce9997f8 CsabaKiraly
        debug("ML: recv_timeout_cb called. Timeout for id:%d\n",recv_id);
655 da5dade7 MarcoBiazzini
656
        if (recvdatabuf[recv_id] == NULL) {
657
                return;
658
        }
659
660
661 0e902e25 CsabaKiraly
/*        if(recvdatabuf[recv_id]->status == ACTIVE) {
662 da5dade7 MarcoBiazzini
                //TODO make timeout at least a DEFINE
663
                struct timeval timeout = { 4, 0 };
664
                recvdatabuf[recv_id]->status = INACTIVE;
665
                event_base_once(base, -1, EV_TIMEOUT, recv_timeout_cb,
666
                        arg, &timeout);
667
                return;
668
        }
669 0e902e25 CsabaKiraly
*/
670 da5dade7 MarcoBiazzini
671 0e902e25 CsabaKiraly
        if(recvdatabuf[recv_id]->status == ACTIVE) {
672 da5dade7 MarcoBiazzini
                // Monitoring layer hook
673
                if(get_Recv_data_inf_cb != NULL) {
674
                        mon_data_inf recv_data_inf;
675
676
                        recv_data_inf.remote_socketID =
677
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
678
                        recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
679
                        recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
680
                        recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
681
                        recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
682
                        recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
683
                                recvdatabuf[recv_id]->recvbuf : NULL;
684
                        gettimeofday(&recv_data_inf.arrival_time, NULL);
685
                        recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
686
                        recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
687
                        recv_data_inf.priority = false;
688
                        recv_data_inf.padding = false;
689
                        recv_data_inf.confirmation = false;
690
                        recv_data_inf.reliable = false;
691
692
                        // send data recv callback to monitoring module
693
694 60b80a11 RobertBirke
//                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
695 da5dade7 MarcoBiazzini
                }
696
697
                // Get the right callback
698
                receive_data_cb receive_data_callback = recvcbbuf[recvdatabuf[recv_id]->msgtype];
699
700
                recv_params rParams;
701
702
                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->arrivedBytes;
703
                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
704
                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
705
                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
706
                rParams.remote_socketID =
707
                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
708
                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
709
710 60b80a11 RobertBirke
//                 (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
711
//                         recvdatabuf[recv_id]->msgtype, &rParams);
712 da5dade7 MarcoBiazzini
713
                //clean up
714 6e975aa4 CsabaKiraly
                if (recvdatabuf[recv_id]->timeout_event) {
715
                        event_del(recvdatabuf[recv_id]->timeout_event);
716
                        event_free(recvdatabuf[recv_id]->timeout_event);
717
                        recvdatabuf[recv_id]->timeout_event = NULL;
718
                }
719 da5dade7 MarcoBiazzini
                free(recvdatabuf[recv_id]->recvbuf);
720
                free(recvdatabuf[recv_id]);
721
                recvdatabuf[recv_id] = NULL;
722
        }
723
}
724
725
// process a single recv data message
726
void recv_data_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
727
{
728 9f09d1ae CsabaKiraly
        debug("ML: received packet of size %d with rconID:%d lconID:%d type:%d offset:%d\n",bufsize,msg_h->remote_con_id,msg_h->local_con_id,msg_h->msg_type,msg_h->offset);
729 da5dade7 MarcoBiazzini
730
        int recv_id, free_recv_id = -1;
731
732
        if(connectbuf[msg_h->remote_con_id] == NULL) {
733 11fce711 MarcoBiazzini
                debug("ML: Received a message not related to any opened connection!\n");
734 da5dade7 MarcoBiazzini
                return;
735
        }
736
737
        // check if a recv_data exist and enter data
738
        for (recv_id = 0; recv_id < RECVDATABUFSIZE; recv_id++)
739
                if (recvdatabuf[recv_id] != NULL) {
740
                        if (msg_h->remote_con_id == recvdatabuf[recv_id]->connectionID &&
741
                                        msg_h->msg_seq_num == recvdatabuf[recv_id]->seqnr)
742
                                                break;
743
                } else
744
                        if(free_recv_id == -1)
745
                                free_recv_id = recv_id;
746
747
748
        if(recv_id == RECVDATABUFSIZE) {
749
                //no recv_data found: create one
750
                recv_id = free_recv_id;
751
                recvdatabuf[recv_id] = (recvdata *) malloc(sizeof(recvdata));
752
                memset(recvdatabuf[recv_id], 0, sizeof(recvdata));
753
                recvdatabuf[recv_id]->connectionID = msg_h->remote_con_id;
754
                recvdatabuf[recv_id]->seqnr = msg_h->msg_seq_num;
755
                recvdatabuf[recv_id]->monitoringDataHeaderLen = msg_h->len_mon_data_hdr;
756
                recvdatabuf[recv_id]->bufsize = msg_h->msg_length + msg_h->len_mon_data_hdr;
757
                recvdatabuf[recv_id]->recvbuf = (char *) malloc(recvdatabuf[recv_id]->bufsize);
758 b6b8c19a CsabaKiraly
                recvdatabuf[recv_id]->arrivedBytes = 0;        //count this without the Mon headers
759 da5dade7 MarcoBiazzini
                /*
760
                * read the timeout data and set it
761
                */
762 d5b9b14d CsabaKiraly
                recvdatabuf[recv_id]->timeout_value = recv_timeout;
763 0e902e25 CsabaKiraly
                recvdatabuf[recv_id]->timeout_event = NULL;
764 da5dade7 MarcoBiazzini
                recvdatabuf[recv_id]->recvID = recv_id;
765
                recvdatabuf[recv_id]->starttime = time(NULL);
766
                recvdatabuf[recv_id]->msgtype = msg_h->msg_type;
767
768
                // fill the buffer with zeros
769 1f8ebe96 RobertBirke
                memset(recvdatabuf[recv_id]->recvbuf, 0, recvdatabuf[recv_id]->bufsize);
770 ce9997f8 CsabaKiraly
                debug(" new @ id:%d\n",recv_id);
771 ada47fe7 CsabaKiraly
        } else {        //message structure already exists, no need to create new
772 9f09d1ae CsabaKiraly
                debug(" found @ id:%d (arrived before this packet: bytes:%d fragments%d\n",recv_id, recvdatabuf[recv_id]->arrivedBytes, recvdatabuf[recv_id]->recvFragments);
773 da5dade7 MarcoBiazzini
        }
774
775 1f8ebe96 RobertBirke
        //if first packet extract mon data header and advance pointer
776
        if (msg_h->offset == 0) {
777
                memcpy(recvdatabuf[recv_id]->recvbuf, msgbuf, msg_h->len_mon_data_hdr);
778
                msgbuf += msg_h->len_mon_data_hdr;
779 b6b8c19a CsabaKiraly
                bufsize -= msg_h->len_mon_data_hdr;
780 da5dade7 MarcoBiazzini
                recvdatabuf[recv_id]->firstPacketArrived = 1;
781 1f8ebe96 RobertBirke
        }
782 da5dade7 MarcoBiazzini
783
784
        // increment fragmentnr
785
        recvdatabuf[recv_id]->recvFragments++;
786
        // increment the arrivedBytes
787
        recvdatabuf[recv_id]->arrivedBytes += bufsize;
788
789
        // enter the data into the buffer
790 1f8ebe96 RobertBirke
        memcpy(recvdatabuf[recv_id]->recvbuf + msg_h->len_mon_data_hdr + msg_h->offset, msgbuf, bufsize);
791 da5dade7 MarcoBiazzini
792
        //TODO very basic checkif all fragments arrived: has to be reviewed
793 b6b8c19a CsabaKiraly
        if(recvdatabuf[recv_id]->arrivedBytes == recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen)
794 da5dade7 MarcoBiazzini
                recvdatabuf[recv_id]->status = COMPLETE; //buffer full -> msg completly arrived
795
        else
796
                recvdatabuf[recv_id]->status = ACTIVE;
797
798
        if (recv_data_callback) {
799
                if(recvdatabuf[recv_id]->status == COMPLETE) {
800
                        // Monitoring layer hook
801
                        if(get_Recv_data_inf_cb != NULL) {
802
                                mon_data_inf recv_data_inf;
803
804
                                recv_data_inf.remote_socketID =
805
                                         &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
806
                                recv_data_inf.buffer = recvdatabuf[recv_id]->recvbuf;
807
                                recv_data_inf.bufSize = recvdatabuf[recv_id]->bufsize;
808
                                recv_data_inf.msgtype = recvdatabuf[recv_id]->msgtype;
809
                                recv_data_inf.monitoringDataHeaderLen = recvdatabuf[recv_id]->monitoringDataHeaderLen;
810
                                recv_data_inf.monitoringDataHeader = recvdatabuf[recv_id]->monitoringDataHeaderLen ?
811
                                        recvdatabuf[recv_id]->recvbuf : NULL;
812
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
813
                                recv_data_inf.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
814
                                recv_data_inf.recvFragments = recvdatabuf[recv_id]->recvFragments;
815
                                recv_data_inf.priority = false;
816
                                recv_data_inf.padding = false;
817
                                recv_data_inf.confirmation = false;
818
                                recv_data_inf.reliable = false;
819
820
                                // send data recv callback to monitoring module
821
822
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
823
                        }
824
825
                        // Get the right callback
826
                        receive_data_cb receive_data_callback = recvcbbuf[msg_h->msg_type];
827
                        if (receive_data_callback) {
828
829
                                recv_params rParams;
830
831 b6b8c19a CsabaKiraly
                                rParams.nrMissingBytes = recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen - recvdatabuf[recv_id]->arrivedBytes;
832 da5dade7 MarcoBiazzini
                                rParams.recvFragments = recvdatabuf[recv_id]->recvFragments;
833
                                rParams.msgtype = recvdatabuf[recv_id]->msgtype;
834
                                rParams.connectionID = recvdatabuf[recv_id]->connectionID;
835
                                rParams.remote_socketID =
836
                                        &(connectbuf[recvdatabuf[recv_id]->connectionID]->external_socketID);
837 f081b938 CsabaKiraly
838
                                char str[1000];
839
                                mlSocketIDToString(rParams.remote_socketID,str,999);
840
                                debug("ML: received message from conID:%d, %s\n",recvdatabuf[recv_id]->connectionID,str);
841 da5dade7 MarcoBiazzini
                                rParams.firstPacketArrived = recvdatabuf[recv_id]->firstPacketArrived;
842
843
                                (receive_data_callback) (recvdatabuf[recv_id]->recvbuf + recvdatabuf[recv_id]->monitoringDataHeaderLen, recvdatabuf[recv_id]->bufsize - recvdatabuf[recv_id]->monitoringDataHeaderLen,
844
                                        recvdatabuf[recv_id]->msgtype, (void *) &rParams);
845
                        } else {
846 fbb6e767 MarcoBiazzini
                            warn("ML: callback not initialized for this message type: %d!\n",msg_h->msg_type);
847 da5dade7 MarcoBiazzini
                        }
848
849
                        //clean up
850 0e902e25 CsabaKiraly
                        if (recvdatabuf[recv_id]->timeout_event) {
851 ce9997f8 CsabaKiraly
                                debug("ML: freeing timeout for %d",recv_id);
852 6e975aa4 CsabaKiraly
                                event_del(recvdatabuf[recv_id]->timeout_event);
853 0e902e25 CsabaKiraly
                                event_free(recvdatabuf[recv_id]->timeout_event);
854 dceb891e CsabaKiraly
                                recvdatabuf[recv_id]->timeout_event = NULL;
855 ce9997f8 CsabaKiraly
                        } else {
856
                                debug("ML: received in 1 packet\n",recv_id);
857 0e902e25 CsabaKiraly
                        }
858 da5dade7 MarcoBiazzini
                        free(recvdatabuf[recv_id]->recvbuf);
859
                        free(recvdatabuf[recv_id]);
860
                        recvdatabuf[recv_id] = NULL;
861
                } else { // not COMPLETE
862 0e902e25 CsabaKiraly
                        if (!recvdatabuf[recv_id]->timeout_event) {
863
                                //start time out
864
                                //TODO make timeout at least a DEFINE
865
                                recvdatabuf[recv_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &recv_timeout_cb, (void *) (long)recv_id);
866 d5b9b14d CsabaKiraly
                                evtimer_add(recvdatabuf[recv_id]->timeout_event, &recv_timeout);
867 0e902e25 CsabaKiraly
                        }
868 da5dade7 MarcoBiazzini
                }
869
        }
870
}
871
872
//done
873
void pmtu_timeout_cb(int fd, short event, void *arg)
874
{
875
876
        int con_id = (long) arg;
877
        pmtu new_pmtusize;
878
879 9f95713e CsabaKiraly
        debug("ML: pmtu timeout called (lcon:%d)\n",con_id);
880 d5b9b14d CsabaKiraly
881 da5dade7 MarcoBiazzini
        if(connectbuf[con_id] == NULL) {
882 11fce711 MarcoBiazzini
                error("ML: pmtu timeout called on non existing con_id\n");
883 da5dade7 MarcoBiazzini
                return;
884
        }
885
886
        if(connectbuf[con_id]->status == READY) {
887
                // nothing to do anymore
888 d5b9b14d CsabaKiraly
                event_del(connectbuf[con_id]->timeout_event);
889
                event_free(connectbuf[con_id]->timeout_event);
890 dceb891e CsabaKiraly
                connectbuf[con_id]->timeout_event = NULL;
891 da5dade7 MarcoBiazzini
                return;
892
        }
893
894 e8ba29d4 CsabaKiraly
        info("ML: pmtu timeout while connecting(to:%s lcon:%d status:%d size:%d trial:%d tout:%ld.%06ld)\n",conid_to_string(con_id), con_id, connectbuf[con_id]->status, connectbuf[con_id]->pmtusize, connectbuf[con_id]->trials, connectbuf[con_id]->timeout_value.tv_sec, connectbuf[con_id]->timeout_value.tv_usec);
895 d5b9b14d CsabaKiraly
896 da5dade7 MarcoBiazzini
        if(connectbuf[con_id]->delay || connectbuf[con_id]->trials == MAX_TRIALS - 1) {
897 9a20e619 CsabaKiraly
                double delay = connectbuf[con_id]->timeout_value.tv_sec + connectbuf[con_id]->timeout_value.tv_usec / 1000000.0;
898 26f3bd83 CsabaKiraly
                delay = delay * 2;
899 9f95713e CsabaKiraly
                info("\tML: increasing pmtu timeout to %f sec\n", delay);
900 9a20e619 CsabaKiraly
                connectbuf[con_id]->timeout_value.tv_sec = floor(delay);
901
                connectbuf[con_id]->timeout_value.tv_usec = fmod(delay, 1.0) * 1000000.0;
902 da5dade7 MarcoBiazzini
                if(connectbuf[con_id]->delay) {
903
                        connectbuf[con_id]->delay = false;
904 d5b9b14d CsabaKiraly
                        reschedule_conn_msg(con_id);
905 da5dade7 MarcoBiazzini
                }
906
        }
907
908
        if(connectbuf[con_id]->trials == MAX_TRIALS) {
909
                // decrement the pmtu size
910 d5b9b14d CsabaKiraly
                struct timeval tout = PMTU_TIMEOUT;
911 cdcc1fe1 CsabaKiraly
                info("\tML: decreasing pmtu estimate from %d to %d\n", connectbuf[con_id]->pmtusize, pmtu_decrement(connectbuf[con_id]->pmtusize));
912 da5dade7 MarcoBiazzini
                connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
913 d5b9b14d CsabaKiraly
                connectbuf[con_id]->timeout_value = tout; 
914 da5dade7 MarcoBiazzini
                connectbuf[con_id]->trials = 0;
915
        }
916
917
        //error in PMTU discovery?
918 7b67b6a1 ArpadBakay
        if (connectbuf[con_id]->pmtusize == P_ERROR) {
919 da5dade7 MarcoBiazzini
                if (connectbuf[con_id]->internal_connect == true) {
920
                        //as of now we tried directly connecting, now let's try trough the NAT
921
                        connectbuf[con_id]->internal_connect = false;
922 80ad8028 CsabaKiraly
                        connectbuf[con_id]->pmtusize = DSLSLIM;
923 da5dade7 MarcoBiazzini
                } else {
924
                        //nothing to do we have to give up
925 11fce711 MarcoBiazzini
                        error("ML: Could not create connection with connectionID %i!\n",con_id);
926 da5dade7 MarcoBiazzini
                        // envoke the callback for failed connection establishment
927
                        if(failed_Connection_cb != NULL)
928
                                (failed_Connection_cb) (con_id, NULL);
929
                        // delete the connection entry
930
                        mlCloseConnection(con_id);
931
                        return;
932
                }
933
        }
934
935 3b68fd99 CsabaKiraly
        //retry
936 d5b9b14d CsabaKiraly
        resend_conn_msg(con_id);
937
}
938 da5dade7 MarcoBiazzini
939 d5b9b14d CsabaKiraly
940
int schedule_pmtu_timeout(int con_id)
941
{
942
        if (! connectbuf[con_id]->timeout_event) {
943
                struct timeval tout = PMTU_TIMEOUT;
944
                connectbuf[con_id]->timeout_value = tout;
945
                connectbuf[con_id]->trials = 1;
946
                connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
947
                evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
948
        }
949 da5dade7 MarcoBiazzini
}
950
951
/*
952
 * decrements the mtu size
953
 */
954
pmtu pmtu_decrement(pmtu pmtusize)
955
{
956
        pmtu pmtu_return_size;
957
        switch(pmtusize) {
958
        case MAX:
959 a4d4fc7c CsabaKiraly
                //return DSL;
960
                return DSLSLIM;        //shortcut to use less vales
961 da5dade7 MarcoBiazzini
        case DSL:
962
                return DSLMEDIUM;
963
        case DSLMEDIUM:
964
                return DSLSLIM;
965
        case DSLSLIM:
966 a4d4fc7c CsabaKiraly
                //return BELOWDSL;
967
                return MIN;        //shortcut to use less vales
968 da5dade7 MarcoBiazzini
        case BELOWDSL:
969
                return MIN;
970 064b7828 CsabaKiraly
        case MIN:
971 7b67b6a1 ArpadBakay
                return P_ERROR;
972 064b7828 CsabaKiraly
        default:
973
                warn("ML: strange pmtu size encountered:%d, changing to some safe value:%d\n", pmtusize, MIN);
974
                return MIN;
975 da5dade7 MarcoBiazzini
        }
976
}
977
978 d5b9b14d CsabaKiraly
// called when an ICMP pmtu error message (type 3, code 4) is received
979 da5dade7 MarcoBiazzini
void pmtu_error_cb_th(char *msg, int msglen)
980
{
981 11fce711 MarcoBiazzini
        debug("ML: pmtu_error callback called msg_size: %d\n",msglen);
982 da5dade7 MarcoBiazzini
        //TODO debug
983
        return;
984
985
    char *msgbufptr = NULL;
986
    int msgtype;
987
    int connectionID;
988
    pmtu pmtusize;
989
    pmtu new_pmtusize;
990
    int dead = 0;
991
992
    // check the packettype
993
    msgbufptr = &msg[0];
994
995
    // check the msgtype
996
    msgbufptr = &msg[1];
997
    memcpy(&msgtype, msgbufptr, 4);
998
999
    if (msgtype == 0) {
1000
1001
        // get the connectionID
1002
        msgbufptr = &msg[5];
1003
        memcpy(&connectionID, msgbufptr, 4);
1004
1005
        int msgtype_c = connectbuf[connectionID]->status;
1006
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
1007
1008
        if (msgtype_c != msgtype) {
1009
            dead = 1;
1010
        }
1011
1012
1013
    } else if (msgtype == 1) {
1014
1015
        // read the connectionID
1016
        msgbufptr = &msg[9];
1017
        memcpy(&connectionID, msgbufptr, 4);
1018
1019
        int msgtype_c = connectbuf[connectionID]->status;
1020
//        pmtusize = connectbuf[connectionID]->pmtutrysize;
1021
1022
        if (msgtype_c != msgtype) {
1023
            dead = 1;
1024
        }
1025
1026
    }
1027
    // decrement the pmtu size
1028
    new_pmtusize = pmtu_decrement(pmtusize);
1029
1030
//    connectbuf[connectionID]->pmtutrysize = new_pmtusize;
1031
1032 7b67b6a1 ArpadBakay
    if (new_pmtusize == P_ERROR) {
1033 11fce711 MarcoBiazzini
                error("ML:  Could not create connection with connectionID %i !\n",
1034 da5dade7 MarcoBiazzini
                        connectionID);
1035
1036
                if(failed_Connection_cb != NULL)
1037
                        (failed_Connection_cb) (connectionID, NULL);
1038
                // set the message type to a non existent message
1039
                msgtype = 2;
1040
                // delete the connection entry
1041
                 mlCloseConnection(connectionID);
1042
        }
1043
1044
    if (msgtype == 0 && dead != 1) {
1045
1046
        // stop the timeout event
1047
        // timeout_del(connectbuf[connectionID]->timeout);
1048
        /*
1049
         * libevent2
1050
         */
1051
1052
        // event_del(connectbuf[connectionID]->timeout);
1053
1054
1055
        // create and send a connection message
1056
//         create_conn_msg(new_pmtusize, connectionID,
1057
//                         &local_socketID, INVITE);
1058
1059
//        send_conn_msg(connectionID, new_pmtusize);
1060
1061
        // set a timeout event for the pmtu discovery
1062
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
1063
        // *)&connectionID);
1064
1065
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1066
1067
        /*
1068
         * libevent2
1069
         */
1070
1071
        struct event *ev;
1072
        ev = evtimer_new(base, pmtu_timeout_cb,
1073
                         (void *) connectbuf[connectionID]);
1074
1075
        // connectbuf[connectionID]->timeout = ev;
1076
1077
        event_add(ev, &connectbuf[connectionID]->timeout_value);
1078 07355669 TivadarSzemethy
1079 da5dade7 MarcoBiazzini
    } else if (msgtype == 1 && dead != 1) {
1080 d18d76c2 TivadarSzemethy
1081 da5dade7 MarcoBiazzini
        // stop the timeout event
1082
        // timeout_del(connectbuf[connectionID]->timeout);
1083
1084
        /*
1085
         * libevent2
1086
         */
1087 fbb6e767 MarcoBiazzini
        // info("still here 11 \n");
1088 da5dade7 MarcoBiazzini
        // printf("ev %d \n",connectbuf[connectionID]->timeout);
1089
        // event_del(connectbuf[connectionID]->timeout );
1090
        // evtimer_del(connectbuf[connectionID]->timeout );
1091
1092
1093
//         // create and send a connection message
1094
//         create_conn_msg(new_pmtusize,
1095
//                         connectbuf[connectionID]->connectionID,
1096
//                         NULL, CONNECT);
1097
1098
        //send_conn_msg(connectionID, new_pmtusize);
1099
1100
        // set a timeout event for the pmtu discovery
1101
        // timeout_set(connectbuf[connectionID]->timeout,pmtu_timeout_cb,(void
1102
        // *)&connectionID);
1103
        // timeout_add(connectbuf[connectionID]->timeout,&connectbuf[connectionID]->timeout_value);
1104
1105
        /*
1106
         * libevent2
1107
         */
1108
        // struct event *ev;
1109
        // ev = evtimer_new(base,pmtu_timeout_cb, (void
1110
        // *)connectbuf[connectionID]);
1111
        // connectbuf[connectionID]->timeout = ev;
1112
        // event_add(ev,&connectbuf[connectionID]->timeout_value);
1113
1114
    }
1115
}
1116
1117
/*
1118
 * what to do once a packet arrived if it is a conn packet send it to
1119
 * recv_conn handler if it is a data packet send it to the recv_data
1120
 * handler
1121
 */
1122
1123
//done --
1124
void recv_pkg(int fd, short event, void *arg)
1125
{
1126 11fce711 MarcoBiazzini
        debug("ML: recv_pkg called\n");
1127 da5dade7 MarcoBiazzini
1128
        struct msg_header *msg_h;
1129
        char msgbuf[MAX];
1130 d5b9b14d CsabaKiraly
        pmtu recvSize = MAX;
1131 da5dade7 MarcoBiazzini
        char *bufptr = msgbuf;
1132
        int ttl;
1133
        struct sockaddr_in recv_addr;
1134
        int msg_size;
1135
1136
        recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
1137
1138
1139
        // check if it is not just an ERROR message
1140
        if(recvSize < 0)
1141
                return;
1142
1143
        // @TODO check if this simplistic STUN message recognition really always works, probably not
1144
        unsigned short stun_bind_response = 0x0101;
1145
        unsigned short * msgspot = (unsigned short *) msgbuf;
1146
        if (*msgspot == stun_bind_response) {
1147 7b67b6a1 ArpadBakay
                debug("ML: recv_pkg: parse stun message called on %d bytes\n", recvSize);
1148 da5dade7 MarcoBiazzini
                recv_stun_msg(msgbuf, recvSize);
1149
                return;
1150
        }
1151
1152
        msg_h = (struct msg_header *) msgbuf;
1153 339a662d CsabaKiraly
1154 4132f78a RobertBirke
        /* convert header from network to host order */
1155
        msg_h->offset = ntohl(msg_h->offset);
1156
        msg_h->msg_length = ntohl(msg_h->msg_length);
1157
        msg_h->local_con_id = ntohl(msg_h->local_con_id);
1158
        msg_h->remote_con_id = ntohl(msg_h->remote_con_id);
1159
        msg_h->msg_seq_num = ntohl(msg_h->msg_seq_num);
1160
1161 339a662d CsabaKiraly
        //verify minimum size
1162
        if (recvSize < sizeof(struct msg_header)) {
1163
          info("UDP packet too small, can't be an ML packet");
1164
          return;
1165
        }
1166
1167
        //TODO add more verifications
1168
1169 da5dade7 MarcoBiazzini
        bufptr += MSG_HEADER_SIZE + msg_h->len_mon_packet_hdr;
1170
        msg_size = recvSize - MSG_HEADER_SIZE - msg_h->len_mon_packet_hdr;
1171
1172 db8c431a CsabaKiraly
        //verify more fields
1173
        if (msg_size < 0) {
1174
          info("Corrupted UDP packet received");
1175
          return;
1176
        }
1177 da5dade7 MarcoBiazzini
1178 e17edb88 RobertBirke
        if(get_Recv_pkt_inf_cb != NULL) {
1179 da5dade7 MarcoBiazzini
                mon_pkt_inf msginfNow;
1180
                msginfNow.monitoringHeaderLen = msg_h->len_mon_packet_hdr;
1181
                msginfNow.monitoringHeader = msg_h->len_mon_packet_hdr ? &msgbuf[0] + MSG_HEADER_SIZE : NULL;
1182
                //TODO rethink this ...
1183
                if(msg_h->msg_type == ML_CON_MSG) {
1184
                        struct conn_msg *c_msg = (struct conn_msg *) bufptr;
1185
                        msginfNow.remote_socketID = &(c_msg->sock_id);
1186
                }
1187
                else if(connectbuf[msg_h->remote_con_id] == NULL) {
1188 11fce711 MarcoBiazzini
                        error("ML: received pkg called with non existent connection\n");
1189 da5dade7 MarcoBiazzini
                        return;
1190
                } else
1191
                        msginfNow.remote_socketID = &(connectbuf[msg_h->remote_con_id]->external_socketID);
1192
                msginfNow.buffer = bufptr;
1193
                msginfNow.bufSize = recvSize;
1194
                msginfNow.msgtype = msg_h->msg_type;
1195
                msginfNow.ttl = ttl;
1196
                msginfNow.dataID = msg_h->msg_seq_num;
1197
                msginfNow.offset = msg_h->offset;
1198
                msginfNow.datasize = msg_h->msg_length;
1199
                gettimeofday(&msginfNow.arrival_time, NULL);
1200
                (get_Recv_pkt_inf_cb) ((void *) &msginfNow);
1201
        }
1202
1203
1204
        switch(msg_h->msg_type) {
1205
                case ML_CON_MSG:
1206 11fce711 MarcoBiazzini
                        debug("ML: received conn pkg\n");
1207 ffb63fbb CsabaKiraly
                        recv_conn_msg(msg_h, bufptr, msg_size, &recv_addr);
1208 da5dade7 MarcoBiazzini
                        break;
1209
                default:
1210
                        if(msg_h->msg_type < 127) {
1211 11fce711 MarcoBiazzini
                                debug("ML: received data pkg\n");
1212 da5dade7 MarcoBiazzini
                                recv_data_msg(msg_h, bufptr, msg_size);
1213
                                break;
1214
                        }
1215 11fce711 MarcoBiazzini
                        debug("ML: unrecognised msg_type\n");
1216 da5dade7 MarcoBiazzini
                        break;
1217
        }
1218
}
1219
1220
/*
1221
 * compare the external IP address of two socketIDs
1222
 */
1223
int
1224
compare_external_address_socketIDs(socketID_handle sock1, socketID_handle sock2)
1225
{
1226
        if( sock1->external_addr.udpaddr.sin_addr.s_addr == sock2->external_addr.udpaddr.sin_addr.s_addr)
1227
                return 0;
1228
        return 1;
1229
}
1230
1231 28c32e01 CsabaKiraly
void try_stun();
1232
1233 da5dade7 MarcoBiazzini
/*
1234
 * the timeout of the NAT traversal
1235
 */
1236
void nat_traversal_timeout(int fd, short event, void *arg)
1237
{
1238 6d7243a7 MarcoMellia
debug("X. NatTrTo %d\n", NAT_traversal);
1239 da5dade7 MarcoBiazzini
        if (NAT_traversal == false) {
1240 11fce711 MarcoBiazzini
                debug("ML: NAT traversal request re-send\n");
1241 da5dade7 MarcoBiazzini
                if(receive_SocketID_cb)
1242
                        (receive_SocketID_cb) (&local_socketID, 2);
1243 98ba8deb CsabaKiraly
                try_stun();
1244 da5dade7 MarcoBiazzini
        }
1245 6d7243a7 MarcoMellia
debug("X. NatTrTo\n");
1246 da5dade7 MarcoBiazzini
}
1247
1248 eb2b09ea CsabaKiraly
//return IP address, or INADDR_NONE if can't resolve
1249 da5dade7 MarcoBiazzini
unsigned long resolve(const char *ipaddr)
1250
{
1251
        struct hostent *h = gethostbyname(ipaddr);
1252
        if (!h) {
1253 fbb6e767 MarcoBiazzini
                error("ML: Unable to resolve host name %s\n", ipaddr);
1254 eb2b09ea CsabaKiraly
                return INADDR_NONE;
1255
        }
1256
        unsigned long *addr = (unsigned long *) (h->h_addr);
1257
        return *addr;
1258 da5dade7 MarcoBiazzini
}
1259
1260
1261
/*
1262 e16669a8 CsabaKiraly
 * returns the file descriptor, or <0 on error. The ipaddr can be a null
1263 da5dade7 MarcoBiazzini
 * pointer. Then all available ipaddr on the machine are choosen.
1264
 */
1265 e16669a8 CsabaKiraly
int create_socket(const int port, const char *ipaddr)
1266 da5dade7 MarcoBiazzini
{
1267 c220a4cb CsabaKiraly
        struct sockaddr_in udpaddr = {0};
1268 da5dade7 MarcoBiazzini
        udpaddr.sin_family = AF_INET;
1269 9e878b89 MarcoMellia
        debug("X. create_socket %s, %d\n", ipaddr, port);
1270 da5dade7 MarcoBiazzini
        if (ipaddr == NULL) {
1271
                /*
1272
                * try to guess the local IP address
1273
                */
1274
                const char *ipaddr_iface = mlAutodetectIPAddress();
1275
                if (ipaddr_iface) {
1276
                        udpaddr.sin_addr.s_addr = inet_addr(ipaddr_iface);
1277
                } else {
1278
                        udpaddr.sin_addr.s_addr = INADDR_ANY;
1279
                }
1280
        } else {
1281
                udpaddr.sin_addr.s_addr = inet_addr(ipaddr);
1282
        }
1283
        udpaddr.sin_port = htons(port);
1284
1285
        socketaddrgen udpgen;
1286 ff683f7d CsabaKiraly
        memset(&udpgen,0,sizeof(socketaddrgen));        //this will be sent over the net, so set it to 0
1287 da5dade7 MarcoBiazzini
        udpgen.udpaddr = udpaddr;
1288
        local_socketID.internal_addr = udpgen;
1289
1290
        socketfd = createSocket(port, ipaddr);
1291 e16669a8 CsabaKiraly
        if (socketfd < 0){
1292
                return socketfd;
1293
        }
1294 da5dade7 MarcoBiazzini
1295
        struct event *ev;
1296
        ev = event_new(base, socketfd, EV_READ | EV_PERSIST, recv_pkg, NULL);
1297
1298
        event_add(ev, NULL);
1299 6d7243a7 MarcoMellia
1300 98ba8deb CsabaKiraly
        try_stun();
1301 6d7243a7 MarcoMellia
1302 e16669a8 CsabaKiraly
        return socketfd;
1303 98ba8deb CsabaKiraly
}
1304
1305 28c32e01 CsabaKiraly
/*
1306
 * try to figure out external IP using STUN, if defined
1307
 */
1308 98ba8deb CsabaKiraly
void try_stun()
1309
{
1310 da5dade7 MarcoBiazzini
        if (isStunDefined()) {
1311
                /*
1312
                * send the NAT traversal STUN request
1313
                */
1314
                 send_stun_request(socketfd, &stun_server);
1315
1316
                /*
1317
                * enter a NAT traversal timeout that takes care of retransmission
1318
                */
1319
                struct event *ev1;
1320 7ed37922 CsabaKiraly
                struct timeval timeout_value_NAT_traversal = NAT_TRAVERSAL_TIMEOUT;
1321 da5dade7 MarcoBiazzini
                ev1 = evtimer_new(base, nat_traversal_timeout, NULL);
1322
                event_add(ev1, &timeout_value_NAT_traversal);
1323
1324
                NAT_traversal = false;
1325
        } else {
1326
                /*
1327
                * Assume we have accessibility and copy internal address to external one
1328
                */
1329
                local_socketID.external_addr = local_socketID.internal_addr;
1330
                NAT_traversal = true; // @TODO: this is not really NAT traversal, but a flag that init is over
1331
                // callback to the upper layer indicating that the socketID is now
1332
                // ready to use
1333 98ba8deb CsabaKiraly
                if(receive_SocketID_cb)
1334
                        (receive_SocketID_cb) (&local_socketID, 0); //success
1335 da5dade7 MarcoBiazzini
        }
1336
}
1337
1338 6f26b958 MarcoBiazzini
/**************************** END OF INTERNAL ***********************/
1339
1340
/**************************** MONL functions *************************/
1341 da5dade7 MarcoBiazzini
1342 e16669a8 CsabaKiraly
int mlInit(bool recv_data_cb,struct timeval timeout_value,const int port,const char *ipaddr,const int stun_port,const char *stun_ipaddr,receive_localsocketID_cb local_socketID_cb,void *arg){
1343 da5dade7 MarcoBiazzini
1344 6d7243a7 MarcoMellia
/*X*/ //  fprintf(stderr,"MLINIT1 %s, %d, %s, %d\n", ipaddr, port, stun_ipaddr, stun_port);
1345 da5dade7 MarcoBiazzini
        base = (struct event_base *) arg;
1346
        recv_data_callback = recv_data_cb;
1347
        mlSetRecvTimeout(timeout_value);
1348
        if (stun_ipaddr) {
1349
                 mlSetStunServer(stun_port, stun_ipaddr);
1350
        } else {
1351
1352
        }
1353
        register_recv_localsocketID_cb(local_socketID_cb);
1354 6d7243a7 MarcoMellia
/*X*/ //  fprintf(stderr,"MLINIT1\n");
1355 e16669a8 CsabaKiraly
        return create_socket(port, ipaddr);
1356 a0a1f630 KristianBeckers
}
1357
1358 08a4230a ArpadBakay
void mlSetThrottle(int bucketsize, int drainrate) {
1359
        setOutputRateParams(bucketsize, drainrate);
1360
}
1361
     
1362
1363 a0a1f630 KristianBeckers
/* register callbacks  */
1364 da5dade7 MarcoBiazzini
void mlRegisterGetRecvPktInf(get_recv_pkt_inf_cb recv_pkt_inf_cb){
1365 a0a1f630 KristianBeckers
1366 028bda1f CsabaKiraly
        if (recv_pkt_inf_cb == NULL) {
1367 fbb6e767 MarcoBiazzini
                error("ML: Register get_recv_pkt_inf_cb failed: NULL ptr  \n");
1368 028bda1f CsabaKiraly
        } else {
1369 da5dade7 MarcoBiazzini
                get_Recv_pkt_inf_cb = recv_pkt_inf_cb;
1370 028bda1f CsabaKiraly
        }
1371 a0a1f630 KristianBeckers
}
1372
1373 9f15e9f6 MarcoBiazzini
void mlRegisterGetSendPktInf(get_send_pkt_inf_cb  send_pkt_inf_cb){
1374 8601bccf RobertBirke
1375 028bda1f CsabaKiraly
        if (send_pkt_inf_cb == NULL) {
1376 fbb6e767 MarcoBiazzini
                error("ML: Register get_send_pkt_inf_cb: NULL ptr  \n");
1377 028bda1f CsabaKiraly
        } else {
1378 da5dade7 MarcoBiazzini
                get_Send_pkt_inf_cb = send_pkt_inf_cb;
1379 028bda1f CsabaKiraly
        }
1380 8601bccf RobertBirke
}
1381
1382
1383 da5dade7 MarcoBiazzini
void mlRegisterSetMonitoringHeaderPktCb(set_monitoring_header_pkt_cb monitoring_header_pkt_cb ){
1384 a0a1f630 KristianBeckers
1385 028bda1f CsabaKiraly
        if (monitoring_header_pkt_cb == NULL) {
1386 fbb6e767 MarcoBiazzini
                error("ML: Register set_monitoring_header_pkt_cb: NULL ptr  \n");
1387 028bda1f CsabaKiraly
        } else {
1388 da5dade7 MarcoBiazzini
                set_Monitoring_header_pkt_cb = monitoring_header_pkt_cb;
1389 028bda1f CsabaKiraly
        }
1390 a0a1f630 KristianBeckers
}
1391
1392 da5dade7 MarcoBiazzini
void mlRegisterGetRecvDataInf(get_recv_data_inf_cb recv_data_inf_cb){
1393 a0a1f630 KristianBeckers
1394 028bda1f CsabaKiraly
        if (recv_data_inf_cb == NULL) {
1395 fbb6e767 MarcoBiazzini
                error("ML: Register get_recv_data_inf_cb: NULL ptr  \n");
1396 028bda1f CsabaKiraly
        } else {
1397 da5dade7 MarcoBiazzini
                get_Recv_data_inf_cb = recv_data_inf_cb;
1398 028bda1f CsabaKiraly
        }
1399 a0a1f630 KristianBeckers
}
1400
1401 da5dade7 MarcoBiazzini
void mlRegisterGetSendDataInf(get_send_data_inf_cb  send_data_inf_cb){
1402 a0a1f630 KristianBeckers
1403 028bda1f CsabaKiraly
        if (send_data_inf_cb == NULL) {
1404 fbb6e767 MarcoBiazzini
                error("ML: Register get_send_data_inf_cb: NULL ptr  \n");
1405 028bda1f CsabaKiraly
        } else {
1406 da5dade7 MarcoBiazzini
                get_Send_data_inf_cb = send_data_inf_cb;
1407 028bda1f CsabaKiraly
        }
1408 a0a1f630 KristianBeckers
}
1409
1410 da5dade7 MarcoBiazzini
void mlRegisterSetMonitoringHeaderDataCb(set_monitoring_header_data_cb monitoring_header_data_cb){
1411 a0a1f630 KristianBeckers
1412 028bda1f CsabaKiraly
        if (monitoring_header_data_cb == NULL) {
1413 fbb6e767 MarcoBiazzini
                error("ML: Register set_monitoring_header_data_cb : NULL ptr  \n");
1414 028bda1f CsabaKiraly
        } else {
1415
                set_Monitoring_header_data_cb = monitoring_header_data_cb;
1416
        }
1417 a0a1f630 KristianBeckers
}
1418
1419 6f26b958 MarcoBiazzini
void mlSetRecvTimeout(struct timeval timeout_value){
1420
1421
        recv_timeout = timeout_value;
1422
1423
}
1424
1425
int mlGetStandardTTL(socketID_handle socketID,uint8_t *ttl){
1426
1427
        return getTTL(socketfd, ttl);
1428
1429
}
1430
1431
socketID_handle mlGetLocalSocketID(int *errorstatus){
1432
1433
        if (NAT_traversal == false) {
1434
                *errorstatus = 2;
1435
                return NULL;
1436
        }
1437
1438
        *errorstatus = 0;
1439
        return &local_socketID;
1440
1441
}
1442
1443
1444
/**************************** END of MONL functions *************************/
1445
1446
/**************************** GENERAL functions *************************/
1447
1448 da5dade7 MarcoBiazzini
void mlRegisterRecvConnectionCb(receive_connection_cb recv_conn_cb){
1449 a0a1f630 KristianBeckers
1450 028bda1f CsabaKiraly
        if (recv_conn_cb == NULL) {
1451 fbb6e767 MarcoBiazzini
                error("ML: Register receive_connection_cb: NULL ptr  \n");
1452 028bda1f CsabaKiraly
        }else {
1453 da5dade7 MarcoBiazzini
                receive_Connection_cb = recv_conn_cb;
1454 028bda1f CsabaKiraly
        }
1455 a0a1f630 KristianBeckers
}
1456
1457 da5dade7 MarcoBiazzini
void mlRegisterErrorConnectionCb(connection_failed_cb conn_failed){
1458 a0a1f630 KristianBeckers
1459 028bda1f CsabaKiraly
        if (conn_failed == NULL) {
1460 fbb6e767 MarcoBiazzini
                error("ML: Register connection_failed_cb: NULL ptr  \n");
1461 028bda1f CsabaKiraly
        } else {
1462
                failed_Connection_cb = conn_failed;
1463
        }
1464 a0a1f630 KristianBeckers
}
1465
1466 da5dade7 MarcoBiazzini
void mlRegisterRecvDataCb(receive_data_cb data_cb,unsigned char msgtype){
1467
1468
    if (msgtype > 126) {
1469 a0a1f630 KristianBeckers
1470 11fce711 MarcoBiazzini
            error
1471
            ("ML: Could not register recv_data callback. Msgtype is greater then 126 \n");
1472 da5dade7 MarcoBiazzini
1473
    }
1474
1475
    if (data_cb == NULL) {
1476
1477 11fce711 MarcoBiazzini
            error("ML: Register receive data callback: NUll ptr \n ");
1478 da5dade7 MarcoBiazzini
1479
    } else {
1480
1481
        recvcbbuf[msgtype] = data_cb;
1482
1483
    }
1484 a0a1f630 KristianBeckers
1485
}
1486
1487 da5dade7 MarcoBiazzini
void mlCloseSocket(socketID_handle socketID){
1488 a0a1f630 KristianBeckers
1489 da5dade7 MarcoBiazzini
        free(socketID);
1490 a0a1f630 KristianBeckers
1491
}
1492
1493 deb34f59 TivadarSzemethy
void keepalive_fn(evutil_socket_t fd, short what, void *arg) {
1494
        socketID_handle peer = arg;
1495
1496
        int con_id = mlConnectionExist(peer, false);
1497
        if (con_id < 0 || connectbuf[con_id]->defaultSendParams.keepalive <= 0) {
1498
                /* Connection fell from under us or keepalive was disabled */
1499
                free(arg);
1500
                return;
1501
        }
1502
1503
        /* do what we gotta do */
1504
        if ( connectbuf[con_id]->status == READY) {
1505
                char keepaliveMsg[32] = "";
1506
                sprintf(keepaliveMsg, "KEEPALIVE %d", connectbuf[con_id]->keepalive_seq++);
1507
                send_msg(con_id, MSG_TYPE_ML_KEEPALIVE, keepaliveMsg, 1 + strlen(keepaliveMsg), false, 
1508
                        &(connectbuf[con_id]->defaultSendParams));
1509
        }
1510
1511
        /* re-schedule */
1512
        struct timeval t = { 0,0 };
1513 b5894e65 TivadarSzemethy
        t.tv_sec = connectbuf[con_id]->defaultSendParams.keepalive;
1514
        if (connectbuf[con_id]->defaultSendParams.keepalive) 
1515
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1516 deb34f59 TivadarSzemethy
}
1517
1518
void setupKeepalive(int conn_id) {
1519
        /* Save the peer's address for us */
1520
        socketID_handle peer = malloc(sizeof(socket_ID));
1521
        memcpy(peer, &connectbuf[conn_id]->external_socketID, sizeof(socket_ID));
1522
1523
        struct timeval t = { 0,0 };
1524 b5894e65 TivadarSzemethy
        t.tv_sec = connectbuf[conn_id]->defaultSendParams.keepalive;
1525 deb34f59 TivadarSzemethy
1526 b5894e65 TivadarSzemethy
        if (connectbuf[conn_id]->defaultSendParams.keepalive) 
1527
                event_base_once(base, -1, EV_TIMEOUT, keepalive_fn, peer, &t);
1528 deb34f59 TivadarSzemethy
}
1529
1530 a0a1f630 KristianBeckers
/* connection functions */
1531 6f256447 TivadarSzemethy
int mlOpenConnection(socketID_handle external_socketID,receive_connection_cb connection_cb,void *arg, const send_params defaultSendParams){
1532 da5dade7 MarcoBiazzini
1533
        int con_id;
1534
        if (external_socketID == NULL) {
1535 11fce711 MarcoBiazzini
                error("ML: cannot open connection: one of the socketIDs is NULL\n");
1536 da5dade7 MarcoBiazzini
                return -1;
1537
        }
1538
        if (NAT_traversal == false) {
1539 11fce711 MarcoBiazzini
                error("ML: cannot open connection: NAT traversal for socketID still in progress\n");
1540 da5dade7 MarcoBiazzini
                return -1;
1541
        }
1542
        if (connection_cb == NULL) {
1543 11fce711 MarcoBiazzini
                error("ML: cannot open connection: connection_cb is NULL\n");
1544 da5dade7 MarcoBiazzini
                return -1;
1545
        }
1546
1547
        // check if that connection already exist
1548
1549
        con_id = mlConnectionExist(external_socketID, false);
1550
        if (con_id >= 0) {
1551 6f256447 TivadarSzemethy
                // overwrite defaultSendParams
1552 deb34f59 TivadarSzemethy
                bool newKeepalive = 
1553
                        connectbuf[con_id]->defaultSendParams.keepalive == 0 && defaultSendParams.keepalive != 0;
1554 6f256447 TivadarSzemethy
                connectbuf[con_id]->defaultSendParams = defaultSendParams;
1555 deb34f59 TivadarSzemethy
                if (newKeepalive) setupKeepalive(con_id);
1556 da5dade7 MarcoBiazzini
                // if so check if it is ready to use
1557
                if (connectbuf[con_id]->status == READY) {
1558 6f26b958 MarcoBiazzini
                                // if so use the callback immediately
1559 da5dade7 MarcoBiazzini
                                (connection_cb) (con_id, arg);
1560
1561
                // otherwise just write the connection cb and the arg pointer
1562
                // into the connection struct
1563
                } else {
1564
                        struct receive_connection_cb_list *temp;
1565
                        temp = malloc(sizeof(struct receive_connection_cb_list));
1566
                        temp->next = NULL;
1567
                        temp->connection_cb = connection_cb;
1568
                        temp->arg = arg;
1569
                        if(connectbuf[con_id]->connection_last != NULL) {
1570
                                connectbuf[con_id]->connection_last->next = temp;
1571
                                connectbuf[con_id]->connection_last = temp;
1572
                        } else
1573
                                connectbuf[con_id]->connection_last = connectbuf[con_id]->connection_head = temp;
1574
                }
1575
                return con_id;
1576
        }
1577
        // make entry in connection_establishment array
1578
        for (con_id = 0; con_id < CONNECTBUFSIZE; con_id++) {
1579
                if (connectbuf[con_id] == NULL) {
1580
                        connectbuf[con_id] = (connect_data *) malloc(sizeof(connect_data));
1581
                        memset(connectbuf[con_id],0,sizeof(connect_data));
1582
                        connectbuf[con_id]->starttime = time(NULL);
1583
                        memcpy(&connectbuf[con_id]->external_socketID, external_socketID, sizeof(socket_ID));
1584 d875a065 CsabaKiraly
                        connectbuf[con_id]->pmtusize = DSLSLIM;
1585 e56673ab CsabaKiraly
                        connectbuf[con_id]->timeout_event = NULL;
1586 da5dade7 MarcoBiazzini
                        connectbuf[con_id]->status = INVITE;
1587
                        connectbuf[con_id]->seqnr = 0;
1588
                        connectbuf[con_id]->internal_connect = !compare_external_address_socketIDs(external_socketID, &local_socketID);
1589
                        connectbuf[con_id]->connectionID = con_id;
1590
1591
                        connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
1592
                        connectbuf[con_id]->connection_last->next = NULL;
1593
                        connectbuf[con_id]->connection_last->connection_cb = connection_cb;
1594
                        connectbuf[con_id]->connection_last->arg = arg;
1595
                        connectbuf[con_id]->external_connectionID = -1;
1596 deb34f59 TivadarSzemethy
1597 6f256447 TivadarSzemethy
                        connectbuf[con_id]->defaultSendParams = defaultSendParams;
1598 deb34f59 TivadarSzemethy
                        if (defaultSendParams.keepalive) setupKeepalive(con_id);
1599 da5dade7 MarcoBiazzini
                        break;
1600
                }
1601
        } //end of for
1602
1603
        if (con_id == CONNECTBUFSIZE) {
1604 11fce711 MarcoBiazzini
                error("ML: Could not open connection: connection buffer full\n");
1605 da5dade7 MarcoBiazzini
                return -1;
1606
        }
1607
1608
        // create and send a connection message
1609 cdcc1fe1 CsabaKiraly
        info("ML:Sending INVITE to %s (lconn:%d)\n",conid_to_string(con_id), con_id);
1610 3a2f1e38 CsabaKiraly
        send_conn_msg_with_pmtu_discovery(con_id, connectbuf[con_id]->pmtusize, INVITE);
1611 da5dade7 MarcoBiazzini
1612
        return con_id;
1613
1614
}
1615 a0a1f630 KristianBeckers
1616 da5dade7 MarcoBiazzini
void mlCloseConnection(const int connectionID){
1617
1618
        // remove it from the connection array
1619
        if(connectbuf[connectionID]) {
1620 d5b9b14d CsabaKiraly
                if(connectbuf[connectionID]->ctrl_msg_buf) {
1621 da5dade7 MarcoBiazzini
                        free(connectbuf[connectionID]->ctrl_msg_buf);
1622 d5b9b14d CsabaKiraly
                }
1623
                // remove related events
1624
                if (connectbuf[connectionID]->timeout_event) {
1625
                        event_del(connectbuf[connectionID]->timeout_event);
1626
                        event_free(connectbuf[connectionID]->timeout_event);
1627 dceb891e CsabaKiraly
                        connectbuf[connectionID]->timeout_event = NULL;
1628 d5b9b14d CsabaKiraly
                }
1629 da5dade7 MarcoBiazzini
                free(connectbuf[connectionID]);
1630
                connectbuf[connectionID] = NULL;
1631
        }
1632 a0a1f630 KristianBeckers
1633
}
1634
1635 da5dade7 MarcoBiazzini
void mlSendData(const int connectionID,char *sendbuf,int bufsize,unsigned char msgtype,send_params *sParams){
1636
1637
        if (connectionID < 0) {
1638 11fce711 MarcoBiazzini
                error("ML: send data failed: connectionID does not exist\n");
1639 da5dade7 MarcoBiazzini
                return;
1640
        }
1641
1642
        if (connectbuf[connectionID] == NULL) {
1643 11fce711 MarcoBiazzini
                error("ML: send data failed: connectionID does not exist\n");
1644 da5dade7 MarcoBiazzini
                return;
1645
        }
1646
        if (connectbuf[connectionID]->status != READY) {
1647 11fce711 MarcoBiazzini
            error("ML: send data failed: connection is not active\n");
1648 da5dade7 MarcoBiazzini
            return;
1649
        }
1650 a0a1f630 KristianBeckers
1651 6f256447 TivadarSzemethy
        if (sParams == NULL) {
1652
                sParams = &(connectbuf[connectionID]->defaultSendParams);
1653
        }
1654
1655 da5dade7 MarcoBiazzini
        send_msg(connectionID, msgtype, sendbuf, bufsize, false, sParams);
1656 a0a1f630 KristianBeckers
1657
}
1658
1659
/* transmit data functions  */
1660 da5dade7 MarcoBiazzini
int mlSendAllData(const int connectionID,send_all_data_container *container,int nr_entries,unsigned char msgtype,send_params *sParams){
1661 2a178954 KristianBeckers
1662 da5dade7 MarcoBiazzini
    if (nr_entries < 1 || nr_entries > 5) {
1663
1664 11fce711 MarcoBiazzini
        error
1665
            ("ML : sendALlData : nr_enties is not between 1 and 5 \n ");
1666 da5dade7 MarcoBiazzini
        return 0;
1667
1668
    } else {
1669
1670
        if (nr_entries == 1) {
1671
1672
                mlSendData(connectionID, container->buffer_1,
1673
                      container->length_1, msgtype, sParams);
1674
1675
            return 1;
1676
1677
        } else if (nr_entries == 2) {
1678
1679
            int buflen = container->length_1 + container->length_2;
1680
            char buf[buflen];
1681
            memcpy(buf, container->buffer_1, container->length_1);
1682
            memcpy(&buf[container->length_1], container->buffer_2,
1683
                   container->length_2);
1684
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1685
1686
            return 1;
1687
1688
        } else if (nr_entries == 3) {
1689
1690
            int buflen =
1691
                container->length_1 + container->length_2 +
1692
                container->length_3;
1693
            char buf[buflen];
1694
            memcpy(buf, container->buffer_1, container->length_1);
1695
            memcpy(&buf[container->length_1], container->buffer_2,
1696
                   container->length_2);
1697
            memcpy(&buf[container->length_2], container->buffer_3,
1698
                   container->length_3);
1699
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1700
1701
1702
            return 1;
1703
1704
        } else if (nr_entries == 4) {
1705
1706
            int buflen =
1707
                container->length_1 + container->length_2 +
1708
                container->length_3 + container->length_4;
1709
            char buf[buflen];
1710
            memcpy(buf, container->buffer_1, container->length_1);
1711
            memcpy(&buf[container->length_1], container->buffer_2,
1712
                   container->length_2);
1713
            memcpy(&buf[container->length_2], container->buffer_3,
1714
                   container->length_3);
1715
            memcpy(&buf[container->length_3], container->buffer_4,
1716
                   container->length_4);
1717
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1718
1719
            return 1;
1720
1721
        } else {
1722
1723
            int buflen =
1724
                container->length_1 + container->length_2 +
1725
                container->length_3 + container->length_4 +
1726
                container->length_5;
1727
            char buf[buflen];
1728
            memcpy(buf, container->buffer_1, container->length_1);
1729
            memcpy(&buf[container->length_1], container->buffer_2,
1730
                   container->length_2);
1731
            memcpy(&buf[container->length_2], container->buffer_3,
1732
                   container->length_3);
1733
            memcpy(&buf[container->length_3], container->buffer_4,
1734
                   container->length_4);
1735
            memcpy(&buf[container->length_4], container->buffer_5,
1736
                   container->length_5);
1737
            mlSendData(connectionID, buf, buflen, msgtype, sParams);
1738
1739
            return 1;
1740
        }
1741
1742
    }
1743 a0a1f630 KristianBeckers
1744
}
1745
1746 da5dade7 MarcoBiazzini
int mlRecvData(const int connectionID,char *recvbuf,int *bufsize,recv_params *rParams){
1747
1748
        //TODO yet to be converted
1749
        return 0;
1750
#if 0
1751
        if (rParams == NULL) {
1752 11fce711 MarcoBiazzini
                error("ML: recv_data failed: recv_params is a NULL ptr\n");
1753 da5dade7 MarcoBiazzini
                return 0;
1754
    } else {
1755

1756 11fce711 MarcoBiazzini
        info("ML: recv data called \n");
1757 da5dade7 MarcoBiazzini

1758
        int i = 0;
1759
        int returnValue = 0;
1760
        double timeout = (double) recv_timeout.tv_sec;
1761
        time_t endtime = time(NULL);
1762

1763
        for (i = 0; i < RECVDATABUFSIZE; i++) {
1764

1765
            if (recvdatabuf[i] != NULL) {
1766

1767
                if (recvdatabuf[i]->connectionID == connectionID) {
1768

1769 11fce711 MarcoBiazzini
                    info("ML: recv data has entry  \n");
1770 da5dade7 MarcoBiazzini

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

1773
                    // check if the specified connection has data and it
1774
                    // is complete
1775
                    // check the data seqnr
1776
                    // if(connectionID == recvdatabuf[i]->connectionID &&
1777
                    // 1 == recvdatabuf[i]->status){
1778

1779
                    if (1 == recvdatabuf[i]->status) {
1780

1781 fbb6e767 MarcoBiazzini
                        // info("transmissionHandler: recv_data set is
1782 da5dade7 MarcoBiazzini
                        // complete \n" );
1783

1784 fbb6e767 MarcoBiazzini
                        // debug("debud \n");
1785 da5dade7 MarcoBiazzini

1786
                        // exchange the pointers
1787
                        int buffersize = 0;
1788
                        buffersize = recvdatabuf[i]->bufsize;
1789
                        *bufsize = buffersize;
1790
                        // recvbuf = recvdatabuf[i]->recvbuf;
1791

1792 fbb6e767 MarcoBiazzini
                        // info("buffersize %d \n",buffersize);
1793 da5dade7 MarcoBiazzini
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1794
                               buffersize);
1795 fbb6e767 MarcoBiazzini
                        // debug(" recvbuf %s \n",recvbuf );
1796 da5dade7 MarcoBiazzini

1797
//                         double nrMissFrags =
1798
//                             (double) recvdatabuf[i]->nrFragments /
1799
//                             (double) recvdatabuf[i]->recvFragments;
1800
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
1801

1802
//                        rParams->nrMissingFragments = nrMissingFragments;
1803
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
1804
                        rParams->msgtype = recvdatabuf[i]->msgtype;
1805
                        rParams->connectionID =
1806
                            recvdatabuf[i]->connectionID;
1807

1808
                        // break from the loop
1809 fbb6e767 MarcoBiazzini
                        // debug(" recvbuf %s \n ",recvbuf);
1810 da5dade7 MarcoBiazzini

1811
                        // double nrMissFrags =
1812
                        // (double)recvdatabuf[i]->nrFragments /
1813
                        // (double)recvdatabuf[i]->recvFragments;
1814
                        // int nrMissingFragments =
1815
                        // (int)ceil(nrMissFrags);
1816 a0a1f630 KristianBeckers

1817 da5dade7 MarcoBiazzini
                        if(get_Recv_data_inf_cb != NULL) {
1818
                                mon_data_inf recv_data_inf;
1819

1820
                                recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1821
                                recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1822
                                recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1823
                                recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1824
//                                 recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1825
//                                 recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1826
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
1827
                                recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1828
                                recv_data_inf.nrMissingFragments = nrMissingFragments;
1829
                                recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1830
                                recv_data_inf.priority = false;
1831
                                recv_data_inf.padding = false;
1832
                                recv_data_inf.confirmation = false;
1833
                                recv_data_inf.reliable = false;
1834

1835
                                // send data recv callback to monitoring module
1836

1837
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1838
                        }
1839

1840

1841
                        // free the allocated memory
1842
                        free(recvdatabuf[i]);
1843
                        recvdatabuf[i] = NULL;
1844

1845
                        returnValue = 1;
1846
                        break;
1847

1848
                    }
1849

1850
                    if (recvdatabuf[i] != NULL) {
1851

1852
                        if (timepass > timeout) {
1853

1854 11fce711 MarcoBiazzini
                            info("ML: recv_data timeout called  \n");
1855 da5dade7 MarcoBiazzini

1856
                            // some data about the missing chunks should
1857
                            // be added here
1858
                            // exchange the pointers
1859
                            int buffersize = 0;
1860
                            buffersize = recvdatabuf[i]->bufsize;
1861
                            *bufsize = buffersize;
1862
                            // recvbuf = recvdatabuf[i]->recvbuf;
1863

1864
                            double nrMissFrags =
1865
                                (double) recvdatabuf[i]->nrFragments /
1866
                                (double) recvdatabuf[i]->recvFragments;
1867
                            int nrMissingFragments =
1868
                                (int) ceil(nrMissFrags);
1869

1870 fbb6e767 MarcoBiazzini
                            // debug(" recvbuf %s \n",recvbuf );
1871 da5dade7 MarcoBiazzini

1872
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1873
                                   buffersize);
1874

1875
                            rParams->nrMissingFragments =
1876
                                nrMissingFragments;
1877
                            rParams->nrFragments =
1878
                                recvdatabuf[i]->nrFragments;
1879
                            rParams->msgtype = recvdatabuf[i]->msgtype;
1880
                            rParams->connectionID =
1881
                                recvdatabuf[i]->connectionID;
1882

1883
                                if(get_Recv_data_inf_cb != NULL) {
1884
                                        mon_data_inf recv_data_inf;
1885

1886
                                        recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1887
                                        recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1888
                                        recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1889
                                        recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1890
                                        recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1891
                                        recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1892
                                        gettimeofday(&recv_data_inf.arrival_time, NULL);
1893
                                        recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1894
                                        recv_data_inf.nrMissingFragments = nrMissingFragments;
1895
                                        recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1896
                                        recv_data_inf.priority = false;
1897
                                        recv_data_inf.padding = false;
1898
                                        recv_data_inf.confirmation = false;
1899
                                        recv_data_inf.reliable = false;
1900

1901
                                        // send data recv callback to monitoring module
1902

1903
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1904
                                }
1905

1906
                            // free the allocated memory
1907
                            free(recvdatabuf[i]);
1908
                            recvdatabuf[i] = NULL;
1909

1910
                            returnValue = 1;
1911
                            break;
1912

1913
                        }
1914
                    }
1915

1916
                }
1917

1918
            }
1919 fbb6e767 MarcoBiazzini
            // debug("2 recvbuf %s \n ",recvbuf);
1920 da5dade7 MarcoBiazzini
        }
1921
        return returnValue;
1922
    }
1923
#endif
1924 a0a1f630 KristianBeckers
1925
}
1926
1927 da5dade7 MarcoBiazzini
int mlSocketIDToString(socketID_handle socketID,char* socketID_string, size_t len){
1928
1929
        char internal_addr[INET_ADDRSTRLEN];
1930
        char external_addr[INET_ADDRSTRLEN];
1931 8fed9f23 CsabaKiraly
1932
        assert(socketID);
1933
1934 da5dade7 MarcoBiazzini
        inet_ntop(AF_INET, &(socketID->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1935
        inet_ntop(AF_INET, &(socketID->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1936 2a178954 KristianBeckers
1937 da5dade7 MarcoBiazzini
        snprintf(socketID_string,len,"%s:%d-%s:%d", internal_addr, ntohs(socketID->internal_addr.udpaddr.sin_port),
1938
                external_addr,        ntohs(socketID->external_addr.udpaddr.sin_port));
1939
        return 0;
1940 2a178954 KristianBeckers
1941
}
1942
1943 da5dade7 MarcoBiazzini
int mlStringToSocketID(const char* socketID_string, socketID_handle socketID){
1944
1945
        //@TODO add checks against malformed string
1946
        char external_addr[INET_ADDRSTRLEN];
1947
        int external_port;
1948
        char internal_addr[INET_ADDRSTRLEN];
1949
        int internal_port;
1950 2a178954 KristianBeckers
1951 da5dade7 MarcoBiazzini
        char *pch;
1952
        char *s = strdup(socketID_string);
1953
1954
        //replace ':' with a blank
1955
        pch=strchr(s,':');
1956
        while (pch!=NULL){
1957
                                *pch = ' ';
1958
                pch=strchr(pch+1,':');
1959
        }
1960
        pch=strchr(s,'-');
1961
        if(pch) *pch = ' ';
1962
1963
        sscanf(s,"%s %d %s %d", internal_addr, &internal_port,
1964
                external_addr, &external_port);
1965
1966 c220a4cb CsabaKiraly
        //set structure to 0, we initialize each byte, since it will be sent on the net later
1967
        memset(socketID, 0, sizeof(struct _socket_ID));
1968
1969 da5dade7 MarcoBiazzini
        if(inet_pton(AF_INET, internal_addr, &(socketID->internal_addr.udpaddr.sin_addr)) == 0)
1970
                return EINVAL;
1971
        socketID->internal_addr.udpaddr.sin_family = AF_INET;
1972
        socketID->internal_addr.udpaddr.sin_port = htons(internal_port);
1973
1974
1975
        if(inet_pton(AF_INET, external_addr, &(socketID->external_addr.udpaddr.sin_addr)) ==0)
1976
                return EINVAL;
1977
        socketID->external_addr.udpaddr.sin_family = AF_INET;
1978
        socketID->external_addr.udpaddr.sin_port = htons(external_port);
1979
1980
        free(s);
1981
        return 0;
1982 2a178954 KristianBeckers
1983
}
1984
1985 da5dade7 MarcoBiazzini
int mlGetConnectionStatus(int connectionID){
1986 2a178954 KristianBeckers
1987 da5dade7 MarcoBiazzini
        if(connectbuf[connectionID])
1988
                return connectbuf[connectionID]->status == READY;
1989
        return -1;
1990 2a178954 KristianBeckers
    
1991
}
1992
1993
1994 da5dade7 MarcoBiazzini
int mlConnectionExist(socketID_handle socketID, bool ready){
1995
1996
    /*
1997
     * check if another connection for the external connectionID exist
1998
     * that was established \ within the last 2 seconds
1999
     */
2000
        int i;
2001
        for (i = 0; i < CONNECTBUFSIZE; i++)
2002
                if (connectbuf[i] != NULL)
2003
                        if (mlCompareSocketIDs(&(connectbuf[i]->external_socketID), socketID) == 0) {
2004
                                if (ready) return (connectbuf[i]->status == READY ? i : -1);;
2005
                                return i;
2006
                                }
2007 2a178954 KristianBeckers
2008 da5dade7 MarcoBiazzini
    return -1;
2009 2a178954 KristianBeckers
2010
}
2011 2c702104 RobertBirke
2012
//Added by Robert Birke as comodity functions
2013
2014 11fce711 MarcoBiazzini
//int mlPrintSocketID(socketID_handle socketID) {
2015
//        char str[SOCKETID_STRING_SIZE];
2016
//        mlSocketIDToString(socketID, str, sizeof(str));
2017
//        printf(stderr,"int->%s<-ext\n",str);
2018
//}
2019 da5dade7 MarcoBiazzini
2020
/*
2021
 * hash code of a socketID
2022
 * TODO might think of a better way
2023
 */
2024
int mlHashSocketID(socketID_handle sock) {
2025 60b80a11 RobertBirke
        //assert(sock);
2026
   return sock->internal_addr.udpaddr.sin_port +
2027
                        sock->external_addr.udpaddr.sin_port;
2028 2c702104 RobertBirke
}
2029
2030 da5dade7 MarcoBiazzini
int mlCompareSocketIDs(socketID_handle sock1, socketID_handle sock2) {
2031 8fed9f23 CsabaKiraly
2032
        assert(sock1 && sock2);
2033
2034 da5dade7 MarcoBiazzini
        /*
2035
        * compare internal addr
2036
        */
2037 48968511 CsabaKiraly
        if(sock1 == NULL || sock2 == NULL)
2038
                return 1;
2039
2040 da5dade7 MarcoBiazzini
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr !=
2041
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
2042
                        return 1;
2043
2044
        if (sock1->internal_addr.udpaddr.sin_port !=
2045
                 sock2->internal_addr.udpaddr.sin_port)
2046
                        return 1;
2047
2048
        /*
2049
        * compare external addr
2050
        */
2051
        if (sock1->external_addr.udpaddr.sin_addr.s_addr !=
2052
            sock2->external_addr.udpaddr.sin_addr.s_addr)
2053
                        return 1;
2054
2055
        if (sock1->external_addr.udpaddr.sin_port !=
2056
                 sock2->external_addr.udpaddr.sin_port)
2057
                        return 1;
2058
2059
        return 0;
2060 2c702104 RobertBirke
}
2061
2062 da5dade7 MarcoBiazzini
int mlCompareSocketIDsByPort(socketID_handle sock1, socketID_handle sock2)
2063 48968511 CsabaKiraly
{
2064
        if(sock1 == NULL || sock2 == NULL)
2065
                return 1;
2066
 
2067 2c702104 RobertBirke
        if (sock1->internal_addr.udpaddr.sin_port !=
2068
                 sock2->internal_addr.udpaddr.sin_port)
2069
                        return 1;
2070
2071
        if (sock1->external_addr.udpaddr.sin_port !=
2072
                 sock2->external_addr.udpaddr.sin_port)
2073
                        return 1;
2074
        return 0;
2075 380cf1b9 RobertBirke
}
2076 bcf9c2dd RobertBirke
2077 da5dade7 MarcoBiazzini
int mlGetPathMTU(int ConnectionId) {
2078
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
2079
                return -1;
2080
        if (connectbuf[ConnectionId] != NULL)
2081
                return connectbuf[ConnectionId]->pmtusize;
2082
        return -1;
2083 bcf9c2dd RobertBirke
}
2084 6f26b958 MarcoBiazzini
2085
/**************************** END of GENERAL functions *************************/
2086
2087
/**************************** NAT functions *************************/
2088
2089
/* setter  */
2090
void mlSetStunServer(const int port,const char *ipaddr){
2091
2092
        stun_server.sin_family = AF_INET;
2093
        if (ipaddr == NULL)
2094 ea1436ee CsabaKiraly
                stun_server.sin_addr.s_addr = htonl(INADDR_NONE);
2095 6f26b958 MarcoBiazzini
        else
2096
                stun_server.sin_addr.s_addr = resolve(ipaddr);
2097
        stun_server.sin_port = htons(port);
2098
2099
}
2100
2101
int mlGetExternalIP(char* external_addr){
2102
2103
        socketaddrgen udpgen;
2104
        struct sockaddr_in udpaddr;
2105
2106
        udpgen = local_socketID.external_addr;
2107
        udpaddr = udpgen.udpaddr;
2108
2109
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
2110
                        INET_ADDRSTRLEN);
2111
2112
        if (external_addr == NULL) {
2113
2114
        return -1;
2115
2116
        } else {
2117
2118
        return 0;
2119
2120
        }
2121
2122
}
2123
2124
/**************************** END of NAT functions *************************/