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;
}
Example #2
0
static int cons_alloc(struct ui_st **stp, struct ui_prm *prm,
		      ui_input_h *h, void *arg)
{
	struct sa local;
	struct ui_st *st;
	int err;

	if (!stp)
		return EINVAL;

	if (cons_cur) {
		*stp = mem_ref(cons_cur);
		return 0;
	}

	st = mem_zalloc(sizeof(*st), cons_destructor);
	if (!st)
		return ENOMEM;

	st->ui  = mem_ref(cons);
	st->h   = h;
	st->arg = arg;

	err = sa_set_str(&local, "0.0.0.0", prm->port ? prm->port : CONS_PORT);
	if (err)
		goto out;
	err = udp_listen(&st->us, &local, udp_recv, st);
	if (err) {
		DEBUG_WARNING("failed to listen on UDP port %d (%m)\n",
			      sa_port(&local), err);
		goto out;
	}

	err = tcp_listen(&st->ts, &local, tcp_conn_handler, st);
	if (err) {
		DEBUG_WARNING("failed to listen on TCP port %d (%m)\n",
			      sa_port(&local), err);
		goto out;
	}

 out:
	if (err)
		mem_deref(st);
	else
		*stp = cons_cur = st;

	return err;
}
Example #3
0
int tcp_conn_alloc(struct tcp_conn **tcp, const struct sa *peer,
		   tcp_estab_h *eh, tcp_recv_h *rh, tcp_close_h *ch,
		   void *arg)
{
	struct tcp_conn *tc;
	int err;

	if (!tcp || !sa_isset(peer, SA_ALL))
		return EINVAL;

	tc = conn_alloc(NULL, eh, rh, ch, arg);
	if (!tc)
		return ENOMEM;

	TInetAddr ia(sa_in(peer), sa_port(peer));

	err = tc->ctc->Open(ia);
	if (err)
		goto out;

	*tcp = tc;

 out:
	if (err) {
		DEBUG_WARNING("conn_alloc: %J (%s)\n", peer, strerror(err));
		mem_deref(tc);
	}
	return err;
}
TEST_F(TestMedia, gather_turn)
{
	TurnServer srv;
	int err;

	candc_expected = 2;

	err = mediaflow_gather_turn(mf, &srv.addr, "user", "pass");
	ASSERT_EQ(0, err);

	err = re_main_wait(10000);
	ASSERT_EQ(0, err);

	/* verify results after traffic is complete */
	ASSERT_TRUE(srv.nrecv > 0);
	ASSERT_EQ(2, candc);
	ASSERT_EQ(1, n_local_eoc);

	ASSERT_TRUE(str_isset(candv[0].foundation));
	ASSERT_EQ(1, candv[0].compid);
	ASSERT_EQ(IPPROTO_UDP, candv[0].proto);
	ASSERT_TRUE(0 != candv[0].prio);
	ASSERT_EQ(mediaflow_lport(mf), sa_port(&candv[0].addr));
	ASSERT_EQ(ICE_CAND_TYPE_SRFLX, candv[0].type);

	ASSERT_TRUE(str_isset(candv[1].foundation));
	ASSERT_EQ(1, candv[1].compid);
	ASSERT_EQ(IPPROTO_UDP, candv[1].proto);
	ASSERT_TRUE(0 != candv[1].prio);
	ASSERT_TRUE(sa_isset(&candv[1].addr, SA_ALL));
	ASSERT_EQ(ICE_CAND_TYPE_RELAY, candv[1].type);
}
Example #5
0
File: pcp.c Project: GGGO/baresip
static int media_alloc(struct mnat_media **mp, struct mnat_sess *sess,
		       int proto, void *sock1, void *sock2,
		       struct sdp_media *sdpm)
{
	struct mnat_media *m;
	struct sa laddr;
	struct pcp_map map;
	unsigned i;
	int err = 0;

	if (!mp || !sess || !sdpm || proto != IPPROTO_UDP)
		return EINVAL;

	m = mem_zalloc(sizeof(*m), media_destructor);
	if (!m)
		return ENOMEM;

