Statistics
| Branch: | Revision:

ml / ml.c @ b6b8c19a

History | View | Annotate | Download (59.6 KB)

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

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

1678
        int i = 0;
1679
        int returnValue = 0;
1680
        double timeout = (double) recv_timeout.tv_sec;
1681
        time_t endtime = time(NULL);
1682

1683
        for (i = 0; i < RECVDATABUFSIZE; i++) {
1684

1685
            if (recvdatabuf[i] != NULL) {
1686

1687
                if (recvdatabuf[i]->connectionID == connectionID) {
1688

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

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

1693
                    // check if the specified connection has data and it
1694
                    // is complete
1695
                    // check the data seqnr
1696
                    // if(connectionID == recvdatabuf[i]->connectionID &&
1697
                    // 1 == recvdatabuf[i]->status){
1698

1699
                    if (1 == recvdatabuf[i]->status) {
1700

1701 fbb6e767 MarcoBiazzini
                        // info("transmissionHandler: recv_data set is
1702 da5dade7 MarcoBiazzini
                        // complete \n" );
1703

1704 fbb6e767 MarcoBiazzini
                        // debug("debud \n");
1705 da5dade7 MarcoBiazzini

1706
                        // exchange the pointers
1707
                        int buffersize = 0;
1708
                        buffersize = recvdatabuf[i]->bufsize;
1709
                        *bufsize = buffersize;
1710
                        // recvbuf = recvdatabuf[i]->recvbuf;
1711

1712 fbb6e767 MarcoBiazzini
                        // info("buffersize %d \n",buffersize);
1713 da5dade7 MarcoBiazzini
                        memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1714
                               buffersize);
1715 fbb6e767 MarcoBiazzini
                        // debug(" recvbuf %s \n",recvbuf );
1716 da5dade7 MarcoBiazzini

1717
//                         double nrMissFrags =
1718
//                             (double) recvdatabuf[i]->nrFragments /
1719
//                             (double) recvdatabuf[i]->recvFragments;
1720
//                         int nrMissingFragments = (int) ceil(nrMissFrags);
1721

1722
//                        rParams->nrMissingFragments = nrMissingFragments;
1723
//                         rParams->nrFragments = recvdatabuf[i]->nrFragments;
1724
                        rParams->msgtype = recvdatabuf[i]->msgtype;
1725
                        rParams->connectionID =
1726
                            recvdatabuf[i]->connectionID;
1727

1728
                        // break from the loop
1729 fbb6e767 MarcoBiazzini
                        // debug(" recvbuf %s \n ",recvbuf);
1730 da5dade7 MarcoBiazzini

1731
                        // double nrMissFrags =
1732
                        // (double)recvdatabuf[i]->nrFragments /
1733
                        // (double)recvdatabuf[i]->recvFragments;
1734
                        // int nrMissingFragments =
1735
                        // (int)ceil(nrMissFrags);
1736 a0a1f630 KristianBeckers

1737 da5dade7 MarcoBiazzini
                        if(get_Recv_data_inf_cb != NULL) {
1738
                                mon_data_inf recv_data_inf;
1739

1740
                                recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1741
                                recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1742
                                recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1743
                                recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1744
//                                 recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1745
//                                 recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1746
                                gettimeofday(&recv_data_inf.arrival_time, NULL);
1747
                                recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1748
                                recv_data_inf.nrMissingFragments = nrMissingFragments;
1749
                                recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1750
                                recv_data_inf.priority = false;
1751
                                recv_data_inf.padding = false;
1752
                                recv_data_inf.confirmation = false;
1753
                                recv_data_inf.reliable = false;
1754

1755
                                // send data recv callback to monitoring module
1756

1757
                                (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1758
                        }
1759

1760

1761
                        // free the allocated memory
1762
                        free(recvdatabuf[i]);
1763
                        recvdatabuf[i] = NULL;
1764

1765
                        returnValue = 1;
1766
                        break;
1767

1768
                    }
1769

1770
                    if (recvdatabuf[i] != NULL) {
1771

1772
                        if (timepass > timeout) {
1773

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

1776
                            // some data about the missing chunks should
1777
                            // be added here
1778
                            // exchange the pointers
1779
                            int buffersize = 0;
1780
                            buffersize = recvdatabuf[i]->bufsize;
1781
                            *bufsize = buffersize;
1782
                            // recvbuf = recvdatabuf[i]->recvbuf;
1783

1784
                            double nrMissFrags =
1785
                                (double) recvdatabuf[i]->nrFragments /
1786
                                (double) recvdatabuf[i]->recvFragments;
1787
                            int nrMissingFragments =
1788
                                (int) ceil(nrMissFrags);
1789

1790 fbb6e767 MarcoBiazzini
                            // debug(" recvbuf %s \n",recvbuf );
1791 da5dade7 MarcoBiazzini

1792
                            memcpy(recvbuf, recvdatabuf[i]->recvbuf,
1793
                                   buffersize);
1794

1795
                            rParams->nrMissingFragments =
1796
                                nrMissingFragments;
1797
                            rParams->nrFragments =
1798
                                recvdatabuf[i]->nrFragments;
1799
                            rParams->msgtype = recvdatabuf[i]->msgtype;
1800
                            rParams->connectionID =
1801
                                recvdatabuf[i]->connectionID;
1802

1803
                                if(get_Recv_data_inf_cb != NULL) {
1804
                                        mon_data_inf recv_data_inf;
1805

1806
                                        recv_data_inf.remote_socketID = &(connectbuf[connectionID]->external_socketID);
1807
                                        recv_data_inf.buffer = recvdatabuf[i]->recvbuf;
1808
                                        recv_data_inf.bufSize = recvdatabuf[i]->bufsize;
1809
                                        recv_data_inf.msgtype = recvdatabuf[i]->msgtype;
1810
                                        recv_data_inf.monitoringHeaderType = recvdatabuf[i]->monitoringHeaderType;
1811
                                        recv_data_inf.monitoringDataHeader = recvdatabuf[i]->monitoringDataHeader;
1812
                                        gettimeofday(&recv_data_inf.arrival_time, NULL);
1813
                                        recv_data_inf.firstPacketArrived = recvdatabuf[i]->firstPacketArrived;
1814
                                        recv_data_inf.nrMissingFragments = nrMissingFragments;
1815
                                        recv_data_inf.nrFragments = recvdatabuf[i]->nrFragments;
1816
                                        recv_data_inf.priority = false;
1817
                                        recv_data_inf.padding = false;
1818
                                        recv_data_inf.confirmation = false;
1819
                                        recv_data_inf.reliable = false;
1820

1821
                                        // send data recv callback to monitoring module
1822

1823
                                        (get_Recv_data_inf_cb) ((void *) &recv_data_inf);
1824
                                }
1825

1826
                            // free the allocated memory
1827
                            free(recvdatabuf[i]);
1828
                            recvdatabuf[i] = NULL;
1829

1830
                            returnValue = 1;
1831
                            break;
1832

1833
                        }
1834
                    }
1835

1836
                }
1837

1838
            }
1839 fbb6e767 MarcoBiazzini
            // debug("2 recvbuf %s \n ",recvbuf);
1840 da5dade7 MarcoBiazzini
        }
