Beispiel #1
0
int test_udp(void)
{
	struct udp_sock *uss2;
	struct udp_test *ut;
	int err;

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

	err  = sa_set_str(&ut->cli, "127.0.0.1", 0);
	err |= sa_set_str(&ut->srv, "127.0.0.1", 0);
	if (err)
		goto out;

	err  = udp_listen(&ut->usc, &ut->cli, udp_recv_client, ut);
	err |= udp_listen(&ut->uss, &ut->srv, udp_recv_server, ut);
	if (err)
		goto out;

	udp_rxbuf_presz_set(ut->uss, 16);

	err  = udp_local_get(ut->usc, &ut->cli);
	err |= udp_local_get(ut->uss, &ut->srv);
	if (err)
		goto out;

	err = udp_register_helper(&ut->uh, ut->usc, 0,
				  udp_helper_send, udp_helper_recv, ut);
	if (err)
		goto out;

	/* expect failure */
	if (!udp_listen(&uss2, &ut->srv, udp_recv_client, ut)) {
		err = EBUSY;
		goto out;
	}

	/* Send from connected client UDP socket */
	err = udp_connect(ut->usc, &ut->srv);
	if (err)
		goto out;

	/* Start test */
	err = send_data(ut->usc, &ut->srv, data0);
	if (err)
		goto out;

	err = re_main_timeout(100);
	if (err)
		goto out;

	if (ut->err)
		err = ut->err;

 out:
	mem_deref(ut);

	return err;
}
Beispiel #2
0
int test_stun_resp(void)
{
	struct sa maddr;
	struct pl resp;
	int err;

	resp.p = (char *)respv4;
	resp.l = sizeof(respv4) - 1;
	err = sa_set_str(&maddr, "192.0.2.1", 32853);
	if (err)
		return err;
	err = test_resp(&resp, &maddr);
	if (err)
		return err;

#ifdef HAVE_INET6
	resp.p = (char *)respv6;
	resp.l = sizeof(respv6) - 1;
	err = sa_set_str(&maddr, "2001:db8:1234:5678:11:2233:4455:6677",
			 32853);
	if (err)
		return err;
	err = test_resp(&resp, &maddr);
#endif

	return err;
}
Beispiel #3
0
int sip_server_create(struct sip_server **srvp)
{
	struct sip_server *srv;
	struct sa laddr_tp;
	int err;

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

	err  = sa_set_str(&laddr_tp, "127.0.0.1", 0);
	err |= sa_set_str(&srv->laddr, "127.0.0.1", 0);
	if (err)
		goto out;

	err = sip_alloc(&srv->sip, NULL, 16, 16, 16,
			"dummy SIP registrar", NULL, NULL);
	if (err)
		goto out;

	err = sip_transp_add(srv->sip, SIP_TRANSP_UDP, &laddr_tp);
	if (err) {
		warning("failed to add sip transport (%m)\n", err);
		goto out;
	}

	err = udp_listen(&srv->us, &srv->laddr, udp_recv, srv);
	if (err) {
		warning("sip: udp_listen on '%J' failed (%d/%m)\n",
			&srv->laddr, err, err);
		goto out;
	}

	err = udp_local_get(srv->us, &srv->laddr);
	if (err) {
		warning("sip: udp_local_get\n");
		goto out;
	}

#if 0
	re_printf("sip: listen on %J\n", &srv->laddr);
#endif

 out:
	if (err)
		mem_deref(srv);
	else
		*srvp = srv;

	return err;
}
void TurnServer::init()
{
	int err;

	err = sa_set_str(&addr, "127.0.0.1", 0);
	if (err)
		goto out;

	err = udp_listen(&us, &addr, turnserver_udp_recv, this);
	if (err)
		goto out;

	err = udp_local_get(us, &addr);
	if (err)
		goto out;

	turnd = (struct turnd *)mem_zalloc(sizeof(*turnd), destructor);

	/* turn_external_addr */
	err = sa_set_str(&turnd->rel_addr, "127.0.0.1", 0);
	if (err) {
		goto out;
	}

	/* turn_max_lifetime, turn_max_allocations, udp_sockbuf_size */
	turnd->lifetime_max = TURN_DEFAULT_LIFETIME;

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

	err = restund_tcp_init(turnd, fake_certificate_rsa);
	ASSERT_EQ(0, err);

	addr_tcp = *restund_tcp_laddr(turnd, false);
	addr_tls = *restund_tcp_laddr(turnd, true);

	turnd->recvh = tcp_handler;
	turnd->arg = this;

	info("turn: listen=%J, lifetime=%u ext=%j\n", &addr,
	      turnd->lifetime_max, &turnd->rel_addr);

 out:
	ASSERT_EQ(0, err);
}
Beispiel #5
0
int dns_server_alloc(struct dns_server **srvp, bool rotate)
{
	struct dns_server *srv;
	int err;

	if (!srvp)
		return EINVAL;

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

	err = sa_set_str(&srv->addr, "127.0.0.1", LOCAL_PORT);
	if (err)
		goto out;

	err = udp_listen(&srv->us, &srv->addr, udp_recv, srv);
	if (err)
		goto out;

	err = udp_local_get(srv->us, &srv->addr);
	if (err)
		goto out;

	srv->rotate = rotate;

 out:
	if (err)
		mem_deref(srv);
	else
		*srvp = srv;

	return err;
}
TEST(media, ice_lite_options_in_sdp)
{
	struct mediaflow *mf = NULL;
	struct sa laddr;
	int err;

	sa_set_str(&laddr, "127.0.0.1", 0);

	err = mediaflow_alloc(&mf, NULL, NULL, &laddr,
			      MEDIAFLOW_ICELITE, CRYPTO_NONE, false,
			      NULL,
			      NULL,
			      NULL,
			      NULL);
	ASSERT_EQ(0, err);
	ASSERT_TRUE(mf != NULL);

	char sdp[4096];

	err = mediaflow_generate_offer(mf, sdp, sizeof(sdp));
	ASSERT_EQ(0, err);

	ASSERT_TRUE(find_in_sdp(sdp, "ice-lite"));
	ASSERT_FALSE(find_in_sdp(sdp, "trickle"));

	mem_deref(mf);
}
	virtual void SetUp() override
	{
		struct sa laddr;
		int err;

#if 0
		log_set_min_level(LOG_LEVEL_WARN);
		log_enable_stderr(true);
#endif

		aucodec_register(&aucodecl, &dummy_opus);
		vidcodec_register(&vidcodecl, &dummy_vp8);

		sa_set_str(&laddr, "127.0.0.1", 0);

		err = create_dtls_srtp_context(&dtls, CERT_TYPE_RSA);
		ASSERT_EQ(0, err);

		err = mediaflow_alloc(&mf, dtls, &aucodecl, &laddr,
				      MEDIAFLOW_TRICKLEICE_DUALSTACK,
				      CRYPTO_DTLS_SRTP,
				      false,
				      mediaflow_localcand_handler,
				      mediaflow_estab_handler,
				      mediaflow_close_handler,
				      this);
		ASSERT_EQ(0, err);
		ASSERT_TRUE(mf != NULL);
	}