	m->compc = sock2 ? 2 : 1;

	list_append(&sess->medial, &m->le, m);
	m->sess = sess;
	m->sdpm = mem_ref(sdpm);

	for (i=0; i<m->compc; i++) {
		struct comp *comp = &m->compv[i];

		comp->id = i+1;
		comp->media = m;

		err = udp_local_get(i==0 ? sock1 : sock2, &laddr);
		if (err)
			goto out;

		rand_bytes(map.nonce, sizeof(map.nonce));
		map.proto = proto;
		map.int_port = sa_port(&laddr);
		/* note: using same address-family as the PCP server */
		sa_init(&map.ext_addr, sa_af(&pcp_srv));

		info("pcp: %s: internal port for %s is %u\n",
		     sdp_media_name(sdpm),
		     i==0 ? "RTP" : "RTCP",
		     map.int_port);

		err = pcp_request(&comp->pcp, NULL, &pcp_srv, PCP_MAP,
				  LIFETIME, &map, pcp_resp_handler, comp, 0);
		if (err)
			goto out;
	}

 out:
	if (err)
		mem_deref(m);
	else if (mp) {
		*mp = m;
	}

	return err;
}
Example #6
0
void sdp_media_align_formats(struct sdp_media *m, bool offer)
{
    struct sdp_format *rfmt, *lfmt;
    struct le *rle, *lle;

    if (!m || m->disabled || !sa_port(&m->raddr))
        return;

    for (lle=m->lfmtl.head; lle; lle=lle->next) {

        lfmt = lle->data;

        lfmt->sup = false;
    }

    for (rle=m->rfmtl.head; rle; rle=rle->next) {

        rfmt = rle->data;

        for (lle=m->lfmtl.head; lle; lle=lle->next) {

            lfmt = lle->data;

            if (sdp_format_cmp(lfmt, rfmt))
                break;
        }

        if (!lle) {
            rfmt->sup = false;
            continue;
        }

        lfmt->sup = true;
        rfmt->sup = true;

        if (rfmt->ref)
            rfmt->data = mem_deref(rfmt->data);
        else
            rfmt->data = NULL;

        if (lfmt->ref)
            rfmt->data = mem_ref(lfmt->data);
        else
            rfmt->data = lfmt->data;

        rfmt->ref = lfmt->ref;

        if (offer) {
            mem_deref(lfmt->id);
            lfmt->id = mem_ref(rfmt->id);
            lfmt->pt = atoi(lfmt->id ? lfmt->id : "");

            list_unlink(&lfmt->le);
            list_append(&m->lfmtl, &lfmt->le, lfmt);
        }
    }
}
/**
 * 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;
}
Example #8
0
int tcp_conn_bind(struct tcp_conn *tc, const struct sa *local)
{
	if (!tc || !tc->ctc || !local)
		return EINVAL;

	TInetAddr ia(sa_in(local), sa_port(local));

	return tc->ctc->Bind(ia);
}
Example #9
0
int tcp_sock_bind(struct tcp_sock *ts, const struct sa *local)
{
	if (!ts || !ts->cts || !local)
		return EINVAL;

	TInetAddr ia(sa_in(local), sa_port(local));

	return ts->cts->Bind(ia);
}
Example #10
0
void sdp_media_raddr_rtcp(const struct sdp_media *m, struct sa *raddr)
{
    if (!m || !raddr)
        return;

    if (sa_isset(&m->raddr_rtcp, SA_ALL)) {
        *raddr = m->raddr_rtcp;
    }
    else if (sa_isset(&m->raddr_rtcp, SA_PORT)) {
        *raddr = m->raddr;
        sa_set_port(raddr, sa_port(&m->raddr_rtcp));
    }
    else {
        uint16_t port = sa_port(&m->raddr);

        *raddr = m->raddr;
        sa_set_port(raddr, port ? port + 1 : 0);
    }
}
Example #11
0
static int conn_decode(struct sa *sa, const struct pl *pl)
{
	struct pl v;

	if (re_regex(pl->p, pl->l, "IN IP[46]1 [^ ]+", NULL, &v))
		return EBADMSG;

	(void)sa_set(sa, &v, sa_port(sa));

	return 0;
}
Example #12
0
int tcp_conn_connect(struct tcp_conn *tc, const struct sa *peer)
{
	if (!tc || !tc->ctc || !sa_isset(peer, SA_ALL))
		return EINVAL;

	tc->active = true;

	TInetAddr ia(sa_in(peer), sa_port(peer));

	return tc->ctc->Connect(ia);
}
Example #13
0
/**
 * Bind to a TCP Socket
 *
 * @param ts    TCP Socket
 * @param local Local bind address
 *
 * @return 0 if success, otherwise errorcode
 */
