int icem_rcand_add(struct icem *icem, enum cand_type type, uint8_t compid, uint32_t prio, const struct sa *addr, const struct sa *rel_addr, const struct pl *foundation) { struct cand *rcand; int err; if (!icem || !foundation) return EINVAL; rcand = mem_zalloc(sizeof(*rcand), cand_destructor); if (!rcand) return ENOMEM; list_append(&icem->rcandl, &rcand->le, rcand); rcand->type = type; rcand->compid = compid; rcand->prio = prio; sa_cpy(&rcand->addr, addr); sa_cpy(&rcand->rel, rel_addr); err = pl_strdup(&rcand->foundation, foundation); if (err) mem_deref(rcand); return err; }
/** * Get the local IP address of the device * * @note Requires at least one IP packet sent in advance! */ int net_if_getaddr4(const char *ifname, int af, struct sa *ip) { (void)ifname; if (AF_INET != af) return EAFNOSUPPORT; /* Already cached? */ if (sa_isset(&local_ip, SA_ADDR)) { sa_cpy(ip, &local_ip); return 0; } RSocketServ ss; RSocket s; TInt ret; ret = ss.Connect(); if (KErrNone != ret) { DEBUG_WARNING("connecting to socket server fail (ret=%d)\n", ret); return ECONNREFUSED; } ret = s.Open(ss, KAfInet, KSockDatagram, KProtocolInetUdp); if (KErrNone != ret) { DEBUG_WARNING("open socket failed (ret=%d)\n", ret); return ECONNREFUSED; } TInetAddr bind; bind.SetPort(0); bind.SetAddress(KInetAddrAny); ret = s.Bind(bind); if (KErrNone != ret) { DEBUG_WARNING("bind socket failed (ret=%d)\n", ret); return ECONNREFUSED; } TInetAddr local; s.LocalName(local); s.Close(); ss.Close(); sa_set_in(&local_ip, local.Address(), local.Port()); DEBUG_NOTICE("local IP addr: %j\n", &local_ip); if (!sa_isset(&local_ip, SA_ADDR)) return EINVAL; sa_cpy(ip, &local_ip); return 0; }
static int start_gathering(struct icem *icem, const struct sa *stun_srv, const char *username, const char *password) { struct le *le; int err = 0; if (icem->ice->lmode != ICE_MODE_FULL) return EINVAL; sa_cpy(&icem->stun_srv, stun_srv); /* for each component */ for (le = icem->compl.head; le; le = le->next) { struct icem_comp *comp = le->data; if (username && password) { err |= cand_gather_relayed(icem, comp, username, password); } else err |= send_binding_request(icem, comp); } return err; }
static bool if_getaddr_handler(const char *ifname, const struct sa *sa, void *arg) { struct ifentry *ife = arg; /* Match name of interface? */ if (str_isset(ife->ifname) && 0 != str_casecmp(ife->ifname, ifname)) return false; if (!sa_isset(sa, SA_ADDR)) return false; #if 1 /* skip loopback and link-local IP */ if (sa_is_loopback(sa) || sa_is_linklocal(sa)) return false; #endif /* Match address family */ if (ife->af != sa_af(sa)) return false; /* Match - copy address */ sa_cpy(ife->ip, sa); ife->found = true; return ife->found; }
static int udp_send_internal(struct udp_sock *us, const struct sa *dst, struct mbuf *mb, struct le *le) { struct sa hdst; int err = 0, fd; /* check for error in e.g. connected state */ if (us->err) { err = us->err; us->err = 0; /* clear error */ return err; } /* choose a socket */ if (AF_INET6 == sa_af(dst) && -1 != us->fd6) fd = us->fd6; else fd = us->fd; /* call helpers in reverse order */ while (le) { struct udp_helper *uh = le->data; le = le->prev; if (dst != &hdst) { sa_cpy(&hdst, dst); dst = &hdst; } if (uh->sendh(&err, &hdst, mb, uh->arg) || err) return err; } /* Connected socket? */ if (us->conn) { if (0 != connect(fd, &dst->u.sa, dst->len)) { DEBUG_WARNING("send: connect: %s\n", strerror(errno)); us->conn = false; } if (send(fd, BUF_CAST mb->buf + mb->pos, mb->end - mb->pos, 0) < 0) return errno; } else { if (sendto(fd, BUF_CAST mb->buf + mb->pos, mb->end - mb->pos, 0, &dst->u.sa, dst->len) < 0) return errno; } return 0; }
void rtcp_sess_rx_rtp(struct rtcp_sess *sess, uint16_t seq, uint32_t ts, uint32_t ssrc, size_t payload_size, const struct sa *peer) { struct rtp_member *mbr; if (!sess) return; mbr = get_member(sess, ssrc); if (!mbr) { DEBUG_NOTICE("could not add member: 0x%08x\n", ssrc); return; } if (!mbr->s) { mbr->s = mem_zalloc(sizeof(*mbr->s), NULL); if (!mbr->s) { DEBUG_NOTICE("could not add sender: 0x%08x\n", ssrc); return; } /* first packet - init sequence number */ source_init_seq(mbr->s, seq); mbr->s->max_seq = seq - 1; /* probation not used */ sa_cpy(&mbr->s->rtp_peer, peer); ++sess->senderc; } if (!source_update_seq(mbr->s, seq)) { DEBUG_WARNING("rtp_update_seq() returned 0\n"); } if (sess->srate_rx) { uint32_t ts_arrive; /* Convert from wall-clock time to timestamp units */ ts_arrive = (uint32_t)(tmr_jiffies()) * sess->srate_rx / 1000; source_calc_jitter(mbr->s, ts, ts_arrive); } mbr->s->rtp_rx_bytes += payload_size; }
int http_clone(struct request **rp, struct request *req) { struct request *request; int ok; request = mem_zalloc(sizeof(*request), destructor); if(!request) return -ENOMEM; ok = hash_alloc(&request->hdrht, HDR_HASH_SIZE); if(ok!=0) goto fail; request->err_h = req->err_h; request->done_h = req->done_h; request->arg = req->arg; if(req->post) request->post = mem_ref(req->post); else request->post = NULL; request->form = req->form; request->host = mem_ref(req->host); request->path = mem_ref(req->path); request->secure = req->secure; request->port = req->port; memcpy(&request->meth, &req->meth, 5); sa_cpy(&request->dest, &req->dest); request->www_auth.p = NULL; request->www_auth.l = 0; request->auth = NULL; // skip network resolution request->state = RESOLVED; request->app = req->app; *rp = request; return 0; fail: return ok; }
// connect callback void p2p_request_handler(struct p2phandle *p2p, const char* peername, struct p2pconnection **p2pcon) { re_fprintf(stderr, "p2p accept from:%s\n", peername); int err = p2p_accept(p2p, p2pcon, peername, p2p_receive_handler, *p2pcon); int fdaccept = udp_sock_fd((*p2pcon)->ulsock, AF_INET); struct sa* lsa = NULL; lsa = (struct sa*)mem_zalloc(sizeof(struct sa),NULL); udp_local_get((*p2pcon)->ulsock, lsa); sa_cpy(lsa, p2p->sactl); int fdlisten = tcp_conn_fd(p2p->ltcp); UDPSOCKET udpsock = (UDPSOCKET)fdlisten; (*p2pcon)->udtsock = CUDT::socket(AF_INET, SOCK_STREAM, 0); CUDT::bind((*p2pcon)->udtsock, &udpsock, &(p2p->sactl->u.sa), p2p->sactl->len); CUDT::listen((*p2pcon)->udtsock, &(lsa->u.sa), 10); if (err) { re_fprintf(stderr, "p2p accept error:%s\n", strerror(err)); return ; } }
int icem_lcand_add(struct icem *icem, struct cand *base, enum cand_type type, const struct sa *addr) { struct cand *cand; int err; if (!base) return EINVAL; err = cand_alloc(&cand, icem, type, base->compid, ice_calc_prio(type, 0, base->compid), base->ifname, base->transp, addr); if (err) return err; cand->base = mem_ref(base); sa_cpy(&cand->rel, &base->addr); return 0; }
struct udp_sock *restund_udp_socket(struct sa *sa, const struct sa *orig, bool ch_ip, bool ch_port) { struct le *le = list_head(&lstnrl); while (le) { struct udp_lstnr *ul = le->data; le = le->next; if (ch_ip && sa_cmp(orig, &ul->bnd_addr, SA_PORT)) continue; if (ch_port && (sa_port(orig) == sa_port(&ul->bnd_addr))) continue; sa_cpy(sa, &ul->bnd_addr); return ul->us; } return NULL; }
static void udp_loop_recv(const struct sa *src, struct mbuf *mb, void *arg) { int err; (void)arg; sa_cpy(&turnc.loop_src, src); if (!turnc.tc) { DEBUG_WARNING("no turn client\n"); return; } if (!sa_isset(turnc.peer, SA_ALL)) { DEBUG_WARNING("Peer not set\n"); return; } err = udp_send(turnc.us, turnc.peer, mb); if (err) { DEBUG_WARNING("turnc send data: %m\n", err); } }
static int cand_alloc(struct cand **candp, struct icem *icem, enum cand_type type, uint8_t compid, uint32_t prio, const char *ifname, enum ice_transp transp, const struct sa *addr) { struct cand *cand; int err; if (!icem) return EINVAL; cand = mem_zalloc(sizeof(*cand), cand_destructor); if (!cand) return ENOMEM; list_append(&icem->lcandl, &cand->le, cand); cand->type = type; cand->compid = compid; cand->prio = prio; cand->transp = transp; sa_cpy(&cand->addr, addr); err = compute_foundation(cand); if (ifname) err |= str_dup(&cand->ifname, ifname); if (err) mem_deref(cand); else if (candp) *candp = cand; return err; }
/** * Allocate a new NAT Hairpinning discovery session * * @param nhp Pointer to allocated NAT Hairpinning object * @param proto Transport protocol * @param srv STUN Server IP address and port number * @param proto Transport protocol * @param conf STUN configuration (Optional) * @param hph Hairpinning result handler * @param arg Handler argument * * @return 0 if success, errorcode if failure */ int nat_hairpinning_alloc(struct nat_hairpinning **nhp, const struct sa *srv, int proto, const struct stun_conf *conf, nat_hairpinning_h *hph, void *arg) { struct nat_hairpinning *nh; struct sa local; int err; if (!srv || !hph) return EINVAL; nh = mem_zalloc(sizeof(*nh), hairpinning_destructor); if (!nh) return ENOMEM; err = stun_alloc(&nh->stun, conf, NULL, NULL); if (err) goto out; sa_cpy(&nh->srv, srv); nh->proto = proto; nh->hph = hph; nh->arg = arg; switch (proto) { case IPPROTO_UDP: err = udp_listen(&nh->us, NULL, udp_recv_handler, nh); break; case IPPROTO_TCP: sa_set_in(&local, 0, 0); /* * Part I - Allocate and bind all sockets */ err = tcp_sock_alloc(&nh->ts, &local, tcp_conn_handler, nh); if (err) break; err = tcp_conn_alloc(&nh->tc, &nh->srv, tcp_estab_handler, tcp_recv_handler, tcp_close_handler, nh); if (err) break; err = tcp_sock_bind(nh->ts, &local); if (err) break; err = tcp_sock_local_get(nh->ts, &local); if (err) break; err = tcp_conn_bind(nh->tc, &local); if (err) break; /* * Part II - Listen and connect all sockets */ err = tcp_sock_listen(nh->ts, 5); break; default: err = EPROTONOSUPPORT; break; } out: if (err) mem_deref(nh); else *nhp = nh; return err; }
/** * Allocate a new NAT Mapping Behaviour Discovery session * * @param nmp Pointer to allocated NAT Mapping object * @param laddr Local IP address * @param srv STUN Server IP address and port * @param proto Transport protocol * @param conf STUN configuration (Optional) * @param mh Mapping handler * @param arg Handler argument * * @return 0 if success, errorcode if failure */ int nat_mapping_alloc(struct nat_mapping **nmp, const struct sa *laddr, const struct sa *srv, int proto, const struct stun_conf *conf, nat_mapping_h *mh, void *arg) { struct nat_mapping *nm; int i, err; if (!nmp || !laddr || !srv || !mh) return EINVAL; nm = mem_zalloc(sizeof(*nm), mapping_destructor); if (!nm) return ENOMEM; err = stun_alloc(&nm->stun, conf, NULL, NULL); if (err) goto out; nm->proto = proto; sa_cpy(&nm->laddr, laddr); switch (proto) { case IPPROTO_UDP: err = udp_listen(&nm->us, &nm->laddr, udp_recv_handler, nm); if (err) goto out; err = udp_local_get(nm->us, &nm->laddr); if (err) goto out; break; case IPPROTO_TCP: /* Allocate and bind 3 TCP Sockets */ for (i=0; i<3; i++) { err = tcp_conn_alloc(&nm->tcv[i], srv, tcp_estab_handler, tcp_recv_handler, tcp_close_handler, nm); if (err) goto out; err = tcp_conn_bind(nm->tcv[i], &nm->laddr); if (err) goto out; err = tcp_conn_local_get(nm->tcv[i], &nm->laddr); if (err) goto out; } break; default: err = EPROTONOSUPPORT; goto out; } sa_cpy(&nm->srv, srv); nm->mh = mh; nm->arg = arg; *nmp = nm; out: if (err) mem_deref(nm); return err; }
int udp_sock::send(const struct sa *dst, struct mbuf *mb) { struct sa hdst; TRequestStatus stat; int err = 0; DEBUG_INFO("udp_sock::send %u bytes to %J\n", mbuf_get_left(mb), dst); /* Check for error in e.g. connected state */ if (cerr) { err = cerr; cerr = 0; /* clear error */ return err; } /* call helpers in reverse order */ struct le *le = list_tail(&helpers); while (le) { struct udp_helper *uh; uh = (struct udp_helper *)le->data; le = le->prev; if (dst != &hdst) { sa_cpy(&hdst, dst); dst = &hdst; } if (uh->sendh(&err, &hdst, mb, uh->arg) || err) return err; } TInetAddr ia(sa_in(dst), sa_port(dst)); const TPtrC8 buf_tx(mb->buf + mb->pos, mb->end - mb->pos); if (conn) { cus->iSocket.Connect(ia, stat); User::WaitForRequest(stat); if (KErrNone != stat.Int()) { DEBUG_WARNING("udp_sock::send Connect: kerr=%d\n", stat.Int()); if (KErrGeneral == stat.Int()) return ECONNREFUSED; } #if 0 /* TODO: Cause Access-Violation in WINS emulator! */ cus->iSocket.Send(buf_tx, 0, stat); #else cus->iSocket.SendTo(buf_tx, ia, 0, stat); #endif } else { cus->iSocket.SendTo(buf_tx, ia, 0, stat); } User::WaitForRequest(stat); return kerr2errno(stat.Int()); }
static void stun_response_handler(int err, uint16_t scode, const char *reason, const struct stun_msg *msg, void *arg) { struct nat_mapping *nm = arg; struct stun_attr *map, *other; if (err) { DEBUG_WARNING("stun_response_handler: (%m)\n", err); nm->mh(err, NAT_TYPE_UNKNOWN, nm->arg); return; } switch (scode) { case 0: other = stun_msg_attr(msg, STUN_ATTR_OTHER_ADDR); map = stun_msg_attr(msg, STUN_ATTR_XOR_MAPPED_ADDR); if (!map) map = stun_msg_attr(msg, STUN_ATTR_MAPPED_ADDR); if (!map || !other) { DEBUG_WARNING("missing attributes: %s %s\n", map ? "" : "MAPPED-ADDR", other ? "" : "OTHER-ADDR"); nm->mh(EPROTO, NAT_TYPE_UNKNOWN, nm->arg); return; } nm->map[nm->test_phase-1] = map->v.sa; break; default: DEBUG_WARNING("Binding Error Resp: %u %s\n", scode, reason); nm->mh(EPROTO, NAT_TYPE_UNKNOWN, nm->arg); return; } switch (nm->test_phase) { case 1: /* Test I completed */ if (sa_cmp(&nm->laddr, &nm->map[0], SA_ALL)) { nm->mh(0, NAT_TYPE_ENDP_INDEP, nm->arg); return; } /* Start Test II - the client sends a Binding Request to the alternate *address* */ ++nm->test_phase; sa_set_port(&other->v.other_addr, sa_port(&nm->srv)); sa_cpy(&nm->srv, &other->v.other_addr); err = mapping_send(nm); if (err) { DEBUG_WARNING("stunc_request_send: (%m)\n", err); nm->mh(err, NAT_TYPE_UNKNOWN, nm->arg); } break; case 2: /* Test II completed */ if (sa_cmp(&nm->map[0], &nm->map[1], SA_ALL)) { nm->mh(0, NAT_TYPE_ENDP_INDEP, nm->arg); return; } /* Start Test III - the client sends a Binding Request to the alternate address and port */ ++nm->test_phase; sa_set_port(&nm->srv, sa_port(&other->v.other_addr)); err = mapping_send(nm); if (err) { DEBUG_WARNING("stunc_request_send: (%m)\n", err); nm->mh(err, NAT_TYPE_UNKNOWN, nm->arg); } break; case 3: /* Test III completed */ if (sa_cmp(&nm->map[1], &nm->map[2], SA_ALL)) { nm->mh(0, NAT_TYPE_ADDR_DEP, nm->arg); } else { nm->mh(0, NAT_TYPE_ADDR_PORT_DEP, nm->arg); } ++nm->test_phase; break; default: DEBUG_WARNING("invalid test phase %d\n", nm->test_phase); nm->mh(EINVAL, NAT_TYPE_UNKNOWN, nm->arg); break; } }
static int add_transp_af(const struct sa *laddr) { struct sa local; int err = 0; if (str_isset(uag.cfg->local)) { err = sa_decode(&local, uag.cfg->local, str_len(uag.cfg->local)); if (err) { err = sa_set_str(&local, uag.cfg->local, 0); if (err) { warning("ua: decode failed: '%s'\n", uag.cfg->local); return err; } } if (!sa_isset(&local, SA_ADDR)) { uint16_t port = sa_port(&local); (void)sa_set_sa(&local, &laddr->u.sa); sa_set_port(&local, port); } if (sa_af(laddr) != sa_af(&local)) return 0; } else { sa_cpy(&local, laddr); sa_set_port(&local, 0); } if (uag.use_udp) err |= sip_transp_add(uag.sip, SIP_TRANSP_UDP, &local); if (uag.use_tcp) err |= sip_transp_add(uag.sip, SIP_TRANSP_TCP, &local); if (err) { warning("ua: SIP Transport failed: %m\n", err); return err; } #ifdef USE_TLS if (uag.use_tls) { /* Build our SSL context*/ if (!uag.tls) { const char *cert = NULL; if (str_isset(uag.cfg->cert)) { cert = uag.cfg->cert; info("SIP Certificate: %s\n", cert); } err = tls_alloc(&uag.tls, TLS_METHOD_SSLV23, cert, NULL); if (err) { warning("ua: tls_alloc() failed: %m\n", err); return err; } } if (sa_isset(&local, SA_PORT)) sa_set_port(&local, sa_port(&local) + 1); err = sip_transp_add(uag.sip, SIP_TRANSP_TLS, &local, uag.tls); if (err) { warning("ua: SIP/TLS transport failed: %m\n", err); return err; } } #endif return err; }