1841
        return returnValue;
1842
    }
1843
#endif
1844 a0a1f630 KristianBeckers
1845
}
1846
1847 da5dade7 MarcoBiazzini
int mlSocketIDToString(socketID_handle socketID,char* socketID_string, size_t len){
1848
1849
        char internal_addr[INET_ADDRSTRLEN];
1850
        char external_addr[INET_ADDRSTRLEN];
1851
        inet_ntop(AF_INET, &(socketID->internal_addr.udpaddr.sin_addr.s_addr), internal_addr, INET_ADDRSTRLEN);
1852
        inet_ntop(AF_INET, &(socketID->external_addr.udpaddr.sin_addr.s_addr), external_addr, INET_ADDRSTRLEN);
1853 2a178954 KristianBeckers
1854 da5dade7 MarcoBiazzini
        snprintf(socketID_string,len,"%s:%d-%s:%d", internal_addr, ntohs(socketID->internal_addr.udpaddr.sin_port),
1855
                external_addr,        ntohs(socketID->external_addr.udpaddr.sin_port));
1856
        return 0;
1857 2a178954 KristianBeckers
1858
}
1859
1860 da5dade7 MarcoBiazzini
int mlStringToSocketID(const char* socketID_string, socketID_handle socketID){
1861
1862
        //@TODO add checks against malformed string
1863
        char external_addr[INET_ADDRSTRLEN];
1864
        int external_port;
1865
        char internal_addr[INET_ADDRSTRLEN];
1866
        int internal_port;
1867 2a178954 KristianBeckers
1868 da5dade7 MarcoBiazzini
        char *pch;
1869
        char *s = strdup(socketID_string);
1870
1871
        //replace ':' with a blank
1872
        pch=strchr(s,':');
1873
        while (pch!=NULL){
1874
                                *pch = ' ';
1875
                pch=strchr(pch+1,':');
1876
        }
1877
        pch=strchr(s,'-');
1878
        if(pch) *pch = ' ';
1879
1880
        sscanf(s,"%s %d %s %d", internal_addr, &internal_port,
1881
                external_addr, &external_port);
1882
1883 c220a4cb CsabaKiraly
        //set structure to 0, we initialize each byte, since it will be sent on the net later
1884
        memset(socketID, 0, sizeof(struct _socket_ID));
1885
1886 da5dade7 MarcoBiazzini
        if(inet_pton(AF_INET, internal_addr, &(socketID->internal_addr.udpaddr.sin_addr)) == 0)
1887
                return EINVAL;
1888
        socketID->internal_addr.udpaddr.sin_family = AF_INET;
1889
        socketID->internal_addr.udpaddr.sin_port = htons(internal_port);
1890
1891
1892
        if(inet_pton(AF_INET, external_addr, &(socketID->external_addr.udpaddr.sin_addr)) ==0)
1893
                return EINVAL;
1894
        socketID->external_addr.udpaddr.sin_family = AF_INET;
1895
        socketID->external_addr.udpaddr.sin_port = htons(external_port);
1896
1897
        free(s);
1898
        return 0;
1899 2a178954 KristianBeckers
1900
}
1901
1902 da5dade7 MarcoBiazzini
int mlGetConnectionStatus(int connectionID){
1903 2a178954 KristianBeckers
1904 da5dade7 MarcoBiazzini
        if(connectbuf[connectionID])
1905
                return connectbuf[connectionID]->status == READY;
1906
        return -1;
1907 2a178954 KristianBeckers
    
1908
}
1909
1910
1911 da5dade7 MarcoBiazzini
int mlConnectionExist(socketID_handle socketID, bool ready){
1912
1913
    /*
1914
     * check if another connection for the external connectionID exist
1915
     * that was established \ within the last 2 seconds
1916
     */
1917
        int i;
1918
        for (i = 0; i < CONNECTBUFSIZE; i++)
1919
                if (connectbuf[i] != NULL)
1920
                        if (mlCompareSocketIDs(&(connectbuf[i]->external_socketID), socketID) == 0) {
1921
                                if (ready) return (connectbuf[i]->status == READY ? i : -1);;
1922
                                return i;
1923
                                }
1924 2a178954 KristianBeckers
1925 da5dade7 MarcoBiazzini
    return -1;
1926 2a178954 KristianBeckers
1927
}
1928 2c702104 RobertBirke
1929
//Added by Robert Birke as comodity functions
1930
1931 11fce711 MarcoBiazzini
//int mlPrintSocketID(socketID_handle socketID) {
1932
//        char str[SOCKETID_STRING_SIZE];
1933
//        mlSocketIDToString(socketID, str, sizeof(str));
1934
//        printf(stderr,"int->%s<-ext\n",str);
1935
//}
1936 da5dade7 MarcoBiazzini
1937
/*
1938
 * hash code of a socketID
1939
 * TODO might think of a better way
1940
 */
1941
int mlHashSocketID(socketID_handle sock) {
1942
    return sock->internal_addr.udpaddr.sin_port +
1943
                          sock->external_addr.udpaddr.sin_port;
1944 2c702104 RobertBirke
}
1945
1946 da5dade7 MarcoBiazzini
int mlCompareSocketIDs(socketID_handle sock1, socketID_handle sock2) {
1947
        /*
1948
        * compare internal addr
1949
        */
1950
        if (sock1->internal_addr.udpaddr.sin_addr.s_addr !=
1951
            sock2->internal_addr.udpaddr.sin_addr.s_addr)
1952
                        return 1;
1953
1954
        if (sock1->internal_addr.udpaddr.sin_port !=
1955
                 sock2->internal_addr.udpaddr.sin_port)
1956
                        return 1;
1957
1958
        /*
1959
        * compare external addr
1960
        */
1961
        if (sock1->external_addr.udpaddr.sin_addr.s_addr !=
1962
            sock2->external_addr.udpaddr.sin_addr.s_addr)
1963
                        return 1;
1964
1965
        if (sock1->external_addr.udpaddr.sin_port !=
1966
                 sock2->external_addr.udpaddr.sin_port)
1967
                        return 1;
1968
1969
        return 0;
1970 2c702104 RobertBirke
}
1971
1972 da5dade7 MarcoBiazzini
int mlCompareSocketIDsByPort(socketID_handle sock1, socketID_handle sock2)
1973 380cf1b9 RobertBirke
{ 
1974 2c702104 RobertBirke
        if (sock1->internal_addr.udpaddr.sin_port !=
1975
                 sock2->internal_addr.udpaddr.sin_port)
1976
                        return 1;
1977
1978
        if (sock1->external_addr.udpaddr.sin_port !=
1979
                 sock2->external_addr.udpaddr.sin_port)
1980
                        return 1;
1981
        return 0;
1982 380cf1b9 RobertBirke
}
1983 bcf9c2dd RobertBirke
1984 da5dade7 MarcoBiazzini
int mlGetPathMTU(int ConnectionId) {
1985
        if(ConnectionId < 0 || ConnectionId >= CONNECTBUFSIZE)
1986
                return -1;
1987
        if (connectbuf[ConnectionId] != NULL)
1988
                return connectbuf[ConnectionId]->pmtusize;
1989
        return -1;
1990 bcf9c2dd RobertBirke
}
1991 6f26b958 MarcoBiazzini
1992
/**************************** END of GENERAL functions *************************/
1993
1994
/**************************** NAT functions *************************/
1995
1996
/* setter  */
1997
void mlSetStunServer(const int port,const char *ipaddr){
1998
1999
        stun_server.sin_family = AF_INET;
2000
        if (ipaddr == NULL)
2001 ea1436ee CsabaKiraly
                stun_server.sin_addr.s_addr = htonl(INADDR_NONE);
2002 6f26b958 MarcoBiazzini
        else
2003
                stun_server.sin_addr.s_addr = resolve(ipaddr);
2004
        stun_server.sin_port = htons(port);
2005
2006
}
2007
2008
int mlGetExternalIP(char* external_addr){
2009
2010
        socketaddrgen udpgen;
2011
        struct sockaddr_in udpaddr;
2012
2013
        udpgen = local_socketID.external_addr;
2014
        udpaddr = udpgen.udpaddr;
2015
2016
        inet_ntop(AF_INET, &(udpaddr.sin_addr), external_addr,
2017
                        INET_ADDRSTRLEN);
2018
2019
        if (external_addr == NULL) {
2020
2021
        return -1;
2022
2023
        } else {
2024
2025
        return 0;
2026
2027
        }
2028
2029
}
2030
2031
/**************************** END of NAT functions *************************/