int tcp_sock_bind(struct tcp_sock *ts, const struct sa *local)
{
	struct addrinfo hints, *res = NULL, *r;
	char addr[64] = "";
	char serv[NI_MAXSERV] = "0";
	int error, err;

	if (!ts || ts->fd<0)
		return EINVAL;

	if (local) {
		(void)re_snprintf(addr, sizeof(addr), "%H",
				  sa_print_addr, local);
		(void)re_snprintf(serv, sizeof(serv), "%u", sa_port(local));
	}

	memset(&hints, 0, sizeof(hints));
	/* set-up hints structure */
	hints.ai_family   = PF_UNSPEC;
	hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	error = getaddrinfo(addr[0] ? addr : NULL, serv, &hints, &res);
	if (error) {
#ifdef WIN32
		DEBUG_WARNING("sock_bind: getaddrinfo: wsaerr=%d\n",
			      WSAGetLastError());
#endif
		DEBUG_WARNING("sock_bind: getaddrinfo: %s:%s error=%d (%s)\n",
			      addr, serv, error, gai_strerror(error));
		return EADDRNOTAVAIL;
	}

	err = EINVAL;
	for (r = res; r; r = r->ai_next) {

		if (bind(ts->fd, r->ai_addr, SIZ_CAST r->ai_addrlen) < 0) {
			err = errno;
			DEBUG_WARNING("sock_bind: bind: %m (af=%d, %J)\n",
				      err, r->ai_family, local);
			continue;
		}

		/* OK */
		err = 0;
		break;
	}

	freeaddrinfo(res);

	return err;
}
Example #14
0
int udp_sock::listen(const struct sa *local)
{
	TInetAddr ia(sa_in(local), sa_port(local));

	const TInt ret = cus->iSocket.Bind(ia);
	if (KErrNone != ret)
		return kerr2errno(ret);

	cus->StartReceiving();

	return 0;
}
Example #15
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;
}
int stun_uri_encode(struct re_printf *pf, const struct stun_uri *uri)
{
	const char *scheme;
	uint16_t dport;
	int err;

	if (!uri)
		return 0;

	dport = uri->secure ? 5349 : 3478;

	switch (uri->scheme) {

	case STUN_SCHEME_STUN:
		scheme = "stun";
		break;

	case STUN_SCHEME_TURN:
		scheme = "turn";
		break;

	default:
		return EINVAL;
	}

	err = re_hprintf(pf, "%s%s:%j", scheme, uri->secure ? "s" : "",
			 &uri->addr);
	if (err)
		return err;

	if (sa_port(&uri->addr) != dport) {
		err |= re_hprintf(pf, ":%u", sa_port(&uri->addr));
	}

	if (uri->proto == IPPROTO_TCP)
		err |= re_hprintf(pf, "?transport=tcp");

	return err;
}
Example #17
0
static bool udp_helper_send(int *err, struct sa *dst,
			    struct mbuf *mb, void *arg)
{
	struct menc_media *st = arg;
	unsigned int length;
	zrtp_status_t s;
	const char *proto_name = "rtp";
	enum pkt_type ptype = get_packet_type(mb);

	if (drop_packets(st))
		return true;

	length = (unsigned int)mbuf_get_left(mb);