Beispiel #8
0
static void lstnr_handler(struct sa *bnd_addr, struct udp_sock *us,
			  void *arg)
{
	const char *maddr;
	struct sa dst;
	int err;

	(void)arg;

	switch (sa_af(bnd_addr)) {

	case AF_INET:
		maddr = "224.0.0.1";
		break;

	case AF_INET6:
		maddr = "ff02::1";
		break;

	default:
		return;
	}

	sa_set_str(&dst, maddr, PCP_PORT_CLI);

	err = pcp_reply(us, &dst, NULL, PCP_ANNOUNCE, PCP_SUCCESS,
			0, repcpd_epoch_time(), NULL);
	if (err) {
		warning("announce: failed to send ANNOUNCE from"
			" %J to %s (%m)\n", bnd_addr, maddr, err);
		return;
	}

	info("announce: sent ANNOUNCE from %J to %s\n", bnd_addr, maddr);
}
Beispiel #9
0
/**
 * List interfaces using GetAdaptersInfo, which handles only IPv4 family.
 *
 * This is available from Windows 2000, and also works under Wine.
 */
static int if_list_gai(net_ifaddr_h *ifh, void *arg)
{
	IP_ADAPTER_INFO info[32];
	PIP_ADAPTER_INFO p = info;
	ULONG ulOutBufLen = sizeof(info);
	DWORD ret;

	ret = GetAdaptersInfo(info, &ulOutBufLen);
	if (ret != ERROR_SUCCESS) {
		DEBUG_WARNING("if_list: GetAdaptersInfo ret=%u\n", ret);
		return ENODEV;
	}

	for (p = info; p; p = p->Next) {
		struct sa sa;

		if (sa_set_str(&sa, p->IpAddressList.IpAddress.String, 0))
			continue;

		if (ifh && ifh(p->AdapterName, &sa, arg))
			break;
	}

	return 0;
}
Beispiel #10
0
void http_init(struct httpc *app, struct request **rpp, char *str_uri)
{
    int ok;
    struct request *request;
    struct pl pl_uri;
    struct url url;

    *rpp = NULL;

    pl_uri.p = NULL;
    str_dup((char**)&pl_uri.p, str_uri);
    pl_uri.l = strlen(str_uri);

    ok = url_decode(&url, &pl_uri);

    if(ok!=0)
        goto err_uri;

    request = mem_zalloc(sizeof(*request), destructor);
    ok = hash_alloc(&request->hdrht, HDR_HASH_SIZE);
    request->err_h = dummy_err;
    request->done_h = http_done;
    request->post = NULL;
    request->form = 0;
    request->www_auth.p = NULL;
    request->www_auth.l = 0;
    request->auth = NULL;

    request->retry = 0;

    pl_strdup(&request->host, &url.host);
    pl_strdup(&request->path, &url.path);
    request->secure = !pl_strcmp(&url.scheme, "https");
    memcpy(&request->meth, "GET", 4);
    request->meth[4] = 0;

    if(url.port)
	request->port = url.port;
    else
        request->port = request->secure ? 443 : 80;

    DEBUG_INFO("secure: %d port %d\n", request->secure, request->port);
    sa_init(&request->dest, AF_INET);
    ok = sa_set_str(&request->dest, request->host, request->port);

    request->state = ok ? START : RESOLVED;

    request->app = app;
    *rpp = request;

err_uri:
    if(pl_uri.p)
        mem_deref((void*)pl_uri.p);

    return;
}
Beispiel #11
0
static int oa_init(struct oa *oa)
{
	struct sa laddr;
	int err;

	if (!oa->alice) {
		(void)sa_set_str(&laddr, "1.2.3.4", 0);
		err = sdp_session_alloc(&oa->alice, &laddr);
		if (err)
			return err;
	}
	if (!oa->bob) {
		(void)sa_set_str(&laddr, "5.6.7.8", 0);
		err = sdp_session_alloc(&oa->bob, &laddr);
		if (err)
			return err;
	}

	return 0;
}
Beispiel #12
0
static int sipstack_fixture(struct sip **sipp)
{
    struct sa laddr, laddrs;
    struct sip *sip = NULL;
    struct tls *tls = NULL;
    int err;

    (void)sa_set_str(&laddr, "127.0.0.1", LOCAL_PORT);
    (void)sa_set_str(&laddrs, "127.0.0.1", LOCAL_SECURE_PORT);

    err = sip_alloc(&sip, NULL, 32, 32, 32, "retest", exit_handler, NULL);
    if (err)
        goto out;

    err |= sip_transp_add(sip, SIP_TRANSP_UDP, &laddr);
    err |= sip_transp_add(sip, SIP_TRANSP_TCP, &laddr);
    if (err)
        goto out;

#ifdef USE_TLS
    /* TLS-context for client -- no certificate needed */
    err = tls_alloc(&tls, TLS_METHOD_SSLV23, NULL, NULL);
    if (err)
        goto out;

    err |= sip_transp_add(sip, SIP_TRANSP_TLS, &laddrs, tls);
    if (err)
        goto out;
#endif

out:
    mem_deref(tls);
    if (err)
        mem_deref(sip);
    else
        *sipp = sip;

    return err;
}
Beispiel #13
0
static int get_android_dns(struct sa *nsv, uint32_t *n)
{
	char value[PROP_VALUE_MAX] = {0};

	if (__system_property_get("net.dns1", value)) {
		int err = sa_set_str(&nsv[0], value, DNS_PORT);
		if (err)
			return err;

		*n = 1;
		return 0;
	}

	return ENOENT;
}
Beispiel #14
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;
}
Beispiel #15
0
static int cons_init(void)
{
	struct sa laddr;
	int err;

	if (conf_get_sa(conf_cur(), "cons_listen", &laddr)) {
		sa_set_str(&laddr, "0.0.0.0", CONS_PORT);
	}

	err = cons_alloc(&cons, &laddr);
	if (err)
		return err;

	ui_register(&ui_cons);

	return 0;
}
Beispiel #16
0
int main(void)
{
	struct sa laddr;
	int err; /* errno return values */

	/* enable coredumps to aid debugging */
	(void)sys_coredump_set(true);

	/* initialize libre state */
	err = libre_init();
	if (err) {
		re_fprintf(stderr, "re init failed: %s\n", strerror(err));
		goto out;
	}

	(void)sa_set_str(&laddr, "0.0.0.0", 3456);

	/* Create listening TCP socket, IP address 0.0.0.0, TCP port 3456 */
	err = tcp_listen(&ts, &laddr, connect_handler, NULL);
	if (err) {
		re_fprintf(stderr, "tcp listen error: %s\n", strerror(err));
		goto out;
	}

	re_printf("listening on TCP socket: %J\n", &laddr);

	/* main loop */
	err = re_main(signal_handler);

 out:
	/* destroy active TCP connections */
	list_flush(&connl);

	/* free TCP socket */
	ts = mem_deref(ts);

	/* free library state */
	libre_close();

	/* check for memory leaks */
	tmr_debug();
	mem_debug();

	return err;
}
TEST(media, ice_cand_decode)
{
	struct ice_cand_attr cand;
	struct sa addr;
	int err;

	err = ice_cand_attr_decode(&cand,
			      "42 1 udp 2113937151 10.0.0.63 2004 typ host");
	ASSERT_EQ(0, err);

	sa_set_str(&addr, "10.0.0.63", 2004);

	ASSERT_STREQ("42", cand.foundation);
	ASSERT_EQ(1, cand.compid);
	ASSERT_EQ(IPPROTO_UDP, cand.proto);
	ASSERT_EQ(2113937151, cand.prio);
	ASSERT_TRUE(sa_cmp(&addr, &cand.addr, SA_ALL));
	ASSERT_EQ(ICE_CAND_TYPE_HOST, cand.type);
}
Beispiel #18
0
static int module_init(void)
{
	struct sa laddr;
	int err;

	if (conf_get_sa(conf_cur(), "http_listen", &laddr)) {
		sa_set_str(&laddr, "0.0.0.0", 8000);
	}

	err = http_listen(&httpsock, &laddr, http_req_handler, NULL);
	if (err)
		return err;

	ui_register(&ui_http);

	info("httpd: listening on %J\n", &laddr);

	return 0;
}
Beispiel #19
0
int turnserver_alloc(struct turnserver **turnp)
{
	struct turnserver *turn;
	struct sa laddr;
	int err = 0;

	if (!turnp)
		return EINVAL;

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

	err = sa_set_str(&laddr, "127.0.0.1", 0);
	if (err)
		goto out;

	err = udp_listen(&turn->us, &laddr, srv_udp_recv, turn);
	if (err)
		goto out;

	err = udp_local_get(turn->us, &turn->laddr);
	if (err)
		goto out;

	err = tcp_listen(&turn->ts, &laddr, tcp_conn_handler, turn);
	if (err)
		goto out;

	err = tcp_sock_local_get(turn->ts, &turn->laddr_tcp);
	if (err)
		goto out;

 out:
	if (err)
		mem_deref(turn);
	else
		*turnp = turn;

	return err;
}
Beispiel #20
0
static int rst_connect(struct rst *rst)
{
	struct sa srv;
	int err;

	if (!sa_set_str(&srv, rst->host, rst->port)) {

		err = tcp_connect(&rst->tc, &srv, estab_handler, recv_handler,
				  close_handler, rst);
		if (err) {
			re_printf("rst: tcp connect error: %m\n", err);
		}
	}
	else {
		err = dnsc_query(&rst->dnsq, net_dnsc(), rst->host, DNS_TYPE_A,
				 DNS_CLASS_IN, true, dns_handler, rst);
		if (err) {
			re_printf("rst: dns query error: %m\n", err);
		}
	}

	return err;
}
Beispiel #21
0
/** Test BFCP in SDP -- RFC 4583 */
int test_sdp_bfcp(void)
{
	static const char *msg_offer =
		"v=0\r\n"
		"o=alice 2890844526 2890844526 IN IP4 1.2.3.4\r\n"
		"s=-\r\n"
		"c=IN IP4 1.2.3.4\r\n"
		"t=0 0\r\n"
		"m=application 50000 TCP/BFCP *\r\n"
		"a=sendrecv\r\n"
		"a=setup:passive\r\n"
		"a=connection:new\r\n"
		"a=floorctrl:s-only\r\n"
		"a=confid:4321\r\n"
		"a=userid:1234\r\n"
		"a=floorid:1 m-stream:10\r\n"
		"a=floorid:2 m-stream:11\r\n"
		"m=audio 50002 RTP/AVP 0\r\n"
		"a=sendrecv\r\n"
		"a=label:10\r\n"
		"m=video 50004 RTP/AVP 31\r\n"
		"a=sendrecv\r\n"
		"a=label:11\r\n"
		;
	struct sdp_session *alice = NULL, *bob = NULL;
	struct sdp_media *bfcp, *audio, *video;
	struct mbuf *mbo = NULL, *mba = NULL;
	struct sa laddr;
	int err;

	/* create sessions */
	(void)sa_set_str(&laddr, "1.2.3.4", 0);
	err  = sdp_session_alloc(&alice, &laddr);
	if (err)
		goto out;

	err = sdp_media_add(&bfcp, alice, "application", 50000, "TCP/BFCP");
	if (err)
		goto out;

	err |= sdp_media_set_lattr(bfcp, true, "setup", "passive");
	err |= sdp_media_set_lattr(bfcp, true, "connection", "new");
	err |= sdp_media_set_lattr(bfcp, true, "floorctrl", "s-only");
	err |= sdp_media_set_lattr(bfcp, true, "confid", "4321");
	err |= sdp_media_set_lattr(bfcp, true, "userid", "1234");
	err |= sdp_media_set_lattr(bfcp, false, "floorid", "1 m-stream:10");
	sdp_media_del_lattr(bfcp, "floorid"); /* test attr delete */
	err |= sdp_media_set_lattr(bfcp, false, "floorid", "1 m-stream:10");
	err |= sdp_media_set_lattr(bfcp, false, "floorid", "2 m-stream:11");
	if (err)
		goto out;

	err = sdp_media_add(&audio, alice, "audio", 50002, "RTP/AVP");
	if (err)
		goto out;

	err = sdp_media_add(&video, alice, "video", 50004, "RTP/AVP");
	if (err)
		goto out;

	err |= sdp_media_set_lattr(audio, true, "label", "10");
	err |= sdp_media_set_lattr(video, true, "label", "11");
	if (err)
		goto out;

	err  = sdp_format_add(NULL, bfcp, false, "*", NULL, 0, 0,
			      NULL, NULL, NULL, false, NULL);
	err |= sdp_format_add(NULL, audio, false, "0", NULL, 0, 0,
			      NULL, NULL, NULL, false, NULL);
	err |= sdp_format_add(NULL, video, false, "31", NULL, 0, 0,
			      NULL, NULL, NULL, false, NULL);
	if (err)
		goto out;

	/* create and send offer, compare offer */
	err = sdp_encode(&mbo, alice, true);
	if (err)
		goto out;

	if (!sdp_cmp(mbo, msg_offer)) {
		DEBUG_WARNING("offer failed:\n%b", mbo->buf, mbo->end);
		err = EBADMSG;
		goto out;
	}

 out:
	mem_deref(alice);
	mem_deref(bob);
	mem_deref(mbo);
	mem_deref(mba);

	return err;
}
TEST_F(TestMedia, firefox45_interop)
{
	char answer[4096];
	struct sa laddr;
	int err;

	static const char *sdp_firefox =
"v=0\r\n"
"o=mozilla...THIS_IS_SDPARTA-45.0.2 7767043308804270395 0 IN IP4 0.0.0.0\r\n"
"s=-\r\n"
"t=0 0\r\n"
"a=sendrecv\r\n"
"a=fingerprint:sha-256 CD:7B:7C:A8:4F:A0:6D:DD:32:6F:3E:DD:F3:2D:07:F6:10:4D:D1:8F:E1:7F:95:32:7E:CB:33:17:BA:5B:65:19\r\n"
"a=group:BUNDLE audio video\r\n"
"a=ice-options:trickle\r\n"
"a=msid-semantic:WMS *\r\n"
"m=audio 50194 RTP/SAVPF 96\r\n"
"c=IN IP4 54.155.57.143\r\n"
"a=candidate:0 1 UDP 2122252543 192.168.10.88 60503 typ host\r\n"
"a=candidate:1 1 UDP 1686052863 62.96.148.44 60503 typ srflx raddr 192.168.10.88 rport 60503\r\n"
"a=candidate:2 1 UDP 92217343 54.155.57.143 50194 typ relay raddr 54.155.57.143 rport 50194\r\n"
"a=sendrecv\r\n"
"a=end-of-candidates\r\n"
"a=ice-pwd:0393917a2d22af7bd38e661130e77d41\r\n"
"a=ice-ufrag:cc92c585\r\n"
"a=mid:audio\r\n"
"a=msid:{da2198be-27c6-3844-871d-313e73fef45d} {d6ff7b2c-f689-a843-832c-843f59b52bbb}\r\n"
"a=rtcp-mux\r\n"
"a=rtpmap:96 opus/48000/2\r\n"
"a=setup:actpass\r\n"
"a=ssrc:2997989063 cname:{84d8043a-40ef-9b42-aff7-1104f80aaf43}\r\n"
"m=video 50194 RTP/SAVPF 100\r\n"
"c=IN IP4 54.155.57.143\r\n"
"a=recvonly\r\n"
"a=fmtp:100 max-fs=12288;max-fr=60\r\n"
"a=ice-pwd:0393917a2d22af7bd38e661130e77d41\r\n"
"a=ice-ufrag:cc92c585\r\n"
"a=mid:video\r\n"
"a=rtcp-fb:100 nack\r\n"
"a=rtcp-fb:100 nack pli\r\n"
"a=rtcp-fb:100 ccm fir\r\n"
"a=rtcp-mux\r\n"
"a=rtpmap:100 VP8/90000\r\n"
"a=setup:actpass\r\n"
"a=ssrc:934653567 cname:{84d8043a-40ef-9b42-aff7-1104f80aaf43}\r\n"
	;

	sa_set_str(&laddr, "127.0.0.1", 0);

	/* Populate only 1 ICE candidate (plus EOC) */
	err = mediaflow_add_local_host_candidate(mf, "eth0", &laddr);
	ASSERT_EQ(0, err);
	mediaflow_set_local_eoc(mf);

	err = mediaflow_add_video(mf, &vidcodecl);
	ASSERT_EQ(0, err);

	err = mediaflow_offeranswer(mf, answer, sizeof(answer), sdp_firefox);
	ASSERT_EQ(0, err);

	ASSERT_EQ(CRYPTO_DTLS_SRTP, mediaflow_crypto(mf));
	ASSERT_TRUE(mediaflow_have_eoc(mf));

#if 0
	re_printf("%s\n", answer);
#endif

	/* verify some SDP attributes */
	ASSERT_TRUE(find_in_sdp(answer, "a=fingerprint:sha-256"));
	ASSERT_TRUE(find_in_sdp(answer, "a=group:BUNDLE audio video"));
	ASSERT_TRUE(find_in_sdp(answer, "a=ice-options:trickle"));
	ASSERT_TRUE(find_in_sdp(answer, "a=end-of-candidates"));
	ASSERT_TRUE(find_in_sdp(answer, "a=ice-pwd"));
	ASSERT_TRUE(find_in_sdp(answer, "a=ice-ufrag"));
	ASSERT_TRUE(find_in_sdp(answer, "a=mid:audio"));
	ASSERT_TRUE(find_in_sdp(answer, "a=rtcp-mux"));
	ASSERT_TRUE(find_in_sdp(answer, "a=setup:active"));

	ASSERT_TRUE(find_in_sdp(answer, "m=video"));
	ASSERT_TRUE(find_in_sdp(answer, "a=mid:video"));
	ASSERT_TRUE(find_in_sdp(answer, "VP8/90000"));
}
Beispiel #23
0
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;
}
Beispiel #24
0
static int test_stun_request(int proto, bool natted)
{
	struct stunserver *srv = NULL;
	struct stun_ctrans *ct = NULL;
	struct nat *nat = NULL;
	struct test test;
	struct sa laddr, public_addr;
	int err;

	memset(&test, 0, sizeof(test));

	err = stunserver_alloc(&srv);
	if (err)
		goto out;

	err = stun_alloc(&test.stun, NULL, NULL, NULL);
	if (err)
		goto out;

	if (proto == IPPROTO_UDP) {
		err = sa_set_str(&laddr, "127.0.0.1", 0);
		TEST_ERR(err);

		err = udp_listen(&test.us, &laddr, udp_recv_handler, &test);
		if (err)
			goto out;
		err = udp_local_get(test.us, &laddr);
		TEST_ERR(err);
	}

	if (natted) {
		err = sa_set_str(&public_addr, "4.5.6.7", 0);
		TEST_ERR(err);

		err = nat_alloc(&nat, srv->us, &public_addr);
		if (err)
			goto out;

		sa_set_port(&public_addr, sa_port(&laddr));
	}
	else {
		public_addr = laddr;
	}

	err = stun_request(&ct, test.stun, proto, test.us,
			   stunserver_addr(srv, proto), 0,
			   STUN_METHOD_BINDING, NULL, 0, true,
			   stun_resp_handler, &test, 0);
	if (err)
		goto out;

	TEST_ASSERT(ct != NULL);

	err = re_main_timeout(100);
	if (err)
		goto out;

	if (srv->err) {
		err = srv->err;
		goto out;
	}
	if (test.err) {
		err = test.err;
		goto out;
	}

	/* verify results */
	TEST_ASSERT(srv->nrecv >= 1);
	TEST_EQUALS(1, test.n_resp);

	if (proto == IPPROTO_UDP) {
		TEST_SACMP(&public_addr, &test.mapped_addr, SA_ALL);
	}

 out:
	mem_deref(test.stun);
	mem_deref(test.us);
	mem_deref(nat);
	mem_deref(srv);

	return err;
}
Beispiel #25
0
int test_sipsess(void)
{
	struct test test;
	struct sa laddr;
	char to_uri[256];
	int err;
	uint16_t port;

	memset(&test, 0, sizeof(test));

#ifndef WIN32
	/* slurp warnings from SIP (todo: temp) */
	(void)freopen("/dev/null", "w", stderr);
#endif

	err = sip_alloc(&test.sip, NULL, 32, 32, 32,
			"retest", exit_handler, NULL);
	if (err)
		goto out;

	(void)sa_set_str(&laddr, "127.0.0.1", 0);
	err = sip_transp_add(test.sip, SIP_TRANSP_UDP, &laddr);
	if (err)
		goto out;

	err = sip_transp_laddr(test.sip, &laddr, SIP_TRANSP_UDP, NULL);
	if (err)
		goto out;

	port = sa_port(&laddr);

	err = sipsess_listen(&test.sock, test.sip, 32, conn_handler, &test);
	if (err)
		goto out;

	/* Connect to "b" */
	(void)re_snprintf(to_uri, sizeof(to_uri), "sip:[email protected]:%u", port);
	err = sipsess_connect(&test.a, test.sock, to_uri, NULL,
			      "sip:[email protected]", "a", NULL, 0,
			      "application/sdp", NULL, NULL, NULL, false,
			      offer_handler, answer_handler, NULL,
			      estab_handler_a, NULL, NULL,
			      close_handler, &test, NULL);
	if (err)
		goto out;

	err = re_main_timeout(200);
	if (err)
		goto out;

	if (test.err) {
		err = test.err;
		goto out;
	}

	/* okay here -- verify */
	TEST_ASSERT(test.estab_a);
	TEST_ASSERT(test.estab_b);

 out:
	test.a = mem_deref(test.a);
	test.b = mem_deref(test.b);

	sipsess_close_all(test.sock);
	test.sock = mem_deref(test.sock);

	sip_close(test.sip, false);
	test.sip = mem_deref(test.sip);

#ifndef WIN32
	/* Restore stderr */
	freopen("/dev/tty", "w", stderr);
#endif

	return err;
}
Beispiel #26
0
int test_sdp_all(void)
{
	struct sdp_session *sess = NULL;
	struct sdp_media *audio = NULL;
	struct mbuf *desc = NULL;
	struct sa ref;
	const struct sdp_format *rc = NULL, *sc;
	struct sa laddr;
	int err;

	(void)sa_set_str(&laddr, ref_host, 0);

	err = sdp_session_alloc(&sess, &laddr);
	if (err)
		goto out;

	err = sdp_media_add(&audio, sess, sdp_media_audio, 5004,
			    sdp_proto_rtpavp);
	if (err)
		goto out;

	err  = sdp_format_add(NULL, audio, false, ref_pt, ref_cname,
			      ref_srate, 1, NULL, NULL, NULL, false, NULL);
	err |= sdp_format_add(NULL, audio, false, "110", cname_speex,
			      16000, 2, NULL, NULL, NULL, false, NULL);
	if (err)
		goto out;

	/* find codec - expected */
	sc = sdp_media_format(audio, true, NULL, 0, "PCMU", 8000, 1);
	if (!sc) {
		DEBUG_WARNING("codec not found\n");
		err = ENOENT;
		goto out;
	}

	sc = sdp_media_format(audio, true, NULL, 110, "Speex", 16000, 2);
	if (!sc) {
		DEBUG_WARNING("codec not found: speex\n");
		err = ENOENT;
		goto out;
	}

	/* find codec - not expected */
	sc = sdp_media_format(audio, true, NULL, -1, "Speex", 8000, 1);
	if (sc) {
		DEBUG_WARNING("unexpected codec found\n");
		err = EINVAL;
		goto out;
	}

	err = sdp_encode(&desc, sess, true);
	if (err)
		goto out;

	if (!sdp_cmp(desc, ref_msg)) {
		DEBUG_WARNING("ref: %s\n", ref_msg);
		DEBUG_WARNING("sdp: %b\n", desc->buf, desc->end);
		err = EBADMSG;
		goto out;
	}

	err = sdp_decode(sess, desc, false);
	if (err)
		goto out;

	rc = sdp_media_rformat(audio, NULL);
	if (!rc) {
		err = ENOENT;
		goto out;
	}

	err = sa_set_str(&ref, ref_host, ref_port);
	if (err)
		goto out;

	err = EINVAL;

	if (!sa_cmp(sdp_media_raddr(audio), &ref, SA_ALL))
		goto out;

	if (!rc)
		goto out;

	if (0 != strcmp(rc->id, ref_pt))
		goto out;

	if (0 != strcmp(ref_cname, rc->name))
		goto out;

	if (rc->srate != ref_srate)
		goto out;

	err = 0;

 out:
	mem_deref(audio);
	mem_deref(sess);
	mem_deref(desc);

	return err;
}
Beispiel #27
0
static void process_msg(struct turnserver *turn, int proto, void *sock,
			const struct sa *src, struct mbuf *mb)
{
	struct stun_msg *msg = NULL;
	struct sa laddr;
	int err = 0;

	if (stun_msg_decode(&msg, mb, NULL)) {

		uint16_t numb, len;
		struct channel *chan;

		if (!turn->us_relay)
			return;

		++turn->n_raw;

		numb = ntohs(mbuf_read_u16(mb));
		len  = ntohs(mbuf_read_u16(mb));

		if (mbuf_get_left(mb) < len) {
			DEBUG_WARNING("short length: %zu < %u\n",
				      mbuf_get_left(mb), len);
		}

		chan = find_channel_numb(turn, numb);
		if (!chan) {
			DEBUG_WARNING("channel not found: numb=%u\n", numb);
			return;
		}

		/* relay data from channel to peer */
		(void)udp_send(turn->us_relay, &chan->peer, mb);
		return;
	}

#if 0
	re_printf("process: %s:%p:%J %s\n",
		  net_proto2name(proto), sock, src,
		  stun_method_name(stun_msg_method(msg)));
#endif

	switch (stun_msg_method(msg)) {

	case STUN_METHOD_ALLOCATE:
		/* Max 1 allocation for now */
		++turn->n_allocate;

		if (turn->us_relay) {
			err = EALREADY;
			goto out;
		}

		turn->cli = *src;

		err = sa_set_str(&laddr, "127.0.0.1", 0);
		if (err)
			goto out;

		err = udp_listen(&turn->us_relay, &laddr,
				 relay_udp_recv, turn);
		if (err)
			goto out;

		err = udp_local_get(turn->us_relay, &turn->relay);
		if (err)
			goto out;

		udp_rxbuf_presz_set(turn->us_relay, 4);

		err = stun_reply(proto, sock, src, 0,
				 msg, NULL, 0, false,
				 2,
				 STUN_ATTR_XOR_MAPPED_ADDR, src,
				 STUN_ATTR_XOR_RELAY_ADDR, &turn->relay);
		break;

	case STUN_METHOD_CREATEPERM: {
		struct stun_attr *peer;

		++turn->n_createperm;

		peer = stun_msg_attr(msg, STUN_ATTR_XOR_PEER_ADDR);
		TEST_ASSERT(peer != NULL);

		add_permission(turn, &peer->v.xor_peer_addr);

		/* todo: install permissions and check them */
		err = stun_reply(proto, sock, src, 0,
				 msg, NULL, 0, false,
				 0);
	}
		break;

	case STUN_METHOD_CHANBIND: {
		struct stun_attr *chnr, *peer;

		++turn->n_chanbind;

		TEST_ASSERT(turn->us_relay != NULL);

		chnr = stun_msg_attr(msg, STUN_ATTR_CHANNEL_NUMBER);
		peer = stun_msg_attr(msg, STUN_ATTR_XOR_PEER_ADDR);
		if (!chnr || !peer) {
			DEBUG_WARNING("CHANBIND: missing chnr/peer attrib\n");
		}

		TEST_ASSERT(turn->chanc < ARRAY_SIZE(turn->chanv));
		turn->chanv[turn->chanc].nr   = chnr->v.channel_number;
		turn->chanv[turn->chanc].peer = peer->v.xor_peer_addr;
		++turn->chanc;

		err = stun_reply(proto, sock, src, 0,
				 msg, NULL, 0, false,
				 0);
	}
		break;

	case STUN_METHOD_SEND: {
		struct stun_attr *peer, *data;

		++turn->n_send;

		TEST_ASSERT(turn->us_relay != NULL);

		peer = stun_msg_attr(msg, STUN_ATTR_XOR_PEER_ADDR);
		data = stun_msg_attr(msg, STUN_ATTR_DATA);

		if (!peer || !data) {
			DEBUG_WARNING("SEND: missing peer/data attrib\n");
			goto out;
		}

		/* check for valid Permission */
		if (!find_permission(turn, &peer->v.xor_peer_addr)) {
			DEBUG_NOTICE("no permission to peer %j\n",
				     &peer->v.xor_peer_addr);
			goto out;
		}

		err = udp_send(turn->us_relay, &peer->v.xor_peer_addr,
			       &data->v.data);
	}
		break;

	default:
		DEBUG_WARNING("unknown STUN method: %s\n",
			      stun_method_name(stun_msg_method(msg)));
		err = EPROTO;
		break;
	}

	if (err)
		goto out;

 out:
	if (err && stun_msg_class(msg) == STUN_CLASS_REQUEST) {
		(void)stun_ereply(proto, sock, src, 0, msg,
				  500, "Server Error",
				  NULL, 0, false, 0);
	}

	mem_deref(msg);
}
Beispiel #28
0
/**
 * Do a DNS Discovery of a STUN Server
 *
 * @param dnsp    Pointer to allocated DNS Discovery object
 * @param dnsc    DNS Client
 * @param service Name of service to discover (e.g. "stun")
 * @param proto   Transport protocol (e.g. "udp")
 * @param af      Preferred Address Family
 * @param domain  Domain name or IP address of STUN server
 * @param port    Port number (if 0 do SRV lookup)
 * @param dnsh    DNS Response handler
 * @param arg     Handler argument
 *
 * @return 0 if success, otherwise errorcode
 */
