⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transport_test.c

📁 一个开源SIP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: transport_test.c 974 2007-02-19 01:13:53Z bennylp $ */
/* 
 * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */

#include "test.h"
#include <pjsip.h>
#include <pjlib.h>

#define THIS_FILE   "transport_test.c"

///////////////////////////////////////////////////////////////////////////////
/*
 * Generic testing for transport, to make sure that basic
 * attributes have been initialized properly.
 */
int generic_transport_test(pjsip_transport *tp)
{
    PJ_LOG(3,(THIS_FILE, "  structure test..."));

    /* Check that local address name is valid. */
    {
	struct pj_in_addr addr;

	/* Note: inet_aton() returns non-zero if addr is valid! */
	if (pj_inet_aton(&tp->local_name.host, &addr) != 0) {
	    if (addr.s_addr==PJ_INADDR_ANY || addr.s_addr==PJ_INADDR_NONE) {
		PJ_LOG(3,(THIS_FILE, "   Error: invalid address name"));
		return -420;
	    }
	} else {
	    /* It's okay. local_name.host may be a hostname instead of
	     * IP address.
	     */
	}
    }

    /* Check that port is valid. */
    if (tp->local_name.port <= 0) {
	return -430;
    }

    /* Check length of address (for now we only check against sockaddr_in). */
    if (tp->addr_len != sizeof(pj_sockaddr_in))
	return -440;

    /* Check type. */
    if (tp->key.type == PJSIP_TRANSPORT_UNSPECIFIED)
	return -450;

    /* That's it. */
    return PJ_SUCCESS;
}

///////////////////////////////////////////////////////////////////////////////
/* 
 * Send/receive test.
 *
 * This test sends a request to loopback address; as soon as request is 
 * received, response will be sent, and time is recorded.
 *
 * The main purpose is to test that the basic transport functionalities works,
 * before we continue with more complicated tests.
 */
#define FROM_HDR    "Bob <sip:bob@example.com>"
#define CONTACT_HDR "Bob <sip:bob@127.0.0.1>"
#define CALL_ID_HDR "SendRecv-Test"
#define CSEQ_VALUE  100
#define BODY	    "Hello World!"

static pj_bool_t my_on_rx_request(pjsip_rx_data *rdata);
static pj_bool_t my_on_rx_response(pjsip_rx_data *rdata);

/* Flag to indicate message has been received
 * (or failed to send)
 */
#define NO_STATUS   -2
static int send_status = NO_STATUS;
static int recv_status = NO_STATUS;
static pj_timestamp my_send_time, my_recv_time;

/* Module to receive messages for this test. */
static pjsip_module my_module = 
{
    NULL, NULL,				/* prev and next	*/
    { "Transport-Test", 14},		/* Name.		*/
    -1,					/* Id			*/
    PJSIP_MOD_PRIORITY_TSX_LAYER-1,	/* Priority		*/
    NULL,				/* load()		*/
    NULL,				/* start()		*/
    NULL,				/* stop()		*/
    NULL,				/* unload()		*/
    &my_on_rx_request,			/* on_rx_request()	*/
    &my_on_rx_response,			/* on_rx_response()	*/
    NULL,				/* on_tsx_state()	*/
};


static pj_bool_t my_on_rx_request(pjsip_rx_data *rdata)
{
    /* Check that this is our request. */
    if (pj_strcmp2(&rdata->msg_info.cid->id, CALL_ID_HDR) == 0) {
	/* It is! */
	/* Send response. */
	pjsip_tx_data *tdata;
	pjsip_response_addr res_addr;
	pj_status_t status;

	status = pjsip_endpt_create_response( endpt, rdata, 200, NULL, &tdata);
	if (status != PJ_SUCCESS) {
	    recv_status = status;
	    return PJ_TRUE;
	}
	status = pjsip_get_response_addr( tdata->pool, rdata, &res_addr);
	if (status != PJ_SUCCESS) {
	    recv_status = status;
	    pjsip_tx_data_dec_ref(tdata);
	    return PJ_TRUE;
	}
	status = pjsip_endpt_send_response( endpt, &res_addr, tdata, NULL, NULL);
	if (status != PJ_SUCCESS) {
	    recv_status = status;
	    pjsip_tx_data_dec_ref(tdata);
	    return PJ_TRUE;
	}
	return PJ_TRUE;
    }
    
    /* Not ours. */
    return PJ_FALSE;
}

static pj_bool_t my_on_rx_response(pjsip_rx_data *rdata)
{
    if (pj_strcmp2(&rdata->msg_info.cid->id, CALL_ID_HDR) == 0) {
	pj_get_timestamp(&my_recv_time);
	recv_status = PJ_SUCCESS;
	return PJ_TRUE;
    }
    return PJ_FALSE;
}

/* Transport callback. */
static void send_msg_callback(pjsip_send_state *stateless_data,
			      pj_ssize_t sent, pj_bool_t *cont)
{
    if (sent < 1) {
	/* Obtain the error code. */
	send_status = -sent;
    } else {
	send_status = PJ_SUCCESS;
    }

    /* Don't want to continue. */
    *cont = PJ_FALSE;
}


