Beispiel #1
0
std::shared_ptr<SipTransport>
SipTransportBroker::getTlsTransport(const std::shared_ptr<TlsListener>& l, const std::string& remoteSipUri)
{
    if (!l) {
        ERROR("Can't create TLS transport without listener.");
        return nullptr;
    }

    static const char SIPS_PREFIX[] = "<sips:";
    size_t sips = remoteSipUri.find(SIPS_PREFIX) + (sizeof SIPS_PREFIX) - 1;
    size_t trns = remoteSipUri.find(";transport");
    const std::string remoteHost {remoteSipUri.substr(sips, trns-sips)};
    IpAddr remoteAddr = {remoteHost};
    DEBUG("getTlsTransport host %s resolved to -> %s", remoteHost.c_str(), remoteAddr.toString(true).c_str());
    if (!remoteAddr)
        return nullptr;
    if (remoteAddr.getPort() == 0)
        remoteAddr.setPort(pjsip_transport_get_default_port_for_type(l->get()->type));

    DEBUG("Get new TLS transport to %s", remoteAddr.toString(true).c_str());
    pjsip_tpselector sel {PJSIP_TPSELECTOR_LISTENER, {
        .listener = l->get()
    }};
    pjsip_transport *transport = nullptr;
    pj_status_t status = pjsip_endpt_acquire_transport(
            endpt_,
            l->get()->type,
            remoteAddr.pjPtr(),
            remoteAddr.getLength(),
            &sel,
            &transport);

    if (!transport || status != PJ_SUCCESS) {
        ERROR("Could not get new TLS transport");
        sip_utils::sip_strerror(status);
        return nullptr;
    }
    auto ret = std::make_shared<SipTransport>(transport, l);
    pjsip_transport_dec_ref(transport);
    {
        std::lock_guard<std::mutex> lock(transportMapMutex_);
        transports_[ret->get()] = ret;
    }
    return ret;
}
Beispiel #2
0
int regc_test(void)
{
    struct test_rec {
	unsigned		 check_contact;
	unsigned		 add_xuid_param;

	const char		*title;
	char			*alt_registrar;
	unsigned		 contact_cnt;
	char			*contacts[4];
	unsigned		 expires;
	struct registrar_cfg	 server_cfg;
	struct client		 client_cfg;
    } test_rec[] = 
    {
	/* immediate error */
	{
	    OFF,			    /* check_contact	*/
	    OFF,			    /* add_xuid_param	*/
	    "immediate error",		    /* title		*/
	    "sip:unresolved-host-xyy",	    /* alt_registrar	*/
	    1,				    /* contact cnt	*/
	    { "sip:[email protected]:5060" },  /* contacts[]	*/
	    600,			    /* expires		*/

	    /* registrar config: */
	    /* respond	code	auth	  contact   exp_prm expires more_contacts */
	    { PJ_FALSE,	200,	PJ_FALSE, NONE,	    0,	    0,	    {NULL, 0}},

	    /* client expected results: */
	    /* error	code	have_reg    expiration	contact_cnt auth?*/
	    { PJ_FALSE,	502,	PJ_FALSE,   600,	0,	    PJ_FALSE}
	},

	/* timeout test */
	{
	    OFF,			    /* check_contact	*/
	    OFF,			    /* add_xuid_param	*/
	    "timeout test (takes ~32 secs)",/* title		*/
	    NULL,			    /* alt_registrar	*/
	    1,				    /* contact cnt	*/
	    { "sip:[email protected]:5060" },  /* contacts[]	*/
	    600,			    /* expires		*/

	    /* registrar config: */
	    /* respond	code	auth	  contact   exp_prm expires more_contacts */
	    { PJ_FALSE,	200,	PJ_FALSE, NONE,	    0,	    0,	    {NULL, 0}},

	    /* client expected results: */
	    /* error	code	have_reg    expiration	contact_cnt auth? */
	    { PJ_FALSE,	408,	PJ_FALSE,   600,	0,	    PJ_FALSE}
	},

	/* Basic successful registration scenario:
	 * a good registrar returns the Contact header as is and
	 * add expires parameter. In this test no additional bindings
	 * are returned.
	 */
	{
	    ON_OFF,			    /* check_contact	*/
	    ON_OFF,			    /* add_xuid_param	*/
	    "basic",			    /* title		*/
	    NULL,			    /* alt_registrar	*/
	    1,				    /* contact cnt	*/
	    { "<sip:[email protected]:5060;transport=udp;x-param=1234>" },  /* contacts[]	*/
	    600,			    /* expires		*/

	    /* registrar config: */
	    /* respond	code	auth	  contact  exp_prm expires more_contacts */
	    { PJ_TRUE,	200,	PJ_FALSE, EXACT,    75,	    65,	    {NULL, 0}},

	    /* client expected results: */
	    /* error	code	have_reg    expiration	contact_cnt auth?*/
	    { PJ_FALSE,	200,	PJ_TRUE,    75,		1,	    PJ_FALSE}
	},

	/* Basic successful registration scenario with authentication
	 */
	{
	    ON_OFF,			    /* check_contact	*/
	    ON_OFF,			    /* add_xuid_param	*/
	    "authentication",		    /* title		*/
	    NULL,			    /* alt_registrar	*/
	    1,				    /* contact cnt	*/
	    { "<sip:[email protected]:5060;transport=udp;x-param=1234>" },  /* contacts[]	*/
	    600,			    /* expires		*/

	    /* registrar config: */
	    /* respond	code	auth	  contact  exp_prm expires more_contacts */
	    { PJ_TRUE,	200,	PJ_TRUE,  EXACT,    75,	    65,	    {NULL, 0}},

	    /* client expected results: */
	    /* error	code	have_reg    expiration	contact_cnt auth?*/
	    { PJ_FALSE,	200,	PJ_TRUE,    75,		1,	    PJ_TRUE}
	},

	/* a good registrar returns the Contact header as is and
	 * add expires parameter. Also it adds bindings from other
	 * clients in this test.
	 */
	{
	    ON_OFF,			    /* check_contact	*/
	    ON,				    /* add_xuid_param	*/
	    "more bindings in response",    /* title		*/
	    NULL,			    /* alt_registrar	*/
	    1,				    /* contact cnt	*/
	    { "<sip:[email protected]:5060;transport=udp>" },  /* contacts[]	*/
	    600,			    /* expires		*/

	    /* registrar config: */
	    /* respond	code	auth	  contact  exp_prm expires more_contacts */
	    { PJ_TRUE,	200,	PJ_FALSE, EXACT,   75,	    65,	    {"<sip:a@a>;expires=70", 0}},

	    /* client expected results: */
	    /* error	code	have_reg    expiration	contact_cnt auth?*/
	    { PJ_FALSE,	200,	PJ_TRUE,    75,		2,	    PJ_FALSE}
	},


	/* a bad registrar returns modified Contact header, but it
	 * still returns all parameters intact. In this case
	 * the expiration is taken from the expires param because
	 * of matching xuid param or because the number of
	 * Contact header matches.
	 */
	{
	    ON_OFF,			    /* check_contact	*/
	    ON_OFF,			    /* add_xuid_param	*/
	    "registrar modifies Contact header",    /* title		*/
	    NULL,			    /* alt_registrar	*/
	    1,				    /* contact cnt	*/
	    { "<sip:[email protected]:5060>" },  /* contacts[]	*/
	    600,			    /* expires		*/

	    /* registrar config: */
	    /* respond	code	auth	  contact   exp_prm expires more_contacts */
	    { PJ_TRUE,	200,	PJ_FALSE, MODIFIED, 75,	    65,	    {NULL, 0}},

	    /* client expected results: */
	    /* error	code	have_reg    expiration	contact_cnt auth?*/
	    { PJ_FALSE,	200,	PJ_TRUE,    75,		1,	    PJ_FALSE}
	},


	/* a bad registrar returns modified Contact header, but it
	 * still returns all parameters intact. In addition it returns
	 * bindings from other clients.
	 *
	 * In this case the expiration is taken from the expires param 
	 * because add_xuid_param is enabled.
	 */
	{
	    ON_OFF,			    /* check_contact	*/
	    ON,				    /* add_xuid_param	*/
	    "registrar modifies Contact header and add bindings",    /* title		*/
	    NULL,			    /* alt_registrar	*/
	    1,				    /* contact cnt	*/
	    { "<sip:[email protected]:5060>" },  /* contacts[]	*/
	    600,			    /* expires		*/

	    /* registrar config: */
	    /* respond	code	auth	  contact   exp_prm expires more_contacts */
	    { PJ_TRUE,	200,	PJ_FALSE, MODIFIED, 75,	    65,	    {"<sip:a@a>;expires=70", 0}},

	    /* client expected results: */
	    /* error	code	have_reg    expiration	contact_cnt auth?*/
	    { PJ_FALSE,	200,	PJ_TRUE,    75,		2,	    PJ_FALSE}
	},


	/* a bad registrar returns completely different Contact and
	 * all parameters are gone. In this case the expiration is 
	 * also taken from the expires param since the number of 
	 * header matches.
	 */
	{
	    ON_OFF,			    /* check_contact	*/
	    ON_OFF,			    /* add_xuid_param	*/
	    "registrar replaces Contact header",    /* title		*/
	    NULL,			    /* alt_registrar	*/
	    1,				    /* contact cnt	*/
	    { "<sip:[email protected]:5060>" },  /* contacts[]	*/
	    600,			    /* expires		*/

	    /* registrar config: */
	    /* respond	code	auth	  contact   exp_prm expires more_contacts */
	    { PJ_TRUE,	202,	PJ_FALSE, NONE,	    0,	    65,	    {"<sip:a@A>;expires=75", 0}},

	    /* client expected results: */
	    /* error	code	have_reg    expiration	contact_cnt auth?*/
	    { PJ_FALSE,	202,	PJ_TRUE,    75,		1,	    PJ_FALSE}
	},


	/* a bad registrar returns completely different Contact (and
	 * all parameters are gone) and it also includes bindings from
	 * other clients.
	 * In this case the expiration is taken from the Expires header.
	 */
	{
	    ON_OFF,			    /* check_contact	*/
	    ON_OFF,			    /* add_xuid_param	*/
	    " as above with additional bindings",    /* title		*/
	    NULL,			    /* alt_registrar	*/
	    1,				    /* contact cnt	*/
	    { "<sip:[email protected]:5060>" },  /* contacts[]	*/
	    600,			    /* expires		*/

	    /* registrar config: */
	    /* respond	code	auth	  contact   exp_prm expires more_contacts */
	    { PJ_TRUE,	200,	PJ_FALSE, NONE,	    0,	    65,	    {"<sip:a@A>;expires=75, <sip:b@B;expires=70>", 0}},

	    /* client expected results: */
	    /* error	code	have_reg    expiration	contact_cnt auth?*/
	    { PJ_FALSE,	200,	PJ_TRUE,    65,		2,	    PJ_FALSE}
	},

	/* the registrar doesn't return any bindings, but for some
	 * reason it includes an Expires header.
	 * In this case the expiration is taken from the Expires header.
	 */
	{
	    ON_OFF,			    /* check_contact	*/
	    ON_OFF,			    /* add_xuid_param	*/
	    "no Contact but with Expires",  /* title		*/
	    NULL,			    /* alt_registrar	*/
	    1,				    /* contact cnt	*/
	    { "<sip:[email protected]:5060>" },  /* contacts[]	*/
	    600,			    /* expires		*/

	    /* registrar config: */
	    /* respond	code	auth	  contact   exp_prm expires more_contacts */
	    { PJ_TRUE,	200,	PJ_FALSE, NONE,	    0,	    65,	    {NULL, 0}},

	    /* client expected results: */
	    /* error	code	have_reg    expiration	contact_cnt auth?*/
	    { PJ_FALSE,	200,	PJ_TRUE,    65,		0,	    PJ_FALSE}
	},

	/* Neither Contact header nor Expires header are present.
	 * In this case the expiration is taken from the request.
	 */
	{
	    ON_OFF,			    /* check_contact	*/
	    ON_OFF,			    /* add_xuid_param	*/
	    "no Contact and no Expires",    /* title		*/
	    NULL,			    /* alt_registrar	*/
	    1,				    /* contact cnt	*/
	    { "<sip:[email protected]:5060>" },/* contacts[]	*/
	    600,			    /* expires		*/

	    /* registrar config: */
	    /* respond	code	auth	  contact   exp_prm expires more_contacts */
	    { PJ_TRUE,	200,	PJ_FALSE, NONE,	    0,	    0,	    {NULL, 0}},

	    /* client expected results: */
	    /* error	code	have_reg    expiration	contact_cnt auth?*/
	    { PJ_FALSE,	200,	PJ_TRUE,    600,	0,	    PJ_FALSE}
	},
    };

    unsigned i;
    pj_sockaddr_in addr;
    pjsip_transport *udp = NULL;
    pj_uint16_t port; 
    char registrar_uri_buf[80];
    pj_str_t registrar_uri;
    int rc = 0;

    pj_sockaddr_in_init(&addr, 0, 0);

    /* Acquire existing transport, if any */
    rc = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_UDP, &addr, sizeof(addr), NULL, &udp);
    if (rc == PJ_SUCCESS) {
	port = pj_sockaddr_get_port(&udp->local_addr);
	pjsip_transport_dec_ref(udp);
	udp = NULL;
    } else {
	rc = pjsip_udp_transport_start(endpt, NULL, NULL, 1, &udp);
	if (rc != PJ_SUCCESS) {
	    app_perror("   error creating UDP transport", rc);
	    rc = -2;
	    goto on_return;
	}

	port = pj_sockaddr_get_port(&udp->local_addr);
    }

    /* Register registrar module */
    rc = pjsip_endpt_register_module(endpt, &registrar.mod);
    if (rc != PJ_SUCCESS) {
	app_perror("   error registering module", rc);
	rc = -3;
	goto on_return;
    }

    /* Register send module */
    rc = pjsip_endpt_register_module(endpt, &send_mod.mod);
    if (rc != PJ_SUCCESS) {
	app_perror("   error registering module", rc);
	rc = -3;
	goto on_return;
    }

    pj_ansi_snprintf(registrar_uri_buf, sizeof(registrar_uri_buf),
		    "sip:127.0.0.1:%d", (int)port);
    registrar_uri = pj_str(registrar_uri_buf);

    for (i=0; i<PJ_ARRAY_SIZE(test_rec); ++i) {
	struct test_rec *t = &test_rec[i];
	unsigned j, x;
	pj_str_t reg_uri;
	pj_str_t contacts[8];

	/* Fill in the registrar address if it's not specified */
	if (t->alt_registrar == NULL) {
	    reg_uri = registrar_uri;
	} else {
	    reg_uri = pj_str(t->alt_registrar);
	}

	/* Build contact pj_str_t's */
	for (j=0; j<t->contact_cnt; ++j) {
	    contacts[j] = pj_str(t->contacts[j]);
	}

	/* Normalize more_contacts field */
	if (t->server_cfg.more_contacts.ptr)
	    t->server_cfg.more_contacts.slen = strlen(t->server_cfg.more_contacts.ptr);

	/* Do tests with three combinations:
	 *  - check_contact on/off
	 *  - add_xuid_param on/off
	 *  - destroy_on_callback on/off
	 */
	for (x=1; x<=2; ++x) {
	    unsigned y;

	    if ((t->check_contact & x) == 0)
		continue;

	    pjsip_cfg()->regc.check_contact = (x-1);

	    for (y=1; y<=2; ++y) {
		unsigned z;

		if ((t->add_xuid_param & y) == 0)
		    continue;

		pjsip_cfg()->regc.add_xuid_param = (y-1);

		for (z=0; z<=1; ++z) {
		    char new_title[200];

		    t->client_cfg.destroy_on_cb = z;

		    sprintf(new_title, "%s [check=%d, xuid=%d, destroy=%d]", 
			    t->title, pjsip_cfg()->regc.check_contact,
			    pjsip_cfg()->regc.add_xuid_param, z);
		    rc = do_test(new_title, &t->server_cfg, &t->client_cfg, 
				 &reg_uri, t->contact_cnt, contacts, 
				 t->expires, PJ_FALSE, NULL);
		    if (rc != 0)
			goto on_return;
		}

	    }
	}

	/* Sleep between test groups to avoid using up too many
	 * active transactions.
	 */
	pj_thread_sleep(1000);
    }

    /* keep-alive test */
    rc = keep_alive_test(&registrar_uri);
    if (rc != 0)
	goto on_return;

    /* Send error on refresh without destroy on callback */
    rc = refresh_error(&registrar_uri, PJ_FALSE);
    if (rc != 0)
	goto on_return;

    /* Send error on refresh, destroy on callback */
    rc = refresh_error(&registrar_uri, PJ_TRUE);
    if (rc != 0)
	goto on_return;

    /* Updating contact */
    rc = update_test(&registrar_uri);
    if (rc != 0)
	goto on_return;

    /* Send error during auth, don't destroy on callback */
    rc = auth_send_error(&registrar_uri, PJ_FALSE);
    if (rc != 0)
	goto on_return;

    /* Send error during auth, destroy on callback */
    rc = auth_send_error(&registrar_uri, PJ_FALSE);
    if (rc != 0)
	goto on_return;

