#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){
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);
}
*/
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);
}
}
-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;
}
* 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"
{
#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
*
**/
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.
* 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
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);
-
/**
* @}
**/
#endif
-#endif
+#endif //LINPHONETUNNEL_H
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;
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")));
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);