]> sjero.net Git - linphone/blob - coreapi/linphone_tunnel.cc
Update linphone tunnel API
[linphone] / coreapi / linphone_tunnel.cc
1 /***************************************************************************
2  *            linphone_tunnel.cc
3  *
4  *  Fri Dec 9, 2011
5  *  Copyright  2011  Belledonne Communications
6  *  Author: Guillaume Beraudo
7  *  Email: guillaume dot beraudo at linphone dot org
8  ****************************************************************************/
9
10 /*
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  */
25
26 #ifdef TUNNEL_ENABLED
27 #include "TunnelManager.hh"
28 #endif
29 #include "linphone_tunnel.h"
30 #include "linphonecore.h"
31 #include "private.h"
32 #include "lpconfig.h"
33
34 LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){
35         return lc->tunnel;
36 }
37
38 struct _LinphoneTunnelConfig {
39         char *host;
40         int port;
41         int remote_udp_mirror_port;
42         int delay;      
43 };
44
45 LinphoneTunnelConfig *linphone_tunnel_config_new() {
46         LinphoneTunnelConfig *ltc = ms_new0(LinphoneTunnelConfig,1);
47         ltc->remote_udp_mirror_port = 12345;
48         ltc->delay = 1000;
49         return ltc;
50 }
51
52 void linphone_tunnel_config_set_host(LinphoneTunnelConfig *tunnel, const char *host) {
53         if(tunnel->host != NULL) {
54                 ms_free(tunnel->host);
55                 tunnel->host = NULL;
56         }
57         if(host != NULL && strlen(host)) {
58                 tunnel->host = ms_strdup(host);
59         }
60 }
61
62 const char *linphone_tunnel_config_get_host(LinphoneTunnelConfig *tunnel) {
63         return tunnel->host;
64 }
65
66 void linphone_tunnel_config_set_port(LinphoneTunnelConfig *tunnel, int port) {
67         tunnel->port = port;
68 }
69
70 int linphone_tunnel_config_get_port(LinphoneTunnelConfig *tunnel) {
71         return tunnel->port;
72 }
73
74 void linphone_tunnel_config_set_remote_udp_mirror_port(LinphoneTunnelConfig *tunnel, int remote_udp_mirror_port) {
75         tunnel->remote_udp_mirror_port = remote_udp_mirror_port;
76 }
77
78 int linphone_tunnel_config_get_remote_udp_mirror_port(LinphoneTunnelConfig *tunnel) {
79         return tunnel->remote_udp_mirror_port;
80 }
81
82 void linphone_tunnel_config_set_delay(LinphoneTunnelConfig *tunnel, int delay) {
83         tunnel->delay = delay;
84 }
85
86 int linphone_tunnel_config_get_delay(LinphoneTunnelConfig *tunnel) {
87         return tunnel->delay;
88 }
89
90 void linphone_tunnel_config_destroy(LinphoneTunnelConfig *tunnel) {
91         if(tunnel->host != NULL) {
92                 ms_free(tunnel->host);
93         }
94         ms_free(tunnel);
95 }
96
97 #ifdef TUNNEL_ENABLED
98
99 struct _LinphoneTunnel {
100         belledonnecomm::TunnelManager *manager;
101         MSList *config_list;
102 };
103
104 extern "C" LinphoneTunnel* linphone_core_tunnel_new(LinphoneCore *lc){
105         LinphoneTunnel* tunnel = ms_new0(LinphoneTunnel, 1);
106         tunnel->manager = new belledonnecomm::TunnelManager(lc);
107         return tunnel;
108 }
109
110 static inline belledonnecomm::TunnelManager *bcTunnel(LinphoneTunnel *tunnel){
111         return tunnel->manager;
112 }
113
114 static inline _LpConfig *config(LinphoneTunnel *tunnel){
115         return tunnel->manager->getLinphoneCore()->config;
116 }
117
118 void linphone_tunnel_destroy(LinphoneTunnel *tunnel){
119         delete tunnel->manager;
120         ms_free(tunnel);
121 }
122
123 static char *linphone_tunnel_config_to_string(const LinphoneTunnelConfig *tunnel_config) {
124         char *str = NULL;
125         if(tunnel_config->remote_udp_mirror_port != -1) {
126                 str = ms_strdup_printf("%s:%d:%d:%d", 
127                         tunnel_config->host,
128                         tunnel_config->port,
129                         tunnel_config->remote_udp_mirror_port,
130                         tunnel_config->delay);
131         } else {
132                 str = ms_strdup_printf("%s:%d",
133                         tunnel_config->host,
134                         tunnel_config->port);
135         }
136         return str;
137 }
138
139 static LinphoneTunnelConfig *linphone_tunnel_config_from_string(const char *str) {
140         LinphoneTunnelConfig *tunnel_config = NULL;
141         char * dstr = ms_strdup(str);
142         const char *host = NULL;
143         int port = -1;
144         int remote_udp_mirror_port = -1;
145         int delay = -1;
146         int pos = 0;
147         char *pch;
148         pch = strtok(dstr, ":");
149         while(pch != NULL) {
150                 switch(pos) {
151                 case 0:
152                         host = pch;
153                         break;
154                 case 1:
155                         port = atoi(pch);
156                         break;
157                 case 2:
158                         remote_udp_mirror_port = atoi(pch);
159                         break;
160                 case 3:
161                         delay = atoi(pch);
162                         break;  
163                 default:
164                         // Abort
165                         pos = 0;
166                         break;
167                         
168                 }
169                 ++pos;
170                 pch = strtok(NULL, ":");
171         }
172         if(pos >= 2) {
173                 tunnel_config = linphone_tunnel_config_new();
174                 linphone_tunnel_config_set_host(tunnel_config, host);
175                 linphone_tunnel_config_set_port(tunnel_config, port);
176         }
177         if(pos >= 3) {
178                 linphone_tunnel_config_set_remote_udp_mirror_port(tunnel_config, remote_udp_mirror_port);
179         }
180         if(pos == 4) {
181                 linphone_tunnel_config_set_delay(tunnel_config, delay);
182         }
183         ms_free(dstr);  
184         return tunnel_config;
185 }
186
187
188 static void linphone_tunnel_save_config(LinphoneTunnel *tunnel) {
189         MSList *elem = tunnel->config_list;
190         char *tmp = NULL, *old_tmp = NULL, *tc_str = NULL;
191         while(elem != NULL) {
192                 LinphoneTunnelConfig *tunnel_config = (LinphoneTunnelConfig *)elem->data;
193                 tc_str = linphone_tunnel_config_to_string(tunnel_config);
194                 if(tmp != NULL) {
195                         old_tmp = tmp;
196                         tmp = ms_strdup_printf("%s %s", old_tmp, tc_str);
197                         ms_free(old_tmp);
198                         ms_free(tc_str);
199                 } else {
200                         tmp = tc_str;
201                 }
202                 elem = elem->next;
203         }
204         lp_config_set_string(config(tunnel), "tunnel", "server_addresses", tmp);
205         if(tmp != NULL) {
206                 ms_free(tmp);
207         }
208 }
209
210
211 static void linphone_tunnel_add_server_intern(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config) {
212         if(tunnel_config->remote_udp_mirror_port == -1) {
213                 bcTunnel(tunnel)->addServer(tunnel_config->host, tunnel_config->port);
214         } else {
215                 bcTunnel(tunnel)->addServer(tunnel_config->host, tunnel_config->port, 
216                         tunnel_config->remote_udp_mirror_port, tunnel_config->delay);
217         }
218         tunnel->config_list = ms_list_append(tunnel->config_list, tunnel_config);
219 }
220
221
222 static void linphone_tunnel_load_config(LinphoneTunnel *tunnel){
223         const char * confaddress = lp_config_get_string(config(tunnel), "tunnel", "server_addresses", NULL);
224         char *tmp;
225         const char *it;
226         LinphoneTunnelConfig *tunnel_config;
227         int adv;
228         if(confaddress != NULL) {
229                 tmp = ms_strdup(confaddress);
230                 it = confaddress;
231                 while(confaddress[0] != '\0') {
232                         int ret = sscanf(it,"%s%n", tmp, &adv);
233                         if (ret >= 1){
234                                 it += adv;
235                                 tunnel_config = linphone_tunnel_config_from_string(tmp);
236                                 if(tunnel_config != NULL) {
237                                         linphone_tunnel_add_server_intern(tunnel, tunnel_config);
238                                 } else {
239                                         ms_error("Tunnel server address incorrectly specified from config file: %s", tmp);
240                                 }
241                         } else break;
242                 }
243                 ms_free(tmp);
244         }
245 }
246
247 static void linphone_tunnel_refresh_config(LinphoneTunnel *tunnel) {
248         MSList *old_list = tunnel->config_list;
249         tunnel->config_list = NULL;
250         bcTunnel(tunnel)->cleanServers();
251         while(old_list != NULL) {
252                 LinphoneTunnelConfig *tunnel_config = (LinphoneTunnelConfig *)old_list->data;
253                 linphone_tunnel_add_server_intern(tunnel, tunnel_config);
254                 old_list = old_list->next;
255         }
256 }
257
258 void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config) {
259         linphone_tunnel_add_server_intern(tunnel, tunnel_config);
260         linphone_tunnel_save_config(tunnel);
261 }
262
263 void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config) {
264         MSList *elem = ms_list_find(tunnel->config_list, tunnel_config);
265         if(elem != NULL) {
266                 tunnel->config_list = ms_list_remove(tunnel->config_list, tunnel_config);
267                 linphone_tunnel_config_destroy(tunnel_config);          
268                 linphone_tunnel_refresh_config(tunnel);
269                 linphone_tunnel_save_config(tunnel);
270         }       
271 }
272
273 const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){
274         return tunnel->config_list;
275 }
276
277 void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){
278         bcTunnel(tunnel)->cleanServers();
279         
280         /* Free the list */
281         ms_list_for_each(tunnel->config_list, (void (*)(void *))linphone_tunnel_config_destroy); 
282         tunnel->config_list = ms_list_free(tunnel->config_list);
283         
284         linphone_tunnel_save_config(tunnel);
285 }
286
287 void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){
288         lp_config_set_int(config(tunnel),"tunnel","enabled",(int)enabled);
289         bcTunnel(tunnel)->enable(enabled);
290 }
291
292 bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){
293         return bcTunnel(tunnel)->isEnabled();
294 }
295
296 static OrtpLogFunc tunnelOrtpLogHandler=NULL;
297
298 /*
299 #define TUNNEL_DEBUG (1)
300 #define TUNNEL_INFO  (1<<1)
301 #define TUNNEL_NOTICE (1<<2)
302 #define TUNNEL_WARN  (1<<3)
303 #define TUNNEL_ERROR (1<<4)
304 #define TUNNEL_ALERT (1<<5)
305 #define TUNNEL_FATAL (1<<6)
306 */
307
308 static void tunnelLogHandler(int level, const char *fmt, va_list l){
309         if (tunnelOrtpLogHandler){
310                 OrtpLogLevel ortp_level=ORTP_DEBUG;
311                 switch(level){
312                         case TUNNEL_DEBUG:
313                                 ortp_level=ORTP_DEBUG;
314                         break;
315                         case TUNNEL_INFO:
316                                 ortp_level=ORTP_MESSAGE;
317                         break;
318                         case TUNNEL_NOTICE:
319                                 ortp_level=ORTP_MESSAGE;
320                         break;
321                         case TUNNEL_WARN:
322                                 ortp_level=ORTP_WARNING;
323                         break;
324                         case TUNNEL_ERROR:
325                                 ortp_level=ORTP_ERROR;
326                         break;
327                         case TUNNEL_ALERT:
328                                 ortp_level=ORTP_ERROR;
329                         break;
330                         case TUNNEL_FATAL:
331                                 ortp_level=ORTP_FATAL;
332                         break;
333                         default:
334                                 ms_fatal("Unexepcted tunnel log %i: %s",level,fmt);
335                         break;
336                 }
337                 tunnelOrtpLogHandler(ortp_level,fmt,l);
338         }
339 }
340
341 void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, OrtpLogFunc logHandler){
342         tunnelOrtpLogHandler=logHandler;
343         bcTunnel(tunnel)->enableLogs(enabled, tunnelLogHandler);
344 }
345
346 void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel *tunnel, const char* username,const char* passwd){
347         bcTunnel(tunnel)->setHttpProxyAuthInfo(username, passwd);
348 }
349
350 void linphone_tunnel_set_http_proxy(LinphoneTunnel*tunnel, const char *host, int port, const char* username,const char* passwd){
351         bcTunnel(tunnel)->setHttpProxy(host, port, username, passwd);
352         lp_config_set_string(config(tunnel),"tunnel","http_proxy_host",host);
353         lp_config_set_int(config(tunnel),"tunnel","http_proxy_port",port);
354         lp_config_set_string(config(tunnel),"tunnel","http_proxy_username",username);
355         lp_config_set_string(config(tunnel),"tunnel","http_proxy_password",passwd);
356 }
357
358 void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int *port, const char **username, const char **passwd){
359         if (host) *host=lp_config_get_string(config(tunnel),"tunnel","http_proxy_host",NULL);
360         if (port) *port=lp_config_get_int(config(tunnel),"tunnel","http_proxy_port",0);
361         if (username) *username=lp_config_get_string(config(tunnel),"tunnel","http_proxy_username",NULL);
362         if (passwd) *passwd=lp_config_get_string(config(tunnel),"tunnel","http_proxy_password",NULL);
363 }
364
365 void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){
366         bcTunnel(tunnel)->reconnect();
367 }
368
369 void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){
370         bcTunnel(tunnel)->autoDetect();
371 }
372
373 static void my_ortp_logv(OrtpLogLevel level, const char *fmt, va_list args){
374         ortp_logv(level,fmt,args);
375 }
376
377 /**
378  * Startup tunnel using configuration.
379  * Called internally from linphonecore at startup.
380  */
381 void linphone_tunnel_configure(LinphoneTunnel *tunnel){
382         bool_t enabled=(bool_t)lp_config_get_int(config(tunnel),"tunnel","enabled",FALSE);
383         linphone_tunnel_enable_logs_with_handler(tunnel,TRUE,my_ortp_logv);
384         linphone_tunnel_load_config(tunnel);
385         linphone_tunnel_enable(tunnel, enabled);
386 }
387
388 #else
389
390 /*stubs to avoid to have #ifdef TUNNEL_ENABLED in upper layers*/
391
392 void linphone_tunnel_destroy(LinphoneTunnel *tunnel){
393 }
394
395
396 void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config){
397 }
398
399 void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config){
400 }
401
402 const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){
403         return NULL;
404 }
405
406 void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){
407 }
408
409 void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){
410 }
411
412 bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){
413         return FALSE;
414 }
415
416
417 void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, OrtpLogFunc logHandler){
418 }
419
420 void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel *tunnel, const char* username,const char* passwd){
421 }
422
423 void linphone_tunnel_set_http_proxy(LinphoneTunnel*tunnel, const char *host, int port, const char* username,const char* passwd){
424 }
425
426 void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int *port, const char **username, const char **passwd){
427 }
428
429 void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){
430 }
431
432 void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){
433 }
434
435 void linphone_tunnel_configure(LinphoneTunnel *tunnel){
436 }
437
438
439 #endif
440
441
442
443
444