on_return:
    if (registrar.mod.id != -1) {
	pjsip_endpt_unregister_module(endpt, &registrar.mod);
    }
    if (send_mod.mod.id != -1) {
	pjsip_endpt_unregister_module(endpt, &send_mod.mod);
    }
    if (udp) {
	pjsip_transport_dec_ref(udp);
    }
    return rc;
}
Beispiel #3
0
/*
 * UDP transport test.
 */
int transport_udp_test(void)
{
    enum { SEND_RECV_LOOP = 8 };
    pjsip_transport *udp_tp, *tp;
    pj_sockaddr_in addr, rem_addr;
    pj_str_t s;
    pj_status_t status;
    int rtt[SEND_RECV_LOOP], min_rtt;
    int i, pkt_lost;

    pj_sockaddr_in_init(&addr, NULL, TEST_UDP_PORT);

    /* Start UDP transport. */
    status = pjsip_udp_transport_start( endpt, &addr, NULL, 1, &udp_tp);
    if (status != PJ_SUCCESS) {
	app_perror("   Error: unable to start UDP transport", status);
	return -10;
    }

    /* UDP transport must have initial reference counter set to 1. */
    if (pj_atomic_get(udp_tp->ref_cnt) != 1)
	return -20;

    /* Test basic transport attributes */
    status = generic_transport_test(udp_tp);
    if (status != PJ_SUCCESS)
	return status;

    /* Test that transport manager is returning the correct
     * transport.
     */
    pj_sockaddr_in_init(&rem_addr, pj_cstr(&s, "1.1.1.1"), 80);
    status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_UDP, 
					   &rem_addr, sizeof(rem_addr),
					   NULL, &tp);
    if (status != PJ_SUCCESS)
	return -50;
    if (tp != udp_tp)
	return -60;

    /* pjsip_endpt_acquire_transport() adds reference, so we need
     * to decrement it.
     */
    pjsip_transport_dec_ref(tp);

    /* Check again that reference counter is 1. */
    if (pj_atomic_get(udp_tp->ref_cnt) != 1)
	return -70;

    /* Basic transport's send/receive loopback test. */
    pj_sockaddr_in_init(&rem_addr, pj_cstr(&s, "127.0.0.1"), TEST_UDP_PORT);
    for (i=0; i<SEND_RECV_LOOP; ++i) {
	status = transport_send_recv_test(PJSIP_TRANSPORT_UDP, tp, 
					  "sip:[email protected]:"TEST_UDP_PORT_STR,
					  &rtt[i]);
	if (status != 0)
	    return status;
    }

    min_rtt = 0xFFFFFFF;
    for (i=0; i<SEND_RECV_LOOP; ++i)
	if (rtt[i] < min_rtt) min_rtt = rtt[i];

    report_ival("udp-rtt-usec", min_rtt, "usec",
		"Best UDP transport round trip time, in microseconds "
		"(time from sending request until response is received. "
		"Tests were performed on local machine only)");


    /* Multi-threaded round-trip test. */
    status = transport_rt_test(PJSIP_TRANSPORT_UDP, tp, 
			       "sip:[email protected]:"TEST_UDP_PORT_STR, 
			       &pkt_lost);
    if (status != 0)
	return status;

    if (pkt_lost != 0)
	PJ_LOG(3,(THIS_FILE, "   note: %d packet(s) was lost", pkt_lost));

    /* Check again that reference counter is 1. */
    if (pj_atomic_get(udp_tp->ref_cnt) != 1)
	return -80;

    /* Destroy this transport. */
    pjsip_transport_dec_ref(udp_tp);

    /* Force destroy this transport. */
    status = pjsip_transport_destroy(udp_tp);
    if (status != PJ_SUCCESS)
	return -90;

    /* Flush events. */
    PJ_LOG(3,(THIS_FILE, "   Flushing events, 1 second..."));
    flush_events(1000);

    /* Done */
    return 0;
}
Beispiel #4
0
static int uas_tsx_bench(unsigned working_set, pj_timestamp *p_elapsed)
{
    unsigned i;
    pjsip_tx_data *request;
    pjsip_via_hdr *via;
    pjsip_rx_data rdata;
    pj_sockaddr_in remote;
    pjsip_transaction **tsx;
    pj_timestamp t1, t2, elapsed;
    char branch_buf[80] = PJSIP_RFC3261_BRANCH_ID "0000000000";
    pj_status_t status;

    /* Create the request first. */
    pj_str_t str_target = pj_str("sip:[email protected]");
    pj_str_t str_from = pj_str("\"Local User\" <sip:[email protected]>");
    pj_str_t str_to = pj_str("\"Remote User\" <sip:[email protected]>");
    pj_str_t str_contact = str_from;

    status = pjsip_endpt_create_request(endpt, &pjsip_invite_method,
					&str_target, &str_from, &str_to,
					&str_contact, NULL, -1, NULL,
					&request);
    if (status != PJ_SUCCESS) {
	app_perror("    error: unable to create request", status);
	return status;
    }

    /* Create  Via */
    via = pjsip_via_hdr_create(request->pool);
    via->sent_by.host = pj_str("192.168.0.7");
    via->sent_by.port = 5061;
    via->transport = pj_str("udp");
    via->rport_param = 1;
    via->recvd_param = pj_str("192.168.0.7");
    pjsip_msg_insert_first_hdr(request->msg, (pjsip_hdr*)via);
    

    /* Create "dummy" rdata from the tdata */
    pj_bzero(&rdata, sizeof(pjsip_rx_data));
    rdata.tp_info.pool = request->pool;
    rdata.msg_info.msg = request->msg;
    rdata.msg_info.from = (pjsip_from_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_FROM, NULL);
    rdata.msg_info.to = (pjsip_to_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_TO, NULL);
    rdata.msg_info.cseq = (pjsip_cseq_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_CSEQ, NULL);
    rdata.msg_info.cid = (pjsip_cid_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_FROM, NULL);
    rdata.msg_info.via = via;
    
    pj_sockaddr_in_init(&remote, 0, 0);
    status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM, 
					   &remote, sizeof(pj_sockaddr_in),
					   NULL, &rdata.tp_info.transport);
    if (status != PJ_SUCCESS) {
	app_perror("    error: unable to get loop transport", status);
	return status;
    }


    /* Create transaction array */
    tsx = (pjsip_transaction**) pj_pool_zalloc(request->pool, working_set * sizeof(pj_pool_t*));

    pj_bzero(&mod_tsx_user, sizeof(mod_tsx_user));
    mod_tsx_user.id = -1;


    /* Benchmark */
    elapsed.u64 = 0;
    pj_get_timestamp(&t1);
    for (i=0; i<working_set; ++i) {
	via->branch_param.ptr = branch_buf;
	via->branch_param.slen = PJSIP_RFC3261_BRANCH_LEN + 
				    pj_ansi_sprintf(branch_buf+PJSIP_RFC3261_BRANCH_LEN,
						    "-%d", i);
	status = pjsip_tsx_create_uas(&mod_tsx_user, &rdata, &tsx[i]);
	if (status != PJ_SUCCESS)
	    goto on_error;

    }
    pj_get_timestamp(&t2);
    pj_sub_timestamp(&t2, &t1);
    pj_add_timestamp(&elapsed, &t2);

    p_elapsed->u64 = elapsed.u64;
    status = PJ_SUCCESS;
    