	/* only RTP/RTCP packets should be processed */
	if (ptype == PKT_TYPE_RTCP) {
		proto_name = "rtcp";
		s = zrtp_process_rtcp(st->zrtp_stream,
			    (char *)mbuf_buf(mb), &length);
	}
	else if (ptype == PKT_TYPE_RTP) {
		s = zrtp_process_rtp(st->zrtp_stream,
			    (char *)mbuf_buf(mb), &length);
	}
	else
		return false;

	if (s != zrtp_status_ok) {

		if (s == zrtp_status_drop)
			return true;

		warning("zrtp: send(port=%d): zrtp_process_%s failed"
			" (status = %d '%s')\n",
			sa_port(dst), proto_name, s, zrtp_log_status2str(s));
		return false;
	}

	/* make sure target buffer is large enough */
	if (length > mbuf_get_space(mb)) {
		warning("zrtp: zrtp_process_%s: length > space (%u > %u)\n",
			proto_name, length, mbuf_get_space(mb));
		*err = ENOMEM;
	}

	mb->end = mb->pos + length;

	return false;
}
/**
 * Encode the SDP "remote-candidates" Attribute
 *
 * @param pf   Print function
 * @param icem ICE Media object
 *
 * @return 0 if success, otherwise errorcode
 */
int ice_remotecands_encode(struct re_printf *pf, const struct icem *icem)
{
	struct le *le;
	int err = 0;

	if (!icem)
		return EINVAL;

	for (le = icem->rcandl.head; le && !err; le = le->next) {

		const struct ice_cand *rcand = le->data;

		err = re_hprintf(pf, "%s%d %j %u",
				 icem->rcandl.head==le ? "" : " ",
				 rcand->compid,
				 &rcand->addr, sa_port(&rcand->addr));
	}

	return err;
}
Example #19
0
static int listen_handler(const struct pl *addrport, void *arg)
{
    uint32_t sockbuf_size = *(uint32_t *)arg;
    struct udp_lstnr *ul = NULL;
    int err = ENOMEM;

    ul = mem_zalloc(sizeof(*ul), destructor);
    if (!ul) {
        restund_warning("udp listen error: %s\n", strerror(err));
        goto out;
    }

    list_append(&lstnrl, &ul->le, ul);

    err = sa_decode(&ul->bnd_addr, addrport->p, addrport->l);
    if (err || sa_is_any(&ul->bnd_addr) || !sa_port(&ul->bnd_addr)) {
        restund_warning("bad udp_listen directive: '%r'\n", addrport);
        err = EINVAL;
        goto out;
    }

    err = udp_listen(&ul->us, &ul->bnd_addr, udp_recv, ul);
    if (err) {
        restund_warning("udp listen %J: %s\n", &ul->bnd_addr,
                        strerror(err));
        goto out;
    }

    if (sockbuf_size > 0)
        (void)udp_sockbuf_set(ul->us, sockbuf_size);

    restund_debug("udp listen: %J\n", &ul->bnd_addr);

out:
    if (err)
        mem_deref(ul);

    return err;
}
Example #20
0
static bool udp_helper_recv(struct sa *src, struct mbuf *mb, void *arg)
{
	struct menc_media *st = arg;
	unsigned int length;
	zrtp_status_t s;
	const char *proto_name = "srtp";
	enum pkt_type ptype = get_packet_type(mb);

	if (drop_packets(st))
		return true;

	length = (unsigned int)mbuf_get_left(mb);

	if (ptype == PKT_TYPE_RTCP) {
		proto_name = "srtcp";
		s = zrtp_process_srtcp(st->zrtp_stream,
			    (char *)mbuf_buf(mb), &length);
	}
	else if (ptype == PKT_TYPE_RTP || ptype == PKT_TYPE_ZRTP) {
		s = zrtp_process_srtp(st->zrtp_stream,
			    (char *)mbuf_buf(mb), &length);
	}
	else
		return false;

	if (s != zrtp_status_ok) {

		if (s == zrtp_status_drop)
			return true;

		warning("zrtp: recv(port=%d): zrtp_process_%s: %d '%s'\n",
			sa_port(src), proto_name, s, zrtp_log_status2str(s));
		return false;
	}

	mb->end = mb->pos + length;

	return false;
}
Example #21
0
const struct sdp_format *sdp_media_rformat(const struct sdp_media *m,
        const char *name)
{
    struct le *le;

    if (!m || !sa_port(&m->raddr))
        return NULL;

    for (le=m->rfmtl.head; le; le=le->next) {

        const struct sdp_format *fmt = le->data;

        if (!fmt->sup)
            continue;

        if (name && str_casecmp(name, fmt->name))
            continue;

        return fmt;
    }

    return NULL;
}
Example #22
0
static int comp_alloc(struct comp *comp, void *sock)
{
	struct sa laddr;
	int err;

	err = udp_local_get(sock, &laddr);
	if (err)
		goto out;

	comp->int_port = sa_port(&laddr);

	info("natpmp: `%s' stream comp %u local UDP port is %u\n",
	     sdp_media_name(comp->media->sdpm), comp->id, comp->int_port);

	err = natpmp_mapping_request(&comp->natpmp, &natpmp_srv,
				     comp->int_port, 0, comp->lifetime,
				     natpmp_resp_handler, comp);
	if (err)
		goto out;

 out:
	return err;
}
Example #23
0
File: comp.c Project: soramimi/qSIP
int icem_comp_alloc(struct icem_comp **cp, struct icem *icem, int id,
		    void *sock)
{
	struct icem_comp *comp;
	struct sa local;
	int err;

	if (!cp || !icem || id<1 || id>255 || !sock)
		return EINVAL;

	comp = mem_zalloc(sizeof(*comp), destructor);
	if (!comp)
		return ENOMEM;

	comp->id = id;
	comp->sock = mem_ref(sock);
	comp->icem = icem;

	err = udp_register_helper(&comp->uh, sock, icem->layer,
				  NULL, helper_recv_handler, comp);
	if (err)
		goto out;

	err = udp_local_get(comp->sock, &local);
	if (err)
		goto out;

	comp->lport = sa_port(&local);

 out:
	if (err)
		mem_deref(comp);
	else
		*cp = comp;

	return err;
}
Example #24
0
static void aaaa_handler(int err, const struct dnshdr *hdr, struct list *ansl,
			 struct list *authl, struct list *addl, void *arg)
{
	struct stun_dns *dns = arg;
	struct dnsrr *rr;

