1 /*
2 liblinphone_tester - liblinphone test suite
3 Copyright (C) 2013 Belledonne Communications SARL
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include "linphone/core.h"
22 #include "linphone/lpconfig.h"
23 #include "private.h"
24 #include "liblinphone_tester.h"
25
26 /* Retrieve the public IP from a given hostname */
get_ip_from_hostname(const char * tunnel_hostname,char * ip,size_t ip_size)27 int get_ip_from_hostname(const char * tunnel_hostname, char *ip, size_t ip_size){
28 struct addrinfo hints;
29 struct addrinfo *res = NULL;
30 int err;
31 memset(&hints, 0, sizeof(hints));
32 hints.ai_family = AF_UNSPEC;
33 hints.ai_socktype = SOCK_STREAM;
34 if ((err = getaddrinfo(tunnel_hostname, NULL, &hints, &res))){
35 ms_error("error while retrieving IP from %s: %s", tunnel_hostname, gai_strerror(err));
36 return err;
37 }
38
39 bctbx_addrinfo_to_ip_address(res, ip, ip_size, NULL);
40 freeaddrinfo(res);
41 return err;
42 }
get_public_contact_ip(LinphoneCore * lc)43 static char* get_public_contact_ip(LinphoneCore* lc) {
44 const LinphoneAddress * contact = linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(lc));
45 BC_ASSERT_PTR_NOT_NULL(contact);
46 return ms_strdup(linphone_address_get_domain(contact));
47 }
48
49
call_with_tunnel_base(LinphoneTunnelMode tunnel_mode,bool_t with_sip,LinphoneMediaEncryption encryption,bool_t with_video_and_ice,bool_t dual_socket)50 static void call_with_tunnel_base(LinphoneTunnelMode tunnel_mode, bool_t with_sip, LinphoneMediaEncryption encryption, bool_t with_video_and_ice, bool_t dual_socket) {
51 if (linphone_core_tunnel_available()){
52 LinphoneCoreManager *pauline = linphone_core_manager_new( "pauline_rc");
53 LinphoneCoreManager *marie = linphone_core_manager_new( "marie_rc");
54 LinphoneCall *pauline_call, *marie_call;
55 LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(pauline->lc);
56 LinphoneAddress *server_addr = linphone_address_new(linphone_proxy_config_get_server_addr(proxy));
57 LinphoneAddress *route = linphone_address_new(linphone_proxy_config_get_route(proxy));
58 char tunnel_ip[64];
59 char *public_ip, *public_ip2=NULL;
60 BC_ASSERT_FALSE(get_ip_from_hostname("tunnel.linphone.org",tunnel_ip,sizeof(tunnel_ip)));
61
62 BC_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneRegistrationOk,1));
63 public_ip = get_public_contact_ip(pauline->lc);
64 BC_ASSERT_STRING_NOT_EQUAL(public_ip, tunnel_ip);
65
66 linphone_core_set_media_encryption(pauline->lc, encryption);
67
68 if (with_video_and_ice){
69 /*we want to test that tunnel is able to work with long SIP message, above mtu.
70 * Enable ICE and many codec to make the SIP message bigger*/
71 linphone_core_set_firewall_policy(marie->lc, LinphonePolicyUseIce);
72 linphone_core_set_firewall_policy(pauline->lc, LinphonePolicyUseIce);
73 linphone_core_enable_payload_type(pauline->lc,
74 linphone_core_find_payload_type(pauline->lc, "speex", 32000, 1), TRUE);
75 linphone_core_enable_payload_type(pauline->lc,
76 linphone_core_find_payload_type(pauline->lc, "speex", 16000, 1), TRUE);
77 linphone_core_enable_payload_type(pauline->lc,
78 linphone_core_find_payload_type(pauline->lc, "G722", 8000, 1), TRUE);
79 }
80
81 if (tunnel_mode != LinphoneTunnelModeDisable){
82 LinphoneTunnel *tunnel = linphone_core_get_tunnel(pauline->lc);
83 LinphoneTunnelConfig *config = linphone_tunnel_config_new();
84
85 linphone_tunnel_config_set_host(config, "tunnel.linphone.org");
86 linphone_tunnel_config_set_port(config, 443);
87 if (!dual_socket) {
88 linphone_tunnel_config_set_host(config, "tunnel.linphone.org");
89 linphone_tunnel_config_set_port(config, 443);
90 linphone_tunnel_config_set_remote_udp_mirror_port(config, 12345);
91 } else {
92 linphone_tunnel_config_set_host(config, "94.23.19.176");
93 linphone_tunnel_config_set_port(config, 4443);
94 linphone_tunnel_config_set_host2(config, "188.165.40.171");
95 linphone_tunnel_config_set_port2(config, 4443);
96 linphone_tunnel_config_set_remote_udp_mirror_port(config, -1);
97 linphone_tunnel_enable_dual_mode(tunnel, TRUE);
98 }
99 linphone_tunnel_add_server(tunnel, config);
100 linphone_tunnel_set_mode(tunnel, tunnel_mode);
101 linphone_tunnel_enable_sip(tunnel, with_sip);
102 linphone_tunnel_config_unref(config);
103
104 /*
105 * Enabling the tunnel with sip cause another REGISTER to be made.
106 * In automatic mode, the udp test should conclude (assuming we have a normal network), that no
107 * tunnel is needed. Thus the number of registrations should stay to 1.
108 * The library is missing a notification of "tunnel connectivity test finished" to enable the
109 * full testing of the automatic mode.
110 */
111
112 if (tunnel_mode == LinphoneTunnelModeEnable && with_sip) {
113 BC_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneRegistrationOk,2));
114 /* Ensure that we did use the tunnel. If so, we should see contact changed from:
115 Contact: <sip:pauline@192.168.0.201>;.[...]
116 To:
117 Contact: <sip:pauline@91.121.209.194:43867>;[....] (91.121.209.194 must be tunnel.liphone.org)
118 */
119 ms_free(public_ip);
120 public_ip = get_public_contact_ip(pauline->lc);
121 if (!dual_socket) {
122 BC_ASSERT_STRING_EQUAL(public_ip, tunnel_ip);
123 } else {
124 BC_ASSERT_STRING_EQUAL(public_ip, "94.23.19.176");
125 }
126 } else {
127 public_ip2 = get_public_contact_ip(pauline->lc);
128 BC_ASSERT_STRING_EQUAL(public_ip, public_ip2);
129 }
130 }
131
132 BC_ASSERT_TRUE(call(pauline,marie));
133 pauline_call=linphone_core_get_current_call(pauline->lc);
134 BC_ASSERT_PTR_NOT_NULL(pauline_call);
135 if (pauline_call!=NULL){
136 BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(pauline_call)),
137 encryption, int, "%d");
138 }
139 if (tunnel_mode == LinphoneTunnelModeEnable && with_sip){
140 /* make sure the call from pauline arrived from the tunnel by checking the contact address*/
141 marie_call = linphone_core_get_current_call(marie->lc);
142 BC_ASSERT_PTR_NOT_NULL(marie_call);
143 if (marie_call){
144 const char *remote_contact = linphone_call_get_remote_contact(marie_call);
145 BC_ASSERT_PTR_NOT_NULL(remote_contact);
146 if (remote_contact){
147 LinphoneAddress *tmp = linphone_address_new(remote_contact);
148 BC_ASSERT_PTR_NOT_NULL(tmp);
149 if (tmp){
150 if (!dual_socket) {
151 BC_ASSERT_STRING_EQUAL(linphone_address_get_domain(tmp), tunnel_ip);
152 } else {
153 BC_ASSERT_STRING_EQUAL(linphone_address_get_domain(tmp), "94.23.19.176");
154 }
155 linphone_address_unref(tmp);
156 }
157 }
158 }
159 }
160 #ifdef VIDEO_ENABLED
161 if (with_video_and_ice){
162 BC_ASSERT_TRUE(request_video(pauline, marie, TRUE));
163 }
164 #endif
165 end_call(pauline,marie);
166
167 ms_free(public_ip);
168 if(public_ip2 != NULL) ms_free(public_ip2);
169 linphone_address_unref(server_addr);
170 linphone_address_unref(route);
171 linphone_core_manager_destroy(pauline);
172 linphone_core_manager_destroy(marie);
173 }else{
174 ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__);
175 }
176 }
177
178
call_with_tunnel(void)179 static void call_with_tunnel(void) {
180 call_with_tunnel_base(LinphoneTunnelModeEnable, TRUE, LinphoneMediaEncryptionNone, FALSE, FALSE);
181 }
182
call_with_tunnel_srtp(void)183 static void call_with_tunnel_srtp(void) {
184 call_with_tunnel_base(LinphoneTunnelModeEnable, TRUE, LinphoneMediaEncryptionSRTP, FALSE, FALSE);
185 }
186
call_with_tunnel_without_sip(void)187 static void call_with_tunnel_without_sip(void) {
188 call_with_tunnel_base(LinphoneTunnelModeEnable, FALSE, LinphoneMediaEncryptionNone, FALSE, FALSE);
189 }
190
call_with_tunnel_auto(void)191 static void call_with_tunnel_auto(void) {
192 call_with_tunnel_base(LinphoneTunnelModeAuto, TRUE, LinphoneMediaEncryptionNone, FALSE, FALSE);
193 }
194
call_with_tunnel_auto_without_sip_with_srtp(void)195 static void call_with_tunnel_auto_without_sip_with_srtp(void) {
196 call_with_tunnel_base(LinphoneTunnelModeAuto, FALSE, LinphoneMediaEncryptionSRTP, FALSE, FALSE);
197 }
198
199 #ifdef VIDEO_ENABLED
200
full_tunnel_video_ice_call(void)201 static void full_tunnel_video_ice_call(void){
202 if (linphone_core_tunnel_available()){
203 call_with_tunnel_base(LinphoneTunnelModeEnable, TRUE, LinphoneMediaEncryptionNone, TRUE, FALSE);
204 }else
205 ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__);
206 }
207
tunnel_srtp_video_ice_call(void)208 static void tunnel_srtp_video_ice_call(void) {
209 if (linphone_core_tunnel_available())
210 call_base(LinphoneMediaEncryptionSRTP,TRUE,FALSE,LinphonePolicyUseIce,TRUE);
211 else
212 ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__);
213 }
tunnel_zrtp_video_ice_call(void)214 static void tunnel_zrtp_video_ice_call(void) {
215 if (linphone_core_tunnel_available())
216 call_base(LinphoneMediaEncryptionZRTP,TRUE,FALSE,LinphonePolicyUseIce,TRUE);
217 else
218 ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__);
219 }
220
tunnel_dtls_video_ice_call(void)221 static void tunnel_dtls_video_ice_call(void) {
222 if (linphone_core_tunnel_available())
223 call_base(LinphoneMediaEncryptionDTLS,TRUE,FALSE,LinphonePolicyUseIce,TRUE);
224 else
225 ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__);
226 }
227
tunnel_video_ice_call(void)228 static void tunnel_video_ice_call(void) {
229 if (linphone_core_tunnel_available())
230 call_base(LinphoneMediaEncryptionNone,TRUE,FALSE,LinphonePolicyUseIce,TRUE);
231 else
232 ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__);
233 }
234 #endif
235
tunnel_srtp_ice_call(void)236 static void tunnel_srtp_ice_call(void) {
237 if (linphone_core_tunnel_available())
238 call_base(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyUseIce,TRUE);
239 else
240 ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__);
241 }
242
tunnel_zrtp_ice_call(void)243 static void tunnel_zrtp_ice_call(void) {
244 if (linphone_core_tunnel_available())
245 call_base(LinphoneMediaEncryptionZRTP,FALSE,FALSE,LinphonePolicyUseIce,TRUE);
246 else
247 ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__);
248 }
249
tunnel_ice_call(void)250 static void tunnel_ice_call(void) {
251 if (linphone_core_tunnel_available())
252 call_base(LinphoneMediaEncryptionNone,FALSE,FALSE,LinphonePolicyUseIce,TRUE);
253 else
254 ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__);
255 }
256
register_on_second_tunnel(void)257 static void register_on_second_tunnel(void) {
258 if (linphone_core_tunnel_available()) {
259 LinphoneCoreManager *pauline = linphone_core_manager_new( "pauline_rc");
260 LinphoneTunnel *tunnel = linphone_core_get_tunnel(pauline->lc);
261 LinphoneTunnelConfig *config1 = linphone_tunnel_config_new();
262 LinphoneTunnelConfig *config2 = linphone_tunnel_config_new();
263 char tunnel_ip[64];
264 char* public_ip;
265
266 BC_ASSERT_FALSE(get_ip_from_hostname("tunnel.linphone.org",tunnel_ip,sizeof(tunnel_ip)));
267 linphone_tunnel_simulate_udp_loss(tunnel, TRUE);
268
269 // add a first tunnel config with an invalid port
270 linphone_tunnel_config_set_host(config1, "sip3.linphone.org");
271 linphone_tunnel_config_set_port(config1, 4141);
272 linphone_tunnel_config_set_remote_udp_mirror_port(config1, 54321);
273 linphone_tunnel_add_server(tunnel, config1);
274
275 // then a proper server
276 linphone_tunnel_config_set_host(config2, "tunnel.linphone.org");
277 linphone_tunnel_config_set_port(config2, 443);
278 linphone_tunnel_config_set_remote_udp_mirror_port(config2, 12345);
279 linphone_tunnel_add_server(tunnel, config2);
280
281 linphone_tunnel_set_mode(tunnel, LinphoneTunnelModeAuto);
282 linphone_tunnel_enable_sip(tunnel, TRUE);
283
284 reset_counters(&pauline->stat);
285
286 linphone_core_refresh_registers(pauline->lc);
287 // we should expect 2 registers: since tunnel autodetection takes several seconds, a first
288 // register will be made, then tunnel will be configured and another register will be fired up
289 BC_ASSERT_TRUE(wait_for(pauline->lc, NULL, &pauline->stat.number_of_LinphoneRegistrationOk,2));
290
291 public_ip = get_public_contact_ip(pauline->lc);
292 BC_ASSERT_STRING_EQUAL(public_ip, tunnel_ip);
293 ms_free(public_ip);
294
295 linphone_tunnel_config_unref(config1);
296 linphone_tunnel_config_unref(config2);
297 linphone_core_manager_destroy(pauline);
298 } else {
299 ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__);
300 }
301 }
302
dual_socket_mode(void)303 static void dual_socket_mode(void) {
304 if (linphone_core_tunnel_available())
305 call_with_tunnel_base(LinphoneTunnelModeEnable, FALSE, LinphoneMediaEncryptionNone, FALSE, TRUE);
306 else
307 ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__);
308 }
309
dual_socket_mode_with_sip(void)310 static void dual_socket_mode_with_sip(void) {
311 if (linphone_core_tunnel_available())
312 call_with_tunnel_base(LinphoneTunnelModeEnable, TRUE, LinphoneMediaEncryptionNone, FALSE, TRUE);
313 else
314 ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__);
315 }
316
317 test_t tunnel_tests[] = {
318 TEST_NO_TAG("Simple", call_with_tunnel),
319 TEST_NO_TAG("With SRTP", call_with_tunnel_srtp),
320 TEST_NO_TAG("Without SIP", call_with_tunnel_without_sip),
321 TEST_NO_TAG("In automatic mode", call_with_tunnel_auto),
322 TEST_NO_TAG("In automatic mode with SRTP without SIP", call_with_tunnel_auto_without_sip_with_srtp),
323 TEST_NO_TAG("Ice call", tunnel_ice_call),
324 TEST_NO_TAG("SRTP ice call", tunnel_srtp_ice_call),
325 TEST_NO_TAG("ZRTP ice call", tunnel_zrtp_ice_call),
326 #ifdef VIDEO_ENABLED
327 TEST_NO_TAG("Ice video call", tunnel_video_ice_call),
328 TEST_NO_TAG("With SIP - ice video call", full_tunnel_video_ice_call),
329 TEST_NO_TAG("SRTP ice video call", tunnel_srtp_video_ice_call),
330 TEST_NO_TAG("DTLS ice video call", tunnel_dtls_video_ice_call),
331 TEST_NO_TAG("ZRTP ice video call", tunnel_zrtp_video_ice_call),
332 #endif
333 TEST_NO_TAG("Register on second tunnel", register_on_second_tunnel),
334 TEST_NO_TAG("Dual socket mode", dual_socket_mode),
335 TEST_NO_TAG("Dual socket mode with SIP", dual_socket_mode_with_sip),
336 };
337
338 test_suite_t tunnel_test_suite = {"Tunnel", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
339 sizeof(tunnel_tests) / sizeof(tunnel_tests[0]), tunnel_tests};
340