From: Yann Diorcet Date: Tue, 15 Jan 2013 11:47:49 +0000 (+0100) Subject: Update linphone tunnel API X-Git-Url: http://sjero.net/git/?p=linphone;a=commitdiff_plain;h=d6b9b813eba377be8810033c83e2b735933389c9 Update linphone tunnel API --- diff --git a/coreapi/linphone_tunnel.cc b/coreapi/linphone_tunnel.cc index f5a5d361..c76441f5 100644 --- a/coreapi/linphone_tunnel.cc +++ b/coreapi/linphone_tunnel.cc @@ -31,60 +31,257 @@ #include "private.h" #include "lpconfig.h" - LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){ return lc->tunnel; } -#ifdef TUNNEL_ENABLED +struct _LinphoneTunnelConfig { + char *host; + int port; + int remote_udp_mirror_port; + int delay; +}; -static inline belledonnecomm::TunnelManager *bcTunnel(LinphoneTunnel *tunnel){ - return (belledonnecomm::TunnelManager *)tunnel; +LinphoneTunnelConfig *linphone_tunnel_config_new() { + LinphoneTunnelConfig *ltc = ms_new0(LinphoneTunnelConfig,1); + ltc->remote_udp_mirror_port = 12345; + ltc->delay = 1000; + return ltc; } -static inline _LpConfig *config(LinphoneTunnel *tunnel){ - return ((belledonnecomm::TunnelManager *)tunnel)->getLinphoneCore()->config; +void linphone_tunnel_config_set_host(LinphoneTunnelConfig *tunnel, const char *host) { + if(tunnel->host != NULL) { + ms_free(tunnel->host); + tunnel->host = NULL; + } + if(host != NULL && strlen(host)) { + tunnel->host = ms_strdup(host); + } +} + +const char *linphone_tunnel_config_get_host(LinphoneTunnelConfig *tunnel) { + return tunnel->host; +} + +void linphone_tunnel_config_set_port(LinphoneTunnelConfig *tunnel, int port) { + tunnel->port = port; +} + +int linphone_tunnel_config_get_port(LinphoneTunnelConfig *tunnel) { + return tunnel->port; +} + +void linphone_tunnel_config_set_remote_udp_mirror_port(LinphoneTunnelConfig *tunnel, int remote_udp_mirror_port) { + tunnel->remote_udp_mirror_port = remote_udp_mirror_port; +} + +int linphone_tunnel_config_get_remote_udp_mirror_port(LinphoneTunnelConfig *tunnel) { + return tunnel->remote_udp_mirror_port; } +void linphone_tunnel_config_set_delay(LinphoneTunnelConfig *tunnel, int delay) { + tunnel->delay = delay; +} + +int linphone_tunnel_config_get_delay(LinphoneTunnelConfig *tunnel) { + return tunnel->delay; +} + +void linphone_tunnel_config_destroy(LinphoneTunnelConfig *tunnel) { + if(tunnel->host != NULL) { + ms_free(tunnel->host); + } + ms_free(tunnel); +} + +#ifdef TUNNEL_ENABLED + +struct _LinphoneTunnel { + belledonnecomm::TunnelManager *manager; + MSList *config_list; +}; + extern "C" LinphoneTunnel* linphone_core_tunnel_new(LinphoneCore *lc){ - LinphoneTunnel* tunnel= (LinphoneTunnel*) new belledonnecomm::TunnelManager(lc); + LinphoneTunnel* tunnel = ms_new0(LinphoneTunnel, 1); + tunnel->manager = new belledonnecomm::TunnelManager(lc); return tunnel; } +static inline belledonnecomm::TunnelManager *bcTunnel(LinphoneTunnel *tunnel){ + return tunnel->manager; +} + +static inline _LpConfig *config(LinphoneTunnel *tunnel){ + return tunnel->manager->getLinphoneCore()->config; +} + void linphone_tunnel_destroy(LinphoneTunnel *tunnel){ - delete bcTunnel(tunnel); + delete tunnel->manager; + ms_free(tunnel); +} + +static char *linphone_tunnel_config_to_string(const LinphoneTunnelConfig *tunnel_config) { + char *str = NULL; + if(tunnel_config->remote_udp_mirror_port != -1) { + str = ms_strdup_printf("%s:%d:%d:%d", + tunnel_config->host, + tunnel_config->port, + tunnel_config->remote_udp_mirror_port, + tunnel_config->delay); + } else { + str = ms_strdup_printf("%s:%d", + tunnel_config->host, + tunnel_config->port); + } + return str; +} + +static LinphoneTunnelConfig *linphone_tunnel_config_from_string(const char *str) { + LinphoneTunnelConfig *tunnel_config = NULL; + char * dstr = ms_strdup(str); + const char *host = NULL; + int port = -1; + int remote_udp_mirror_port = -1; + int delay = -1; + int pos = 0; + char *pch; + pch = strtok(dstr, ":"); + while(pch != NULL) { + switch(pos) { + case 0: + host = pch; + break; + case 1: + port = atoi(pch); + break; + case 2: + remote_udp_mirror_port = atoi(pch); + break; + case 3: + delay = atoi(pch); + break; + default: + // Abort + pos = 0; + break; + + } + ++pos; + pch = strtok(NULL, ":"); + } + if(pos >= 2) { + tunnel_config = linphone_tunnel_config_new(); + linphone_tunnel_config_set_host(tunnel_config, host); + linphone_tunnel_config_set_port(tunnel_config, port); + } + if(pos >= 3) { + linphone_tunnel_config_set_remote_udp_mirror_port(tunnel_config, remote_udp_mirror_port); + } + if(pos == 4) { + linphone_tunnel_config_set_delay(tunnel_config, delay); + } + ms_free(dstr); + return tunnel_config; +} + + +static void linphone_tunnel_save_config(LinphoneTunnel *tunnel) { + MSList *elem = tunnel->config_list; + char *tmp = NULL, *old_tmp = NULL, *tc_str = NULL; + while(elem != NULL) { + LinphoneTunnelConfig *tunnel_config = (LinphoneTunnelConfig *)elem->data; + tc_str = linphone_tunnel_config_to_string(tunnel_config); + if(tmp != NULL) { + old_tmp = tmp; + tmp = ms_strdup_printf("%s %s", old_tmp, tc_str); + ms_free(old_tmp); + ms_free(tc_str); + } else { + tmp = tc_str; + } + elem = elem->next; + } + lp_config_set_string(config(tunnel), "tunnel", "server_addresses", tmp); + if(tmp != NULL) { + ms_free(tmp); + } +} + + +static void linphone_tunnel_add_server_intern(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config) { + if(tunnel_config->remote_udp_mirror_port == -1) { + bcTunnel(tunnel)->addServer(tunnel_config->host, tunnel_config->port); + } else { + bcTunnel(tunnel)->addServer(tunnel_config->host, tunnel_config->port, + tunnel_config->remote_udp_mirror_port, tunnel_config->delay); + } + tunnel->config_list = ms_list_append(tunnel->config_list, tunnel_config); } -static void add_server_to_config(LinphoneTunnel *tunnel, const char *host, int port){ - const char *orig=lp_config_get_string(config(tunnel),"tunnel","server_addresses", NULL); + +static void linphone_tunnel_load_config(LinphoneTunnel *tunnel){ + const char * confaddress = lp_config_get_string(config(tunnel), "tunnel", "server_addresses", NULL); char *tmp; - if (orig){ - tmp=ms_strdup_printf("%s %s:%i",orig,host,port); - }else tmp=ms_strdup_printf("%s:%i",host, port); - lp_config_set_string(config(tunnel),"tunnel","server_addresses",tmp); - ms_free(tmp); + const char *it; + LinphoneTunnelConfig *tunnel_config; + int adv; + if(confaddress != NULL) { + tmp = ms_strdup(confaddress); + it = confaddress; + while(confaddress[0] != '\0') { + int ret = sscanf(it,"%s%n", tmp, &adv); + if (ret >= 1){ + it += adv; + tunnel_config = linphone_tunnel_config_from_string(tmp); + if(tunnel_config != NULL) { + linphone_tunnel_add_server_intern(tunnel, tunnel_config); + } else { + ms_error("Tunnel server address incorrectly specified from config file: %s", tmp); + } + } else break; + } + ms_free(tmp); + } } -void linphone_tunnel_add_server(LinphoneTunnel *tunnel, const char *host, int port){ - bcTunnel(tunnel)->addServer(host, port); - add_server_to_config(tunnel,host,port); +static void linphone_tunnel_refresh_config(LinphoneTunnel *tunnel) { + MSList *old_list = tunnel->config_list; + tunnel->config_list = NULL; + bcTunnel(tunnel)->cleanServers(); + while(old_list != NULL) { + LinphoneTunnelConfig *tunnel_config = (LinphoneTunnelConfig *)old_list->data; + linphone_tunnel_add_server_intern(tunnel, tunnel_config); + old_list = old_list->next; + } } -void linphone_tunnel_add_server_and_mirror(LinphoneTunnel *tunnel, const char *host, int port, int remote_udp_mirror, int delay){ - bcTunnel(tunnel)->addServer(host, port, remote_udp_mirror, delay); - /*FIXME, udp-mirror feature not saved in config*/ - add_server_to_config(tunnel,host,port); +void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config) { + linphone_tunnel_add_server_intern(tunnel, tunnel_config); + linphone_tunnel_save_config(tunnel); } -char *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){ - const char *tmp=lp_config_get_string(config(tunnel),"tunnel","server_addresses",NULL); - if (tmp) return ms_strdup(tmp); - return NULL; +void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config) { + MSList *elem = ms_list_find(tunnel->config_list, tunnel_config); + if(elem != NULL) { + tunnel->config_list = ms_list_remove(tunnel->config_list, tunnel_config); + linphone_tunnel_config_destroy(tunnel_config); + linphone_tunnel_refresh_config(tunnel); + linphone_tunnel_save_config(tunnel); + } +} + +const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){ + return tunnel->config_list; } void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){ bcTunnel(tunnel)->cleanServers(); - lp_config_set_string(config(tunnel),"tunnel","server_addresses",NULL); + + /* Free the list */ + ms_list_for_each(tunnel->config_list, (void (*)(void *))linphone_tunnel_config_destroy); + tunnel->config_list = ms_list_free(tunnel->config_list); + + linphone_tunnel_save_config(tunnel); } void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){ @@ -173,28 +370,6 @@ void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){ bcTunnel(tunnel)->autoDetect(); } -static void tunnel_add_servers_from_config(LinphoneTunnel *tunnel, const char* confaddress){ - char *tmp=(char*)ms_malloc0(strlen(confaddress)+1); - const char *it=confaddress; - int adv; - do{ - int ret=sscanf(it,"%s%n",tmp,&adv); - if (ret>=1){ - it+=adv; - char *port=strchr(tmp,':'); - if (!port){ - ms_error("Tunnel server addresses incorrectly specified from config file: %s",it); - break; - }else{ - *port='\0'; - port++; - bcTunnel(tunnel)->addServer(tmp, atoi(port)); - } - }else break; - }while(1); - ms_free(tmp); -} - static void my_ortp_logv(OrtpLogLevel level, const char *fmt, va_list args){ ortp_logv(level,fmt,args); } @@ -205,10 +380,8 @@ static void my_ortp_logv(OrtpLogLevel level, const char *fmt, va_list args){ */ void linphone_tunnel_configure(LinphoneTunnel *tunnel){ bool_t enabled=(bool_t)lp_config_get_int(config(tunnel),"tunnel","enabled",FALSE); - const char* addresses=lp_config_get_string(config(tunnel),"tunnel","server_addresses", NULL); linphone_tunnel_enable_logs_with_handler(tunnel,TRUE,my_ortp_logv); - if (addresses) - tunnel_add_servers_from_config(tunnel,addresses); + linphone_tunnel_load_config(tunnel); linphone_tunnel_enable(tunnel, enabled); } @@ -220,13 +393,13 @@ void linphone_tunnel_destroy(LinphoneTunnel *tunnel){ } -void linphone_tunnel_add_server(LinphoneTunnel *tunnel, const char *host, int port){ +void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config){ } -void linphone_tunnel_add_server_and_mirror(LinphoneTunnel *tunnel, const char *host, int port, int remote_udp_mirror, int delay){ +void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config){ } -char *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){ +const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){ return NULL; } diff --git a/coreapi/linphone_tunnel.h b/coreapi/linphone_tunnel.h index bb343008..03c568e4 100644 --- a/coreapi/linphone_tunnel.h +++ b/coreapi/linphone_tunnel.h @@ -23,8 +23,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef LINPHONETUNNELMANAGER_H -#define LINPHONETUNNELMANAGER_H +#ifndef LINPHONETUNNEL_H +#define LINPHONETUNNEL_H #include "linphonecore.h" @@ -48,34 +48,108 @@ extern "C" { #endif +typedef struct _LinphoneTunnelConfig LinphoneTunnelConfig; + /** - * Add a tunnel server. At least one should be provided to be able to connect. - * When several addresses are provided, the tunnel client may try each of them until it gets connected. - * @param tunnel object - * @param host server ip address - * @param port tunnel server tls port, recommended value is 443 + * Create a new tunnel configuration */ -void linphone_tunnel_add_server(LinphoneTunnel *tunnel, const char *host, int port); +LinphoneTunnelConfig *linphone_tunnel_config_new(); + /** - *Add tunnel server with auto detection capabilities + * Set address of server. * - * @param tunnel object + * @param tunnel configuration object * @param host tunnel server ip address + */ +void linphone_tunnel_config_set_host(LinphoneTunnelConfig *tunnel, const char *host); + +/** + * Get address of server. + * + * @param tunnel configuration object + */ +const char *linphone_tunnel_config_get_host(LinphoneTunnelConfig *tunnel); + +/** + * Set tls port of server. + * + * @param tunnel configuration object * @param port tunnel server tls port, recommended value is 443 - * @param remote_udp_mirror_port remote port on the tunnel server side used to test udp reachability + */ +void linphone_tunnel_config_set_port(LinphoneTunnelConfig *tunnel, int port); + +/** + * Get tls port of server. + * + * @param tunnel configuration object + */ +int linphone_tunnel_config_get_port(LinphoneTunnelConfig *tunnel); + +/** + * Set the remote port on the tunnel server side used to test udp reachability. + * + * @param tunnel configuration object + * @param remote_udp_mirror_port remote port on the tunnel server side used to test udp reachability, set to -1 to disable the feature + */ +void linphone_tunnel_config_set_remote_udp_mirror_port(LinphoneTunnelConfig *tunnel, int remote_udp_mirror_port); + +/** + * Get the remote port on the tunnel server side used to test udp reachability. + * + * @param tunnel configuration object + */ +int linphone_tunnel_config_get_remote_udp_mirror_port(LinphoneTunnelConfig *tunnel); + +/** + * Set the udp packet round trip delay in ms for a tunnel configuration. + * + * @param tunnel configuration object * @param delay udp packet round trip delay in ms considered as acceptable. recommended value is 1000 ms. */ -void linphone_tunnel_add_server_and_mirror(LinphoneTunnel *tunnel, const char *host, int port, int remote_udp_mirror_port, int delay); +void linphone_tunnel_config_set_delay(LinphoneTunnelConfig *tunnel, int delay); + +/** + * Get the udp packet round trip delay in ms for a tunnel configuration. + * + * @param tunnel configuration object + */ +int linphone_tunnel_config_get_delay(LinphoneTunnelConfig *tunnel); + +/** + * Destroy a tunnel configuration + * + * @param tunnel configuration object + */ +void linphone_tunnel_config_destroy(LinphoneTunnelConfig *tunnel); + +/** + * Add tunnel server configuration + * + * @param tunnel object + * @param tunnel_config object + */ +void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config); + +/** + * Remove tunnel server configuration + * + * @param tunnel object + * @param tunnel_config object + */ +void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config); + /** * @param tunnel object * returns a string of space separated list of host:port of tunnel server addresses * */ -char *linphone_tunnel_get_servers(LinphoneTunnel *tunnel); +const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel); + /** * @param tunnel object * Removes all tunnel server address previously entered with addServer() **/ void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel); + /** * Sets whether tunneling of SIP and RTP is required. * @param tunnel object @@ -84,11 +158,13 @@ void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel); * **/ void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled); + /** * @param tunnel object * Returns a boolean indicating whether tunneled operation is enabled. **/ bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel); + /** * @param tunnel object * Forces reconnection to the tunnel server. @@ -97,6 +173,7 @@ bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel); * the lost connection to be closed and new connection to be issued. **/ void linphone_tunnel_reconnect(LinphoneTunnel *tunnel); + /** * Start tunnel need detection. * @param tunnel object @@ -129,8 +206,6 @@ void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel*tunnel, const char* username,const char* passwd); -void linphone_tunnel_enable_logs(LinphoneTunnel *tunnel, bool_t enabled); - /** * @} **/ @@ -140,5 +215,5 @@ void linphone_tunnel_enable_logs(LinphoneTunnel *tunnel, bool_t enabled); #endif -#endif +#endif //LINPHONETUNNEL_H diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index f1a9174c..2b53f7a7 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -1429,7 +1429,7 @@ void linphone_core_init_default_params(LinphoneCore*lc, LinphoneCallParams *para */ bool_t linphone_core_tunnel_available(void); -typedef struct LinphoneTunnel LinphoneTunnel; +typedef struct _LinphoneTunnel LinphoneTunnel; /** * get tunnel instance if available */ diff --git a/gtk/propertybox.c b/gtk/propertybox.c index ea0095fc..41fe854e 100644 --- a/gtk/propertybox.c +++ b/gtk/propertybox.c @@ -1177,44 +1177,22 @@ void linphone_gtk_edit_tunnel_closed(GtkWidget *button){ gtk_widget_destroy(pb); } - -static void tunnel_get_server_host_and_port(LinphoneTunnel *tunnel, char *host, int size, int *port){ - char *colon; - char *addresses; - char *str1; - char *address; - const char* configured_addresses; - - configured_addresses=linphone_tunnel_get_servers(tunnel); - - if (configured_addresses==NULL){ - host[0]=0; - *port=0; - return; - } - addresses=ms_strdup(configured_addresses); - str1=addresses; - address=strtok(str1," "); // Not thread safe - if (!address) return; - colon=strchr(address, ':'); - if (!colon) return; - *colon++='\0'; - *port=atoi(colon); - strncpy(host,address,size); - ms_free(addresses); -} - - void linphone_gtk_edit_tunnel(GtkButton *button){ GtkWidget *w=linphone_gtk_create_window("tunnel_config"); LinphoneCore *lc=linphone_gtk_get_core(); LinphoneTunnel *tunnel=linphone_core_get_tunnel(lc); - char host[128]={'\0'}; + const MSList *configs; + const char *host = NULL; int port=0; if (!tunnel) return; - tunnel_get_server_host_and_port(tunnel, host, sizeof(host), &port); + configs = linphone_tunnel_get_servers(tunnel); + if(configs != NULL) { + LinphoneTunnelConfig *ltc = (LinphoneTunnelConfig *)configs->data; + host = linphone_tunnel_config_get_host(ltc); + port = linphone_tunnel_config_get_port(ltc); + } gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"host")),host); if (port==0) port=443; @@ -1247,6 +1225,7 @@ void linphone_gtk_tunnel_ok(GtkButton *button){ GtkWidget *w=gtk_widget_get_toplevel(GTK_WIDGET(button)); LinphoneCore *lc=linphone_gtk_get_core(); LinphoneTunnel *tunnel=linphone_core_get_tunnel(lc); + LinphoneTunnelConfig *config=linphone_tunnel_config_new(); gint port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port"))); gboolean enabled=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_enable"))); @@ -1260,7 +1239,9 @@ void linphone_gtk_tunnel_ok(GtkButton *button){ if (host && *host=='\0') host=NULL; if (http_port==0) http_port=8080; linphone_tunnel_clean_servers(tunnel); - linphone_tunnel_add_server(tunnel,host,port); + linphone_tunnel_config_set_host(config, host); + linphone_tunnel_config_set_port(config, port); + linphone_tunnel_add_server(tunnel, config); linphone_tunnel_enable(tunnel,enabled); linphone_tunnel_set_http_proxy(tunnel,http_host,http_port,username,password);