📄 tsx_uas_test.c
字号:
/* $Id: tsx_uas_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 "tsx_uas_test.c"/***************************************************************************** ** ** UAS tests. ** ** This file performs various tests for UAC transactions. Each test will have ** a different Via branch param so that message receiver module and ** transaction user module can identify which test is being carried out. ** ** TEST1_BRANCH_ID ** Test that non-INVITE transaction returns 2xx response to the correct ** transport and correctly terminates the transaction. ** This also checks that transaction is destroyed immediately after ** it sends final response when reliable transport is used. ** ** TEST2_BRANCH_ID ** As above, for non-2xx final response. ** ** TEST3_BRANCH_ID ** Transaction correctly progressing to PROCEEDING state when provisional ** response is sent. ** ** TEST4_BRANCH_ID ** Transaction retransmits last response (if any) without notifying ** transaction user upon receiving request retransmissions on TRYING ** state ** ** TEST5_BRANCH_ID ** As above, in PROCEEDING state. ** ** TEST6_BRANCH_ID ** As above, in COMPLETED state, with first sending provisional response. ** (Only applicable for non-reliable transports). ** ** TEST7_BRANCH_ID ** INVITE transaction MUST retransmit non-2xx final response. ** ** TEST8_BRANCH_ID ** As above, for INVITE's 2xx final response (this is PJSIP specific). ** ** TEST9_BRANCH_ID ** INVITE transaction MUST cease retransmission of final response when ** ACK is received. (Note: PJSIP also retransmit 2xx final response ** until it's terminated by user). ** Transaction also MUST terminate in T4 seconds. ** (Only applicable for non-reliable transports). ** ** TEST11_BRANCH_ID ** Test scenario where transport fails before response is sent (i.e. ** in TRYING state). ** ** TEST12_BRANCH_ID ** As above, after provisional response is sent but before final ** response is sent (i.e. in PROCEEDING state). ** ** TEST13_BRANCH_ID ** As above, for INVITE, after final response has been sent but before ** ACK is received (i.e. in CONNECTED state). ** ** TEST14_BRANCH_ID ** When UAS failed to deliver the response with the selected transport, ** it should try contacting the client with other transport or begin ** RFC 3263 server resolution procedure. ** This should be tested on: ** a. TRYING state (when delivering first response). ** b. PROCEEDING state (when failed to retransmit last response ** upon receiving request retransmission). ** c. COMPLETED state. ** **/static char *TEST1_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test1";static char *TEST2_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test2";static char *TEST3_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test3";static char *TEST4_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test4";static char *TEST5_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test5";static char *TEST6_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test6";static char *TEST7_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test7";static char *TEST8_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test8";static char *TEST9_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test9";static char *TEST10_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test10";static char *TEST11_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test11";static char *TEST12_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test12";//static char *TEST13_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test13";#define TEST1_STATUS_CODE 200#define TEST2_STATUS_CODE 301#define TEST3_PROVISIONAL_CODE PJSIP_SC_QUEUED#define TEST3_STATUS_CODE 202#define TEST4_STATUS_CODE 200#define TEST4_REQUEST_COUNT 2#define TEST5_PROVISIONAL_CODE 100#define TEST5_STATUS_CODE 200 #define TEST5_REQUEST_COUNT 2#define TEST5_RESPONSE_COUNT 2#define TEST6_PROVISIONAL_CODE 100#define TEST6_STATUS_CODE 200 /* Must be final */#define TEST6_REQUEST_COUNT 2#define TEST6_RESPONSE_COUNT 3#define TEST7_STATUS_CODE 301#define TEST8_STATUS_CODE 302#define TEST9_STATUS_CODE 301#define TEST4_TITLE "test4: absorbing request retransmission"#define TEST5_TITLE "test5: retransmit last response in PROCEEDING state"#define TEST6_TITLE "test6: retransmit last response in COMPLETED state"static char TARGET_URI[128];static char FROM_URI[128];static struct tsx_test_param *test_param;static unsigned tp_flag;#define TEST_TIMEOUT_ERROR -30#define MAX_ALLOWED_DIFF 150static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e);static pj_bool_t on_rx_message(pjsip_rx_data *rdata);/* UAC transaction user module. */static pjsip_module tsx_user = { NULL, NULL, /* prev and next */ { "Tsx-UAS-User", 12}, /* Name. */ -1, /* Id */ PJSIP_MOD_PRIORITY_APPLICATION-1, /* Priority */ NULL, /* load() */ NULL, /* start() */ NULL, /* stop() */ NULL, /* unload() */ NULL, /* on_rx_request() */ NULL, /* on_rx_response() */ NULL, /* on_tx_request() */ NULL, /* on_tx_response() */ &tsx_user_on_tsx_state, /* on_tsx_state() */};/* Module to send request. */static pjsip_module msg_sender = { NULL, NULL, /* prev and next */ { "Msg-Sender", 10}, /* Name. */ -1, /* Id */ PJSIP_MOD_PRIORITY_APPLICATION-1, /* Priority */ NULL, /* load() */ NULL, /* start() */ NULL, /* stop() */ NULL, /* unload() */ &on_rx_message, /* on_rx_request() */ &on_rx_message, /* on_rx_response() */ NULL, /* on_tx_request() */ NULL, /* on_tx_response() */ NULL, /* on_tsx_state() */};/* Static vars, which will be reset on each test. */static int recv_count;static pj_time_val recv_last;static pj_bool_t test_complete;/* Loop transport instance. */static pjsip_transport *loop;/* UAS transaction key. */static char key_buf[64];static pj_str_t tsx_key = { key_buf, 0 };/* General timer entry to be used by tests. *///static pj_timer_entry timer;/* Timer to send response via transaction. */struct response{ pj_str_t tsx_key; pjsip_tx_data *tdata;};/* Timer callback to send response. */static void send_response_timer( pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry){ pjsip_transaction *tsx; struct response *r = entry->user_data; pj_status_t status; tsx = pjsip_tsx_layer_find_tsx(&r->tsx_key, PJ_TRUE); if (!tsx) { PJ_LOG(3,(THIS_FILE," error: timer unable to find transaction")); pjsip_tx_data_dec_ref(r->tdata); return; } status = pjsip_tsx_send_msg(tsx, r->tdata); if (status != PJ_SUCCESS) { // Some tests do expect failure! //PJ_LOG(3,(THIS_FILE," error: timer unable to send response")); pj_mutex_unlock(tsx->mutex); pjsip_tx_data_dec_ref(r->tdata); return; } pj_mutex_unlock(tsx->mutex);}/* Utility to send response. */static void send_response( pjsip_rx_data *rdata, pjsip_transaction *tsx, int status_code ){ pj_status_t status; pjsip_tx_data *tdata; status = pjsip_endpt_create_response( endpt, rdata, status_code, NULL, &tdata); if (status != PJ_SUCCESS) { app_perror(" error: unable to create response", status); test_complete = -196; return; } status = pjsip_tsx_send_msg(tsx, tdata); if (status != PJ_SUCCESS) { pjsip_tx_data_dec_ref(tdata); // Some tests do expect failure! //app_perror(" error: unable to send response", status); //test_complete = -197; return; }}/* Schedule timer to send response for the specified UAS transaction */static void schedule_send_response( pjsip_rx_data *rdata, const pj_str_t *tsx_key, int status_code, int msec_delay ){ pj_status_t status; pjsip_tx_data *tdata; pj_timer_entry *t; struct response *r; pj_time_val delay; status = pjsip_endpt_create_response( endpt, rdata, status_code, NULL, &tdata); if (status != PJ_SUCCESS) { app_perror(" error: unable to create response", status); test_complete = -198; return; } r = pj_pool_alloc(tdata->pool, sizeof(*r)); pj_strdup(tdata->pool, &r->tsx_key, tsx_key); r->tdata = tdata; delay.sec = 0; delay.msec = msec_delay; pj_time_val_normalize(&delay); t = pj_pool_zalloc(tdata->pool, sizeof(*t)); t->user_data = r; t->cb = &send_response_timer; status = pjsip_endpt_schedule_timer(endpt, t, &delay); if (status != PJ_SUCCESS) { pjsip_tx_data_dec_ref(tdata); app_perror(" error: unable to schedule timer", status); test_complete = -199; return; }}/* Find and terminate tsx with the specified key. */static void terminate_our_tsx(int status_code){ pjsip_transaction *tsx; tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE); if (!tsx) { PJ_LOG(3,(THIS_FILE," error: timer unable to find transaction")); return; } pjsip_tsx_terminate(tsx, status_code); pj_mutex_unlock(tsx->mutex);}#if 0 /* Unused for now *//* Timer callback to terminate transaction. */static void terminate_tsx_timer( pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry){ terminate_our_tsx(entry->id);}/* Schedule timer to terminate transaction. */static void schedule_terminate_tsx( pjsip_transaction *tsx, int status_code, int msec_delay ){ pj_time_val delay; delay.sec = 0; delay.msec = msec_delay; pj_time_val_normalize(&delay); pj_assert(pj_strcmp(&tsx->transaction_key, &tsx_key)==0); timer.user_data = NULL; timer.id = status_code; timer.cb = &terminate_tsx_timer; pjsip_endpt_schedule_timer(endpt, &timer, &delay);}#endif/* * This is the handler to receive state changed notification from the * transaction. It is used to verify that the transaction behaves according * to the test scenario. */static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e){ if (pj_strcmp2(&tsx->branch, TEST1_BRANCH_ID)==0 || pj_strcmp2(&tsx->branch, TEST2_BRANCH_ID)==0) { /* * TEST1_BRANCH_ID tests that non-INVITE transaction transmits final * response using correct transport and terminates transaction after * T4 (PJSIP_T4_TIMEOUT, 5 seconds). * * TEST2_BRANCH_ID does similar test for non-2xx final response. */ int status_code = (pj_strcmp2(&tsx->branch, TEST1_BRANCH_ID)==0) ? TEST1_STATUS_CODE : TEST2_STATUS_CODE; if (tsx->state == PJSIP_TSX_STATE_TERMINATED) { test_complete = 1; /* Check that status code is status_code. */ if (tsx->status_code != status_code) { PJ_LOG(3,(THIS_FILE, " error: incorrect status code")); test_complete = -100; } /* Previous state must be completed. */ if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) { PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state")); test_complete = -101; } } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED) { /* Previous state must be TRYING. */ if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_TRYING) { PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state")); test_complete = -102; } } } else if (pj_strcmp2(&tsx->branch, TEST3_BRANCH_ID)==0) { /* * TEST3_BRANCH_ID tests sending provisional response. */ if (tsx->state == PJSIP_TSX_STATE_TERMINATED) { test_complete = 1; /* Check that status code is status_code. */ if (tsx->status_code != TEST3_STATUS_CODE) { PJ_LOG(3,(THIS_FILE, " error: incorrect status code")); test_complete = -110; } /* Previous state must be completed. */ if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) { PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state")); test_complete = -111; } } else if (tsx->state == PJSIP_TSX_STATE_PROCEEDING) { /* Previous state must be TRYING. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -