void icem_candpair_set_state(struct candpair *cp, enum candpair_state state) { if (!cp) return; if (cp->state != state) { icecomp_printf(cp->comp, "%5s <---> %5s FSM: %10s ===> %-10s\n", ice_cand_type2name(cp->lcand->type), ice_cand_type2name(cp->rcand->type), ice_candpair_state2name(cp->state), ice_candpair_state2name(state)); cp->state = state; } }
int ice_cand_attr_encode(struct re_printf *pf, const struct ice_cand_attr *cand) { int err = 0; if (!cand) return 0; err |= re_hprintf(pf, "%s %u %s %u %j %u typ %s", cand->foundation, cand->compid, net_proto2name(cand->proto), cand->prio, &cand->addr, sa_port(&cand->addr), ice_cand_type2name(cand->type)); if (sa_isset(&cand->rel_addr, SA_ADDR)) err |= re_hprintf(pf, " raddr %j", &cand->rel_addr); if (sa_isset(&cand->rel_addr, SA_PORT)) err |= re_hprintf(pf, " rport %u", sa_port(&cand->rel_addr)); if (cand->proto == IPPROTO_TCP) { err |= re_hprintf(pf, " tcptype %s", ice_tcptype_name(cand->tcptype)); } return err; }
/* The incoming data should not get here */ static void dummy_udp_recv(const struct sa *src, struct mbuf *mb, void *arg) { struct ice_lcand *lcand = arg; DEBUG_NOTICE("@@@@ NO-ONE cared about this UDP packet? @@@@@" " (%zu bytes from %J to %s.%J)\n", mbuf_get_left(mb), src, ice_cand_type2name(lcand->attr.type), &lcand->attr.addr); }
int icem_cand_print(struct re_printf *pf, const struct cand *c) { int err = 0; if (!c) return 0; if (c->ifname) err |= re_hprintf(pf, "%s:", c->ifname); err |= re_hprintf(pf, "%s:%J", ice_cand_type2name(c->type), &c->addr); return err; }
void *trice_lcand_sock(struct trice *icem, const struct ice_lcand *lcand) { struct ice_lcand *base = NULL; if (!icem || !lcand) return NULL; if (sa_isset(&lcand->base_addr, SA_ALL)) { enum ice_cand_type base_type; base_type = ice_cand_type_base(lcand->attr.type); base = trice_lcand_find(icem, base_type, lcand->attr.compid, lcand->attr.proto, &lcand->base_addr); } /* note: original lcand has presedence, fallback to base-candidate */ switch (lcand->attr.type) { case ICE_CAND_TYPE_HOST: return lcand->us; case ICE_CAND_TYPE_SRFLX: case ICE_CAND_TYPE_PRFLX: if (lcand->us) return lcand->us; else if (base && base->us) return base->us; else { DEBUG_NOTICE("lcand_sock: no SOCK or BASE for " " type '%s'\n", ice_cand_type2name(lcand->attr.type)); return NULL; } break; case ICE_CAND_TYPE_RELAY: return lcand->us; default: return NULL; } return NULL; }
void icem_comp_set_default_rcand(struct icem_comp *comp, struct cand *rcand) { if (!comp) return; icecomp_printf(comp, "Set default remote candidate: %s:%J\n", ice_cand_type2name(rcand->type), &rcand->addr); mem_deref(comp->def_rcand); comp->def_rcand = mem_ref(rcand); if (comp->turnc) { DEBUG_NOTICE("{%s.%u} Default: Add TURN Channel to peer %J\n", comp->icem->name, comp->id, &rcand->addr); (void)turnc_add_chan(comp->turnc, &rcand->addr, NULL, NULL); } }
/** * Encode SDP candidate attribute * * @param pf Print function * @param cand Candidate to encode * * @return 0 if success, otherwise errorcode */ int ice_cand_encode(struct re_printf *pf, const struct ice_cand *cand) { int err; err = re_hprintf(pf, "%s %u %s %u %j %u typ %s", cand->foundation, cand->compid, transp_name(cand->transp), cand->prio, &cand->addr, sa_port(&cand->addr), ice_cand_type2name(cand->type)); if (sa_isset(&cand->rel, SA_ADDR)) err |= re_hprintf(pf, " raddr %j", &cand->rel); if (sa_isset(&cand->rel, SA_PORT)) err |= re_hprintf(pf, " rport %u", sa_port(&cand->rel)); return err; }
/* * you can call this at any time * * @param addr HOST: SA_ADDR portion is used * non-HOST: SA_ADDR + SA_PORT portion is used * * @param base_addr Optional * @param rel_addr Optional * * @param layer mandatory for HOST and RELAY candidates */ int trice_lcand_add(struct ice_lcand **lcandp, struct trice *icem, unsigned compid, int proto, uint32_t prio, const struct sa *addr, const struct sa *base_addr, enum ice_cand_type type, const struct sa *rel_addr, enum ice_tcptype tcptype, void *sock, int layer) { struct ice_lcand *lcand; int err = 0; if (!icem || !compid || !proto || !addr) return EINVAL; if (!sa_isset(addr, SA_ADDR)) { DEBUG_WARNING("lcand_add: SA_ADDR is not set\n"); return EINVAL; } if (type != ICE_CAND_TYPE_HOST) { if (!sa_isset(addr, SA_PORT)) { DEBUG_WARNING("lcand_add: %s: SA_PORT" " must be set (%J)\n", ice_cand_type2name(type), addr); return EINVAL; } } /* lookup candidate, replace if PRIO is higher */ /* TODO: dont look up TCP-ACTIVE types for now (port is zero) */ if (proto == IPPROTO_UDP) { lcand = trice_lcand_find(icem, -1, compid, proto, addr); if (lcand) { trice_printf(icem, "add_local[%s.%J] --" " candidate already exists" " (%H)\n", ice_cand_type2name(type), addr, trice_cand_print, lcand); if (prio > lcand->attr.prio) lcand = mem_deref(lcand); else { goto out; } } } err = trice_add_lcandidate(&lcand, icem, &icem->lcandl, compid, NULL, proto, prio, addr, base_addr, type, rel_addr, tcptype); if (err) return err; if (type == ICE_CAND_TYPE_HOST) { switch (proto) { case IPPROTO_UDP: if (sock) { struct sa laddr; lcand->us = mem_ref(sock); err = udp_local_get(lcand->us, &laddr); if (err) goto out; lcand->attr.addr = *addr; sa_set_port(&lcand->attr.addr, sa_port(&laddr)); } else { err = udp_listen(&lcand->us, addr, dummy_udp_recv, lcand); if (err) goto out; err = udp_local_get(lcand->us, &lcand->attr.addr); if (err) goto out; } err = udp_register_helper(&lcand->uh, lcand->us, layer, udp_helper_send_handler, udp_helper_recv_handler, lcand); if (err) goto out; break; case IPPROTO_TCP: /* TCP-transport has 3 variants: active, passive, so */ if (lcand->attr.tcptype == ICE_TCP_ACTIVE) { /* the port MUST be set to 9 (i.e., Discard) */ /*sa_set_port(&lcand->attr.addr, 9); */ } else if (lcand->attr.tcptype == ICE_TCP_PASSIVE || lcand->attr.tcptype == ICE_TCP_SO) { err = tcp_listen(&lcand->ts, addr, tcp_conn_handler, lcand); if (err) goto out; err = tcp_local_get(lcand->ts, &lcand->attr.addr); if (err) goto out; } else { err = EPROTONOSUPPORT; goto out; } break; default: err = EPROTONOSUPPORT; goto out; } } else if (type == ICE_CAND_TYPE_RELAY) { switch (proto) { case IPPROTO_UDP: if (sock) { lcand->us = mem_ref(sock); } else { err = udp_listen(&lcand->us, NULL, dummy_udp_recv, lcand); if (err) goto out; } err = udp_register_helper(&lcand->uh, lcand->us, layer, udp_helper_send_handler, udp_helper_recv_handler, lcand); if (err) goto out; break; default: err = EPROTONOSUPPORT; goto out; } } else if (type == ICE_CAND_TYPE_SRFLX || type == ICE_CAND_TYPE_PRFLX) { /* Special case for SRFLX UDP candidates, if he has * its own UDP-socket that can be used. */ if (proto == IPPROTO_UDP && sock) { lcand->us = mem_ref(sock); err = udp_register_helper(&lcand->uh, lcand->us, layer, udp_helper_send_handler, udp_helper_recv_handler, lcand); if (err) goto out; } } lcand->layer = layer; /* pair this local-candidate with all existing remote-candidates */ err = trice_candpair_with_local(icem, lcand); if (err) goto out; /* new pair -- refresh the checklist timer */ trice_checklist_refresh(icem); out: if (err) mem_deref(lcand); else if (lcandp) *lcandp = lcand; return err; }