/* agent must be locked */ static struct ice_candidate_pair *__learned_candidate(struct ice_agent *ag, struct packet_stream *ps, struct sockaddr_in6 *src, struct interface_address *ifa, unsigned long priority) { struct ice_candidate *cand, *old_cand; struct ice_candidate_pair *pair; struct call *call = ag->call; cand = g_slice_alloc0(sizeof(*cand)); cand->component_id = ps->component; cand->transport = ITP_UDP; cand->priority = priority; cand->endpoint.ip46 = src->sin6_addr; cand->endpoint.port = ntohs(src->sin6_port); cand->type = ICT_PRFLX; __cand_ice_foundation(call, cand); old_cand = __foundation_lookup(ag, &cand->foundation, ps->component); if (old_cand && old_cand->priority > priority) { /* this is possible if two distinct requests are received from the same NAT IP * address, but from different ports. we cannot distinguish such candidates and * will drop the one with the lower priority */ g_slice_free1(sizeof(*cand), cand); pair = __pair_lookup(ag, old_cand, ifa); if (pair) goto out; /* nothing to do */ cand = old_cand; goto pair; } g_queue_push_tail(&ag->remote_candidates, cand); g_hash_table_insert(ag->candidate_hash, cand, cand); g_hash_table_insert(ag->foundation_hash, cand, cand); pair: pair = __pair_candidate(ifa, ag, cand, ps); PAIR_SET(pair, LEARNED); __all_pairs_list(ag); out: return pair; }
/* agent must be locked */ static struct ice_candidate_pair *__learned_candidate(struct ice_agent *ag, struct stream_fd *sfd, const endpoint_t *src, unsigned long priority) { struct ice_candidate *cand, *old_cand; struct ice_candidate_pair *pair; struct call *call = ag->call; struct packet_stream *ps = sfd->stream; cand = g_slice_alloc0(sizeof(*cand)); cand->component_id = ps->component; cand->transport = sfd->local_intf->spec->local_address.type; // XXX add socket type into socket_t? cand->priority = priority; cand->endpoint = *src; cand->type = ICT_PRFLX; __cand_ice_foundation(call, cand); old_cand = __foundation_lookup(ag, &cand->foundation, ps->component); if (old_cand && old_cand->priority > priority) { /* this is possible if two distinct requests are received from the same NAT IP * address, but from different ports. we cannot distinguish such candidates and * will drop the one with the lower priority */ g_slice_free1(sizeof(*cand), cand); pair = __pair_lookup(ag, old_cand, sfd->local_intf); if (pair) goto out; /* nothing to do */ cand = old_cand; goto pair; } g_queue_push_tail(&ag->remote_candidates, cand); g_hash_table_insert(ag->candidate_hash, cand, cand); g_hash_table_insert(ag->foundation_hash, cand, cand); pair: pair = __pair_candidate(sfd, ag, cand); PAIR_SET(pair, LEARNED); __all_pairs_list(ag); out: return pair; }