	(void)hdr;
	(void)authl;
	(void)addl;

	/* Find A answers */
	rr = dns_rrlist_find(ansl, NULL, DNS_TYPE_AAAA, DNS_CLASS_IN, false);
	if (!rr) {
		err = err ? err : EDESTADDRREQ;
		goto out;
	}

	sa_set_in6(&dns->srv, rr->rdata.aaaa.addr, sa_port(&dns->srv));

	DEBUG_INFO("AAAA answer: %j\n", &dns->srv);

 out:
	resolved(dns, err);
}
Example #25
0
int stream_alloc(struct stream **sp, const struct config_avt *cfg,
		 struct call *call, struct sdp_session *sdp_sess,
		 const char *name, int label,
		 const struct mnat *mnat, struct mnat_sess *mnat_sess,
		 const struct menc *menc, struct menc_sess *menc_sess,
		 const char *cname,
		 stream_rtp_h *rtph, stream_rtcp_h *rtcph, void *arg)
{
	struct stream *s;
	int err;

	if (!sp || !cfg || !call || !rtph)
		return EINVAL;

	s = mem_zalloc(sizeof(*s), stream_destructor);
	if (!s)
		return ENOMEM;

	s->cfg   = *cfg;
	s->call  = call;
	s->rtph  = rtph;
	s->rtcph = rtcph;
	s->arg   = arg;
	s->pseq  = -1;
	s->rtcp  = s->cfg.rtcp_enable;

	err = stream_sock_alloc(s, call_af(call));
	if (err) {
		warning("stream: failed to create socket for media '%s'"
			" (%m)\n", name, err);
		goto out;
	}

	err = str_dup(&s->cname, cname);
	if (err)
		goto out;

	/* Jitter buffer */
	if (cfg->jbuf_del.min && cfg->jbuf_del.max) {

		err = jbuf_alloc(&s->jbuf, cfg->jbuf_del.min,
				 cfg->jbuf_del.max);
		if (err)
			goto out;
	}

	err = sdp_media_add(&s->sdp, sdp_sess, name,
			    sa_port(rtp_local(s->rtp)),
			    (menc && menc->sdp_proto) ? menc->sdp_proto :
			    sdp_proto_rtpavp);
	if (err)
		goto out;

	if (label) {
		err |= sdp_media_set_lattr(s->sdp, true,
					   "label", "%d", label);
	}

	/* RFC 5506 */
	if (s->rtcp)
		err |= sdp_media_set_lattr(s->sdp, true, "rtcp-rsize", NULL);

	/* RFC 5576 */
	if (s->rtcp) {
		err |= sdp_media_set_lattr(s->sdp, true,
					   "ssrc", "%u cname:%s",
					   rtp_sess_ssrc(s->rtp), cname);
	}

	/* RFC 5761 */
	if (cfg->rtcp_mux)
		err |= sdp_media_set_lattr(s->sdp, true, "rtcp-mux", NULL);

	if (err)
		goto out;

	if (mnat) {
		err = mnat->mediah(&s->mns, mnat_sess, IPPROTO_UDP,
				   rtp_sock(s->rtp),
				   s->rtcp ? rtcp_sock(s->rtp) : NULL,
				   s->sdp);
		if (err)
			goto out;
	}

	if (menc) {
		s->menc  = menc;
		s->mencs = mem_ref(menc_sess);
		err = menc->mediah(&s->mes, menc_sess,
				   s->rtp,
				   IPPROTO_UDP,
				   rtp_sock(s->rtp),
				   s->rtcp ? rtcp_sock(s->rtp) : NULL,
				   s->sdp);
		if (err)
			goto out;
	}

	if (err)
		goto out;

	s->pt_enc = -1;

	metric_init(&s->metric_tx);
	metric_init(&s->metric_rx);

	list_append(call_streaml(call), &s->le, s);

 out:
	if (err)
		mem_deref(s);
	else
		*sp = s;

	return err;
}
Example #26
0
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());
}
Example #27
0
int stream_alloc(struct stream **sp, struct call *call,
		 struct sdp_session *sdp_sess,
		 const char *name, int label,
		 const struct mnat *mnat, struct mnat_sess *mnat_sess,
		 const struct menc *menc, struct menc_sess *menc_sess,
		 stream_rtp_h *rtph, stream_rtcp_h *rtcph, void *arg)
{
	struct stream *s;
	int err;

	if (!sp || !call || !rtph)
		return EINVAL;

	s = mem_zalloc(sizeof(*s), stream_destructor);
	if (!s)
		return ENOMEM;

	MAGIC_INIT(s);

	tmr_init(&s->tmr_stats);

	s->call  = call;

	if (!str_casecmp(name, "audio"))
		s->type = STREAM_AUDIO;
	else if (!str_casecmp(name, "video"))
		s->type = STREAM_VIDEO;
	else
		s->type = STREAM_UNKNOWN;

	s->rtph  = rtph;
	s->rtcph = rtcph;
	s->arg   = arg;
	s->pseq  = -1;
	s->rtcp  = config.avt.rtcp_enable;

	err = stream_sock_alloc(s, call_af(call));
	if (err)
		goto out;

	/* Jitter buffer */
	if (config.avt.jbuf_del.min && config.avt.jbuf_del.max) {

		err = jbuf_alloc(&s->jbuf, config.avt.jbuf_del.min,
				 config.avt.jbuf_del.max);
		if (err)
			goto out;
	}

	err = sdp_media_add(&s->sdp, sdp_sess, name,
			    sa_port(rtp_local(s->rtp)),
			    (menc && menc->sdp_proto) ? menc->sdp_proto :
			    sdp_proto_rtpavp);
	if (err)
		goto out;

	if (label) {
		err |= sdp_media_set_lattr(s->sdp, true,
					   "label", "%d", label);
	}

	/* RFC 5761 */
	if (config.avt.rtcp_mux)
		err |= sdp_media_set_lattr(s->sdp, true, "rtcp-mux", NULL);

	if (mnat) {
		err |= mnat->mediah(&s->mns, mnat_sess, IPPROTO_UDP,
				    rtp_sock(s->rtp),
				    (s->rtcp && !config.avt.rtcp_mux)
				    ? rtcp_sock(s->rtp) : NULL,
				    s->sdp);
	}

	if (menc) {
		s->menc = menc;
		s->mencs = mem_ref(menc_sess);
		err |= menc->mediah(&s->mes, menc_sess, IPPROTO_UDP,
				    rtp_sock(s->rtp),
				    s->rtcp ? rtcp_sock(s->rtp) : NULL,
				    s->sdp);
	}

	if (err)
		goto out;

	s->pt_enc = -1;

	list_append(call_streaml(call), &s->le, s);

 out:
	if (err)
		mem_deref(s);
	else
		*sp = s;

	return err;
}
Example #28
0
static int media_encode(const struct sdp_media *m, struct mbuf *mb, bool offer)
{
	enum sdp_bandwidth i;
	int err, supc = 0;
	bool disabled;
	struct le *le;
	uint16_t port;

	for (le=m->lfmtl.head; le; le=le->next) {

		const struct sdp_format *fmt = le->data;

		if (fmt->sup)
			++supc;
	}

	if (m->disabled || supc == 0 || (!offer && !sa_port(&m->raddr))) {
		disabled = true;
		port = 0;
	}
	else {
		disabled = false;
		port = sa_port(&m->laddr);
	}

	err = mbuf_printf(mb, "m=%s %u %s", m->name, port, m->proto);

	if (disabled) {
		err |= mbuf_write_str(mb, " 0\r\n");
		return err;
	}

	for (le=m->lfmtl.head; le; le=le->next) {

		const struct sdp_format *fmt = le->data;

		if (!fmt->sup)
			continue;

		err |= mbuf_printf(mb, " %s", fmt->id);
	}

	err |= mbuf_write_str(mb, "\r\n");

	if (sa_isset(&m->laddr, SA_ADDR)) {
		const int ipver = sa_af(&m->laddr) == AF_INET ? 4 : 6;
		err |= mbuf_printf(mb, "c=IN IP%d %j\r\n", ipver, &m->laddr);
	}

	for (i=SDP_BANDWIDTH_MIN; i<SDP_BANDWIDTH_MAX; i++) {

		if (m->lbwv[i] < 0)
			continue;

		err |= mbuf_printf(mb, "b=%s:%i\r\n",
				   sdp_bandwidth_name(i), m->lbwv[i]);
	}

	for (le=m->lfmtl.head; le; le=le->next) {

		const struct sdp_format *fmt = le->data;

		if (!fmt->sup || !str_len(fmt->name))
			continue;

		err |= mbuf_printf(mb, "a=rtpmap:%s %s/%u",
				   fmt->id, fmt->name, fmt->srate);

		if (fmt->ch > 1)
			err |= mbuf_printf(mb, "/%u", fmt->ch);

		err |= mbuf_printf(mb, "\r\n");

		if (str_len(fmt->params))
			err |= mbuf_printf(mb, "a=fmtp:%s %s\r\n",
					   fmt->id, fmt->params);
	}

	if (sa_isset(&m->laddr_rtcp, SA_ALL))
		err |= mbuf_printf(mb, "a=rtcp:%u IN IP%d %j\r\n",
				   sa_port(&m->laddr_rtcp),
				   (AF_INET == sa_af(&m->laddr_rtcp)) ? 4 : 6,
				   &m->laddr_rtcp);
	else if (sa_isset(&m->laddr_rtcp, SA_PORT))
		err |= mbuf_printf(mb, "a=rtcp:%u\r\n",
				   sa_port(&m->laddr_rtcp));

	err |= mbuf_printf(mb, "a=%s\r\n",
			   sdp_dir_name(offer ? m->ldir : m->ldir & m->rdir));

	for (le = m->lattrl.head; le; le = le->next)
		err |= mbuf_printf(mb, "%H", sdp_attr_print, le->data);

	return err;
}
Example #29
0
/**
 * Bind a TCP Connection to a local address
 *
 * @param tc    TCP Connection object
 * @param local Local bind address
 *
 * @return 0 if success, otherwise errorcode
 */