/* Test that we receive loopback message. */
int transport_send_recv_test( pjsip_transport_type_e tp_type,
			      pjsip_transport *ref_tp,
			      char *target_url,
			      int *p_usec_rtt)
{
    pj_bool_t msg_log_enabled;
    pj_status_t status;
    pj_str_t target, from, to, contact, call_id, body;
    pjsip_method method;
    pjsip_tx_data *tdata;
    pj_time_val timeout;

    PJ_LOG(3,(THIS_FILE, "  single message round-trip test..."));

    /* Register out test module to receive the message (if necessary). */
    if (my_module.id == -1) {
	status = pjsip_endpt_register_module( endpt, &my_module );
	if (status != PJ_SUCCESS) {
	    app_perror("   error: unable to register module", status);
	    return -500;
	}
    }

    /* Disable message logging. */
    msg_log_enabled = msg_logger_set_enabled(0);

    /* Create a request message. */
    target = pj_str(target_url);
    from = pj_str(FROM_HDR);
    to = pj_str(target_url);
    contact = pj_str(CONTACT_HDR);
    call_id = pj_str(CALL_ID_HDR);
    body = pj_str(BODY);

    pjsip_method_set(&method, PJSIP_OPTIONS_METHOD);
    status = pjsip_endpt_create_request( endpt, &method, &target, &from, &to,
					 &contact, &call_id, CSEQ_VALUE, 
					 &body, &tdata );
    if (status != PJ_SUCCESS) {
	app_perror("   error: unable to create request", status);
	return -510;
    }

    /* Reset statuses */
    send_status = recv_status = NO_STATUS;

    /* Start time. */
    pj_get_timestamp(&my_send_time);

    /* Send the message (statelessly). */
    PJ_LOG(5,(THIS_FILE, "Sending request to %.*s", 
			 (int)target.slen, target.ptr));
    status = pjsip_endpt_send_request_stateless( endpt, tdata, NULL,
					         &send_msg_callback);
    if (status != PJ_SUCCESS) {
	/* Immediate error! */
	pjsip_tx_data_dec_ref(tdata);
	send_status = status;
    }

    /* Set the timeout (2 seconds from now) */
    pj_gettimeofday(&timeout);
    timeout.sec += 2;

    /* Loop handling events until we get status */
    do {
	pj_time_val now;
	pj_time_val poll_interval = { 0, 10 };

	pj_gettimeofday(&now);
	if (PJ_TIME_VAL_GTE(now, timeout)) {
	    PJ_LOG(3,(THIS_FILE, "   error: timeout in send/recv test"));
	    status = -540;
	    goto on_return;
	}

	if (send_status!=NO_STATUS && send_status!=PJ_SUCCESS) {
	    app_perror("   error sending message", send_status);
	    status = -550;
	    goto on_return;
	}

	if (recv_status!=NO_STATUS && recv_status!=PJ_SUCCESS) {
	    app_perror("   error receiving message", recv_status);
	    status = -560;
	    goto on_return;
	}

	if (send_status!=NO_STATUS && recv_status!=NO_STATUS) {
	    /* Success! */
	    break;
	}

	pjsip_endpt_handle_events(endpt, &poll_interval);

    } while (1);

    if (status == PJ_SUCCESS) {
	unsigned usec_rt;
	usec_rt = pj_elapsed_usec(&my_send_time, &my_recv_time);

	PJ_LOG(3,(THIS_FILE, "    round-trip = %d usec", usec_rt));

	*p_usec_rtt = usec_rt;
    }

    /* Restore message logging. */
    msg_logger_set_enabled(msg_log_enabled);

    status = PJ_SUCCESS;

on_return:
    return status;
}


///////////////////////////////////////////////////////////////////////////////
/* 
 * Multithreaded round-trip test
 *
 * This test will spawn multiple threads, each of them send a request. As soon
 * as request is received, response will be sent, and time is recorded.
 *
 * The main purpose of this test is to ensure there's no crash when multiple
 * threads are sending/receiving messages.
 *
 */
static pj_bool_t rt_on_rx_request(pjsip_rx_data *rdata);
static pj_bool_t rt_on_rx_response(pjsip_rx_data *rdata);

static pjsip_module rt_module = 
{
    NULL, NULL,				/* prev and next	*/
    { "Transport-RT-Test", 17},		/* Name.		*/
    -1,					/* Id			*/
    PJSIP_MOD_PRIORITY_TSX_LAYER-1,	/* Priority		*/
    NULL,				/* load()		*/
    NULL,				/* start()		*/
    NULL,				/* stop()		*/
    NULL,				/* unload()		*/
    &rt_on_rx_request,			/* on_rx_request()	*/
    &rt_on_rx_response,			/* on_rx_response()	*/
    NULL,				/* tsx_handler()	*/
};

static struct
{
    pj_thread_t *thread;
    pj_timestamp send_time;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -