diff options
Diffstat (limited to 'pjsip-apps/src')
-rw-r--r-- | pjsip-apps/src/pjsua/pjsua_app.c | 69 | ||||
-rw-r--r-- | pjsip-apps/src/test-pjsua/mod_recvfrom.py | 22 | ||||
-rw-r--r-- | pjsip-apps/src/test-pjsua/scripts-sipp/inv_401_retry_after_100.xml | 106 | ||||
-rw-r--r-- | pjsip-apps/src/test-pjsua/scripts-sipp/uas-template.xml | 84 |
4 files changed, 269 insertions, 12 deletions
diff --git a/pjsip-apps/src/pjsua/pjsua_app.c b/pjsip-apps/src/pjsua/pjsua_app.c index 0bdc4c34..870d0129 100644 --- a/pjsip-apps/src/pjsua/pjsua_app.c +++ b/pjsip-apps/src/pjsua/pjsua_app.c @@ -62,6 +62,7 @@ static struct app_config pj_bool_t use_tls; pjsua_transport_config udp_cfg; pjsua_transport_config rtp_cfg; + pjsip_redirect_op redir_op; unsigned acc_cnt; pjsua_acc_config acc_cfg[PJSUA_MAX_ACC]; @@ -278,6 +279,8 @@ static void usage(void) puts (" --norefersub Suppress event subscription when transfering calls"); puts (" --use-compact-form Minimize SIP message size"); puts (" --no-force-lr Allow strict-route to be used (i.e. do not force lr)"); + puts (" --accept-redirect=N Specify how to handle call redirect (3xx) response."); + puts (" 0: reject, 1: follow automatically (default), 2: ask"); puts (""); puts ("When URL is specified, pjsua will immediately initiate call to that URL"); @@ -303,6 +306,7 @@ static void default_config(struct app_config *cfg) cfg->udp_cfg.port = 5060; pjsua_transport_config_default(&cfg->rtp_cfg); cfg->rtp_cfg.port = 4000; + cfg->redir_op = PJSIP_REDIRECT_ACCEPT; cfg->duration = NO_LIMIT; cfg->wav_id = PJSUA_INVALID_ID; cfg->rec_id = PJSUA_INVALID_ID; @@ -472,7 +476,7 @@ static pj_status_t parse_args(int argc, char *argv[], OPT_RX_DROP_PCT, OPT_TX_DROP_PCT, OPT_EC_TAIL, OPT_EC_OPT, OPT_NEXT_ACCOUNT, OPT_NEXT_CRED, OPT_MAX_CALLS, OPT_DURATION, OPT_NO_TCP, OPT_NO_UDP, OPT_THREAD_CNT, - OPT_NOREFERSUB, + OPT_NOREFERSUB, OPT_ACCEPT_REDIRECT, OPT_USE_TLS, OPT_TLS_CA_FILE, OPT_TLS_CERT_FILE, OPT_TLS_PRIV_FILE, OPT_TLS_PASSWORD, OPT_TLS_VERIFY_SERVER, OPT_TLS_VERIFY_CLIENT, OPT_TLS_NEG_TIMEOUT, OPT_TLS_SRV_NAME, @@ -515,6 +519,7 @@ static pj_status_t parse_args(int argc, char *argv[], { "contact", 1, 0, OPT_CONTACT}, { "auto-update-nat", 1, 0, OPT_AUTO_UPDATE_NAT}, { "use-compact-form", 0, 0, OPT_USE_COMPACT_FORM}, + { "accept-redirect", 1, 0, OPT_ACCEPT_REDIRECT}, { "no-force-lr",0, 0, OPT_NO_FORCE_LR}, { "realm", 1, 0, OPT_REALM}, { "username", 1, 0, OPT_USERNAME}, @@ -840,6 +845,15 @@ static pj_status_t parse_args(int argc, char *argv[], } break; + case OPT_ACCEPT_REDIRECT: + cfg->redir_op = my_atoi(pj_optarg); + if (cfg->redir_op<0 || cfg->redir_op>PJSIP_REDIRECT_STOP) { + PJ_LOG(1,(THIS_FILE, + "Error: accept-redirect value '%s' ", pj_optarg)); + return PJ_EINVAL; + } + break; + case OPT_NO_FORCE_LR: cfg->cfg.force_lr = PJ_FALSE; break; @@ -1785,6 +1799,13 @@ static int write_settings(const struct app_config *config, pj_strcat2(&cfg, line); } + /* accept-redirect */ + if (config->redir_op != PJSIP_REDIRECT_ACCEPT) { + pj_ansi_sprintf(line, "--accept-redirect %d\n", + config->redir_op); + pj_strcat2(&cfg, line); + } + /* Max calls. */ pj_ansi_sprintf(line, "--max-calls %d\n", config->cfg.max_calls); @@ -1840,7 +1861,8 @@ static void app_dump(pj_bool_t detail) * printing it is a bit tricky, it should be printed part by part as long * as the logger can accept. */ -static void log_call_dump(int call_id) { +static void log_call_dump(int call_id) +{ unsigned call_dump_len; unsigned part_len; unsigned part_idx; @@ -2369,6 +2391,33 @@ static void call_on_dtmf_callback(pjsua_call_id call_id, int dtmf) } /* + * Redirection handler. + */ +static void call_on_redirected(pjsua_call_id call_id, const pjsip_uri *target, + pjsip_redirect_op *cmd, const pjsip_event *e) +{ + *cmd = app_config.redir_op; + + PJ_UNUSED_ARG(e); + + if (*cmd == PJSIP_REDIRECT_PENDING) { + char uristr[PJSIP_MAX_URL_SIZE]; + int len; + + len = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, target, uristr, + sizeof(uristr)); + if (len < 1) { + pj_ansi_strcpy(uristr, "--URI too long--"); + } + + PJ_LOG(3,(THIS_FILE, "Call %d is being redirected to %.*s. " + "Press 'Ra' to accept, 'Rr' to reject, or 'Rd' to " + "disconnect.", + call_id, len, uristr)); + } +} + +/* * Handler registration status has changed. */ static void on_reg_state(pjsua_acc_id acc_id) @@ -3915,6 +3964,21 @@ void console_app_main(const pj_str_t *uri_to_call) goto on_exit; + case 'R': + if (!pjsua_call_is_active(current_call)) { + PJ_LOG(1,(THIS_FILE, "Call %d has gone", current_call)); + } else if (menuin[1] == 'a') { + pjsua_call_process_redirect(current_call, + PJSIP_REDIRECT_ACCEPT); + } else if (menuin[1] == 'r') { + pjsua_call_process_redirect(current_call, + PJSIP_REDIRECT_REJECT); + } else { + pjsua_call_process_redirect(current_call, + PJSIP_REDIRECT_STOP); + } + break; + default: if (menuin[0] != '\n' && menuin[0] != '\r') { printf("Invalid input %s", menuin); @@ -3962,6 +4026,7 @@ pj_status_t app_init(int argc, char *argv[]) app_config.cfg.cb.on_incoming_call = &on_incoming_call; app_config.cfg.cb.on_call_tsx_state = &on_call_tsx_state; app_config.cfg.cb.on_dtmf_digit = &call_on_dtmf_callback; + app_config.cfg.cb.on_call_redirected = &call_on_redirected; app_config.cfg.cb.on_reg_state = &on_reg_state; app_config.cfg.cb.on_incoming_subscribe = &on_incoming_subscribe; app_config.cfg.cb.on_buddy_state = &on_buddy_state; diff --git a/pjsip-apps/src/test-pjsua/mod_recvfrom.py b/pjsip-apps/src/test-pjsua/mod_recvfrom.py index 259083f5..1510aed1 100644 --- a/pjsip-apps/src/test-pjsua/mod_recvfrom.py +++ b/pjsip-apps/src/test-pjsua/mod_recvfrom.py @@ -1,4 +1,4 @@ -# $Id:$ +# $Id$ import imp import sys import inc_sip as sip @@ -67,15 +67,17 @@ def test_func(test): tname = "" raise TestError("Excluded pattern " + pat + " found" + tname) # Create response - response = dlg.create_response(request, t.resp_code, "Status reason") - # Add headers to response - for h in t.resp_hdr: - response = response + h + "\r\n" - # Add message body if required - if t.body: - response = response + t.body - # Send response - dlg.send_msg(response, src_addr) + if t.resp_code!=0: + response = dlg.create_response(request, t.resp_code, "Status reason") + # Add headers to response + for h in t.resp_hdr: + response = response + h + "\r\n" + # Add message body if required + if t.body: + response = response + t.body + # Send response + dlg.send_msg(response, src_addr) + # Expect something to happen in pjsua if t.expect != "": pjsua.expect(t.expect) diff --git a/pjsip-apps/src/test-pjsua/scripts-sipp/inv_401_retry_after_100.xml b/pjsip-apps/src/test-pjsua/scripts-sipp/inv_401_retry_after_100.xml new file mode 100644 index 00000000..6debd134 --- /dev/null +++ b/pjsip-apps/src/test-pjsua/scripts-sipp/inv_401_retry_after_100.xml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE scenario SYSTEM "sipp.dtd"> + +<!-- 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 --> +<!-- --> +<!-- --> + +<scenario name="Authorization retry after 1xx response test"> + <!-- Wait for INVITE request --> + <recv request="INVITE" crlf="true"> + </recv> + + <!-- Send 100 Trying --> + <send> + <![CDATA[ + + SIP/2.0 100 Trying + [last_Via:] + [last_From:] + [last_To:] + [last_Call-ID:] + [last_CSeq:] + ]]> + </send> + + <!-- Send 180 Ringing (with tag) --> + <send> + <![CDATA[ + + SIP/2.0 180 Ringing + [last_Via:] + [last_From:] + [last_To:];tag=[call_number] + [last_Call-ID:] + [last_CSeq:] + ]]> + </send> + + <!-- Send 401 Unauthorized --> + <send retrans="500"> + <![CDATA[ + + SIP/2.0 401 Unauthorized + [last_Via:] + [last_From:] + [last_To:];tag=[call_number] + [last_Call-ID:] + [last_CSeq:] + WWW-Authenticate: Digest realm="sipp", nonce="1234" + Content-Length: 0 + ]]> + </send> + + <!-- Wait for ACK --> + <recv request="ACK" + optional="false" + rtd="true" + crlf="true"> + </recv> + + <!-- Wait for INVITE retransmission --> + <recv request="INVITE" crlf="true"> + </recv> + + <!-- Send 500 Test Success to terminate the call --> + <send retrans="500"> + <![CDATA[ + + SIP/2.0 500 Test Success + [last_Via:] + [last_From:] + [last_To:];tag=[call_number] + [last_Call-ID:] + [last_CSeq:] + Content-Length: 0 + ]]> + </send> + + <!-- Wait for ACK --> + <recv request="ACK" + optional="false" + rtd="true" + crlf="true"> + </recv> + + <!-- definition of the response time repartition table (unit is ms) --> + <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> + + <!-- definition of the call length repartition table (unit is ms) --> + <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> + +</scenario> + diff --git a/pjsip-apps/src/test-pjsua/scripts-sipp/uas-template.xml b/pjsip-apps/src/test-pjsua/scripts-sipp/uas-template.xml new file mode 100644 index 00000000..d51f89c8 --- /dev/null +++ b/pjsip-apps/src/test-pjsua/scripts-sipp/uas-template.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE scenario SYSTEM "sipp.dtd"> + +<!-- 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 --> +<!-- --> +<!-- Sipp default 'uas' scenario. --> +<!-- --> + +<scenario name="Basic UAS responder"> + <!-- By adding rrs="true" (Record Route Sets), the route sets --> + <!-- are saved and used for following messages sent. Useful to test --> + <!-- against stateful SIP proxies/B2BUAs. --> + <recv request="INVITE" crlf="true"> + </recv> + + <!-- The '[last_*]' keyword is replaced automatically by the --> + <!-- specified header if it was present in the last message received --> + <!-- (except if it was a retransmission). If the header was not --> + <!-- present or if no message has been received, the '[last_*]' --> + <!-- keyword is discarded, and all bytes until the end of the line --> + <!-- are also discarded. --> + <!-- --> + <!-- If the specified header was present several times in the --> + <!-- message, all occurences are concatenated (CRLF seperated) --> + <!-- to be used in place of the '[last_*]' keyword. --> + + <send> + <![CDATA[ + + SIP/2.0 100 Trying + [last_Via:] + [last_From:] + [last_To:];tag=[call_number] + [last_Call-ID:] + [last_CSeq:] + ]]> + </send> + + <send retrans="500"> + <![CDATA[ + + SIP/2.0 301 Redirection + [last_Via:] + [last_From:] + [last_To:];tag=[call_number] + [last_Call-ID:] + [last_CSeq:] + Contact: <sip:target@192.168.254.254> + Content-Length: 0 + ]]> + </send> + + <recv request="ACK" + optional="false" + rtd="true" + crlf="true"> + </recv> + + <!-- Keep the call open for a while in case the 200 is lost to be --> + <!-- able to retransmit it if we receive the BYE again. --> + <pause milliseconds="4000"/> + + + <!-- definition of the response time repartition table (unit is ms) --> + <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> + + <!-- definition of the call length repartition table (unit is ms) --> + <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> + +</scenario> + |