From f4e961df3cc5eaa502c8a42c8d3d0d2bfbadde66 Mon Sep 17 00:00:00 2001 From: Jakub Adam Date: Sun, 15 May 2011 22:57:27 +0200 Subject: [PATCH] media: distinguish TCP active and passive candidates --- src/api/sipe-backend.h | 3 +- src/core/sdpmsg.c | 118 ++++++++++++++++++++++++++++++++-------------- src/purple/purple-media.c | 22 ++++++--- 3 files changed, 101 insertions(+), 42 deletions(-) diff --git a/src/api/sipe-backend.h b/src/api/sipe-backend.h index a1fe9706..fddc608b 100644 --- a/src/api/sipe-backend.h +++ b/src/api/sipe-backend.h @@ -333,7 +333,8 @@ typedef enum { } SipeMediaType; typedef enum { - SIPE_NETWORK_PROTOCOL_TCP, + SIPE_NETWORK_PROTOCOL_TCP_ACTIVE, + SIPE_NETWORK_PROTOCOL_TCP_PASSIVE, SIPE_NETWORK_PROTOCOL_UDP } SipeNetworkProtocol; diff --git a/src/core/sdpmsg.c b/src/core/sdpmsg.c index c2501c7b..baa4f0b3 100644 --- a/src/core/sdpmsg.c +++ b/src/core/sdpmsg.c @@ -88,6 +88,7 @@ parse_attributes(struct sdpmsg *smsg, gchar *msg) { return TRUE; } +static struct sdpcandidate * sdpcandidate_copy(struct sdpcandidate *candidate); static void sdpcandidate_free(struct sdpcandidate *candidate); static SipeComponentType @@ -122,8 +123,8 @@ base64_pad(const gchar* str) return g_strdup(str); } -static struct sdpcandidate * -parse_candidate_draft_6(gchar **tokens) +static GSList * +parse_append_candidate_draft_6(gchar **tokens, GSList *candidates) { struct sdpcandidate *candidate = g_new0(struct sdpcandidate, 1); @@ -133,22 +134,31 @@ parse_candidate_draft_6(gchar **tokens) if (sipe_strequal(tokens[3], "UDP")) candidate->protocol = SIPE_NETWORK_PROTOCOL_UDP; + else if (sipe_strequal(tokens[3], "TCP")) + candidate->protocol = SIPE_NETWORK_PROTOCOL_TCP_ACTIVE; else { - // Ignore TCP candidates, at least for now... - // Also, if this is ICEv6 candidate list, candidates are dropped here sdpcandidate_free(candidate); - return NULL; + return candidates; } candidate->priority = atoi(tokens[4] + 2); candidate->ip = g_strdup(tokens[5]); candidate->port = atoi(tokens[6]); - return candidate; + candidates = g_slist_append(candidates, candidate); + + // draft 6 candidates are both active and passive + if (candidate->protocol == SIPE_NETWORK_PROTOCOL_TCP_ACTIVE) { + candidate = sdpcandidate_copy(candidate); + candidate->protocol = SIPE_NETWORK_PROTOCOL_TCP_PASSIVE; + candidates = g_slist_append(candidates, candidate); + } + + return candidates; } -static struct sdpcandidate * -parse_candidate_rfc_5245(gchar **tokens) +static GSList * +parse_append_candidate_rfc_5245(gchar **tokens, GSList *candidates) { struct sdpcandidate *candidate = g_new0(struct sdpcandidate, 1); @@ -157,11 +167,13 @@ parse_candidate_rfc_5245(gchar **tokens) if (sipe_strequal(tokens[2], "UDP")) candidate->protocol = SIPE_NETWORK_PROTOCOL_UDP; + else if (sipe_strequal(tokens[2], "TCP-ACT")) + candidate->protocol = SIPE_NETWORK_PROTOCOL_TCP_ACTIVE; + else if (sipe_strequal(tokens[2], "TCP-PASS")) + candidate->protocol = SIPE_NETWORK_PROTOCOL_TCP_PASSIVE; else { - // Ignore TCP candidates, at least for now... - // Also, if this is ICEv6 candidate list, candidates are dropped here sdpcandidate_free(candidate); - return NULL; + return candidates; } candidate->priority = atoi(tokens[3]); @@ -178,10 +190,10 @@ parse_candidate_rfc_5245(gchar **tokens) candidate->type = SIPE_CANDIDATE_TYPE_PRFLX; else { sdpcandidate_free(candidate); - return NULL; + return candidates; } - return candidate; + return g_slist_append(candidates, candidate); } static GSList * @@ -195,18 +207,13 @@ parse_candidates(GSList *attrs, SipeIceVersion *ice_version) gchar **tokens = g_strsplit_set(attr, " ", 0); if (sipe_strequal(tokens[6], "typ")) { - struct sdpcandidate *c = parse_candidate_rfc_5245(tokens); - - if (c) { + candidates = parse_append_candidate_rfc_5245(tokens, candidates); + if (candidates) *ice_version = SIPE_ICE_RFC_5245; - candidates = g_slist_append(candidates, c); - } } else { - struct sdpcandidate *c = parse_candidate_draft_6(tokens); - if (c) { + candidates = parse_append_candidate_draft_6(tokens, candidates); + if (candidates) *ice_version = SIPE_ICE_DRAFT_6; - candidates = g_slist_append(candidates, c); - } } g_strfreev(tokens); @@ -434,21 +441,24 @@ candidates_to_string(GSList *candidates, SipeIceVersion ice_version) const gchar *type; gchar *related = NULL; - switch (c->protocol) { - case SIPE_NETWORK_PROTOCOL_TCP: - protocol = "TCP"; - break; - case SIPE_NETWORK_PROTOCOL_UDP: - protocol = "UDP"; - break; - default: - /* error unknown/unsupported type */ - protocol = "UNKOWN"; - break; - } - if (ice_version == SIPE_ICE_RFC_5245) { + switch (c->protocol) { + case SIPE_NETWORK_PROTOCOL_TCP_ACTIVE: + protocol = "TCP-ACT"; + break; + case SIPE_NETWORK_PROTOCOL_TCP_PASSIVE: + protocol = "TCP-PASS"; + break; + case SIPE_NETWORK_PROTOCOL_UDP: + protocol = "UDP"; + break; + default: + /* error unknown/unsupported type */ + protocol = "UNKOWN"; + break; + } + switch (c->type) { case SIPE_CANDIDATE_TYPE_HOST: type = "host"; @@ -490,6 +500,21 @@ candidates_to_string(GSList *candidates, SipeIceVersion ice_version) gchar *username = base64_unpad(c->username); gchar *password = base64_unpad(c->password); + // TODO: remove active/passive pairs for the same host IP + switch (c->protocol) { + case SIPE_NETWORK_PROTOCOL_TCP_ACTIVE: + case SIPE_NETWORK_PROTOCOL_TCP_PASSIVE: + protocol = "TCP"; + break; + case SIPE_NETWORK_PROTOCOL_UDP: + protocol = "UDP"; + break; + default: + /* error unknown/unsupported type */ + protocol = "UNKOWN"; + break; + } + g_string_append_printf(result, "a=candidate:%s %u %s %s 0.%u %s %d\r\n", username, @@ -650,6 +675,29 @@ sdpmsg_to_string(const struct sdpmsg *msg) return g_string_free(body, FALSE); } +static struct sdpcandidate * +sdpcandidate_copy(struct sdpcandidate *candidate) +{ + if (candidate) { + struct sdpcandidate *copy = g_new0(struct sdpcandidate, 1); + + copy->foundation = g_strdup(candidate->foundation); + copy->component = candidate->component; + copy->type = candidate->type; + copy->protocol = candidate->protocol; + copy->priority = candidate->priority; + copy->ip = g_strdup(candidate->ip); + copy->port = candidate->port; + copy->base_ip = g_strdup(candidate->base_ip); + copy->base_port = candidate->base_port; + copy->username = g_strdup(candidate->username); + copy->password = g_strdup(candidate->password); + + return copy; + } else + return NULL; +} + static void sdpcandidate_free(struct sdpcandidate *candidate) { diff --git a/src/purple/purple-media.c b/src/purple/purple-media.c index 4d840b5a..8c850562 100644 --- a/src/purple/purple-media.c +++ b/src/purple/purple-media.c @@ -866,9 +866,14 @@ static PurpleMediaNetworkProtocol sipe_network_protocol_to_purple(SipeNetworkProtocol proto) { switch (proto) { - case SIPE_NETWORK_PROTOCOL_TCP: return PURPLE_MEDIA_NETWORK_PROTOCOL_TCP; - case SIPE_NETWORK_PROTOCOL_UDP: return PURPLE_MEDIA_NETWORK_PROTOCOL_UDP; - default: return PURPLE_MEDIA_NETWORK_PROTOCOL_TCP; + case SIPE_NETWORK_PROTOCOL_TCP_ACTIVE: + return PURPLE_MEDIA_NETWORK_PROTOCOL_TCP_ACTIVE; + case SIPE_NETWORK_PROTOCOL_TCP_PASSIVE: + return PURPLE_MEDIA_NETWORK_PROTOCOL_TCP_PASSIVE; + case SIPE_NETWORK_PROTOCOL_UDP: + return PURPLE_MEDIA_NETWORK_PROTOCOL_UDP; + default: + return PURPLE_MEDIA_NETWORK_PROTOCOL_UDP; } } @@ -876,9 +881,14 @@ static SipeNetworkProtocol purple_network_protocol_to_sipe(PurpleMediaNetworkProtocol proto) { switch (proto) { - case PURPLE_MEDIA_NETWORK_PROTOCOL_TCP: return SIPE_NETWORK_PROTOCOL_TCP; - case PURPLE_MEDIA_NETWORK_PROTOCOL_UDP: return SIPE_NETWORK_PROTOCOL_UDP; - default: return SIPE_NETWORK_PROTOCOL_UDP; + case PURPLE_MEDIA_NETWORK_PROTOCOL_TCP_ACTIVE: + return SIPE_NETWORK_PROTOCOL_TCP_ACTIVE; + case PURPLE_MEDIA_NETWORK_PROTOCOL_TCP_PASSIVE: + return SIPE_NETWORK_PROTOCOL_TCP_PASSIVE; + case PURPLE_MEDIA_NETWORK_PROTOCOL_UDP: + return SIPE_NETWORK_PROTOCOL_UDP; + default: + return SIPE_NETWORK_PROTOCOL_UDP; } } -- 2.11.4.GIT