From 7ac053271f74f3c3d3b2d2d01dccda13237b344b Mon Sep 17 00:00:00 2001 From: Jakub Adam Date: Thu, 12 Feb 2015 18:43:57 +0100 Subject: [PATCH] Fix #278: 488 error after libnice upgrade When libnice 0.1.10 is combined with Farstream 0.1.x, TCP candidates that libnice now always generates are incorrectly labeled as UDP by Farstream (which has no support for TCP in 0.1 branch). We try to filter them in SIPE, assuming that RTP+RTCP UDP pairs that share the same port are actually mistagged TCP candidates. --- ChangeLog | 3 +++ src/core/sipe-media.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index a216fe18..40fef998 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +version 1.20.0 "???" (XXXX-XX-XX) + - Fixed #278: 488 error after libnice upgrade (Jakub Adam) + version 1.19.0 "Auto Authentication, MFA & Search Improvements" (2015-02-07) - Feature #80: Move parsing of login name (Stefan Becker) - Feature #79: support for Adium group chat bookmarks (David Matz, Stefan Becker) diff --git a/src/core/sipe-media.c b/src/core/sipe-media.c index 90b195bc..710662e8 100644 --- a/src/core/sipe-media.c +++ b/src/core/sipe-media.c @@ -3,7 +3,7 @@ * * pidgin-sipe * - * Copyright (C) 2011-2014 SIPE Project + * Copyright (C) 2011-2015 SIPE Project * Copyright (C) 2010 Jakub Adam * * This program is free software; you can redistribute it and/or modify @@ -191,6 +191,56 @@ sdpcodec_compare(gconstpointer a, gconstpointer b) ((const struct sdpcodec *)b)->id; } +static GList * +remove_wrong_farstream_0_1_tcp_candidates(GList *candidates) +{ + GList *i = candidates; + GHashTable *foundation_to_candidate = g_hash_table_new_full(g_str_hash, + g_str_equal, + g_free, + NULL); + + while (i) { + GList *next = i->next; + struct sipe_backend_candidate *c1 = i->data; + + if (sipe_backend_candidate_get_protocol(c1) == SIPE_NETWORK_PROTOCOL_UDP) { + gchar *foundation = sipe_backend_candidate_get_foundation(c1); + struct sipe_backend_candidate *c2 = g_hash_table_lookup(foundation_to_candidate, + foundation); + + if (c2) { + g_free(foundation); + + if (sipe_backend_candidate_get_port(c1) == + sipe_backend_candidate_get_port(c2) || + (sipe_backend_candidate_get_type(c1) != + SIPE_CANDIDATE_TYPE_HOST && + sipe_backend_candidate_get_base_port(c1) == + sipe_backend_candidate_get_base_port(c2))) { + /* + * We assume that RTP+RTCP UDP pairs + * that share the same port are + * actually mistagged TCP candidates. + */ + candidates = g_list_remove(candidates, c2); + candidates = g_list_delete_link(candidates, i); + sipe_backend_candidate_free(c1); + sipe_backend_candidate_free(c2); + } + } else + /* hash table takes ownership of "foundation" */ + g_hash_table_insert(foundation_to_candidate, foundation, c1); + } + + i = next; + } + + g_hash_table_destroy(foundation_to_candidate); + + return candidates; +} + static void fill_zero_tcp_act_ports_from_tcp_pass(GSList *candidates) { @@ -315,9 +365,11 @@ backend_stream_to_sdpmedia(struct sipe_backend_media *backend_media, // Otherwise send all available local candidates. candidates = sipe_backend_media_get_active_local_candidates(backend_media, backend_stream); - if (!candidates) + if (!candidates) { candidates = sipe_backend_get_local_candidates(backend_media, backend_stream); + candidates = remove_wrong_farstream_0_1_tcp_candidates(candidates); + } media->candidates = backend_candidates_to_sdpcandidate(candidates); fill_zero_tcp_act_ports_from_tcp_pass(media->candidates); -- 2.11.4.GIT