Statistics
| Branch: | Revision:

ml / ml.c @ e3923e27

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

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

1976
        int i = 0;
1977
        int returnValue = 0;
1978
        double timeout = (double) recv_timeout.tv_sec;
1979
        time_t endtime = time(NULL);
1980

1981
        for (i = 0; i < RECVDATABUFSIZE; i++) {
1982

1983
            if (recvdatabuf[i] != NULL) {
1984

1985
                if (recvdatabuf[i]->connectionID == connectionID) {
1986

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

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

1991
                    // check if the specified connection has data and it
1992
                    // is complete
1993
                    // check the data seqnr
1994
                    // if(connectionID == recvdatabuf[i]->connectionID &&
1995
                    // 1 == recvdatabuf[i]->status){
1996

1997
                    if (1 == recvdatabuf[i]->status) {
1998

1999 fbb6e767 MarcoBiazzini
                        // info("transmissionHandler: recv_data set is
2000 da5dade7 MarcoBiazzini
                        // complete \n" );
2001

2002 fbb6e767 MarcoBiazzini
                        // debug("debud \n");
2003 da5dade7 MarcoBiazzini

2004
                        // exchange the pointers
2005
                        int buffersize = 0;
2006
                        buffersize = recvdatabuf[i]->bufsize;
2007
                        *bufsize = buffersize;
2008
                        // recvbuf = recvdatabuf[i]->recvbuf;
2009

2010 fbb6e767 MarcoBiazzini
                        // info("buffersize %d \n",buffersize);
2011 da5dade7 MarcoBiazzini
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
2012
                               buffersize);
2013 fbb6e767 MarcoBiazzini
                        // debug(" recvbuf %s \n",recvbuf );
2014 da5dade7 MarcoBiazzini

2015
//                         double nrMissFrags =
2016
//                             (double) recvdatabuf[i]->nrFragments /
2017
//                             (double) recvdatabuf[i]->recvFragments;
2018
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
2019

2020
//                        rParams->nrMissingFragments = nrMissingFragments;
2021
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
2022
                        rParams->msgtype = recvdatabuf[i]->msgtype;
2023
                        rParams->connectionID =
2024
                            recvdatabuf[i]->connectionID;
2025

2026
                        // break from the loop
2027 fbb6e767 MarcoBiazzini
                        // debug(" recvbuf %s \n ",recvbuf);
2028 da5dade7 MarcoBiazzini

2029
                        // double nrMissFrags =
2030
                        // (double)recvdatabuf[i]->nrFragments /
2031
                        // (double)recvdatabuf[i]->recvFragments;
2032
                        // int nrMissingFragments =
2033
                        // (int)ceil(nrMissFrags);
2034 a0a1f630 KristianBeckers

2035 da5dade7 MarcoBiazzini
                        if(get_Recv_data_inf_cb != NULL) {
2036
                                mon_data_inf recv_data_inf;
2037

2038
                                recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
2039
                                recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
2040
                                recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
2041
                                recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
2042
//                                 recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
2043
//                                 recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
2044
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
2045
                                recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
2046
                                recv_data_inf.nrMissingFragments = nrMissingFragments;
2047
                                recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
2048
                                recv_data_inf.priority = false;
2049
                                recv_data_inf.padding = false;
2050
                                recv_data_inf.confirmation = false;
2051
                                recv_data_inf.reliable = false;
2052

2053
                                // send data recv callback to monitoring module
2054

2055
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
2056
                        }
2057

2058

2059
                        // free the allocated memory
2060
                        free(recvdatabuf[i]);
2061
                        recvdatabuf[i] = NULL;
2062

2063
                        returnValue = 1;
2064
                        break;
2065

2066
                    }
2067

2068
                    if (recvdatabuf[i] != NULL) {
2069

2070
                        if (timepass > timeout) {
2071

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

2074
                            // some data about the missing chunks should
2075
                            // be added here
2076
                            // exchange the pointers
2077
                            int buffersize = 0;
2078
                            buffersize = recvdatabuf[i]->bufsize;
2079
                            *bufsize = buffersize;
2080
                            // recvbuf = recvdatabuf[i]->recvbuf;
2081

2082
                            double nrMissFrags =
2083
                                (double) recvdatabuf[i]->nrFragments /
2084
                                (double) recvdatabuf[i]->recvFragments;
2085
                            int nrMissingFragments =
2086
                                (int) ceil(nrMissFrags);
2087

2088 fbb6e767 MarcoBiazzini
                            // debug(" recvbuf %s \n",recvbuf );
2089 da5dade7 MarcoBiazzini

2090
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
2091
                                   buffersize);
2092

2093
                            rParams->nrMissingFragments =
2094
                                nrMissingFragments;
2095
                            rParams->nrFragments =
2096
                                recvdatabuf[i]->nrFragments;
2097
                            rParams->msgtype = recvdatabuf[i]->msgtype;
2098
                            rParams->connectionID =
2099
                                recvdatabuf[i]->connectionID;
2100

2101
                                if(get_Recv_data_inf_cb != NULL) {
2102
                                        mon_data_inf recv_data_inf;
2103

2104
                                        recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
2105
                                        recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
2106
                                        recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
2107
                                        recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
2108
                                        recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
2109
                                        recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
2110
                                        gettimeofday(&recv_data_inf.arrival_time, NULL);
2111
                                        recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
2112
                                        recv_data_inf.nrMissingFragments = nrMissingFragments;
2113
                                        recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
2114
                                        recv_data_inf.priority = false;
2115
                                        recv_data_inf.padding = false;
2116
                                        recv_data_inf.confirmation = false;
2117
                                        recv_data_inf.reliable = false;
2118

2119
                                        // send data recv callback to monitoring module
2120

2121
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
2122
                                }
2123

2124
                            // free the allocated memory
2125
                            free(recvdatabuf[i]);
2126
                            recvdatabuf[i] = NULL;
2127

2128
                            returnValue = 1;
2129
                            break;
2130

2131
                        }
2132
                    }
2133

2134
                }
