static int update(struct mnat_sess *sess) { struct le *le; int err = 0; if (!sess) return EINVAL; for (le=sess->medial.head; le; le=le->next) { struct mnat_media *m = le->data; struct sa raddr1, raddr2; raddr1 = *sdp_media_raddr(m->sdpm); sdp_media_raddr_rtcp(m->sdpm, &raddr2); if (m->turnc1 && sa_isset(&raddr1, SA_ALL)) err |= turnc_add_chan(m->turnc1, &raddr1, NULL, NULL); if (m->turnc2 && sa_isset(&raddr2, SA_ALL)) err |= turnc_add_chan(m->turnc2, &raddr2, NULL, NULL); } return err; }
static void turnc_handler(int err, uint16_t scode, const char *reason, const struct sa *relay, const struct sa *mapped, const struct stun_msg *msg, void *arg) { (void)msg; (void)arg; /* Transaction errors */ if (err) { DEBUG_WARNING("TURN Client error: %m\n", err); turn_done(); return; } /* STUN errors */ if (scode) { DEBUG_WARNING("TURN Client error: %u %s\n", scode, reason); turn_done(); return; } (void)re_fprintf(stderr, "Allocate Request: relay_addr=%J" ", mapped_addr=%J\n", relay, mapped); if (sa_isset(turnc.peer, SA_ALL)) { (void)re_fprintf(stderr, "ChannelBind: %J\n", turnc.peer); err = turnc_add_chan(turnc.tc, turnc.peer, NULL, NULL); if (err) { DEBUG_WARNING("TURN add channel: %m\n", err); } } }
/* Incoming data from TURN-server */ static void data_handler(struct allocation *alloc, const struct sa *src, struct mbuf *mb) { int err; if (!alloc->ok) { re_fprintf(stderr, "allocation not ready" " -- ignore %zu bytes from %J\n", mbuf_get_left(mb), src); return; } if (!sa_cmp(src, &alloc->peer, SA_ALL)) { re_printf("updating peer address: %J --> %J\n", &alloc->peer, src); alloc->peer = *src; if (!alloc->turn_ind) turnc_add_chan(alloc->turnc, src, NULL, NULL); tmr_start(&alloc->tmr_ping, PING_INTERVAL, tmr_ping_handler, alloc); } err = receiver_recv(&alloc->recv, src, mb); if (err) { re_fprintf(stderr, "corrupt packet coming from %J (%m)\n", src, err); } }
static int set_peer(struct allocation *alloc, const struct sa *peer) { alloc->peer = *peer; tmr_start(&alloc->tmr_ping, PING_INTERVAL, tmr_ping_handler, alloc); if (alloc->turn_ind) return turnc_add_perm(alloc->turnc, peer, perm_handler, alloc); else return turnc_add_chan(alloc->turnc, peer, perm_handler, alloc); }
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); } }
/** * Add a TURN Channel for the selected remote address * * @param icem ICE Media object * @param compid Component ID * @param raddr Remote network address * * @return 0 if success, otherwise errorcode */ int icem_add_chan(struct icem *icem, unsigned compid, const struct sa *raddr) { struct icem_comp *comp; if (!icem) return EINVAL; comp = icem_comp_find(icem, compid); if (!comp) return ENOENT; if (comp->turnc) { DEBUG_NOTICE("{%s.%u} Add TURN Channel to peer %J\n", comp->icem->name, comp->id, raddr); return turnc_add_chan(comp->turnc, raddr, NULL, NULL); } return 0; }
int icem_conncheck_send(struct ice_candpair *cp, bool use_cand, bool trigged) { struct ice_cand *lcand = cp->lcand; struct icem *icem = cp->icem; char username_buf[64]; size_t presz = 0; uint32_t prio_prflx; uint16_t ctrl_attr; int err = 0; icem_candpair_set_state(cp, ICE_CANDPAIR_INPROGRESS); (void)re_snprintf(username_buf, sizeof(username_buf), "%s:%s", icem->rufrag, icem->lufrag); /* PRIORITY and USE-CANDIDATE */ prio_prflx = ice_cand_calc_prio(ICE_CAND_TYPE_PRFLX, 0, lcand->compid); switch (icem->lrole) { case ICE_ROLE_CONTROLLING: ctrl_attr = STUN_ATTR_CONTROLLING; if (icem->conf.nom == ICE_NOMINATION_AGGRESSIVE) use_cand = true; break; case ICE_ROLE_CONTROLLED: ctrl_attr = STUN_ATTR_CONTROLLED; break; default: return EINVAL; } #if ICE_TRACE icecomp_printf(cp->comp, "Tx %H ---> %H (%s) %s %s\n", icem_cand_print, cp->lcand, icem_cand_print, cp->rcand, ice_candpair_state2name(cp->state), use_cand ? "[USE]" : "", trigged ? "[Trigged]" : ""); #else (void)trigged; #endif /* A connectivity check MUST utilize the STUN short term credential mechanism. */ /* The password is equal to the password provided by the peer */ if (!icem->rpwd) { DEBUG_WARNING("no remote password!\n"); } if (cp->ct_conn) { DEBUG_WARNING("send_req: CONNCHECK already Pending!\n"); return EBUSY; } switch (lcand->type) { case ICE_CAND_TYPE_RELAY: /* Creating Permissions for Relayed Candidates */ err = turnc_add_chan(cp->comp->turnc, &cp->rcand->addr, NULL, NULL); if (err) { DEBUG_WARNING("add channel: %m\n", err); break; } presz = 4; /*@fallthrough@*/ case ICE_CAND_TYPE_HOST: case ICE_CAND_TYPE_SRFLX: case ICE_CAND_TYPE_PRFLX: cp->ct_conn = mem_deref(cp->ct_conn); err = stun_request(&cp->ct_conn, icem->stun, icem->proto, cp->comp->sock, &cp->rcand->addr, presz, STUN_METHOD_BINDING, (uint8_t *)icem->rpwd, str_len(icem->rpwd), true, stunc_resp_handler, cp, 4, STUN_ATTR_USERNAME, username_buf, STUN_ATTR_PRIORITY, &prio_prflx, ctrl_attr, &icem->tiebrk, STUN_ATTR_USE_CAND, use_cand ? &use_cand : 0); break; default: DEBUG_WARNING("unknown candidate type %d\n", lcand->type); err = EINVAL; break; } return err; }