예제 #1
0
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;
}
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;
}
예제 #3
0
/**
 * 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;
}
예제 #4
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);
}
예제 #6
0
static void turn_handler2(int err, uint16_t scode, const char *reason,
			  const struct sa *relay_addr,
			  const struct sa *mapped_addr,
			  const struct stun_msg *msg,
			  void *arg)
{
	struct mnat_media *m = arg;
	(void)mapped_addr;
	(void)msg;

	if (!err && !scode) {

		sdp_media_set_laddr_rtcp(m->sdpm, relay_addr);

		m->addr2 = *relay_addr;

		if (m->turnc1 && !sa_isset(&m->addr1, SA_ALL))
			return;

		if (--m->sess->mediac)
			return;
	}

	m->sess->estabh(err, scode, reason, m->sess->arg);
}
예제 #7
0
파일: turn.c 프로젝트: alfredh/restunc
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);
		}
	}
}
예제 #8
0
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;
}
예제 #9
0
파일: cons.c 프로젝트: GGGO/baresip
static int output_handler(const char *str)
{
	struct mbuf *mb;
	int err = 0;

	if (!str)
		return EINVAL;

	mb = mbuf_alloc(256);
	if (!mb)
		return ENOMEM;

	mbuf_write_str(mb, str);

	if (sa_isset(&cons->udp_peer, SA_ALL)) {
		mb->pos = 0;
		err |= udp_send(cons->us, &cons->udp_peer, mb);
	}

	if (cons->tc) {
		mb->pos = 0;
		err |= tcp_send(cons->tc, mb);
	}

	mem_deref(mb);

	return err;
}
예제 #10
0
파일: zrtp.c 프로젝트: Studio-Link/baresip
static int on_send_packet(const zrtp_stream_t *stream,
			  char *rtp_packet,
			  unsigned int rtp_packet_length)
{
	struct menc_media *st = zrtp_stream_get_userdata(stream);
	struct mbuf *mb;
	int err;

	if (drop_packets(st))
		return zrtp_status_ok;

	if (!sa_isset(&st->raddr, SA_ALL))
		return zrtp_status_ok;

	mb = mbuf_alloc(PRESZ + rtp_packet_length);
	if (!mb)
		return zrtp_status_alloc_fail;

	mb->pos = PRESZ;
	(void)mbuf_write_mem(mb, (void *)rtp_packet, rtp_packet_length);
	mb->pos = PRESZ;

	err = udp_send_helper(st->rtpsock, &st->raddr, mb, st->uh_rtp);
	if (err) {
		warning("zrtp: udp_send %u bytes (%m)\n",
			rtp_packet_length, err);
	}

	mem_deref(mb);

	return zrtp_status_ok;
}
예제 #11
0
int stream_send(struct stream *s, bool marker, int pt, uint32_t ts,
		struct mbuf *mb)
{
	int err = 0;

	if (!s)
		return EINVAL;

	if (!sa_isset(sdp_media_raddr(s->sdp), SA_ALL))
		return 0;
	if (sdp_media_dir(s->sdp) != SDP_SENDRECV)
		return 0;

	s->stats.b_tx += mbuf_get_left(mb);

	if (pt < 0)
		pt = s->pt_enc;

	if (pt >= 0) {
		err = rtp_send(s->rtp, sdp_media_raddr(s->sdp),
			       marker, pt, ts, mb);
	}

	rtpkeep_refresh(s->rtpkeep, ts);

	++s->stats.n_tx;

	return err;
}
예제 #12
0
파일: ua.c 프로젝트: pasichnichenko/baresip
static int ua_add_transp(void)
{
	int err = 0;

	if (!uag.prefer_ipv6) {
		if (sa_isset(net_laddr_af(AF_INET), SA_ADDR))
			err |= add_transp_af(net_laddr_af(AF_INET));
	}

#if HAVE_INET6
	if (sa_isset(net_laddr_af(AF_INET6), SA_ADDR))
		err |= add_transp_af(net_laddr_af(AF_INET6));
#endif

	return err;
}
예제 #13
0
int stream_send(struct stream *s, bool marker, int pt, uint32_t ts,
		struct mbuf *mb)
{
	int err = 0;

	if (!s)
		return EINVAL;

	if (!sa_isset(sdp_media_raddr(s->sdp), SA_ALL))
		return 0;
	if (sdp_media_dir(s->sdp) != SDP_SENDRECV)
		return 0;

	metric_add_packet(&s->metric_tx, mbuf_get_left(mb));

	if (pt < 0)
		pt = s->pt_enc;

	if (pt >= 0) {
		err = rtp_send(s->rtp, sdp_media_raddr(s->sdp),
			       marker, pt, ts, mb);
		if (err)
			s->metric_tx.n_err++;
	}

	rtpkeep_refresh(s->rtpkeep, ts);

	return err;
}
예제 #14
0
/**
 * Get the Link-local address for a specific network interface
 *
 * @param ifname Name of the interface
 * @param af     Address family
 * @param ip     Returned link-local address
 *
 * @return 0 if success, otherwise errorcode
 */