int stun_server_discover(struct stun_dns **dnsp, struct dnsc *dnsc,
			 const char *service, const char *proto,
			 int af, const char *domain, uint16_t port,
			 stun_dns_h *dnsh, void *arg)
{
	struct stun_dns *dns;
	int err;

	if (!dnsp || !service || !proto || !domain || !domain[0] || !dnsh)
		return EINVAL;

	dns = mem_zalloc(sizeof(*dns), dnsdisc_destructor);
	if (!dns)
		return ENOMEM;

	dns->port = service[strlen(service)-1] == 's' ? STUNS_PORT : STUN_PORT;
	dns->dnsh = dnsh;
	dns->arg  = arg;
	dns->dnsc = dnsc;
	dns->af   = af;

	/* Numeric IP address - no lookup */
	if (0 == sa_set_str(&dns->srv, domain, port ? port : dns->port)) {

		DEBUG_INFO("IP (%s)\n", domain);

		resolved(dns, 0);
		err = 0;
		goto out; /* free now */
	}
	/* Port specified - use AAAA or A lookup */
	else if (port) {
		sa_set_in(&dns->srv, 0, port);
		DEBUG_INFO("resolving A query: (%s)\n", domain);

		err = a_or_aaaa_query(dns, domain);
		if (err) {
			DEBUG_WARNING("%s: A/AAAA lookup failed (%m)\n",
				      domain, err);
			goto out;
		}
	}
	/* SRV lookup */
	else {
		char q[256];
		str_ncpy(dns->domain, domain, sizeof(dns->domain));
		(void)re_snprintf(q, sizeof(q), "_%s._%s.%s", service, proto,
				  domain);
		DEBUG_INFO("resolving SRV query: (%s)\n", q);
		err = dnsc_query(&dns->dq, dnsc, q, DNS_TYPE_SRV, DNS_CLASS_IN,
				 true, srv_handler, dns);
		if (err) {
			DEBUG_WARNING("%s: SRV lookup failed (%m)\n", q, err);
			goto out;
		}
	}

	*dnsp = dns;

	return 0;

 out:
	mem_deref(dns);
	return err;
}
Beispiel #29
0
/**
 * Send a SIP request
 *
 * @param reqp     Pointer to allocated SIP request object
 * @param sip      SIP Stack
 * @param stateful Stateful client transaction
 * @param met      SIP Method string
 * @param metl     Length of SIP Method string
 * @param uri      Request URI
 * @param uril     Length of Request URI string
 * @param route    Next hop route URI
 * @param mb       Buffer containing SIP request
 * @param sendh    Send handler
 * @param resph    Response handler
 * @param arg      Handler argument
 *
 * @return 0 if success, otherwise errorcode
 */