int tcp_conn_bind(struct tcp_conn *tc, const struct sa *local)
{
	struct addrinfo hints, *res = NULL, *r;
	char addr[64] = "";
	char serv[NI_MAXSERV] = "0";
	int error, err;

	if (!tc)
		return EINVAL;

	if (local) {
		(void)re_snprintf(addr, sizeof(addr), "%H",
				  sa_print_addr, local);
		(void)re_snprintf(serv, sizeof(serv), "%u", sa_port(local));
	}

	memset(&hints, 0, sizeof(hints));
	/* set-up hints structure */
	hints.ai_family   = PF_UNSPEC;
	hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	error = getaddrinfo(addr[0] ? addr : NULL, serv, &hints, &res);
	if (error) {
		DEBUG_WARNING("conn_bind: getaddrinfo(): (%s)\n",
			      gai_strerror(error));
		return EADDRNOTAVAIL;
	}

	err = EINVAL;
	for (r = res; r; r = r->ai_next) {

		(void)net_sockopt_reuse_set(tc->fdc, true);

		/* bind to local address */
		if (bind(tc->fdc, r->ai_addr, SIZ_CAST r->ai_addrlen) < 0) {

			/* Special case for mingw32/wine */
			if (0 == errno) {
				goto ok;
			}

			err = errno;
			DEBUG_WARNING("conn_bind: bind(): %J: %m\n",
				      local, err);
			continue;
		}

	ok:
		/* OK */
		err = 0;
		break;
	}

	freeaddrinfo(res);

	if (err) {
		DEBUG_WARNING("conn_bind failed: %J (%m)\n", local, err);
	}

	return err;
}
Example #30
0
/**
 * Connect to a remote peer
 *
 * @param tc   TCP Connection object
 * @param peer Network address of peer
 *
 * @return 0 if success, otherwise errorcode
 */