int net_if_getlinklocal(const char *ifname, int af, struct sa *ip)
{
	struct sa addr;
	void *argv[3];
	int err;

	if (!ip)
		return EINVAL;

	sa_init(&addr, sa_af(ip));

	argv[0] = (void *)ifname;
	argv[1] = &af;
	argv[2] = &addr;

	err = net_if_apply(linklocal_handler, argv);
	if (err)
		return err;

	if (!sa_isset(&addr, SA_ADDR))
		return ENOENT;

	*ip = addr;

	return 0;
}
예제 #15
0
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;
	int err = 0;

	if (!mp || !sess || !sdpm)
		return EINVAL;

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

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

	if (sa_isset(&sess->srv, SA_ALL))
		err = media_start(sess, m);

	if (err)
		mem_deref(m);
	else {
		*mp = m;
		++sess->mediac;
	}

	return err;
}
예제 #16
0
파일: zrtp.c 프로젝트: czarkoff/baresip
static int media_alloc(struct menc_media **stp, struct menc_sess *sess,
		       struct rtp_sock *rtp,
		       int proto, void *rtpsock, void *rtcpsock,
		       struct sdp_media *sdpm)
{
	struct menc_media *st;
	zrtp_status_t s;
	int layer = 10; /* above zero */
	int err = 0;
	(void)rtcpsock;

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

	st = *stp;
	if (st)
		goto start;

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

	st->sess = sess;
	st->rtpsock = mem_ref(rtpsock);

	err = udp_register_helper(&st->uh, rtpsock, layer,
				  udp_helper_send, udp_helper_recv, st);
	if (err)
		goto out;

	s = zrtp_stream_attach(sess->zrtp_session, &st->zrtp_stream);
	if (s != zrtp_status_ok) {
		warning("zrtp: zrtp_stream_attach failed (status=%d)\n", s);
		err = EPROTO;
		goto out;
	}

	zrtp_stream_set_userdata(st->zrtp_stream, st);

 out:
	if (err) {
		mem_deref(st);
		return err;
	}
	else
		*stp = st;

 start:
	if (sa_isset(sdp_media_raddr(sdpm), SA_ALL)) {
		st->raddr = *sdp_media_raddr(sdpm);

		s = zrtp_stream_start(st->zrtp_stream, rtp_sess_ssrc(rtp));
		if (s != zrtp_status_ok) {
			warning("zrtp: zrtp_stream_start: status = %d\n", s);
		}
	}

	return err;
}
예제 #17
0
파일: rtp.c 프로젝트: hbowden/re
/**
 * Send RTCP packet(s) to the Peer
 *
 * @param rs RTP Socket
 * @param mb Buffer containing the RTCP Packet(s)
 *
 * @return 0 for success, otherwise errorcode
 */