int sip_request(struct sip_request **reqp, struct sip *sip, bool stateful,
		const char *met, int metl, const char *uri, int uril,
		const struct uri *route, struct mbuf *mb,
		sip_send_h *sendh, sip_resp_h *resph, void *arg)
{
	struct sip_request *req;
	struct sa dst;
	struct pl pl;
	int err;

	if (!sip || !met || !uri || !route || !mb)
		return EINVAL;

	if (pl_strcasecmp(&route->scheme, "sip"))
		return ENOSYS;

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

	list_append(&sip->reql, &req->le, req);

	err = str_ldup(&req->met, met, metl);
	if (err)
		goto out;

	err = str_ldup(&req->uri, uri, uril);
	if (err)
		goto out;

	if (sip_param_decode(&route->params, "maddr", &pl))
		pl = route->host;

	err = pl_strdup(&req->host, &pl);
	if (err)
		goto out;

	req->stateful = stateful;
	req->mb    = mem_ref(mb);
	req->sip   = sip;
	req->sendh = sendh;
	req->resph = resph;
	req->arg   = arg;

	if (!sip_param_decode(&route->params, "transport", &pl)) {

		if (!pl_strcasecmp(&pl, "udp"))
			req->tp = SIP_TRANSP_UDP;
		else if (!pl_strcasecmp(&pl, "tcp"))
			req->tp = SIP_TRANSP_TCP;
		else if (!pl_strcasecmp(&pl, "tls"))
			req->tp = SIP_TRANSP_TLS;
		else {
			err = EPROTONOSUPPORT;
			goto out;
		}

		if (!sip_transp_supported(sip, req->tp, AF_UNSPEC)) {
			err = EPROTONOSUPPORT;
			goto out;
		}

		req->tp_selected = true;
	}
	else {
		req->tp = SIP_TRANSP_NONE;
		if (!transp_next(sip, &req->tp)) {
			err = EPROTONOSUPPORT;
			goto out;
		}

		req->tp_selected = false;
	}

	if (!sa_set_str(&dst, req->host,
			sip_transp_port(req->tp, route->port))) {

		err = request(req, req->tp, &dst);
		if (!req->stateful) {
			mem_deref(req);
			return err;
		}
	}
	else if (route->port) {

		req->port = sip_transp_port(req->tp, route->port);
		err = addr_lookup(req, req->host);
	}
	else if (req->tp_selected) {

		err = srv_lookup(req, req->host);
	}
	else {
	        err = dnsc_query(&req->dnsq, sip->dnsc, req->host,
				 DNS_TYPE_NAPTR, DNS_CLASS_IN, true,
				 naptr_handler, req);
	}

 out:
	if (err)
		mem_deref(req);
	else if (reqp) {
		req->reqp = reqp;
		*reqp = req;
	}

	return err;
}
Beispiel #30
0
/**
 * Send an HTTP request
 *
 * @param reqp      Pointer to allocated HTTP request object
 * @param cli       HTTP Client
 * @param met       Request method
 * @param uri       Request URI
 * @param resph     Response handler
 * @param datah     Content handler (optional)
 * @param arg       Handler argument
 * @param fmt       Formatted HTTP headers and body (optional)
 *
 * @return 0 if success, otherwise errorcode
 */
