Revision 5e9e29e0 ice.c

View differences:

ice.c
16 16
 
17 17
#include <sys/socket.h>
18 18
#include <netdb.h>
19
#include <stun/usages/bind.h>
19 20

  
20 21
#include "janus.h"
21 22
#include "debug.h"
......
38 39
}
39 40

  
40 41

  
42
/* RTP/RTCP port range */
43
uint16_t rtp_range_min = 0;
44
uint16_t rtp_range_max = 0;
45

  
46

  
41 47
/* libnice initialization */
42
gint janus_ice_init(gchar *stun_server, uint16_t stun_port) {
48
gint janus_ice_init(gchar *stun_server, uint16_t stun_port, uint16_t rtp_min_port, uint16_t rtp_max_port) {
43 49
	if(stun_server == NULL)
44 50
		return 0;	/* No initialization needed */
45 51
	if(stun_port == 0)
46 52
		stun_port = 3478;
53
	/*! \todo The RTP/RTCP port range configuration may be just a placeholder: for
54
	 * instance, libnice supports this since 0.1.0, but the 0.1.3 on Fedora fails
55
	 * when linking with an undefined reference to \c nice_agent_set_port_range 
56
	 * so this is checked by the install.sh script in advance. */
57
	rtp_range_min = rtp_min_port;
58
	rtp_range_max = rtp_max_port;
59
#ifndef HAVE_PORTRANGE
60
	JANUS_DEBUG("nice_agent_set_port_range unavailable, port range disabled\n");
61
#endif
47 62
	JANUS_PRINT("STUN server to use: %s:%u\n", stun_server, stun_port);
48 63
	/* Resolve address to get an IP */
49 64
	struct hostent *he = gethostbyname(stun_server);
......
63 78
	}
64 79
	janus_stun_port = stun_port;
65 80
	JANUS_PRINT("  >> %s:%u\n", janus_stun_server, janus_stun_port);
66
	return 0;
81
	/* Test the STUN server */
82
	StunAgent stun;
83
	stun_agent_init (&stun, STUN_ALL_KNOWN_ATTRIBUTES, STUN_COMPATIBILITY_RFC5389, 0);
84
	StunMessage msg;
85
	uint8_t buf[1500];
86
	size_t len = stun_usage_bind_create(&stun, &msg, buf, 1500);
87
	JANUS_PRINT("Testing STUN server: message is of %zu bytes\n", len);
88
	int fd = socket(AF_INET, SOCK_DGRAM, 0);
89
	int yes = 1;	/* For setsockopt() SO_REUSEADDR */
90
	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
91
	struct sockaddr_in address, remote;
92
	address.sin_family = AF_INET;
93
	address.sin_port = 0;
94
	address.sin_addr.s_addr = INADDR_ANY;
95
	remote.sin_family = AF_INET;
96
	remote.sin_port = htons(janus_stun_port);
97
	remote.sin_addr.s_addr = inet_addr(janus_stun_server);
98
	if(bind(fd, (struct sockaddr *)(&address), sizeof(struct sockaddr)) < 0) {
99
		JANUS_PRINT("Bind failed for STUN BINDING test\n");
100
		return -1;
101
	}
102
	int bytes = sendto(fd, buf, len, 0, (struct sockaddr*)&remote, sizeof(remote));
103
	if(bytes < 0) {
104
		JANUS_PRINT("Error sending STUN BINDING test\n");
105
		return -1;
106
	}
107
	JANUS_PRINT("  >> Sent %d bytes %s:%u, waiting for reply...\n", bytes, janus_stun_server, janus_stun_port);
108
	struct timeval timeout;
109
	fd_set readfds;
110
	FD_SET(fd, &readfds);
111
	timeout.tv_sec = 5;	/* FIXME Don't wait forever */
112
	timeout.tv_usec = 0;
113
	select(fd+1, &readfds, NULL, NULL, &timeout);
114
	if(!FD_ISSET(fd, &readfds)) {
115
		JANUS_PRINT("No response to our STUN BINDING test\n");
116
		return -1;
117
	}
118
	socklen_t addrlen = sizeof(remote);
119
	bytes = recvfrom(fd, buf, 1500, 0, (struct sockaddr*)&remote, &addrlen);
120
	JANUS_PRINT("  >> Got %d bytes...\n", bytes);
121
	if(stun_agent_validate (&stun, &msg, buf, bytes, NULL, NULL) < 0) {
122
		JANUS_PRINT("Failed to validate STUN BINDING response\n");
123
		return -1;
124
	}
125
	StunClass class = stun_message_get_class(&msg);
126
	StunMethod method = stun_message_get_method(&msg);
127
	if(class != STUN_RESPONSE || method != STUN_BINDING) {
128
		JANUS_PRINT("Unexpected STUN response: %d/%d\n", class, method);
129
		return -1;
130
	}
131
	StunMessageReturn ret = stun_message_find_xor_addr(&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, (struct sockaddr *)&address, &addrlen);
132
	JANUS_PRINT("  >> XOR-MAPPED-ADDRESS: %d\n", ret);
133
	if(ret == STUN_MESSAGE_RETURN_SUCCESS) {
134
		janus_set_public_ip(inet_ntoa(address.sin_addr));
135
		JANUS_PRINT("  >> Our public address is %s\n", janus_get_public_ip());
136
		return 0;
137
	}
138
	ret = stun_message_find_addr(&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS, (struct sockaddr *)&address, &addrlen);
139
	JANUS_PRINT("  >> MAPPED-ADDRESS: %d\n", ret);
140
	if(ret == STUN_MESSAGE_RETURN_SUCCESS) {
141
		janus_set_public_ip(inet_ntoa(address.sin_addr));
142
		JANUS_PRINT("  >> Our public address is %s\n", janus_get_public_ip());
143
		return 0;
144
	}
145
	return -1;
67 146
}
68 147

  
69 148
/* ICE stuff */
......
502 581
	handle->icectx = g_main_context_new();