int tcp_conn_connect(struct tcp_conn *tc, const struct sa *peer)
{
	struct addrinfo hints, *res = NULL, *r;
	char addr[64];
	char serv[NI_MAXSERV];
	int error, err = 0;

	if (!tc || !sa_isset(peer, SA_ALL))
		return EINVAL;

	tc->active = true;

	if (tc->fdc < 0) {
		DEBUG_WARNING("invalid fd\n");
		return EBADF;
	}

	memset(&hints, 0, sizeof(hints));
	/* set-up hints structure */
	hints.ai_family   = PF_UNSPEC;
	hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	(void)re_snprintf(addr, sizeof(addr), "%H",
			  sa_print_addr, peer);
	(void)re_snprintf(serv, sizeof(serv), "%u", sa_port(peer));

	error = getaddrinfo(addr, serv, &hints, &res);
	if (error) {
		DEBUG_WARNING("connect: getaddrinfo(): (%s)\n",
			      gai_strerror(error));
		return EADDRNOTAVAIL;
	}

	for (r = res; r; r = r->ai_next) {
		struct sockaddr *sa = r->ai_addr;

	again:
		if (0 == connect(tc->fdc, sa, SIZ_CAST r->ai_addrlen)) {
			err = 0;
			goto out;
		}
		else {
#ifdef WIN32
			/* Special error handling for Windows */
			if (WSAEWOULDBLOCK == WSAGetLastError()) {
				err = 0;
				goto out;
			}
#endif

			/* Special case for mingw32/wine */
			if (0 == errno) {
				err = 0;
				goto out;
			}

			if (EINTR == errno)
				goto again;

			if (EINPROGRESS != errno && EALREADY != errno) {
				err = errno;
				DEBUG_INFO("connect: connect() %J: %m\n",
					   peer, err);
			}
		}
	}

 out:
	freeaddrinfo(res);

	if (err)
		return err;

	return fd_listen(tc->fdc, FD_READ | FD_WRITE | FD_EXCEPT,
			 tcp_recv_handler, tc);
}