2135

2136
            }
2137 fbb6e767 MarcoBiazzini
            // debug("2 recvbuf %s \n ",recvbuf);
2138 da5dade7 MarcoBiazzini
        }
2139
        return returnValue;
2140
    }
2141
#endif
2142 a0a1f630 KristianBeckers
2143
}
2144
2145 da5dade7 MarcoBiazzini
int mlSocketIDToString(socketID_handle socketID,char* socketID_string, size_t len){
2146
2147
        char internal_addr[INET_ADDRSTRLEN];
2148
        char external_addr[INET_ADDRSTRLEN];
2149 8fed9f23 CsabaKiraly
2150
        assert(socketID);
2151
2152 da5dade7 MarcoBiazzini
        inet_ntop(AF_INET, &(socketID->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
2153
        inet_ntop(AF_INET, &(socketID->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
2154 2a178954 KristianBeckers
2155 da5dade7 MarcoBiazzini
        snprintf(socketID_string,len,"%s:%d-%s:%d", internal_addr, ntohs(socketID->internal_addr.udpaddr.sin_port),
2156
                external_addr,        ntohs(socketID->external_addr.udpaddr.sin_port));
2157
        return 0;
2158 2a178954 KristianBeckers
2159
}
2160
2161 da5dade7 MarcoBiazzini
int mlStringToSocketID(const char* socketID_string, socketID_handle socketID){
2162
2163
        //@TODO add checks against malformed string
2164
        char external_addr[INET_ADDRSTRLEN];
2165
        int external_port;
2166
        char internal_addr[INET_ADDRSTRLEN];
2167
        int internal_port;
2168 2a178954 KristianBeckers
2169 da5dade7 MarcoBiazzini
        char *pch;
2170
        char *s = strdup(socketID_string);
2171
2172
        //replace ':' with a blank
2173
        pch=strchr(s,':');
2174
        while (pch!=NULL){
2175
                                *pch = ' ';
2176
                pch=strchr(pch+1,':');
2177
        }
2178
        pch=strchr(s,'-');
2179
        if(pch) *pch = ' ';
2180
2181
        sscanf(s,"%s %d %s %d", internal_addr, &internal_port,
2182
                external_addr, &external_port);
2183
2184 c220a4cb CsabaKiraly
        //set structure to 0, we initialize each byte, since it will be sent on the net later
2185
        memset(socketID, 0, sizeof(struct _socket_ID));
2186
2187 da5dade7 MarcoBiazzini
        if(inet_pton(AF_INET, internal_addr, &(socketID->internal_addr.udpaddr.sin_addr)) == 0)
2188
                return EINVAL;
2189
        socketID->internal_addr.udpaddr.sin_family = AF_INET;
2190
        socketID->internal_addr.udpaddr.sin_port = htons(internal_port);
2191
2192
2193
        if(inet_pton(AF_INET, external_addr, &(socketID->external_addr.udpaddr.sin_addr)) ==0)
2194
                return EINVAL;
2195
        socketID->external_addr.udpaddr.sin_family = AF_INET;
2196
        socketID->external_addr.udpaddr.sin_port = htons(external_port);
2197
2198
        free(s);
2199
        return 0;
2200 2a178954 KristianBeckers
2201
}
2202
2203 da5dade7 MarcoBiazzini
int mlGetConnectionStatus(int connectionID){
2204 2a178954 KristianBeckers
2205 da5dade7 MarcoBiazzini
        if(connectbuf[connectionID])
2206
                return connectbuf[connectionID]->status == READY;
2207
        return -1;
2208 2a178954 KristianBeckers
    
2209
}
2210
2211
2212 da5dade7 MarcoBiazzini
int mlConnectionExist(socketID_handle socketID, bool ready){
2213
2214
    /*
2215
     * check if another connection for the external connectionID exist
2216
     * that was established \ within the last 2 seconds
2217
     */
2218
        int i;
2219
        for (i = 0; i < CONNECTBUFSIZE; i++)
2220
                if (connectbuf[i] != NULL)
2221
                        if (mlCompareSocketIDs(&(connectbuf[i]->external_socketID), socketID) == 0) {
2222
                                if (ready) return (connectbuf[i]->status == READY ? i : -1);;
2223
                                return i;
2224
                                }
2225 2a178954 KristianBeckers
2226 da5dade7 MarcoBiazzini
    return -1;
2227 2a178954 KristianBeckers
2228
}
2229 2c702104 RobertBirke
2230
//Added by Robert Birke as comodity functions
2231
2232 11fce711 MarcoBiazzini
//int mlPrintSocketID(socketID_handle socketID) {
2233
//        char str[SOCKETID_STRING_SIZE];
2234
//        mlSocketIDToString(socketID, str, sizeof(str));
2235
//        printf(stderr,"int->%s<-ext\n",str);
2236
//}
2237 da5dade7 MarcoBiazzini
2238
/*
2239
 * hash code of a socketID
2240
 * TODO might think of a better way
2241
 */
2242
int mlHashSocketID(socketID_handle sock) {
2243 60b80a11 RobertBirke
        //assert(sock);
2244
   return sock->internal_addr.udpaddr.sin_port +
2245
                        sock->external_addr.udpaddr.sin_port;
2246 2c702104 RobertBirke
}
2247
2248 da5dade7 MarcoBiazzini
int mlCompareSocketIDs(socketID_handle sock1, socketID_handle sock2) {
2249 8fed9f23 CsabaKiraly
2250
        assert(sock1 && sock2);
2251
2252 da5dade7 MarcoBiazzini
        /*
2253
        * compare internal addr
2254
        */
2255 48968511 CsabaKiraly
        if(sock1 == NULL || sock2 == NULL)
2256
                return 1;
2257
2258 da5dade7 MarcoBiazzini
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr !=
2259
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
2260
                        return 1;
2261
2262
        if (sock1->internal_addr.udpaddr.sin_port !=
2263
                 sock2->internal_addr.udpaddr.sin_port)
2264
                        return 1;
2265
2266
        /*
2267
        * compare external addr
2268
        */
2269
        if (sock1->external_addr.udpaddr.sin_addr.s_addr !=
2270
            sock2->external_addr.udpaddr.sin_addr.s_addr)
2271
                        return 1;
2272
2273
        if (sock1->external_addr.udpaddr.sin_port !=
2274
                 sock2->external_addr.udpaddr.sin_port)
2275
                        return 1;
2276
2277
        return 0;
2278 2c702104 RobertBirke
}
2279
2280 da5dade7 MarcoBiazzini
int mlCompareSocketIDsByPort(socketID_handle sock1, socketID_handle sock2)
2281 48968511 CsabaKiraly
{
2282
        if(sock1 == NULL || sock2 == NULL)
2283
                return 1;
2284
 
2285 2c702104 RobertBirke
        if (sock1->internal_addr.udpaddr.sin_port !=
2286
                 sock2->internal_addr.udpaddr.sin_port)
2287
                        return 1;
2288
2289
        if (sock1->external_addr.udpaddr.sin_port !=
2290
                 sock2->external_addr.udpaddr.sin_port)
2291
                        return 1;
2292
        return 0;
2293 380cf1b9 RobertBirke
}
2294 bcf9c2dd RobertBirke
2295 da5dade7 MarcoBiazzini
int mlGetPathMTU(int ConnectionId) {
2296
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
2297
                return -1;
2298
        if (connectbuf[ConnectionId] != NULL)
2299
                return connectbuf[ConnectionId]->pmtusize;
2300
        return -1;
2301 bcf9c2dd RobertBirke
}
2302 6f26b958 MarcoBiazzini
2303
/**************************** END of GENERAL functions *************************/
2304
2305
/**************************** NAT functions *************************/
2306
2307
/* setter  */
2308
void mlSetStunServer(const int port,const char *ipaddr){
2309
2310
        stun_server.sin_family = AF_INET;
2311
        if (ipaddr == NULL)
2312 ea1436ee CsabaKiraly
                stun_server.sin_addr.s_addr = htonl(INADDR_NONE);
2313 6f26b958 MarcoBiazzini
        else
2314
                stun_server.sin_addr.s_addr = resolve(ipaddr);
2315
        stun_server.sin_port = htons(port);
2316
2317
}
2318
2319
int mlGetExternalIP(char* external_addr){
2320
2321
        socketaddrgen udpgen;
2322
        struct sockaddr_in udpaddr;
2323
2324
        udpgen = local_socketID.external_addr;
2325
        udpaddr = udpgen.udpaddr;
2326
2327
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
2328
                        INET_ADDRSTRLEN);
2329
2330
        if (external_addr == NULL) {
2331
2332
        return -1;
2333
2334
        } else {
2335
2336
        return 0;
2337
2338
        }
2339
2340
}
2341
2342
/**************************** END of NAT functions *************************/