503 582
	handle->iceloop = g_main_loop_new(handle->icectx, FALSE);
504 583
	handle->icethread = g_thread_new("ice thread", &janus_ice_thread, handle);
505
	handle->agent = nice_agent_new(handle->icectx, NICE_COMPATIBILITY_RFC5245);
584
	/* Note: NICE_COMPATIBILITY_RFC5245 is only available in more recent versions of libnice */
585
	handle->agent = nice_agent_new(handle->icectx, NICE_COMPATIBILITY_DRAFT19);
506 586
	/* Any STUN server to use? */
507 587
	if(janus_stun_server != NULL && janus_stun_port > 0) {
508 588
		g_object_set (G_OBJECT(handle->agent),
......
566 646
		audio_stream->rtp_component = audio_rtp;
567 647
		g_hash_table_insert(audio_stream->components, GUINT_TO_POINTER(2), audio_rtcp);
568 648
		audio_stream->rtcp_component = audio_rtcp;
649
#ifdef HAVE_PORTRANGE
650
		/* FIXME: libnice supports this since 0.1.0, but the 0.1.3 on Fedora fails with an undefined reference! */
651
		nice_agent_set_port_range(handle->agent, handle->audio_id, 1, rtp_range_min, rtp_range_max);
652
		nice_agent_set_port_range(handle->agent, handle->audio_id, 2, rtp_range_min, rtp_range_max);
653
#endif
569 654
		nice_agent_gather_candidates (handle->agent, handle->audio_id);
570 655
		nice_agent_attach_recv (handle->agent, handle->audio_id, 1, g_main_loop_get_context (handle->iceloop), janus_ice_cb_nice_recv, audio_rtp);
571 656
		nice_agent_attach_recv (handle->agent, handle->audio_id, 2, g_main_loop_get_context (handle->iceloop), janus_ice_cb_nice_recv, audio_rtcp);
......
611 696
		video_stream->rtp_component = video_rtp;
612 697
		g_hash_table_insert(video_stream->components, GUINT_TO_POINTER(2), video_rtcp);
613 698
		video_stream->rtcp_component = video_rtcp;
699
#ifdef HAVE_PORTRANGE
700
		/* FIXME: libnice supports this since 0.1.0, but the 0.1.3 on Fedora fails with an undefined reference! */
701
		nice_agent_set_port_range(handle->agent, handle->video_id, 1, rtp_range_min, rtp_range_max);
702
		nice_agent_set_port_range(handle->agent, handle->video_id, 2, rtp_range_min, rtp_range_max);
703
#endif
614 704
		nice_agent_gather_candidates (handle->agent, handle->video_id);
615 705
		nice_agent_attach_recv (handle->agent, handle->video_id, 1, g_main_loop_get_context (handle->iceloop), janus_ice_cb_nice_recv, video_rtp);
616 706
		nice_agent_attach_recv (handle->agent, handle->video_id, 2, g_main_loop_get_context (handle->iceloop), janus_ice_cb_nice_recv, video_rtcp);

Also available in: Unified diff