bool NiceConnection::setRemoteCandidates( std::vector<CandidateInfo> &candidates) { ELOG_DEBUG("Setting remote candidates %d", candidates.size()); for (unsigned int compId = 1; compId <= iceComponents_; compId++) { GSList* candList = NULL; for (unsigned int it = 0; it < candidates.size(); it++) { NiceCandidateType nice_cand_type; CandidateInfo cinfo = candidates[it]; if (cinfo.mediaType != this->mediaType || this->transportName->compare(cinfo.transProtocol) || cinfo.componentId != compId) continue; switch (cinfo.hostType) { case HOST: nice_cand_type = NICE_CANDIDATE_TYPE_HOST; break; case SRLFX: nice_cand_type = NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE; break; case PRFLX: nice_cand_type = NICE_CANDIDATE_TYPE_PEER_REFLEXIVE; break; case RELAY: nice_cand_type = NICE_CANDIDATE_TYPE_RELAYED; break; default: nice_cand_type = NICE_CANDIDATE_TYPE_HOST; break; } NiceCandidate* thecandidate = nice_candidate_new(nice_cand_type); NiceAddress* naddr = nice_address_new(); nice_address_set_from_string(naddr, cinfo.hostAddress.c_str()); nice_address_set_port(naddr, cinfo.hostPort); thecandidate->addr = *naddr; sprintf(thecandidate->foundation, "%s", cinfo.foundation.c_str()); thecandidate->username = strdup(cinfo.username.c_str()); thecandidate->password = strdup(cinfo.password.c_str()); thecandidate->stream_id = (guint) 1; thecandidate->component_id = cinfo.componentId; thecandidate->priority = cinfo.priority; thecandidate->transport = NICE_CANDIDATE_TRANSPORT_UDP; candList = g_slist_append(candList, thecandidate); ELOG_DEBUG("New Candidate SET %s %d", cinfo.hostAddress.c_str(), cinfo.hostPort); } nice_agent_set_remote_candidates(agent_, (guint) 1, compId, candList); } ELOG_DEBUG("Candidates SET"); this->updateIceState(NICE_CANDIDATES_RECEIVED); return true; }
/* * Creates a server reflexive candidate for 'component_id' of stream * 'stream_id'. * * @return pointer to the created candidate, or NULL on error */ NiceCandidate* discovery_add_server_reflexive_candidate ( NiceAgent *agent, guint stream_id, guint component_id, NiceAddress *address, NiceCandidateTransport transport, NiceSocket *base_socket, gboolean nat_assisted) { NiceCandidate *candidate; NiceComponent *component; NiceStream *stream; gboolean result = FALSE; if (!agent_find_component (agent, stream_id, component_id, &stream, &component)) return NULL; candidate = nice_candidate_new (NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE); candidate->transport = transport; candidate->stream_id = stream_id; candidate->component_id = component_id; candidate->addr = *address; /* step: link to the base candidate+socket */ candidate->sockptr = base_socket; candidate->base_addr = base_socket->addr; if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) { candidate->priority = nice_candidate_jingle_priority (candidate); } else if (agent->compatibility == NICE_COMPATIBILITY_MSN || agent->compatibility == NICE_COMPATIBILITY_OC2007) { candidate->priority = nice_candidate_msn_priority (candidate); } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) { candidate->priority = nice_candidate_ms_ice_priority (candidate, agent->reliable, nat_assisted); } else { candidate->priority = nice_candidate_ice_priority (candidate, agent->reliable, nat_assisted); } candidate->priority = ensure_unique_priority (component, candidate->priority); priv_generate_candidate_credentials (agent, candidate); priv_assign_foundation (agent, candidate); result = priv_add_local_candidate_pruned (agent, stream_id, component, candidate); if (result) { agent_signal_new_candidate (agent, candidate); } else { /* error: duplicate candidate */ nice_candidate_free (candidate), candidate = NULL; } return candidate; }
/* * Copies a candidate */ NICEAPI_EXPORT NiceCandidate * nice_candidate_copy (const NiceCandidate *candidate) { NiceCandidate *copy = nice_candidate_new (candidate->type); memcpy (copy, candidate, sizeof(NiceCandidate)); copy->username = g_strdup (copy->username); copy->password = g_strdup (copy->password); return copy; }
static NiceCandidate * parse_candidate(char *scand, guint stream_id) { NiceCandidate *cand = NULL; NiceCandidateType ntype; gchar **tokens = NULL; guint i; tokens = g_strsplit (scand, ",", 5); for (i = 0; tokens[i]; i++); if (i != 5) goto end; for (i = 0; i < G_N_ELEMENTS (candidate_type_name); i++) { if (strcmp(tokens[4], candidate_type_name[i]) == 0) { ntype = i; break; } } if (i == G_N_ELEMENTS (candidate_type_name)) goto end; cand = nice_candidate_new(ntype); cand->component_id = 1; cand->stream_id = stream_id; cand->transport = NICE_CANDIDATE_TRANSPORT_UDP; strncpy(cand->foundation, tokens[0], NICE_CANDIDATE_MAX_FOUNDATION); cand->foundation[NICE_CANDIDATE_MAX_FOUNDATION - 1] = 0; cand->priority = atoi (tokens[1]); if (!nice_address_set_from_string(&cand->addr, tokens[2])) { g_message("failed to parse addr: %s", tokens[2]); nice_candidate_free(cand); cand = NULL; goto end; } nice_address_set_port(&cand->addr, atoi (tokens[3])); end: g_strfreev(tokens); return cand; }
static void add_bad_candidate (NiceAgent *agent, guint stream_id, NiceCandidate *cand) { NiceAddress bad_addr; GSList *cand_list = NULL; g_assert (nice_address_set_from_string (&bad_addr, "172.1.0.1")); cand = nice_candidate_new (NICE_CANDIDATE_TYPE_HOST); cand->stream_id = stream_id; cand->component_id = NICE_COMPONENT_TYPE_RTP; cand->addr = bad_addr; nice_agent_get_local_credentials (agent, stream_id, &cand->username, &cand->password); cand_list = g_slist_prepend (cand_list, cand); g_debug ("Adding buggy candidate to the agent %p", agent); g_assert (nice_agent_set_remote_candidates (agent, stream_id, NICE_COMPONENT_TYPE_RTP, cand_list)); g_slist_free_full (cand_list, (GDestroyNotify) nice_candidate_free); }
nsresult createNiceCandidate(otIICECandidate *aCandidate, PRUint32 aStreamID, NiceCandidate **_retval) { nsresult res; PRInt16 val16; PRUint32 val32; nsCString valStr; NiceCandidate *cand; res = aCandidate->GetType(&val16); if (NS_FAILED(res)) return res; cand = nice_candidate_new((NiceCandidateType)val16); cand->transport = NICE_CANDIDATE_TRANSPORT_UDP; res = aCandidate->GetIp(valStr); if (NS_FAILED(res)) goto fail; nice_address_set_from_string(&cand->addr, valStr.get()); res = aCandidate->GetPort(&val32); if (NS_FAILED(res)) goto fail; nice_address_set_port(&cand->addr, val32); res = aCandidate->GetPriority(&val32); if (NS_FAILED(res)) goto fail; cand->priority = val32; cand->stream_id = aStreamID; res = aCandidate->GetComponent(&val32); if (NS_FAILED(res)) goto fail; cand->component_id = val32; res = aCandidate->GetFoundation(valStr); if (NS_FAILED(res)) goto fail; strncpy(cand->foundation, valStr.get(), NICE_CANDIDATE_MAX_FOUNDATION); res = aCandidate->GetUfrag(valStr); if (NS_FAILED(res)) goto fail; if (!valStr.IsEmpty()) cand->username = strdup(valStr.get()); res = aCandidate->GetPwd(valStr); if (NS_FAILED(res)) goto fail; if (!valStr.IsEmpty()) cand->password = strdup(valStr.get()); res = aCandidate->GetRelIp(valStr); if (NS_FAILED(res)) goto fail; if (!valStr.IsEmpty()) { nice_address_set_from_string(&cand->base_addr, valStr.get()); res = aCandidate->GetRelPort(&val32); if (NS_FAILED(res)) goto fail; nice_address_set_port(&cand->base_addr, val32); } *_retval = cand; return NS_OK; fail: nice_candidate_free(cand); return res; }
GSList* soy_net_xmpp_agent_get_remote_candidates (soynetXMPPAgent* self, LmMessageNode* transport, guint stream_id) { GSList* result = NULL; GSList* rcands = NULL; LmMessageNode* candidate = NULL; LmMessageNode* _tmp0_ = NULL; LmMessageNode* _tmp1_ = NULL; LmMessageNode* _tmp2_ = NULL; LmMessageNode* _tmp3_ = NULL; GSList* _tmp45_ = NULL; GSList* _tmp46_ = NULL; #line 119 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" g_return_val_if_fail (self != NULL, NULL); #line 119 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" g_return_val_if_fail (transport != NULL, NULL); #line 120 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" rcands = NULL; #line 121 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp0_ = transport; #line 121 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp1_ = lm_message_node_get_child (_tmp0_, "candidate"); #line 121 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp2_ = _lm_message_node_ref0 (_tmp1_); #line 121 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" candidate = _tmp2_; #line 124 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp3_ = candidate; #line 124 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" if (_tmp3_ == NULL) { #line 125 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" result = rcands; #line 125 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _lm_message_node_unref0 (candidate); #line 125 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" return result; #line 584 "XMPPAgent.c" } #line 127 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" while (TRUE) { #line 588 "XMPPAgent.c" LmMessageNode* _tmp4_ = NULL; NiceCandidate* rcand = NULL; GeeHashMap* _tmp5_ = NULL; LmMessageNode* _tmp6_ = NULL; const gchar* _tmp7_ = NULL; gpointer _tmp8_ = NULL; NiceCandidate* _tmp9_ = NULL; LmMessageNode* _tmp10_ = NULL; const gchar* _tmp11_ = NULL; LmMessageNode* _tmp12_ = NULL; const gchar* _tmp13_ = NULL; LmMessageNode* _tmp14_ = NULL; const gchar* _tmp15_ = NULL; LmMessageNode* _tmp16_ = NULL; const gchar* _tmp17_ = NULL; NiceCandidate* _tmp18_ = NULL; LmMessageNode* _tmp19_ = NULL; const gchar* _tmp20_ = NULL; NiceCandidate* _tmp21_ = NULL; LmMessageNode* _tmp22_ = NULL; const gchar* _tmp23_ = NULL; gint _tmp24_ = 0; NiceCandidate* _tmp25_ = NULL; NiceCandidate* _tmp26_ = NULL; LmMessageNode* _tmp27_ = NULL; const gchar* _tmp28_ = NULL; gint _tmp29_ = 0; NiceCandidate* _tmp30_ = NULL; LmMessageNode* _tmp31_ = NULL; const gchar* _tmp32_ = NULL; gint _tmp33_ = 0; NiceCandidate* _tmp34_ = NULL; guint _tmp35_ = 0U; NiceCandidate* _tmp36_ = NULL; gboolean _tmp37_ = FALSE; gchar* _tmp38_ = NULL; gchar* _tmp39_ = NULL; NiceCandidate* _tmp40_ = NULL; NiceCandidate* _tmp41_ = NULL; LmMessageNode* _tmp42_ = NULL; LmMessageNode* _tmp43_ = NULL; LmMessageNode* _tmp44_ = NULL; #line 127 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp4_ = candidate; #line 127 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" if (!(_tmp4_ != NULL)) { #line 127 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" break; #line 637 "XMPPAgent.c" } #line 129 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp5_ = soy_net_xmpp_agent_candidate_type_dict; #line 129 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp6_ = candidate; #line 129 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp7_ = lm_message_node_get_attribute (_tmp6_, "type"); #line 129 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp8_ = gee_abstract_map_get ((GeeAbstractMap*) _tmp5_, _tmp7_); #line 129 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp9_ = nice_candidate_new ((guint) ((gint) ((gintptr) _tmp8_))); #line 129 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" rcand = _tmp9_; #line 131 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" g_print ("Remote Candidate\n"); #line 132 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp10_ = candidate; #line 132 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp11_ = lm_message_node_get_attribute (_tmp10_, "ip"); #line 132 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" g_print ("%s\n", _tmp11_); #line 133 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp12_ = candidate; #line 133 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp13_ = lm_message_node_get_attribute (_tmp12_, "port"); #line 133 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" g_print ("port: %s\n", _tmp13_); #line 134 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp14_ = candidate; #line 134 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp15_ = lm_message_node_get_attribute (_tmp14_, "priority"); #line 134 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" g_print ("priority: %s\n", _tmp15_); #line 135 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp16_ = candidate; #line 135 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp17_ = lm_message_node_get_attribute (_tmp16_, "component"); #line 135 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" g_print ("component %s\n", _tmp17_); #line 138 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp18_ = rcand; #line 138 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp19_ = candidate; #line 138 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp20_ = lm_message_node_get_attribute (_tmp19_, "ip"); #line 138 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" nice_address_set_from_string (&_tmp18_->addr, _tmp20_); #line 139 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp21_ = rcand; #line 139 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp22_ = candidate; #line 139 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp23_ = lm_message_node_get_attribute (_tmp22_, "port"); #line 139 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp24_ = atoi (_tmp23_); #line 139 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" nice_address_set_port (&_tmp21_->addr, (guint) _tmp24_); #line 140 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp25_ = rcand; #line 140 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp25_->transport = NICE_CANDIDATE_TRANSPORT_UDP; #line 141 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp26_ = rcand; #line 141 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp27_ = candidate; #line 141 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp28_ = lm_message_node_get_attribute (_tmp27_, "priority"); #line 141 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp29_ = atoi (_tmp28_); #line 141 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp26_->priority = (guint32) _tmp29_; #line 142 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp30_ = rcand; #line 142 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp31_ = candidate; #line 142 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp32_ = lm_message_node_get_attribute (_tmp31_, "component"); #line 142 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp33_ = atoi (_tmp32_); #line 142 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp30_->component_id = (guint) _tmp33_; #line 143 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp34_ = rcand; #line 143 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp35_ = stream_id; #line 143 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp34_->stream_id = _tmp35_; #line 145 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp36_ = rcand; #line 145 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp37_ = nice_address_is_valid (&_tmp36_->addr); #line 145 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp38_ = bool_to_string (_tmp37_); #line 145 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp39_ = _tmp38_; #line 145 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" g_print ("%s\n", _tmp39_); #line 145 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _g_free0 (_tmp39_); #line 146 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp40_ = rcand; #line 146 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp41_ = nice_candidate_copy (_tmp40_); #line 146 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" rcands = g_slist_append (rcands, _tmp41_); #line 147 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp42_ = candidate; #line 147 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp43_ = _tmp42_->next; #line 147 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp44_ = _lm_message_node_ref0 (_tmp43_); #line 147 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _lm_message_node_unref0 (candidate); #line 147 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" candidate = _tmp44_; #line 127 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _nice_candidate_free0 (rcand); #line 755 "XMPPAgent.c" } #line 148 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp45_ = rcands; #line 148 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _tmp46_ = g_slist_copy (_tmp45_); #line 148 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" result = _tmp46_; #line 148 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _lm_message_node_unref0 (candidate); #line 148 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" _g_slist_free0 (rcands); #line 148 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs" return result; #line 769 "XMPPAgent.c" }
NiceCandidate * _owr_candidate_to_nice_candidate(OwrCandidate *candidate) { OwrCandidatePrivate *priv; NiceCandidate *nice_candidate; NiceCandidateType candidate_type; NiceComponentType component_type; NiceCandidateTransport transport; g_return_val_if_fail(candidate, NULL); priv = candidate->priv; switch (priv->type) { case OWR_CANDIDATE_TYPE_HOST: candidate_type = NICE_CANDIDATE_TYPE_HOST; break; case OWR_CANDIDATE_TYPE_SERVER_REFLEXIVE: candidate_type = NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE; break; case OWR_CANDIDATE_TYPE_PEER_REFLEXIVE: candidate_type = NICE_CANDIDATE_TYPE_PEER_REFLEXIVE; break; case OWR_CANDIDATE_TYPE_RELAY: candidate_type = NICE_CANDIDATE_TYPE_RELAYED; break; default: g_return_val_if_reached(NULL); } switch (priv->component_type) { case OWR_COMPONENT_TYPE_RTP: component_type = NICE_COMPONENT_TYPE_RTP; break; case OWR_COMPONENT_TYPE_RTCP: component_type = NICE_COMPONENT_TYPE_RTCP; break; default: g_return_val_if_reached(NULL); } switch (priv->transport_type) { case OWR_TRANSPORT_TYPE_UDP: transport = NICE_CANDIDATE_TRANSPORT_UDP; break; case OWR_TRANSPORT_TYPE_TCP_ACTIVE: transport = NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE; break; case OWR_TRANSPORT_TYPE_TCP_PASSIVE: transport = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE; break; case OWR_TRANSPORT_TYPE_TCP_SO: transport = NICE_CANDIDATE_TRANSPORT_TCP_SO; break; default: g_return_val_if_reached(NULL); } g_return_val_if_fail(priv->address && strlen(priv->address) > 0, NULL); g_return_val_if_fail(priv->port || transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE, NULL); nice_candidate = nice_candidate_new(candidate_type); nice_candidate->transport = NICE_CANDIDATE_TRANSPORT_UDP; nice_candidate->component_id = component_type; nice_candidate->transport = transport; nice_address_set_from_string(&nice_candidate->addr, priv->address); nice_address_set_port(&nice_candidate->addr, priv->port); if (priv->base_address && strlen(priv->base_address) > 0) nice_address_set_from_string(&nice_candidate->base_addr, priv->base_address); if (priv->base_port) nice_address_set_port(&nice_candidate->base_addr, priv->base_port); if (priv->foundation && strlen(priv->foundation) > 0) { g_strlcpy((gchar *)&nice_candidate->foundation, priv->foundation, MIN(NICE_CANDIDATE_MAX_FOUNDATION, 1 + strlen(priv->foundation))); } nice_candidate->priority = candidate->priv->priority; if (priv->ufrag && strlen(priv->ufrag) > 0) nice_candidate->username = g_strdup(priv->ufrag); if (priv->password && strlen(priv->password) > 0) nice_candidate->password = g_strdup(priv->password); return nice_candidate; }
bool NiceConnection::setRemoteCandidates( std::vector<CandidateInfo> &candidates) { if(agent_==NULL){ running_=false; return false; } ELOG_DEBUG("Setting remote candidates %lu", candidates.size()); for (unsigned int compId = 1; compId <= iceComponents_; compId++) { GSList* candList = NULL; for (unsigned int it = 0; it < candidates.size(); it++) { NiceCandidateType nice_cand_type; CandidateInfo cinfo = candidates[it]; if (cinfo.mediaType != this->mediaType || cinfo.componentId != compId) continue; switch (cinfo.hostType) { case HOST: nice_cand_type = NICE_CANDIDATE_TYPE_HOST; break; case SRFLX: nice_cand_type = NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE; break; case PRFLX: nice_cand_type = NICE_CANDIDATE_TYPE_PEER_REFLEXIVE; break; case RELAY: nice_cand_type = NICE_CANDIDATE_TYPE_RELAYED; break; default: nice_cand_type = NICE_CANDIDATE_TYPE_HOST; break; } NiceCandidate* thecandidate = nice_candidate_new(nice_cand_type); sprintf(thecandidate->foundation, "%s", cinfo.foundation.c_str()); thecandidate->username = strdup(cinfo.username.c_str()); thecandidate->password = strdup(cinfo.password.c_str()); thecandidate->stream_id = (guint) 1; thecandidate->component_id = cinfo.componentId; thecandidate->priority = cinfo.priority; thecandidate->transport = NICE_CANDIDATE_TRANSPORT_UDP; nice_address_set_from_string(&thecandidate->addr, cinfo.hostAddress.c_str()); nice_address_set_port(&thecandidate->addr, cinfo.hostPort); if (cinfo.hostType == RELAY||cinfo.hostType==SRFLX){ nice_address_set_from_string(&thecandidate->base_addr, cinfo.rAddress.c_str()); nice_address_set_port(&thecandidate->base_addr, cinfo.rPort); ELOG_DEBUG("Adding remote candidate type %d addr %s port %d raddr %s rport %d", cinfo.hostType, cinfo.hostAddress.c_str(), cinfo.hostPort, cinfo.rAddress.c_str(), cinfo.rPort); }else{ ELOG_DEBUG("Adding remote candidate type %d addr %s port %d", cinfo.hostType, cinfo.hostAddress.c_str(), cinfo.hostPort); } candList = g_slist_prepend(candList, thecandidate); } nice_agent_set_remote_candidates(agent_, (guint) 1, compId, candList); g_slist_free_full(candList, (GDestroyNotify)&nice_candidate_free); } ELOG_DEBUG("Finished setting candidates\n"); this->updateIceState(NICE_CANDIDATES_RECEIVED); return true; }
int janus_sdp_parse_candidate(janus_ice_stream *stream, const char *candidate, int trickle) { if(stream == NULL || candidate == NULL) return -1; janus_ice_handle *handle = stream->handle; if(handle == NULL) return -2; janus_mutex_lock(&handle->mutex); janus_ice_component *component = NULL; if(strstr(candidate, "candidate:") == candidate) { /* Skipping the 'candidate:' prefix Firefox puts in trickle candidates */ candidate += strlen("candidate:"); } char rfoundation[32], rtransport[4], rip[40], rtype[6], rrelip[40]; guint32 rcomponent, rpriority, rport, rrelport; int res = sscanf(candidate, "%31s %30u %3s %30u %39s %30u typ %5s %*s %39s %*s %30u", rfoundation, &rcomponent, rtransport, &rpriority, rip, &rport, rtype, rrelip, &rrelport); if(res < 7) { /* Failed to parse this address, can it be IPv6? */ if(!janus_ice_is_ipv6_enabled()) { JANUS_LOG(LOG_WARN, "[%"SCNu64"] Received IPv6 candidate, but IPv6 support is disabled...\n", handle->handle_id); janus_mutex_unlock(&handle->mutex); return res; } } if(res >= 7) { /* Add remote candidate */ component = g_hash_table_lookup(stream->components, GUINT_TO_POINTER(rcomponent)); if(component == NULL) { if(rcomponent == 2 && janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_RTCPMUX)) { JANUS_LOG(LOG_VERB, "[%"SCNu64"] -- Skipping component %d in stream %d (rtcp-muxing)\n", handle->handle_id, rcomponent, stream->stream_id); } else { JANUS_LOG(LOG_ERR, "[%"SCNu64"] -- No such component %d in stream %d?\n", handle->handle_id, rcomponent, stream->stream_id); } } else { if(rcomponent == 2 && janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_RTCPMUX)) { JANUS_LOG(LOG_VERB, "[%"SCNu64"] -- Skipping component %d in stream %d (rtcp-muxing)\n", handle->handle_id, rcomponent, stream->stream_id); janus_mutex_unlock(&handle->mutex); return 0; } //~ if(trickle) { //~ if(component->dtls != NULL) { //~ /* This component is already ready, ignore this further candidate */ //~ JANUS_LOG(LOG_VERB, "[%"SCNu64"] -- Ignoring this candidate, the component is already ready\n", handle->handle_id); //~ janus_mutex_unlock(&handle->mutex); //~ return 0; //~ } //~ } component->component_id = rcomponent; component->stream_id = stream->stream_id; NiceCandidate *c = NULL; if(!strcasecmp(rtype, "host")) { JANUS_LOG(LOG_VERB, "[%"SCNu64"] Adding remote candidate component:%d stream:%d type:host %s:%d\n", handle->handle_id, rcomponent, stream->stream_id, rip, rport); /* Unless this is libnice >= 0.1.8, we only support UDP... */ if(!strcasecmp(rtransport, "udp")) { c = nice_candidate_new(NICE_CANDIDATE_TYPE_HOST); #ifdef HAVE_LIBNICE_TCP } else if(!strcasecmp(rtransport, "tcp") && janus_ice_is_ice_tcp_enabled()) { c = nice_candidate_new(NICE_CANDIDATE_TYPE_HOST); #endif } else { JANUS_LOG(LOG_VERB, "[%"SCNu64"] Skipping unsupported transport '%s' for media\n", handle->handle_id, rtransport); } } else if(!strcasecmp(rtype, "srflx")) { JANUS_LOG(LOG_VERB, "[%"SCNu64"] Adding remote candidate component:%d stream:%d type:srflx %s:%d --> %s:%d \n", handle->handle_id, rcomponent, stream->stream_id, rrelip, rrelport, rip, rport); /* Unless this is libnice >= 0.1.8, we only support UDP... */ if(!strcasecmp(rtransport, "udp")) { c = nice_candidate_new(NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE); #ifdef HAVE_LIBNICE_TCP } else if(!strcasecmp(rtransport, "tcp") && janus_ice_is_ice_tcp_enabled()) { c = nice_candidate_new(NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE); #endif } else { JANUS_LOG(LOG_VERB, "[%"SCNu64"] Skipping unsupported transport '%s' for media\n", handle->handle_id, rtransport); } } else if(!strcasecmp(rtype, "prflx")) { JANUS_LOG(LOG_VERB, "[%"SCNu64"] Adding remote candidate component:%d stream:%d type:prflx %s:%d --> %s:%d\n", handle->handle_id, rcomponent, stream->stream_id, rrelip, rrelport, rip, rport); /* Unless this is libnice >= 0.1.8, we only support UDP... */ if(!strcasecmp(rtransport, "udp")) { c = nice_candidate_new(NICE_CANDIDATE_TYPE_PEER_REFLEXIVE); #ifdef HAVE_LIBNICE_TCP } else if(!strcasecmp(rtransport, "tcp") && janus_ice_is_ice_tcp_enabled()) { c = nice_candidate_new(NICE_CANDIDATE_TYPE_PEER_REFLEXIVE); #endif } else { JANUS_LOG(LOG_VERB, "[%"SCNu64"] Skipping unsupported transport '%s' for media\n", handle->handle_id, rtransport); } } else if(!strcasecmp(rtype, "relay")) { JANUS_LOG(LOG_VERB, "[%"SCNu64"] Adding remote candidate component:%d stream:%d type:relay %s:%d --> %s:%d\n", handle->handle_id, rcomponent, stream->stream_id, rrelip, rrelport, rip, rport); /* We only support UDP/TCP/TLS... */ if(strcasecmp(rtransport, "udp") && strcasecmp(rtransport, "tcp") && strcasecmp(rtransport, "tls")) { JANUS_LOG(LOG_VERB, "[%"SCNu64"] Skipping unsupported transport '%s' for media\n", handle->handle_id, rtransport); } else { c = nice_candidate_new(NICE_CANDIDATE_TYPE_RELAYED); } } else { /* FIXME What now? */ JANUS_LOG(LOG_ERR, "[%"SCNu64"] Unknown remote candidate type:%s for component:%d stream:%d!\n", handle->handle_id, rtype, rcomponent, stream->stream_id); } if(c != NULL) { c->component_id = rcomponent; c->stream_id = stream->stream_id; #ifndef HAVE_LIBNICE_TCP c->transport = NICE_CANDIDATE_TRANSPORT_UDP; #else if(!strcasecmp(rtransport, "udp")) { JANUS_LOG(LOG_VERB, "[%"SCNu64"] Transport: UDP\n", handle->handle_id); c->transport = NICE_CANDIDATE_TRANSPORT_UDP; } else { /* Check the type (https://tools.ietf.org/html/rfc6544#section-4.5) */ const char *type = NULL; int ctype = 0; if(strstr(candidate, "tcptype active")) { type = "active"; ctype = NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE; } else if(strstr(candidate, "tcptype passive")) { type = "passive"; ctype = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE; } else if(strstr(candidate, "tcptype so")) { type = "so"; ctype = NICE_CANDIDATE_TRANSPORT_TCP_SO; } else { /* TODO: We should actually stop here... */ JANUS_LOG(LOG_ERR, "[%"SCNu64"] Missing tcptype info for the TCP candidate!\n", handle->handle_id); } JANUS_LOG(LOG_VERB, "[%"SCNu64"] Transport: TCP (%s)\n", handle->handle_id, type); c->transport = ctype; } #endif strncpy(c->foundation, rfoundation, NICE_CANDIDATE_MAX_FOUNDATION); c->priority = rpriority; nice_address_set_from_string(&c->addr, rip); nice_address_set_port(&c->addr, rport); c->username = g_strdup(stream->ruser); c->password = g_strdup(stream->rpass); if(c->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE || c->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE) { nice_address_set_from_string(&c->base_addr, rrelip); nice_address_set_port(&c->base_addr, rrelport); } else if(c->type == NICE_CANDIDATE_TYPE_RELAYED) { /* FIXME Do we really need the base address for TURN? */ nice_address_set_from_string(&c->base_addr, rrelip); nice_address_set_port(&c->base_addr, rrelport); } component->candidates = g_slist_append(component->candidates, c); JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Candidate added to the list! (%u elements for %d/%d)\n", handle->handle_id, g_slist_length(component->candidates), stream->stream_id, component->component_id); /* Save for the summary, in case we need it */ component->remote_candidates = g_slist_append(component->remote_candidates, g_strdup(candidate)); if(trickle) { if(janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_START)) { /* This is a trickle candidate and ICE has started, we should process it right away */ if(!component->process_started) { /* Actually, ICE has JUST started for this component, take care of the candidates we've added so far */ JANUS_LOG(LOG_INFO, "[%"SCNu64"] ICE already started for this component, setting candidates we have up to now\n", handle->handle_id); janus_ice_setup_remote_candidates(handle, component->stream_id, component->component_id); } else { GSList *candidates = NULL; candidates = g_slist_append(candidates, c); if(nice_agent_set_remote_candidates(handle->agent, stream->stream_id, component->component_id, candidates) < 1) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] Failed to add trickle candidate :-(\n", handle->handle_id); } else { JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Trickle candidate added!\n", handle->handle_id); } g_slist_free(candidates); } } else { /* ICE hasn't started yet: to make sure we're not stuck, also check if we stopped processing the SDP */ if(!janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_PROCESSING_OFFER)) { janus_flags_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_START); /* This is a trickle candidate and ICE has started, we should process it right away */ if(!component->process_started) { /* Actually, ICE has JUST started for this component, take care of the candidates we've added so far */ JANUS_LOG(LOG_INFO, "[%"SCNu64"] SDP processed but ICE not started yet for this component, setting candidates we have up to now\n", handle->handle_id); janus_ice_setup_remote_candidates(handle, component->stream_id, component->component_id); } else { GSList *candidates = NULL; candidates = g_slist_append(candidates, c); if(nice_agent_set_remote_candidates(handle->agent, stream->stream_id, component->component_id, candidates) < 1) { JANUS_LOG(LOG_ERR, "[%"SCNu64"] Failed to add trickle candidate :-(\n", handle->handle_id); } else { JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Trickle candidate added!\n", handle->handle_id); } g_slist_free(candidates); } } else { /* Still processing the offer/answer: queue the trickle candidate for now, we'll process it later */ JANUS_LOG(LOG_VERB, "[%"SCNu64"] Queueing trickle candidate, status is not START yet\n", handle->handle_id); } } } } } } else { JANUS_LOG(LOG_ERR, "[%"SCNu64"] Failed to parse candidate (res=%d)...\n", handle->handle_id, res); janus_mutex_unlock(&handle->mutex); return res; } janus_mutex_unlock(&handle->mutex); return 0; }
/* Parse SDP */ int janus_sdp_parse(janus_ice_handle *handle, janus_sdp *sdp) { if(!handle || !sdp) return -1; //~ sdp_parser_t *parser = (sdp_parser_t *)sdp->parser; //~ if(!parser) //~ return -1; sdp_session_t *remote_sdp = (sdp_session_t *)sdp->sdp; if(!remote_sdp) return -1; janus_ice_stream *stream = NULL; janus_ice_component *component = NULL; gchar *ruser = NULL, *rpass = NULL, *rhashing = NULL, *rfingerprint = NULL; int audio = 0, video = 0; gint rstream = 0; /* Ok, let's start */ sdp_attribute_t *a = remote_sdp->sdp_attributes; while(a) { if(a->a_name) { if(!strcasecmp(a->a_name, "fingerprint")) { JANUS_PRINT("[%"SCNu64"] Fingerprint (global) : %s\n", handle->handle_id, a->a_value); if(strcasestr(a->a_value, "sha-256 ") == a->a_value) { rhashing = g_strdup("sha-256"); rfingerprint = g_strdup(a->a_value + strlen("sha-256 ")); } else if(strcasestr(a->a_value, "sha-1 ") == a->a_value) { JANUS_PRINT("[%"SCNu64"] Hashing algorithm not the one we expected (sha-1 instead of sha-256), but that's ok\n", handle->handle_id); rhashing = g_strdup("sha-1"); rfingerprint = g_strdup(a->a_value + strlen("sha-1 ")); } else { /* FIXME We should handle this somehow anyway... OpenSSL supports them all */ JANUS_PRINT("[%"SCNu64"] Hashing algorithm not the one we expected (sha-256/sha-1), *NOT* cool\n", handle->handle_id); } } else if(!strcasecmp(a->a_name, "ice-ufrag")) { JANUS_PRINT("[%"SCNu64"] ICE ufrag (global): %s\n", handle->handle_id, a->a_value); ruser = g_strdup(a->a_value); } else if(!strcasecmp(a->a_name, "ice-pwd")) { JANUS_PRINT("[%"SCNu64"] ICE pwd (global): %s\n", handle->handle_id, a->a_value); rpass = g_strdup(a->a_value); } } a = a->a_next; } sdp_media_t *m = remote_sdp->sdp_media; while(m) { /* What media type is this? */ if(m->m_type == sdp_media_audio) { audio++; if(audio > 1) { m = m->m_next; continue; } JANUS_PRINT("[%"SCNu64"] Parsing audio candidates (stream=%d)...\n", handle->handle_id, handle->audio_id); rstream = handle->audio_id; stream = g_hash_table_lookup(handle->streams, GUINT_TO_POINTER(handle->audio_id)); } else if(m->m_type == sdp_media_video) { video++; if(video > 1) { m = m->m_next; continue; } JANUS_PRINT("[%"SCNu64"] Parsing video candidates (stream=%d)...\n", handle->handle_id, handle->video_id); rstream = handle->video_id; stream = g_hash_table_lookup(handle->streams, GUINT_TO_POINTER(handle->video_id)); } else { JANUS_PRINT("[%"SCNu64"] Skipping unsupported media line...\n", handle->handle_id); m = m->m_next; continue; } /* Look for ICE credentials and fingerprint first: check media attributes */ a = m->m_attributes; while(a) { if(a->a_name) { if(!strcasecmp(a->a_name, "fingerprint")) { JANUS_PRINT("[%"SCNu64"] Fingerprint (local) : %s\n", handle->handle_id, a->a_value); if(strcasestr(a->a_value, "sha-256 ") == a->a_value) { if(rhashing) g_free(rhashing); /* FIXME We're overwriting the global one, if any */ rhashing = g_strdup("sha-256"); if(rfingerprint) g_free(rfingerprint); /* FIXME We're overwriting the global one, if any */ rfingerprint = g_strdup(a->a_value + strlen("sha-256 ")); } else if(strcasestr(a->a_value, "sha-1 ") == a->a_value) { JANUS_PRINT("[%"SCNu64"] Hashing algorithm not the one we expected (sha-1 instead of sha-256), but that's ok\n", handle->handle_id); if(rhashing) g_free(rhashing); /* FIXME We're overwriting the global one, if any */ rhashing = g_strdup("sha-1"); if(rfingerprint) g_free(rfingerprint); /* FIXME We're overwriting the global one, if any */ rfingerprint = g_strdup(a->a_value + strlen("sha-1 ")); } else { /* FIXME We should handle this somehow anyway... OpenSSL supports them all */ JANUS_PRINT("[%"SCNu64"] Hashing algorithm not the one we expected (sha-256), *NOT* cool\n", handle->handle_id); } } else if(!strcasecmp(a->a_name, "setup")) { JANUS_PRINT("[%"SCNu64"] DTLS setup (local): %s\n", handle->handle_id, a->a_value); if(!strcasecmp(a->a_value, "actpass") || !strcasecmp(a->a_value, "passive")) stream->dtls_role = JANUS_DTLS_ROLE_CLIENT; else if(!strcasecmp(a->a_value, "active")) stream->dtls_role = JANUS_DTLS_ROLE_SERVER; /* TODO Handle holdconn... */ } else if(!strcasecmp(a->a_name, "ice-ufrag")) { JANUS_PRINT("[%"SCNu64"] ICE ufrag (local): %s\n", handle->handle_id, a->a_value); if(ruser) g_free(ruser); /* FIXME We're overwriting the global one, if any */ ruser = g_strdup(a->a_value); } else if(!strcasecmp(a->a_name, "ice-pwd")) { JANUS_PRINT("[%"SCNu64"] ICE pwd (local): %s\n", handle->handle_id, a->a_value); if(rpass) g_free(rpass); /* FIXME We're overwriting the global one, if any */ rpass = g_strdup(a->a_value); } } a = a->a_next; } if(!ruser || !rpass || !rfingerprint || !rhashing) { /* Missing mandatory information, failure... */ if(ruser) g_free(ruser); ruser = NULL; if(rpass) g_free(rpass); rpass = NULL; if(rhashing) g_free(rhashing); rhashing = NULL; if(rfingerprint) g_free(rfingerprint); rfingerprint = NULL; return -2; } handle->remote_hashing = g_strdup(rhashing); handle->remote_fingerprint = g_strdup(rfingerprint); /* Now look for candidates and codec info */ a = m->m_attributes; while(a) { if(a->a_name) { if(!strcasecmp(a->a_name, "candidate")) { char rfoundation[32], rtransport[4], rip[24], rtype[6], rrelip[24]; guint32 rcomponent, rpriority, rport, rrelport; int res = 0; if((res = sscanf(a->a_value, "%31s %30u %3s %30u %23s %30u typ %5s %*s %23s %*s %30u", rfoundation, &rcomponent, rtransport, &rpriority, rip, &rport, rtype, rrelip, &rrelport)) >= 7) { /* Add remote candidate */ JANUS_PRINT("[%"SCNu64"] Adding remote candidate for component %d to stream %d\n", handle->handle_id, rcomponent, rstream); component = g_hash_table_lookup(stream->components, GUINT_TO_POINTER(rcomponent)); if(component == NULL) { JANUS_DEBUG("[%"SCNu64"] No such component %d in stream %d?\n", handle->handle_id, rcomponent, rstream); } else { component->component_id = rcomponent; component->stream_id = rstream; NiceCandidate *c = NULL; if(!strcasecmp(rtype, "host")) { JANUS_PRINT("[%"SCNu64"] Adding host candidate... %s:%d\n", handle->handle_id, rip, rport); /* We only support UDP... */ if(strcasecmp(rtransport, "udp")) { JANUS_DEBUG("[%"SCNu64"] Unsupported transport %s!\n", handle->handle_id, rtransport); } else { c = nice_candidate_new(NICE_CANDIDATE_TYPE_HOST); } } else if(!strcasecmp(rtype, "srflx")) { JANUS_PRINT("[%"SCNu64"] Adding srflx candidate... %s:%d --> %s:%d \n", handle->handle_id, rrelip, rrelport, rip, rport); /* We only support UDP... */ if(strcasecmp(rtransport, "udp")) { JANUS_DEBUG("[%"SCNu64"] Unsupported transport %s!\n", handle->handle_id, rtransport); }else { c = nice_candidate_new(NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE); } } else if(!strcasecmp(rtype, "prflx")) { JANUS_PRINT("[%"SCNu64"] Adding prflx candidate... %s:%d --> %s:%d\n", handle->handle_id, rrelip, rrelport, rip, rport); /* We only support UDP... */ if(strcasecmp(rtransport, "udp")) { JANUS_DEBUG("[%"SCNu64"] Unsupported transport %s!\n", handle->handle_id, rtransport); } else { c = nice_candidate_new(NICE_CANDIDATE_TYPE_PEER_REFLEXIVE); } } else if(!strcasecmp(rtype, "relay")) { JANUS_PRINT("[%"SCNu64"] Adding relay candidate... %s:%d --> %s:%d\n", handle->handle_id, rrelip, rrelport, rip, rport); /* We only support UDP/TCP/TLS... */ if(strcasecmp(rtransport, "udp") && strcasecmp(rtransport, "tcp") && strcasecmp(rtransport, "tls")) { JANUS_DEBUG("[%"SCNu64"] Unsupported transport %s!\n", handle->handle_id, rtransport); } else { c = nice_candidate_new(NICE_CANDIDATE_TYPE_RELAYED); } } else { /* FIXME What now? */ JANUS_DEBUG("[%"SCNu64"] Unknown candidate type %s!\n", handle->handle_id, rtype); } if(c != NULL) { c->component_id = rcomponent; c->stream_id = rstream; c->transport = NICE_CANDIDATE_TRANSPORT_UDP; strncpy(c->foundation, rfoundation, NICE_CANDIDATE_MAX_FOUNDATION); c->priority = rpriority; nice_address_set_from_string(&c->addr, rip); nice_address_set_port(&c->addr, rport); c->username = g_strdup(ruser); c->password = g_strdup(rpass); if(c->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE || c->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE) { nice_address_set_from_string(&c->base_addr, rrelip); nice_address_set_port(&c->base_addr, rrelport); } else if(c->type == NICE_CANDIDATE_TYPE_RELAYED) { /* FIXME Do we really need the base address for TURN? */ nice_address_set_from_string(&c->base_addr, rrelip); nice_address_set_port(&c->base_addr, rrelport); } component->candidates = g_slist_append(component->candidates, c); JANUS_PRINT("[%"SCNu64"] Candidate added to the list! (%u elements for %d/%d)\n", handle->handle_id, g_slist_length(component->candidates), stream->stream_id, component->component_id); } } } else { JANUS_DEBUG("[%"SCNu64"] Failed to parse candidate... (%d)\n", handle->handle_id, res); } } } a = a->a_next; } m = m->m_next; } if(ruser) g_free(ruser); ruser = NULL; if(rpass) g_free(rpass); rpass = NULL; if(rhashing) g_free(rhashing); rhashing = NULL; if(rfingerprint) g_free(rfingerprint); rfingerprint = NULL; return 0; /* FIXME Handle errors better */ }
bool NiceConnection::setRemoteCandidates(std::vector<CandidateInfo> &candidates, bool isBundle) { if(agent_==NULL){ running_=false; return false; } GSList* candList = NULL; ELOG_DEBUG("Setting remote candidates %lu, mediatype %d", candidates.size(), this->mediaType); for (unsigned int it = 0; it < candidates.size(); it++) { NiceCandidateType nice_cand_type; CandidateInfo cinfo = candidates[it]; //If bundle we will add the candidates regardless the mediaType if (cinfo.componentId !=1 || (!isBundle && cinfo.mediaType!=this->mediaType )) continue; switch (cinfo.hostType) { case HOST: nice_cand_type = NICE_CANDIDATE_TYPE_HOST; break; case SRFLX: nice_cand_type = NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE; break; case PRFLX: nice_cand_type = NICE_CANDIDATE_TYPE_PEER_REFLEXIVE; break; case RELAY: nice_cand_type = NICE_CANDIDATE_TYPE_RELAYED; break; default: nice_cand_type = NICE_CANDIDATE_TYPE_HOST; break; } NiceCandidate* thecandidate = nice_candidate_new(nice_cand_type); thecandidate->username = strdup(cinfo.username.c_str()); thecandidate->password = strdup(cinfo.password.c_str()); thecandidate->stream_id = (guint) 1; thecandidate->component_id = cinfo.componentId; thecandidate->priority = cinfo.priority; thecandidate->transport = NICE_CANDIDATE_TRANSPORT_UDP; nice_address_set_from_string(&thecandidate->addr, cinfo.hostAddress.c_str()); nice_address_set_port(&thecandidate->addr, cinfo.hostPort); if (cinfo.hostType == RELAY||cinfo.hostType==SRFLX){ nice_address_set_from_string(&thecandidate->base_addr, cinfo.rAddress.c_str()); nice_address_set_port(&thecandidate->base_addr, cinfo.rPort); ELOG_DEBUG("Adding remote candidate type %d addr %s port %d raddr %s rport %d", cinfo.hostType, cinfo.hostAddress.c_str(), cinfo.hostPort, cinfo.rAddress.c_str(), cinfo.rPort); }else{ ELOG_DEBUG("Adding remote candidate type %d addr %s port %d priority %d componentId %d, username %s, pass %s", cinfo.hostType, cinfo.hostAddress.c_str(), cinfo.hostPort, cinfo.priority, cinfo.componentId, cinfo.username.c_str(), cinfo.password.c_str() ); } candList = g_slist_prepend(candList, thecandidate); } //TODO: Set Component Id properly, now fixed at 1 nice_agent_set_remote_candidates(agent_, (guint) 1, 1, candList); g_slist_free_full(candList, (GDestroyNotify)&nice_candidate_free); return true; }
/* * Adds a new peer reflexive candidate to the list of known * remote candidates. The candidate is however not paired with * existing local candidates. * * See ICE sect 7.2.1.3 "Learning Peer Reflexive Candidates" (ID-19). * * @return pointer to the created candidate, or NULL on error */ NiceCandidate *discovery_learn_remote_peer_reflexive_candidate ( NiceAgent *agent, NiceStream *stream, NiceComponent *component, guint32 priority, const NiceAddress *remote_address, NiceSocket *nicesock, NiceCandidate *local, NiceCandidate *remote) { NiceCandidate *candidate; candidate = nice_candidate_new (NICE_CANDIDATE_TYPE_PEER_REFLEXIVE); candidate->addr = *remote_address; candidate->base_addr = *remote_address; if (remote) candidate->transport = remote->transport; else if (local) candidate->transport = conn_check_match_transport (local->transport); else { if (nicesock->type == NICE_SOCKET_TYPE_UDP_BSD || nicesock->type == NICE_SOCKET_TYPE_UDP_TURN) candidate->transport = NICE_CANDIDATE_TRANSPORT_UDP; else candidate->transport = NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE; } candidate->sockptr = nicesock; candidate->stream_id = stream->id; candidate->component_id = component->id; /* if the check didn't contain the PRIORITY attribute, then the priority will * be 0, which is invalid... */ if (priority != 0) { candidate->priority = priority; } else if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) { candidate->priority = nice_candidate_jingle_priority (candidate); } else if (agent->compatibility == NICE_COMPATIBILITY_MSN || agent->compatibility == NICE_COMPATIBILITY_OC2007) { candidate->priority = nice_candidate_msn_priority (candidate); } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) { candidate->priority = nice_candidate_ms_ice_priority (candidate, agent->reliable, FALSE); } else { candidate->priority = nice_candidate_ice_priority (candidate, agent->reliable, FALSE); } priv_assign_remote_foundation (agent, candidate); if ((agent->compatibility == NICE_COMPATIBILITY_MSN || agent->compatibility == NICE_COMPATIBILITY_OC2007) && remote && local) { guchar *new_username = NULL; guchar *decoded_local = NULL; guchar *decoded_remote = NULL; gsize local_size; gsize remote_size; g_free(candidate->username); g_free (candidate->password); decoded_local = g_base64_decode (local->username, &local_size); decoded_remote = g_base64_decode (remote->username, &remote_size); new_username = g_new0(guchar, local_size + remote_size); memcpy(new_username, decoded_remote, remote_size); memcpy(new_username + remote_size, decoded_local, local_size); candidate->username = g_base64_encode (new_username, local_size + remote_size); g_free(new_username); g_free(decoded_local); g_free(decoded_remote); candidate->password = g_strdup(remote->password); } else if (remote) { g_free (candidate->username); g_free (candidate->password); candidate->username = g_strdup(remote->username); candidate->password = g_strdup(remote->password); } /* note: candidate username and password are left NULL as stream level ufrag/password are used */ component->remote_candidates = g_slist_append (component->remote_candidates, candidate); agent_signal_new_remote_candidate (agent, candidate); return candidate; }
/* * Creates a peer reflexive candidate for 'component_id' of stream * 'stream_id'. * * @return pointer to the created candidate, or NULL on error */ NiceCandidate* discovery_add_peer_reflexive_candidate ( NiceAgent *agent, guint stream_id, guint component_id, NiceAddress *address, NiceSocket *base_socket, NiceCandidate *local, NiceCandidate *remote) { NiceCandidate *candidate; NiceComponent *component; NiceStream *stream; gboolean result; if (!agent_find_component (agent, stream_id, component_id, &stream, &component)) return NULL; candidate = nice_candidate_new (NICE_CANDIDATE_TYPE_PEER_REFLEXIVE); if (local) candidate->transport = local->transport; else if (remote) candidate->transport = conn_check_match_transport (remote->transport); else { if (base_socket->type == NICE_SOCKET_TYPE_UDP_BSD || base_socket->type == NICE_SOCKET_TYPE_UDP_TURN) candidate->transport = NICE_CANDIDATE_TRANSPORT_UDP; else candidate->transport = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE; } candidate->stream_id = stream_id; candidate->component_id = component_id; candidate->addr = *address; candidate->sockptr = base_socket; candidate->base_addr = base_socket->addr; if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) { candidate->priority = nice_candidate_jingle_priority (candidate); } else if (agent->compatibility == NICE_COMPATIBILITY_MSN || agent->compatibility == NICE_COMPATIBILITY_OC2007) { candidate->priority = nice_candidate_msn_priority (candidate); } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) { candidate->priority = nice_candidate_ms_ice_priority (candidate, agent->reliable, FALSE); } else { candidate->priority = nice_candidate_ice_priority (candidate, agent->reliable, FALSE); } candidate->priority = ensure_unique_priority (component, candidate->priority); priv_assign_foundation (agent, candidate); if ((agent->compatibility == NICE_COMPATIBILITY_MSN || agent->compatibility == NICE_COMPATIBILITY_OC2007) && remote && local) { guchar *new_username = NULL; guchar *decoded_local = NULL; guchar *decoded_remote = NULL; gsize local_size; gsize remote_size; g_free(candidate->username); g_free(candidate->password); decoded_local = g_base64_decode (local->username, &local_size); decoded_remote = g_base64_decode (remote->username, &remote_size); new_username = g_new0(guchar, local_size + remote_size); memcpy(new_username, decoded_local, local_size); memcpy(new_username + local_size, decoded_remote, remote_size); candidate->username = g_base64_encode (new_username, local_size + remote_size); g_free(new_username); g_free(decoded_local); g_free(decoded_remote); candidate->password = g_strdup(local->password); } else if (local) { g_free(candidate->username); g_free(candidate->password); candidate->username = g_strdup(local->username); candidate->password = g_strdup(local->password); } result = priv_add_local_candidate_pruned (agent, stream_id, component, candidate); if (result != TRUE) { /* error: memory allocation, or duplicate candidate */ nice_candidate_free (candidate), candidate = NULL; } return candidate; }
/* * Creates a server reflexive candidate for 'component_id' of stream * 'stream_id'. * * @return pointer to the created candidate, or NULL on error */ NiceCandidate* discovery_add_relay_candidate ( NiceAgent *agent, guint stream_id, guint component_id, NiceAddress *address, NiceCandidateTransport transport, NiceSocket *base_socket, TurnServer *turn) { NiceCandidate *candidate; NiceComponent *component; NiceStream *stream; NiceSocket *relay_socket = NULL; if (!agent_find_component (agent, stream_id, component_id, &stream, &component)) return NULL; candidate = nice_candidate_new (NICE_CANDIDATE_TYPE_RELAYED); candidate->transport = transport; candidate->stream_id = stream_id; candidate->component_id = component_id; candidate->addr = *address; candidate->turn = turn_server_ref (turn); /* step: link to the base candidate+socket */ relay_socket = nice_udp_turn_socket_new (agent->main_context, address, base_socket, &turn->server, turn->username, turn->password, agent_to_turn_socket_compatibility (agent)); if (!relay_socket) goto errors; candidate->sockptr = relay_socket; candidate->base_addr = base_socket->addr; if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) { candidate->priority = nice_candidate_jingle_priority (candidate); } else if (agent->compatibility == NICE_COMPATIBILITY_MSN || agent->compatibility == NICE_COMPATIBILITY_OC2007) { candidate->priority = nice_candidate_msn_priority (candidate); } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) { candidate->priority = nice_candidate_ms_ice_priority (candidate, agent->reliable, FALSE); } else { candidate->priority = nice_candidate_ice_priority (candidate, agent->reliable, FALSE); } candidate->priority = ensure_unique_priority (component, candidate->priority); priv_generate_candidate_credentials (agent, candidate); /* Google uses the turn username as the candidate username */ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) { g_free (candidate->username); candidate->username = g_strdup (turn->username); } priv_assign_foundation (agent, candidate); if (!priv_add_local_candidate_pruned (agent, stream_id, component, candidate)) goto errors; nice_component_attach_socket (component, relay_socket); agent_signal_new_candidate (agent, candidate); return candidate; errors: nice_candidate_free (candidate); if (relay_socket) nice_socket_free (relay_socket); return NULL; }
/* * Creates a local host candidate for 'component_id' of stream * 'stream_id'. * * @return pointer to the created candidate, or NULL on error */ HostCandidateResult discovery_add_local_host_candidate ( NiceAgent *agent, guint stream_id, guint component_id, NiceAddress *address, NiceCandidateTransport transport, NiceCandidate **outcandidate) { NiceCandidate *candidate; NiceComponent *component; NiceStream *stream; NiceSocket *nicesock = NULL; HostCandidateResult res = HOST_CANDIDATE_FAILED; if (!agent_find_component (agent, stream_id, component_id, &stream, &component)) return res; candidate = nice_candidate_new (NICE_CANDIDATE_TYPE_HOST); candidate->transport = transport; candidate->stream_id = stream_id; candidate->component_id = component_id; candidate->addr = *address; candidate->base_addr = *address; if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) { candidate->priority = nice_candidate_jingle_priority (candidate); } else if (agent->compatibility == NICE_COMPATIBILITY_MSN || agent->compatibility == NICE_COMPATIBILITY_OC2007) { candidate->priority = nice_candidate_msn_priority (candidate); } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) { candidate->priority = nice_candidate_ms_ice_priority (candidate, agent->reliable, FALSE); } else { candidate->priority = nice_candidate_ice_priority (candidate, agent->reliable, FALSE); } candidate->priority = ensure_unique_priority (component, candidate->priority); priv_generate_candidate_credentials (agent, candidate); priv_assign_foundation (agent, candidate); /* note: candidate username and password are left NULL as stream level ufrag/password are used */ if (transport == NICE_CANDIDATE_TRANSPORT_UDP) { nicesock = nice_udp_bsd_socket_new (address); } else if (transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE) { nicesock = nice_tcp_active_socket_new (agent->main_context, address); } else if (transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE) { nicesock = nice_tcp_passive_socket_new (agent->main_context, address); } else { /* TODO: Add TCP-SO */ } if (!nicesock) { res = HOST_CANDIDATE_CANT_CREATE_SOCKET; goto errors; } candidate->sockptr = nicesock; candidate->addr = nicesock->addr; candidate->base_addr = nicesock->addr; if (!priv_add_local_candidate_pruned (agent, stream_id, component, candidate)) { res = HOST_CANDIDATE_REDUNDANT; goto errors; } _priv_set_socket_tos (agent, nicesock, stream->tos); nice_component_attach_socket (component, nicesock); *outcandidate = candidate; return HOST_CANDIDATE_SUCCESS; errors: nice_candidate_free (candidate); if (nicesock) nice_socket_free (nicesock); return res; }