on_error:
    for (i=0; i<working_set; ++i) {
	if (tsx[i]) {
	    pjsip_tsx_terminate(tsx[i], 601);
	    tsx[i] = NULL;
	}
    }
    pjsip_tx_data_dec_ref(request);
    flush_events(2000);
    return status;
}
Beispiel #5
0
/*****************************************************************************
 **
 ** UAC Transaction Test.
 **
 *****************************************************************************
 */
int tsx_uac_test(struct tsx_test_param *param)
{
    pj_sockaddr_in addr;
    pj_status_t status;

    timer.tsx_key.ptr = timer.key_buf;

    test_param = param;

    /* Get transport flag */
    tp_flag = pjsip_transport_get_flag_from_type(test_param->type);

    pj_ansi_sprintf(TARGET_URI, "sip:[email protected]:%d;transport=%s", 
		    param->port, param->tp_type);
    pj_ansi_sprintf(FROM_URI, "sip:[email protected]:%d;transport=%s", 
		    param->port, param->tp_type);

    /* Check if loop transport is configured. */
    status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM, 
				      &addr, sizeof(addr), NULL, &loop);
    if (status != PJ_SUCCESS) {
	PJ_LOG(3,(THIS_FILE, "  Error: loop transport is not configured!"));
	return -10;
    }

    /* Register modules. */
    status = pjsip_endpt_register_module(endpt, &tsx_user);
    if (status != PJ_SUCCESS) {
	app_perror("   Error: unable to register module", status);
	return -30;
    }
    status = pjsip_endpt_register_module(endpt, &msg_receiver);
    if (status != PJ_SUCCESS) {
	app_perror("   Error: unable to register module", status);
	return -40;
    }

    /* TEST1_BRANCH_ID: Basic retransmit and timeout test. */
    status = tsx_uac_retransmit_test();
    if (status != 0)
	return status;

    /* TEST2_BRANCH_ID: Resolve error test. */
    status = tsx_resolve_error_test();
    if (status != 0)
	return status;

    /* TEST3_BRANCH_ID: UAC terminate while resolving test. */
    status = tsx_terminate_resolving_test();
    if (status != 0)
	return status;

    /* TEST4_BRANCH_ID: Transport failed after several retransmissions.
     *                  Only applies to loop transport.
     */
    if (test_param->type == PJSIP_TRANSPORT_LOOP_DGRAM) {
	status = tsx_retransmit_fail_test();
	if (status != 0)
	    return status;
    }

    /* TEST5_BRANCH_ID: Terminate transaction after several retransmissions 
     *			Only applicable to non-reliable transports.
     */
    if ((tp_flag & PJSIP_TRANSPORT_RELIABLE) == 0) {
	status = tsx_terminate_after_retransmit_test();
	if (status != 0)
	    return status;
    }

    /* TEST6_BRANCH_ID: Successfull non-invite transaction */
    status = perform_generic_test("test6: successfull non-invite transaction",
				  TEST6_BRANCH_ID, &pjsip_options_method);
    if (status != 0)
	return status;

    /* TEST7_BRANCH_ID: Successfull non-invite transaction */
    status = perform_generic_test("test7: successfull non-invite transaction "
				  "with provisional response",
				  TEST7_BRANCH_ID, &pjsip_options_method);
    if (status != 0)
	return status;

    /* TEST8_BRANCH_ID: Failed invite transaction */
    status = perform_generic_test("test8: failed invite transaction",
				  TEST8_BRANCH_ID, &pjsip_invite_method);
    if (status != 0)
	return status;

    /* TEST9_BRANCH_ID: Failed invite transaction with provisional response */
    status = perform_generic_test("test9: failed invite transaction with "
				  "provisional response",
				  TEST9_BRANCH_ID, &pjsip_invite_method);
    if (status != 0)
	return status;

    pjsip_transport_dec_ref(loop);
    flush_events(500);

    /* Unregister modules. */
    status = pjsip_endpt_unregister_module(endpt, &tsx_user);
    if (status != PJ_SUCCESS) {
	app_perror("   Error: unable to unregister module", status);
	return -31;
    }
    status = pjsip_endpt_unregister_module(endpt, &msg_receiver);
    if (status != PJ_SUCCESS) {
	app_perror("   Error: unable to unregister module", status);
	return -41;
    }

    return 0;
}
Beispiel #6
0
/*****************************************************************************
 **
 ** UAS Transaction Test.
 **
 *****************************************************************************
 */