int http_request(struct http_req **reqp, struct http_cli *cli, const char *met,
		 const char *uri, http_resp_h *resph, http_data_h *datah,
		 void *arg, const char *fmt, ...)
{
	struct pl scheme, host, port, path;
	struct http_req *req;
	uint16_t defport;
	bool secure;
	va_list ap;
	int err;

	if (!reqp || !cli || !met || !uri)
		return EINVAL;

	if (re_regex(uri, strlen(uri), "[a-z]+://[^:/]+[:]*[0-9]*[^]+",
		     &scheme, &host, NULL, &port, &path) || scheme.p != uri)
		return EINVAL;

	if (!pl_strcasecmp(&scheme, "http") ||
	    !pl_strcasecmp(&scheme, "ws")) {
		secure  = false;
		defport = 80;
	}
#ifdef USE_TLS
	else if (!pl_strcasecmp(&scheme, "https") ||
		 !pl_strcasecmp(&scheme, "wss")) {
		secure  = true;
		defport = 443;
	}
#endif
	else
		return ENOTSUP;

	req = mem_zalloc(sizeof(*req), req_destructor);
	if (!req)
		return ENOMEM;

	req->tls    = mem_ref(cli->tls);
	req->secure = secure;
	req->port   = pl_isset(&port) ? pl_u32(&port) : defport;
	req->resph  = resph;
	req->datah  = datah;
	req->arg    = arg;

	err = pl_strdup(&req->host, &host);
	if (err)
		goto out;

	req->mbreq = mbuf_alloc(1024);
	if (!req->mbreq) {
		err = ENOMEM;
		goto out;
	}

	err = mbuf_printf(req->mbreq,
			  "%s %r HTTP/1.1\r\n"
			  "Host: %r\r\n",
			  met, &path, &host);
	if (fmt) {
		va_start(ap, fmt);
		err |= mbuf_vprintf(req->mbreq, fmt, ap);
		va_end(ap);
	}
	else {
		err |= mbuf_write_str(req->mbreq, "\r\n");
	}
	if (err)
		goto out;

	req->mbreq->pos = 0;

	if (!sa_set_str(&req->srvv[0], req->host, req->port)) {

		req->srvc = 1;

		err = req_connect(req);
		if (err)
			goto out;
	}
	else {
		err = dnsc_query(&req->dq, cli->dnsc, req->host,
				 DNS_TYPE_A, DNS_CLASS_IN, true,
				 query_handler, req);
		if (err)
			goto out;
	}

 out:
	if (err)
		mem_deref(req);
	else {
		req->reqp = reqp;
		*reqp = req;
	}

	return err;
}