From f3ebc19432e457f0c112a0d1cf4055c76ac165c8 Mon Sep 17 00:00:00 2001 From: Jakub Adam Date: Tue, 21 Oct 2014 08:40:06 +0200 Subject: [PATCH] media: obey port range settings from the server So far libnice was picking listen ports at random from the full available range, which doesn't have to play well with firewalls along the way. Lync administrator can restrict which ports the clients are meant to use and Sipe should respect that setting as well. --- src/api/sipe-backend.h | 3 ++- src/core/sipe-core-private.h | 12 +++++++++ src/core/sipe-media.c | 27 ++++++++++++++++++- src/core/sipe-notify.c | 58 +++++++++++++++++++++++++++++++++++++++++ src/miranda/miranda-media.c | 3 ++- src/purple/purple-media.c | 19 ++++++++++++-- src/telepathy/telepathy-stubs.c | 4 ++- 7 files changed, 120 insertions(+), 6 deletions(-) diff --git a/src/api/sipe-backend.h b/src/api/sipe-backend.h index 6df3ba97..9e0a8cfc 100644 --- a/src/api/sipe-backend.h +++ b/src/api/sipe-backend.h @@ -431,7 +431,8 @@ struct sipe_backend_media_stream *sipe_backend_media_add_stream(struct sipe_medi SipeMediaType type, SipeIceVersion ice_version, gboolean initiator, - struct sipe_backend_media_relays *media_relays); + struct sipe_backend_media_relays *media_relays, + guint min_port, guint max_port); void sipe_backend_media_add_remote_candidates(struct sipe_media_call *media, struct sipe_media_stream *stream, GList *candidates); diff --git a/src/core/sipe-core-private.h b/src/core/sipe-core-private.h index 3789d163..e740e0ae 100644 --- a/src/core/sipe-core-private.h +++ b/src/core/sipe-core-private.h @@ -175,6 +175,18 @@ struct sipe_core_private { /* Dial-in conferencing phone numbers for different regions */ GHashTable *access_numbers; const gchar *default_access_number; + + /* Port ranges to use for media connections. Zero means any port. */ + guint min_media_port; + guint max_media_port; + guint min_audio_port; + guint max_audio_port; + guint min_video_port; + guint max_video_port; + guint min_appsharing_port; + guint max_appsharing_port; + guint min_filetransfer_port; + guint max_filetransfer_port; }; /** diff --git a/src/core/sipe-media.c b/src/core/sipe-media.c index 3f5f4cdc..b045e5d2 100644 --- a/src/core/sipe-media.c +++ b/src/core/sipe-media.c @@ -1073,6 +1073,8 @@ sipe_media_stream_add(struct sipe_media_call *call, const gchar *id, struct sipe_media_stream_private *stream_private; struct sipe_backend_media_stream *backend_stream; struct sipe_backend_media_relays *backend_media_relays; + guint min_port; + guint max_port; sipe_private = SIPE_MEDIA_CALL_PRIVATE->sipe_private; @@ -1081,10 +1083,33 @@ sipe_media_stream_add(struct sipe_media_call *call, const gchar *id, sipe_private->media_relay_username, sipe_private->media_relay_password); + min_port = sipe_private->min_media_port; + max_port = sipe_private->max_media_port; + switch (type) { + case SIPE_MEDIA_AUDIO: + min_port = sipe_private->min_audio_port; + max_port = sipe_private->max_audio_port; + break; + case SIPE_MEDIA_VIDEO: + min_port = sipe_private->min_video_port; + max_port = sipe_private->max_audio_port; + break; + case SIPE_MEDIA_APPLICATION: + if (sipe_strequal(id, "data")) { + min_port = sipe_private->min_filetransfer_port; + max_port = sipe_private->max_filetransfer_port; + } else if (sipe_strequal(id, "applicationsharing")) { + min_port = sipe_private->min_appsharing_port; + max_port = sipe_private->max_appsharing_port; + } + break; + } + backend_stream = sipe_backend_media_add_stream(call, id, call->with, type, ice_version, initiator, - backend_media_relays); + backend_media_relays, + min_port, max_port); sipe_backend_media_relays_free(backend_media_relays); diff --git a/src/core/sipe-notify.c b/src/core/sipe-notify.c index 2d0630ae..3cba372e 100644 --- a/src/core/sipe-notify.c +++ b/src/core/sipe-notify.c @@ -99,6 +99,7 @@ static void sipe_process_provisioning_v2(struct sipe_core_private *sipe_private, const gchar *addressbook_uri_str = SIPE_CORE_PRIVATE_FLAG_IS(REMOTE_USER) ? "absExternalServerUrl" : "absInternalServerUrl"; gchar *ucPC2PCAVEncryption = NULL; + gchar *ucPortRangeEnabled = NULL; g_free(sipe_private->focus_factory_uri); sipe_private->focus_factory_uri = sipe_xml_data(sipe_xml_child(node, "focusFactoryUri")); @@ -141,6 +142,63 @@ static void sipe_process_provisioning_v2(struct sipe_core_private *sipe_private, } g_free(ucPC2PCAVEncryption); + ucPortRangeEnabled = g_strstrip(sipe_xml_data(sipe_xml_child(node, "ucPortRangeEnabled"))); + if (sipe_strequal(ucPortRangeEnabled, "true")) { + gchar *port_str; + + port_str = g_strstrip(sipe_xml_data(sipe_xml_child(node, "ucMinMediaPort"))); + sipe_private->min_media_port = atoi(port_str); + g_free(port_str); + + port_str = g_strstrip(sipe_xml_data(sipe_xml_child(node, "ucMaxMediaPort"))); + sipe_private->max_media_port = atoi(port_str); + g_free(port_str); + + port_str = g_strstrip(sipe_xml_data(sipe_xml_child(node, "ucMinAudioPort"))); + sipe_private->min_audio_port = atoi(port_str); + g_free(port_str); + + port_str = g_strstrip(sipe_xml_data(sipe_xml_child(node, "ucMaxAudioPort"))); + sipe_private->max_audio_port = atoi(port_str); + g_free(port_str); + + port_str = g_strstrip(sipe_xml_data(sipe_xml_child(node, "ucMinVideoPort"))); + sipe_private->min_video_port = atoi(port_str); + g_free(port_str); + + port_str = g_strstrip(sipe_xml_data(sipe_xml_child(node, "ucMaxVideoPort"))); + sipe_private->max_video_port = atoi(port_str); + g_free(port_str); + + port_str = g_strstrip(sipe_xml_data(sipe_xml_child(node, "ucMinAppSharingPort"))); + sipe_private->min_appsharing_port = atoi(port_str); + g_free(port_str); + + port_str = g_strstrip(sipe_xml_data(sipe_xml_child(node, "ucMaxAppSharingPort"))); + sipe_private->max_appsharing_port = atoi(port_str); + g_free(port_str); + + port_str = g_strstrip(sipe_xml_data(sipe_xml_child(node, "ucMinFileTransferPort"))); + sipe_private->min_filetransfer_port = atoi(port_str); + g_free(port_str); + + port_str = g_strstrip(sipe_xml_data(sipe_xml_child(node, "ucMaxFileTransferPort"))); + sipe_private->max_filetransfer_port = atoi(port_str); + g_free(port_str); + } else { + sipe_private->min_media_port = 0; + sipe_private->max_media_port = 0; + sipe_private->min_audio_port = 0; + sipe_private->max_audio_port = 0; + sipe_private->min_video_port = 0; + sipe_private->max_video_port = 0; + sipe_private->min_appsharing_port = 0; + sipe_private->max_appsharing_port = 0; + sipe_private->min_filetransfer_port = 0; + sipe_private->max_filetransfer_port = 0; + } + g_free(ucPortRangeEnabled); + /* persistentChatConfiguration */ } else if (sipe_strequal("persistentChatConfiguration", node_name)) { const sipe_xml *property; diff --git a/src/miranda/miranda-media.c b/src/miranda/miranda-media.c index 0b7ccdb9..2e64800b 100644 --- a/src/miranda/miranda-media.c +++ b/src/miranda/miranda-media.c @@ -81,7 +81,8 @@ sipe_backend_media_add_stream(struct sipe_media_call *media, SipeMediaType type, SipeIceVersion ice_version, gboolean initiator, - struct sipe_backend_media_relays *media_relays) + struct sipe_backend_media_relays *media_relays, + guint min_port, guint max_port) { _NIF(); return NULL; diff --git a/src/purple/purple-media.c b/src/purple/purple-media.c index 5c9799d3..cd1fc658 100644 --- a/src/purple/purple-media.c +++ b/src/purple/purple-media.c @@ -527,13 +527,14 @@ sipe_backend_media_add_stream(struct sipe_media_call *call, SipeMediaType type, SipeIceVersion ice_version, gboolean initiator, - struct sipe_backend_media_relays *media_relays) + struct sipe_backend_media_relays *media_relays, + guint min_port, guint max_port) { struct sipe_backend_media *media = call->backend_private; struct sipe_backend_media_stream *stream = NULL; PurpleMediaSessionType prpl_type = sipe_media_to_purple(type); // Preallocate enough space for all potential parameters to fit. - GParameter *params = g_new0(GParameter, 5); + GParameter *params = g_new0(GParameter, 6); guint params_cnt = 0; gchar *transmitter; GValue *relay_info = NULL; @@ -554,6 +555,20 @@ sipe_backend_media_add_stream(struct sipe_media_call *call, NICE_COMPATIBILITY_OC2007R2); ++params_cnt; + if (min_port != 0) { + params[params_cnt].name = "min-port"; + g_value_init(¶ms[params_cnt].value, G_TYPE_UINT); + g_value_set_uint(¶ms[params_cnt].value, min_port); + ++params_cnt; + } + + if (max_port != 0) { + params[params_cnt].name = "max-port"; + g_value_init(¶ms[params_cnt].value, G_TYPE_UINT); + g_value_set_uint(¶ms[params_cnt].value, max_port); + ++params_cnt; + } + if (media_relays) { params[params_cnt].name = "relay-info"; g_value_init(¶ms[params_cnt].value, SIPE_RELAYS_G_TYPE); diff --git a/src/telepathy/telepathy-stubs.c b/src/telepathy/telepathy-stubs.c index da557fd6..71c473c1 100644 --- a/src/telepathy/telepathy-stubs.c +++ b/src/telepathy/telepathy-stubs.c @@ -195,7 +195,9 @@ struct sipe_backend_media_stream *sipe_backend_media_add_stream(SIPE_UNUSED_PARA SIPE_UNUSED_PARAMETER SipeMediaType type, SIPE_UNUSED_PARAMETER SipeIceVersion ice_version, SIPE_UNUSED_PARAMETER gboolean initiator, - SIPE_UNUSED_PARAMETER struct sipe_backend_media_relays *media_relays) { return(NULL); } + SIPE_UNUSED_PARAMETER struct sipe_backend_media_relays *media_relays, + SIPE_UNUSED_PARAMETER guint min_port, + SIPE_UNUSED_PARAMETER guint max_port) { return(NULL); } void sipe_backend_media_add_remote_candidates(SIPE_UNUSED_PARAMETER struct sipe_media_call *media, SIPE_UNUSED_PARAMETER struct sipe_media_stream *stream, SIPE_UNUSED_PARAMETER GList *candidates) {} -- 2.11.4.GIT