int tsx_uas_test(struct tsx_test_param *param)
{
    pj_sockaddr_in addr;
    pj_status_t status;

    test_param = param;
    tp_flag = pjsip_transport_get_flag_from_type((pjsip_transport_type_e)param->type);

    pj_ansi_sprintf(TARGET_URI, "sip:[email protected]:%d;transport=%s", 
		    param->port, param->tp_type);
    pj_ansi_sprintf(FROM_URI, "sip:[email protected]:%d;transport=%s", 
		    param->port, param->tp_type);

    /* Check if loop transport is configured. */
    status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM, 
				      &addr, sizeof(addr), NULL, &loop);
    if (status != PJ_SUCCESS) {
	PJ_LOG(3,(THIS_FILE, "  Error: loop transport is not configured!"));
	return -10;
    }
    /* Register modules. */
    status = pjsip_endpt_register_module(endpt, &tsx_user);
    if (status != PJ_SUCCESS) {
	app_perror("   Error: unable to register module", status);
	return -3;
    }
    status = pjsip_endpt_register_module(endpt, &msg_sender);
    if (status != PJ_SUCCESS) {
	app_perror("   Error: unable to register module", status);
	return -4;
    }

    /* TEST1_BRANCH_ID: Basic 2xx final response. 
     * TEST2_BRANCH_ID: Basic non-2xx final response. 
     */
    status = tsx_basic_final_response_test();
    if (status != 0)
	return status;

    /* TEST3_BRANCH_ID: with provisional response
     */
    status = tsx_basic_provisional_response_test();
    if (status != 0)
	return status;

    /* TEST4_BRANCH_ID: absorbs retransmissions in TRYING state
     */
    status = tsx_retransmit_last_response_test(TEST4_TITLE,
					       TEST4_BRANCH_ID, 
					       TEST4_REQUEST_COUNT,
					       TEST4_STATUS_CODE);
    if (status != 0)
	return status;

    /* TEST5_BRANCH_ID: retransmit last response in PROCEEDING state
     */
    status = tsx_retransmit_last_response_test(TEST5_TITLE,
					       TEST5_BRANCH_ID, 
					       TEST5_REQUEST_COUNT,
					       TEST5_STATUS_CODE);
    if (status != 0)
	return status;

    /* TEST6_BRANCH_ID: retransmit last response in COMPLETED state
     *                  This only applies to non-reliable transports,
     *			since UAS transaction is destroyed as soon
     *			as final response is sent for reliable transports.
     */
    if ((tp_flag & PJSIP_TRANSPORT_RELIABLE) == 0) {
	status = tsx_retransmit_last_response_test(TEST6_TITLE,
						   TEST6_BRANCH_ID, 
						   TEST6_REQUEST_COUNT,
						   TEST6_STATUS_CODE);
	if (status != 0)
	    return status;
    }

    /* TEST7_BRANCH_ID: INVITE non-2xx final response retransmission test
     * TEST8_BRANCH_ID: INVITE 2xx final response retransmission test
     */
    status = tsx_final_response_retransmission_test();
    if (status != 0)
	return status;

    /* TEST9_BRANCH_ID: retransmission of non-2xx INVITE final response must 
     * cease when ACK is received
     * Only applicable for non-reliable transports.
     */
    if ((tp_flag & PJSIP_TRANSPORT_RELIABLE) == 0) {
	status = tsx_ack_test();
	if (status != 0)
	    return status;
    }


    /* TEST10_BRANCH_ID: test transport failure in TRYING state.
     * TEST11_BRANCH_ID: test transport failure in PROCEEDING state.
     * TEST12_BRANCH_ID: test transport failure in CONNECTED state.
     * TEST13_BRANCH_ID: test transport failure in CONFIRMED state.
     */
    /* Only valid for loop-dgram */
    if (param->type == PJSIP_TRANSPORT_LOOP_DGRAM) {
	status = tsx_transport_failure_test();
	if (status != 0)
	    return status;
    }


    /* Register modules. */
    status = pjsip_endpt_unregister_module(endpt, &tsx_user);
    if (status != PJ_SUCCESS) {
	app_perror("   Error: unable to unregister module", status);
	return -8;
    }
    status = pjsip_endpt_unregister_module(endpt, &msg_sender);
    if (status != PJ_SUCCESS) {
	app_perror("   Error: unable to unregister module", status);
	return -9;
    }


    if (loop)
	pjsip_transport_dec_ref(loop);

    return 0;
}
static int datagram_loop_test()
{
    enum { LOOP = 8 };
    pjsip_transport *loop;
    int i, pkt_lost;
    pj_sockaddr_in addr;
    pj_status_t status;
    long ref_cnt;
    int rtt[LOOP], min_rtt;

    PJ_LOG(3,(THIS_FILE, "testing datagram loop transport"));

    /* Test acquire transport. */
    status = pjsip_endpt_acquire_transport( endpt, PJSIP_TRANSPORT_LOOP_DGRAM,
					    &addr, sizeof(addr), NULL, &loop);
    if (status != PJ_SUCCESS) {
	app_perror("   error: loop transport is not configured", status);
	return -20;
    }

    /* Get initial reference counter */
    ref_cnt = pj_atomic_get(loop->ref_cnt);

    /* Test basic transport attributes */
    status = generic_transport_test(loop);
    if (status != PJ_SUCCESS)
	return status;

    /* Basic transport's send/receive loopback test. */
    for (i=0; i<LOOP; ++i) {
	status = transport_send_recv_test(PJSIP_TRANSPORT_LOOP_DGRAM, loop, 
					  "sip:[email protected];transport=loop-dgram",
					  &rtt[i]);
	if (status != 0)
	    return status;
    }

    min_rtt = 0xFFFFFFF;
    for (i=0; i<LOOP; ++i)
	if (rtt[i] < min_rtt) min_rtt = rtt[i];

    report_ival("loop-rtt-usec", min_rtt, "usec",
		"Best Loopback transport round trip time, in microseconds "
		"(time from sending request until response is received. "
		"Tests were performed on local machine only)");


    /* Multi-threaded round-trip test. */
    status = transport_rt_test(PJSIP_TRANSPORT_LOOP_DGRAM, loop, 
			       "sip:[email protected];transport=loop-dgram",
			       &pkt_lost);
    if (status != 0)
	return status;

    if (pkt_lost != 0) {
	PJ_LOG(3,(THIS_FILE, "   error: %d packet(s) was lost", pkt_lost));
	return -40;
    }

    /* Put delay. */
    PJ_LOG(3,(THIS_FILE,"  setting network delay to 10 ms"));
    pjsip_loop_set_delay(loop, 10);

    /* Multi-threaded round-trip test. */
    status = transport_rt_test(PJSIP_TRANSPORT_LOOP_DGRAM, loop, 
			       "sip:[email protected];transport=loop-dgram",
			       &pkt_lost);
    if (status != 0)
	return status;

    if (pkt_lost != 0) {
	PJ_LOG(3,(THIS_FILE, "   error: %d packet(s) was lost", pkt_lost));
	return -50;
    }

    /* Restore delay. */
    pjsip_loop_set_delay(loop, 0);

    /* Check reference counter. */
    if (pj_atomic_get(loop->ref_cnt) != ref_cnt) {
	PJ_LOG(3,(THIS_FILE, "   error: ref counter is not %d (%d)", 
			     ref_cnt, pj_atomic_get(loop->ref_cnt)));
	return -51;
    }

    /* Decrement reference. */
    pjsip_transport_dec_ref(loop);

    return 0;
}
Beispiel #8
0
int transport_tcp_test(void)
{
    enum { SEND_RECV_LOOP = 8 };
    pjsip_tpfactory *tpfactory;
    pjsip_transport *tcp;
    pj_sockaddr_in rem_addr;
    pj_status_t status;
    char url[PJSIP_MAX_URL_SIZE];
    int rtt[SEND_RECV_LOOP], min_rtt;
    int i, pkt_lost;

    /* Start TCP listener on arbitrary port. */
    status = pjsip_tcp_transport_start(endpt, NULL, 1, &tpfactory);
    if (status != PJ_SUCCESS) {
	app_perror("   Error: unable to start TCP transport", status);
	return -10;
    }


    /* Get the listener address */
    status = pj_sockaddr_in_init(&rem_addr, &tpfactory->addr_name.host,
				 (pj_uint16_t)tpfactory->addr_name.port);
    if (status != PJ_SUCCESS) {
	app_perror("   Error: possibly invalid TCP address name", status);
	return -14;
    }

    pj_ansi_sprintf(url, "sip:alice@%s:%d;transport=tcp",
		    pj_inet_ntoa(rem_addr.sin_addr),
		    pj_ntohs(rem_addr.sin_port));


    /* Acquire one TCP transport. */
    status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_TCP, 
					   &rem_addr, sizeof(rem_addr),
					   NULL, &tcp);
    if (status != PJ_SUCCESS || tcp == NULL) {
	app_perror("   Error: unable to acquire TCP transport", status);
	return -17;
    }

    /* After pjsip_endpt_acquire_transport, TCP transport must have
     * reference counter 1. 
     */
    if (pj_atomic_get(tcp->ref_cnt) != 1)
	return -20;

    /* Test basic transport attributes */
    status = generic_transport_test(tcp);
    if (status != PJ_SUCCESS)
	return status;


    /* Check again that reference counter is 1. */
    if (pj_atomic_get(tcp->ref_cnt) != 1)
	return -40;

    /* Load test */
    if (transport_load_test(url) != 0)
	return -60;

    /* Basic transport's send/receive loopback test. */
    for (i=0; i<SEND_RECV_LOOP; ++i) {
	status = transport_send_recv_test(PJSIP_TRANSPORT_TCP, tcp, url, &rtt[i]);

	if (status != 0) {
	    pjsip_transport_dec_ref(tcp);
	    flush_events(500);
	    return -72;
	}
    }

    min_rtt = 0xFFFFFFF;
    for (i=0; i<SEND_RECV_LOOP; ++i)
	if (rtt[i] < min_rtt) min_rtt = rtt[i];

    report_ival("tcp-rtt-usec", min_rtt, "usec",
		"Best TCP transport round trip time, in microseconds "
		"(time from sending request until response is received. "
		"Tests were performed on local machine only, and after "
		"TCP socket has been established by previous test)");


    /* Multi-threaded round-trip test. */
    status = transport_rt_test(PJSIP_TRANSPORT_TCP, tcp, url, &pkt_lost);
    if (status != 0) {
	pjsip_transport_dec_ref(tcp);
	return status;
    }

    if (pkt_lost != 0)
	PJ_LOG(3,(THIS_FILE, "   note: %d packet(s) was lost", pkt_lost));

    /* Check again that reference counter is still 1. */
    if (pj_atomic_get(tcp->ref_cnt) != 1)
	return -80;

    /* Destroy this transport. */
    pjsip_transport_dec_ref(tcp);

    /* Force destroy this transport. */
    status = pjsip_transport_destroy(tcp);
    if (status != PJ_SUCCESS)
	return -90;

    /* Unregister factory */
    status = pjsip_tpmgr_unregister_tpfactory(pjsip_endpt_get_tpmgr(endpt), 
					      tpfactory);
    if (status != PJ_SUCCESS)
	return -95;

    /* Flush events. */
    PJ_LOG(3,(THIS_FILE, "   Flushing events, 1 second..."));
    flush_events(1000);

    /* Done */
    return 0;
}
Beispiel #9
0
pj_status_t UE::init_int(pj_log_func* logger,
             std::string realm,
             std::string myurl,
             std::string username,
             std::string password,
             std::string outbound_proxy)
{
  pj_status_t status;
  char errmsg[PJ_ERR_MSG_SIZE];
  pj_sockaddr addr;
  pj_str_t remote;
  pj_sockaddr remote_addr;

  init_pjsip(logger);
  std::string server_uri = std::string("sip:") + realm + std::string(";lr;transport=tcp");
  _pool = pj_pool_create(get_global_pool_factory(), "a", 256, 256, NULL);

  pj_sockaddr_init(pj_AF_INET(), &addr, NULL, (pj_uint16_t)0);

  //status = pjsip_udp_transport_start(get_global_endpoint(), &addr.ipv4, NULL, 1, &_transport);
  //assert(status == PJ_SUCCESS);

  if (outbound_proxy.empty())
  {
    outbound_proxy = realm;
  }
  
  pj_cstr(&remote, outbound_proxy.c_str());
  pj_sockaddr_init(pj_AF_INET(), &remote_addr, &remote, (pj_uint16_t)5060);

  pjsip_tpselector sel2;
  sel2.type = PJSIP_TPSELECTOR_LISTENER;
  sel2.u.listener = get_global_tcp_factory();
  status = pjsip_endpt_acquire_transport(get_global_endpoint(),
      PJSIP_TRANSPORT_TCP,
      &remote_addr,
      pj_sockaddr_get_len(&remote_addr),
      &sel2,
      &_transport);
  
  if (status != PJ_SUCCESS)
  {
    pj_strerror(status, errmsg, sizeof(errmsg));
    PJ_LOG(1, (__FILE__, "TCP connection to %s failed: %s (%d)", outbound_proxy.c_str(), errmsg, status));
    return status;
  }
  
  transport_mapping[_transport] = this;

  status = pjsip_regc_create(get_global_endpoint(), this, &regc_cb, &_regc);

  if (status != PJ_SUCCESS)
  {
    pj_strerror(status, errmsg, sizeof(errmsg));
    PJ_LOG(1, (__FILE__, "Creating the REGISTER session failed: %s (%d)", errmsg, status));
    return status;
  }

  pjsip_regc_set_reg_tsx_cb(_regc, &reg_tsx_cb);

  pjsip_tpselector sel;
  sel.type = PJSIP_TPSELECTOR_TRANSPORT;
  sel.u.transport = _transport;
  pjsip_regc_set_transport(_regc, &sel);

  pjsip_auth_clt_pref prefs = {};
  prefs.initial_auth = PJ_TRUE;

  pjsip_regc_set_prefs(_regc, &prefs);

  pjsip_cred_info cred;
  stra(&cred.realm, realm.c_str());
  stra(&cred.scheme, "Digest");
  stra(&cred.username, username.c_str());
  stra(&cred.data, password.c_str());
  cred.data_type = 0; // Plaintext password
  pjsip_cred_info creds[1] = {cred};
  pjsip_regc_set_credentials(_regc, 1, creds);

  char contact[32];
  snprintf(contact, 32, "sip:phone@%.*s:%d", (int)_transport->local_name.host.slen, _transport->local_name.host.ptr, _transport->local_name.port);

  stra(&_realm, realm.c_str());
  stra(&_server, server_uri.c_str());
  _server_uri = pjsip_parse_uri(_pool, _server.ptr, _server.slen, 0);
  stra(&_my_uri, myurl.c_str());
  stra(&_username, username.c_str());
  stra(&_contact, contact);

  return PJ_SUCCESS;
}