📄 transport_test.c
字号:
/* $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 + -