Revision d5b9b14d ml.c

View differences:

ml.c
84 84
#define NAT_TRAVERSAL_TIMEOUT { 1, 0 }
85 85

  
86 86
/*
87
 * 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
/*
87 97
 * default timeout value between the first and the last received packet of a message
88 98
 */
89 99
#define RECV_TIMEOUT_DEFAULT { 2, 0 }
......
115 125
 * receive timeout
116 126
 */
117 127
static struct timeval recv_timeout = RECV_TIMEOUT_DEFAULT;
118
struct timeval recv_timeout;
119 128

  
120 129
/*
121 130
 * boolean NAT traversal successful if true
......
316 325
	} while(retry);
317 326
}
318 327

  
328
void pmtu_timeout_cb(int fd, short event, void *arg);
329

  
330
void reschedule_conn_msg(int con_id)
331
{
332
	if (connectbuf[con_id]->timeout_event) {
333
		/* delete old timout */	
334
		event_del(connectbuf[con_id]->timeout_event);
335
		event_free(connectbuf[con_id]->timeout_event);
336
	}
337
	connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
338
	evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
339
}
340

  
319 341
void send_conn_msg(int con_id, int buf_size, int command_type)
320 342
{
321 343
	if (buf_size < sizeof(struct conn_msg)) {
......
343 365
	send_msg(con_id, ML_CON_MSG, connectbuf[con_id]->ctrl_msg_buf, buf_size, true, &(connectbuf[con_id]->defaultSendParams));
344 366
}
345 367

  
368
void send_conn_msg_with_pmtu_discovery(int con_id, int buf_size, int command_type)
369
{
370
	struct timeval tout = PMTU_TIMEOUT;
371
	connectbuf[con_id]->timeout_value = tout;
372
	connectbuf[con_id]->trials = 1;
373
	send_conn_msg(con_id, buf_size, command_type);
374
	reschedule_conn_msg(con_id);
375
}
376

  
377
void resend_conn_msg(int con_id)
378
{
379
	connectbuf[con_id]->trials++;
380
	send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
381
	reschedule_conn_msg(con_id);
382
}
383

  
346 384
void
347 385
recv_conn_msg(struct msg_header *msg_h, char *msgbuf, int bufsize)
348 386
{
......
424 462
				connectbuf[free_con_id]->connection_head = connectbuf[free_con_id]->connection_last = NULL;
425 463
				connectbuf[free_con_id]->starttime = time(NULL);
426 464
				memcpy(&(connectbuf[free_con_id]->external_socketID), &(con_msg->sock_id), sizeof(socket_ID));
427
				connectbuf[free_con_id]->pmtusize = con_msg->pmtu_size;
465
				connectbuf[free_con_id]->pmtusize = con_msg->pmtu_size;	// bootstrap pmtu from the other's size. Not strictly needed, but a good hint
428 466
				connectbuf[free_con_id]->external_connectionID = msg_h->local_con_id;
429 467
				connectbuf[free_con_id]->internal_connect =
430 468
					!compare_external_address_socketIDs(&(con_msg->sock_id), loc_socketID);
......
434 472
			//if(connectbuf[con_id]->status <= CONNECT) { //TODO: anwer anyway. Why the outher would invite otherwise?
435 473
				//update status and send back answer
436 474
				connectbuf[con_id]->status = CONNECT;
437
				send_conn_msg(con_id, con_msg->pmtu_size, CONNECT);
475
				send_conn_msg_with_pmtu_discovery(con_id, con_msg->pmtu_size, CONNECT);
438 476
			//}
439 477
			break;
440 478
		case CONNECT:
......
453 491
				connectbuf[msg_h->remote_con_id]->external_connectionID = msg_h->local_con_id;
454 492
				// change status con_msg the connection_data
455 493
				connectbuf[msg_h->remote_con_id]->status = READY;
456
				// change pmtusize in the connection_data
457
				connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
494
				// change pmtusize in the connection_data: not needed. receiving a CONNECT means our INVITE went through. So why change pmtu?
495
				//connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
458 496

  
459 497
				// send the READY
460
				send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
498
				send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
461 499

  
462 500
				if (receive_Connection_cb != NULL)
463 501
					(receive_Connection_cb) (msg_h->remote_con_id, NULL);
......
472 510
				}
473 511
				connectbuf[msg_h->remote_con_id]->connection_head =
474 512
					connectbuf[msg_h->remote_con_id]->connection_last = NULL;
475
			} else
513
			} else {
476 514
				// send the READY
477
				send_conn_msg(msg_h->remote_con_id, con_msg->pmtu_size, READY);
515
				send_conn_msg_with_pmtu_discovery(msg_h->remote_con_id, con_msg->pmtu_size, READY);
516
			}
478 517

  
479 518
			debug("ML: active connection established\n");
480 519
			break;
......
494 533
			*/
495 534
			if (connectbuf[msg_h->remote_con_id]->status == CONNECT) {
496 535
				// change status of the connection
497
				connectbuf[msg_h->remote_con_id]->status = 2;
498
				// change pmtusize
499
				connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
536
				connectbuf[msg_h->remote_con_id]->status = READY;
537
				// change pmtusize: not needed. pmtu doesn't have to be symmetric
538
				//connectbuf[msg_h->remote_con_id]->pmtusize = con_msg->pmtu_size;
500 539

  
501 540
				if (receive_Connection_cb != NULL)
502 541
					(receive_Connection_cb) (msg_h->remote_con_id, NULL);
......
653 692
		/*
654 693
		* read the timeout data and set it
655 694
		*/
656
		recvdatabuf[recv_id]->timeout_value.tv_sec = recv_timeout.tv_sec;
657
		recvdatabuf[recv_id]->timeout_value.tv_usec = recv_timeout.tv_usec;
695
		recvdatabuf[recv_id]->timeout_value = recv_timeout;
658 696
		recvdatabuf[recv_id]->timeout_event = NULL;
659 697
		recvdatabuf[recv_id]->recvID = recv_id;
660 698
		recvdatabuf[recv_id]->starttime = time(NULL);
......
753 791
			if (!recvdatabuf[recv_id]->timeout_event) {
754 792
				//start time out
755 793
				//TODO make timeout at least a DEFINE
756
				struct timeval timeout = { 2, 0 };	//TODO: use some configurable timeout here
757 794
				recvdatabuf[recv_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &recv_timeout_cb, (void *) (long)recv_id);
758
				evtimer_add(recvdatabuf[recv_id]->timeout_event, &timeout);
795
				evtimer_add(recvdatabuf[recv_id]->timeout_event, &recv_timeout);
759 796
			}
760 797
		}
761 798
	}