int rtcp_send(struct rtp_sock *rs, struct mbuf *mb)
{
	if (!rs || !rs->sock_rtcp || !sa_isset(&rs->rtcp_peer, SA_ALL))
		return EINVAL;

	return udp_send(rs->rtcp_mux ? rs->sock_rtp : rs->sock_rtcp,
			&rs->rtcp_peer, mb);
}
예제 #18
0
/**
 * 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;
}
예제 #19
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);
    }
}
예제 #20
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);
}
예제 #21
0
파일: lcand.c 프로젝트: alfredh/rew
int trice_lcands_debug(struct re_printf *pf, const struct list *lst)
{
	struct le *le;
	int err;

	err = re_hprintf(pf, " (%u)\n", list_count(lst));

	for (le = list_head(lst); le && !err; le = le->next) {

		const struct ice_lcand *cand = le->data;

		err |= re_hprintf(pf, "  {%u} [tx=%3zu, rx=%3zu] "
				  "fnd=%-8s prio=%08x ",
				  cand->attr.compid,
				  cand->stats.n_tx,
				  cand->stats.n_rx,
				  cand->attr.foundation,
				  cand->attr.prio);

		if (str_isset(cand->ifname))
			err |= re_hprintf(pf, "%s:", cand->ifname);

		err |= re_hprintf(pf, "%24H", trice_cand_print, cand);

		if (sa_isset(&cand->base_addr, SA_ADDR)) {
			err |= re_hprintf(pf, " (base-addr = %J)",
					  &cand->base_addr);
		}

		if (sa_isset(&cand->attr.rel_addr, SA_ADDR)) {
			err |= re_hprintf(pf, " (rel-addr = %J)",
					  &cand->attr.rel_addr);
		}

		err |= re_hprintf(pf, "\n");
	}

	return err;
}
예제 #22
0
파일: lcand.c 프로젝트: alfredh/rew
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;
}
	static void mediaflow_localcand_handler(
					const struct zapi_candidate *candv,
					size_t candc, void *arg)
	{
		TestMedia *tm = static_cast<TestMedia *>(arg);
		ASSERT_TRUE(tm->candc < ARRAY_SIZE(tm->candv));

		for (size_t i=0; i<candc; i++) {
			struct ice_cand_attr *cand = &tm->candv[tm->candc];
			const struct zapi_candidate *zcand = &candv[i];
			int err;

			if (0 == str_casecmp(zcand->sdp,
					     "a=end-of-candidates")) {
				++tm->n_local_eoc;
				continue;
			}

			tm->candc++;

			err = ice_cand_attr_decode(cand, zcand->sdp);
			ASSERT_EQ(0, err);

			ASSERT_STREQ("audio", zcand->mid);
			ASSERT_EQ(0, zcand->mline_index);

			/* verify that SRFLX and RELAY candidates contain
			   the related address */
			switch (cand->type) {

			case ICE_CAND_TYPE_SRFLX:
			case ICE_CAND_TYPE_RELAY:
				ASSERT_TRUE(sa_isset(&cand->rel_addr, SA_ALL));
				break;
			default:
				break;
			}
		}

		if (tm->candc >= tm->candc_expected)
			re_cancel();
	}