......
764 801
//done
765 802
void pmtu_timeout_cb(int fd, short event, void *arg)
766 803
{
767
	debug("ML: pmtu timeout called\n");
768 804

  
769 805
	int con_id = (long) arg;
770 806
	pmtu new_pmtusize;
771 807
	struct timeval timeout;
772 808

  
809

  
773 810
	if(connectbuf[con_id] == NULL) {
774 811
		error("ML: pmtu timeout called on non existing con_id\n");
775 812
		return;
......
777 814

  
778 815
	if(connectbuf[con_id]->status == READY) {
779 816
		// nothing to do anymore
817
		event_del(connectbuf[con_id]->timeout_event);
818
		event_free(connectbuf[con_id]->timeout_event);
780 819
		return;
781 820
	}
782 821

  
822

  
783 823
	timeout = connectbuf[con_id]->timeout_value;
784 824

  
785 825
	if(connectbuf[con_id]->delay || connectbuf[con_id]->trials == MAX_TRIALS - 1) {
......
789 829
		timeout.tv_usec = fmod(delay, 1.0) * 1000000.0;
790 830
		if(connectbuf[con_id]->delay) {
791 831
			connectbuf[con_id]->delay = false;
792
			goto reschedule;
832
			reschedule_conn_msg(con_id);
793 833
		}
794 834
	}
795 835

  
796 836
	if(connectbuf[con_id]->trials == MAX_TRIALS) {
797 837
		// decrement the pmtu size
838
		struct timeval tout = PMTU_TIMEOUT;
798 839
		connectbuf[con_id]->pmtusize = pmtu_decrement(connectbuf[con_id]->pmtusize);
840
		connectbuf[con_id]->timeout_value = tout; 
799 841
		connectbuf[con_id]->trials = 0;
800 842
	}
801 843

  
......
819 861

  
820 862
	//retry with new pmtu size
821 863
	connectbuf[con_id]->trials++;
822
	send_conn_msg(con_id, connectbuf[con_id]->pmtusize, connectbuf[con_id]->status);
864
	resend_conn_msg(con_id);
865
}
823 866

  
824
reschedule:
825
	/* reschedule */
826
	event_base_once(base, -1, EV_TIMEOUT, pmtu_timeout_cb, (void *) (long)con_id, &timeout);
867

  
868
int schedule_pmtu_timeout(int con_id)
869
{
870
	if (! connectbuf[con_id]->timeout_event) {
871
		struct timeval tout = PMTU_TIMEOUT;
872
		connectbuf[con_id]->timeout_value = tout;
873
		connectbuf[con_id]->trials = 1;
874
		connectbuf[con_id]->timeout_event = event_new(base, -1, EV_TIMEOUT, &pmtu_timeout_cb, (void *) (long)con_id);
875
		evtimer_add(connectbuf[con_id]->timeout_event, &connectbuf[con_id]->timeout_value);
876
	}
827 877
}
828 878

  
829 879
/*
......
848 898
	}
849 899
}
850 900

  
901
// called when an ICMP pmtu error message (type 3, code 4) is received
851 902
void pmtu_error_cb_th(char *msg, int msglen)
852 903
{
853 904
	debug("ML: pmtu_error callback called msg_size: %d\n",msglen);
......
999 1050

  
1000 1051
	struct msg_header *msg_h;
1001 1052
	char msgbuf[MAX];
1053
	pmtu recvSize = MAX;
1002 1054
	char *bufptr = msgbuf;
1003 1055
	int ttl;
1004 1056
	struct sockaddr_in recv_addr;
1005
	pmtu recvSize = MAX;
1006 1057
	int msg_size;
1007 1058

  
1008 1059
	recvPacket(fd, msgbuf, &recvSize, &recv_addr, pmtu_error_cb_th, &ttl);
......
1421 1472
			connectbuf[con_id]->status = INVITE;
1422 1473
			connectbuf[con_id]->seqnr = 0;
1423 1474
			connectbuf[con_id]->internal_connect = !compare_external_address_socketIDs(external_socketID, &local_socketID);
1424
			/*
1425
			* timeout values for the pmtu discovery
1426
			*/
1427
			connectbuf[con_id]->timeout_value.tv_sec = 0;	//TODO: make this timeout configurable
1428
			connectbuf[con_id]->timeout_value.tv_usec = 250000;
1429 1475
			connectbuf[con_id]->connectionID = con_id;
1430 1476

  
1431 1477
			connectbuf[con_id]->connection_head = connectbuf[con_id]->connection_last = malloc(sizeof(struct receive_connection_cb_list));
......
1446 1492
	}
1447 1493

  
1448 1494
	// create and send a connection message
1449
	send_conn_msg(con_id, MAX, INVITE);
1450

  
1451
	struct event *ev;
1452
	ev = evtimer_new(base, pmtu_timeout_cb, (void *) (long)con_id);
1453
	event_add(ev, &connectbuf[con_id]->timeout_value);
1495
	send_conn_msg_with_pmtu_discovery(con_id, MAX, INVITE);
1454 1496

  
1455 1497
	return con_id;
1456 1498

  
......
1460 1502

  
1461 1503
	// remove it from the connection array
1462 1504
	if(connectbuf[connectionID]) {
1463
		if(connectbuf[connectionID]->ctrl_msg_buf)
1505
		if(connectbuf[connectionID]->ctrl_msg_buf) {
1464 1506
			free(connectbuf[connectionID]->ctrl_msg_buf);
1507
		}
1508
		// remove related events
1509
		if (connectbuf[connectionID]->timeout_event) {
1510
			event_del(connectbuf[connectionID]->timeout_event);
1511
			event_free(connectbuf[connectionID]->timeout_event);
1512
		}
1465 1513
		free(connectbuf[connectionID]);
1466 1514
		connectbuf[connectionID] = NULL;
1467 1515
	}

Also available in: Unified diff