예제 #24
0
static void stun_response_handler(int err, uint16_t scode, const char *reason,
				  const struct stun_msg *msg, void *arg)
{
	struct sip_udpconn *uc = arg;
	struct stun_attr *attr;
	(void)reason;

	if (err || scode) {
		err = err ? err : EPROTO;
		goto out;
	}

	attr = stun_msg_attr(msg, STUN_ATTR_XOR_MAPPED_ADDR);
	if (!attr) {
		attr = stun_msg_attr(msg, STUN_ATTR_MAPPED_ADDR);
		if (!attr) {
			err = EPROTO;
			goto out;
		}
	}

	if (!sa_isset(&uc->maddr, SA_ALL)) {
		uc->maddr = attr->v.sa;
	}
	else if (!sa_cmp(&uc->maddr, &attr->v.sa, SA_ALL)) {
		err = ENOTCONN;
		goto out;
	}

 out:
	if (err) {
		udpconn_close(uc, err);
		mem_deref(uc);
	}
	else {
		tmr_start(&uc->tmr_ka, sip_keepalive_wait(uc->ka_interval),
			  udpconn_keepalive_handler, uc);
	}
}
예제 #25
0
파일: cand.c 프로젝트: Issic47/libre
int icem_cands_debug(struct re_printf *pf, const struct list *lst)
{
	struct le *le;
	int err;

	err = re_hprintf(pf, " (%u)\n", list_count(lst));

	for (le = list_head(lst); le && !err; le = le->next) {

		const struct cand *cand = le->data;

		err |= re_hprintf(pf, "  {%u} fnd=%-2s prio=%08x %24H",
				  cand->compid, cand->foundation, cand->prio,
				  icem_cand_print, cand);

		if (sa_isset(&cand->rel, SA_ADDR))
			err |= re_hprintf(pf, " (rel-addr=%J)", &cand->rel);

		err |= re_hprintf(pf, "\n");
	}

	return err;
}
예제 #26
0
파일: turn.c 프로젝트: alfredh/restunc
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);
	}
}
예제 #27
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);
}
예제 #28
0
파일: turn.c 프로젝트: AmesianX/restund
static int module_init(void)
{
	uint32_t x, bsize = ALLOC_DEFAULT_BSIZE;
	struct pl opt;
	int err = 0;

	restund_stun_register_handler(&stun);
	restund_cmd_subscribe(&cmd_turn);
	restund_cmd_subscribe(&cmd_turnstats);

	/* turn_external_addr */
	if (!conf_get(restund_conf(), "turn_relay_addr", &opt))
		err = sa_set(&turnd.rel_addr, &opt, 0);
	else
		sa_init(&turnd.rel_addr, AF_UNSPEC);

	if (err) {
		restund_error("turn: bad turn_relay_addr: '%r'\n", &opt);
		goto out;
	}

	/* turn_external_addr6 */
	if (!conf_get(restund_conf(), "turn_relay_addr6", &opt))
		err = sa_set(&turnd.rel_addr6, &opt, 0);
	else
		sa_init(&turnd.rel_addr6, AF_UNSPEC);

	if (err) {
		restund_error("turn: bad turn_relay_addr6: '%r'\n", &opt);
		goto out;
	}

	if (!sa_isset(&turnd.rel_addr, SA_ADDR) &&
	    !sa_isset(&turnd.rel_addr6, SA_ADDR)) {
		restund_error("turn: no relay address configured\n");
		err = EINVAL;
		goto out;
	}

	/* turn_max_lifetime, turn_max_allocations, udp_sockbuf_size */
	turnd.lifetime_max = TURN_DEFAULT_LIFETIME;
	conf_get_u32(restund_conf(), "turn_max_lifetime", &turnd.lifetime_max);
	conf_get_u32(restund_conf(), "turn_max_allocations", &bsize);
	conf_get_u32(restund_conf(), "udp_sockbuf_size",
		     &turnd.udp_sockbuf_size);

	for (x=2; (uint32_t)1<<x<bsize; x++);
	bsize = 1<<x;

	err = hash_alloc(&turnd.ht_alloc, bsize);
	if (err) {
		restund_error("turnd hash alloc error: %m\n", err);
		goto out;
	}

	restund_debug("turn: lifetime=%u ext=%j ext6=%j bsz=%u\n",
		      turnd.lifetime_max, &turnd.rel_addr, &turnd.rel_addr6,
		      bsize);

 out:
	return err;
}
예제 #29
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;
}
예제 #30
0
/**
 * Allocate a TCP Connection
 *
 * @param tcp  Returned TCP Connection object
 * @param peer Network address of peer
 * @param eh   TCP Connection Established handler
 * @param rh   TCP Connection Receive data handler
 * @param ch   TCP Connection close handler
 * @param arg  Handler argument
 *
 * @return 0 if success, otherwise errorcode
 */
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;
	struct addrinfo hints, *res = NULL, *r;
	char addr[64];
	char serv[NI_MAXSERV] = "0";
	int error, err;

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

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

	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));
		err = EADDRNOTAVAIL;
		goto out;
	}

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

		tc->fdc = SOK_CAST socket(r->ai_family, SOCK_STREAM,
					  IPPROTO_TCP);
		if (tc->fdc < 0) {
			err = errno;
			continue;
		}

		err = net_sockopt_blocking_set(tc->fdc, false);
		if (err) {
			DEBUG_WARNING("connect: nonblock set: %m\n", err);
			(void)close(tc->fdc);
			tc->fdc = -1;
			continue;
		}

		tcp_sockopt_set(tc->fdc);

		err = 0;
		break;
	}

	freeaddrinfo(res);

 out:
	if (err)
		mem_deref(tc);
	else
		*tcp = tc;

	return err;
}