Changeset 563 for pjproject/trunk
- Timestamp:
- Jun 28, 2006 4:46:49 PM (18 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 2 added
- 28 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib/src/pj/config.c
r503 r563 22 22 23 23 static const char *id = "config.c"; 24 const char *PJ_VERSION = "0.5.6. 0";24 const char *PJ_VERSION = "0.5.6.1"; 25 25 26 26 PJ_DEF(void) pj_dump_config(void) -
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
r544 r563 30 30 pjsua_logging_config log_cfg; 31 31 pjsua_media_config media_cfg; 32 pj_bool_t no_tcp; 33 pj_bool_t no_udp; 32 34 pjsua_transport_config udp_cfg; 33 35 pjsua_transport_config rtp_cfg; … … 96 98 puts (""); 97 99 puts ("Transport Options:"); 98 puts (" --local-port=port Set TCP/UDP port"); 100 puts (" --local-port=port Set TCP/UDP port. This implicitly enables both "); 101 puts (" TCP and UDP transports on the specified port, unless"); 102 puts (" if TCP or UDP is disabled."); 103 puts (" --no-tcp Disable TCP transport."); 104 puts (" --no-udp Disable UDP transport."); 99 105 puts (" --outbound=url Set the URL of global outbound proxy server"); 100 106 puts (" May be specified multiple times"); … … 240 246 OPT_COMPLEXITY, OPT_QUALITY, OPT_PTIME, 241 247 OPT_NEXT_ACCOUNT, OPT_NEXT_CRED, OPT_MAX_CALLS, 242 OPT_DURATION, 248 OPT_DURATION, OPT_NO_TCP, OPT_NO_UDP, 243 249 }; 244 250 struct pj_getopt_option long_options[] = { … … 252 258 { "null-audio", 0, 0, OPT_NULL_AUDIO}, 253 259 { "local-port", 1, 0, OPT_LOCAL_PORT}, 260 { "no-tcp", 0, 0, OPT_NO_TCP}, 261 { "no-udp", 0, 0, OPT_NO_UDP}, 254 262 { "proxy", 1, 0, OPT_PROXY}, 255 263 { "outbound", 1, 0, OPT_OUTBOUND_PROXY}, … … 385 393 break; 386 394 395 case OPT_NO_UDP: /* no-udp */ 396 if (cfg->no_tcp) { 397 PJ_LOG(1,(THIS_FILE,"Error: can not disable both TCP and UDP")); 398 return PJ_EINVAL; 399 } 400 401 cfg->no_udp = PJ_TRUE; 402 break; 403 404 case OPT_NO_TCP: /* no-tcp */ 405 if (cfg->no_udp) { 406 PJ_LOG(1,(THIS_FILE,"Error: can not disable both TCP and UDP")); 407 return PJ_EINVAL; 408 } 409 410 cfg->no_tcp = PJ_TRUE; 411 break; 412 387 413 case OPT_PROXY: /* proxy */ 388 414 if (pjsua_verify_sip_url(pj_optarg) != 0) { … … 2047 2073 pj_status_t app_init(int argc, char *argv[]) 2048 2074 { 2049 pjsua_transport_id transport_id ;2075 pjsua_transport_id transport_id = -1; 2050 2076 unsigned i; 2051 2077 pj_status_t status; … … 2097 2123 } 2098 2124 2099 /* Add UDP transport */ 2100 status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, 2101 &app_config.udp_cfg, 2102 &transport_id); 2103 if (status != PJ_SUCCESS) 2125 2126 /* Add TCP transport unless it's disabled */ 2127 if (!app_config.no_tcp) { 2128 status = pjsua_transport_create(PJSIP_TRANSPORT_TCP, 2129 &app_config.udp_cfg, 2130 &transport_id); 2131 if (status != PJ_SUCCESS) 2132 goto on_error; 2133 2134 /* Add local account */ 2135 pjsua_acc_add_local(transport_id, PJ_TRUE, ¤t_acc); 2136 pjsua_acc_set_online_status(current_acc, PJ_TRUE); 2137 2138 } 2139 2140 2141 /* Add UDP transport unless it's disabled. */ 2142 if (!app_config.no_udp) { 2143 status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, 2144 &app_config.udp_cfg, 2145 &transport_id); 2146 if (status != PJ_SUCCESS) 2147 goto on_error; 2148 2149 /* Add local account */ 2150 pjsua_acc_add_local(transport_id, PJ_TRUE, ¤t_acc); 2151 pjsua_acc_set_online_status(current_acc, PJ_TRUE); 2152 } 2153 2154 if (transport_id == -1) { 2155 PJ_LOG(3,(THIS_FILE, "Error: no transport is configured")); 2156 status = -1; 2104 2157 goto on_error; 2105 2106 /* Add local account */ 2107 pjsua_acc_add_local(transport_id, PJ_TRUE, ¤t_acc); 2108 pjsua_acc_set_online_status(current_acc, PJ_TRUE); 2158 } 2109 2159 2110 2160 -
pjproject/trunk/pjsip/build
- Property svn:ignore
-
old new 10 10 *.sln 11 11 *.suo 12 *.htm 13 *.html
-
- Property svn:ignore
-
pjproject/trunk/pjsip/build/Makefile
r528 r563 26 26 $(subst /,$(HOST_PSEP),$(PJSIP_SIMPLE_LIB)) \ 27 27 $(subst /,$(HOST_PSEP),$(PJSIP_LIB)) \ 28 $(subst /,$(HOST_PSEP),$(PJMEDIA_CODEC_LIB)) \29 28 $(subst /,$(HOST_PSEP),$(PJMEDIA_LIB)) \ 30 29 $(subst /,$(HOST_PSEP),$(PJLIB_UTIL_LIB)) \ … … 41 40 sip_errno.o sip_msg.o sip_parser.o sip_tel_uri.o sip_uri.o \ 42 41 sip_endpoint.o sip_util.o sip_util_proxy.o \ 43 sip_resolve.o sip_transport.o sip_transport_loop.o sip_transport_udp.o \ 44 sip_auth_client.o sip_auth_msg.o sip_auth_parser.o sip_auth_server.o \ 42 sip_resolve.o sip_transport.o sip_transport_loop.o \ 43 sip_transport_udp.o sip_transport_tcp.o \ 44 sip_auth_client.o sip_auth_msg.o sip_auth_parser.o \ 45 sip_auth_server.o \ 45 46 sip_transaction.o sip_util_statefull.o \ 46 47 sip_dialog.o sip_ua_layer.o … … 77 78 78 79 export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT 80 81 ############################################################################### 82 # Defines for building test application 83 # 84 export TEST_SRCDIR = ../src/test-pjsip 85 export TEST_OBJS += dlg_core_test.o msg_err_test.o msg_logger.o msg_test.o \ 86 test.o transport_loop_test.o transport_tcp_test.o \ 87 transport_test.o transport_udp_test.o \ 88 tsx_basic_test.o tsx_bench.o tsx_uac_test.o \ 89 tsx_uas_test.o txdata_test.o uri_test.o 90 export TEST_OBJS += main.o 91 export TEST_CFLAGS += $(_CFLAGS) 92 export TEST_LDFLAGS += $(_LDFLAGS) 93 export TEST_EXE := ../bin/pjsip-test-$(TARGET_NAME)$(HOST_EXE) 94 95 96 export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT 79 97 ############################################################################### 80 98 # Main entry 81 99 # 82 100 # 83 TARGETS := pjsip pjsip-ua pjsip-simple pjsua-lib 101 TARGETS := pjsip pjsip-ua pjsip-simple pjsua-lib pjsip-test 84 102 85 103 .PHONY: $(TARGETS) … … 106 124 pjsua-lib: 107 125 $(MAKE) -f $(RULES_MAK) APP=PJSUA_LIB app=pjsua-lib $(PJSUA_LIB_LIB) 126 127 pjsip-test: 128 $(MAKE) -f $(RULES_MAK) APP=TEST app=pjsip-test $(TEST_EXE) 108 129 109 130 .PHONY: ../lib/pjsip.ko … … 132 153 $(MAKE) -f $(RULES_MAK) APP=PJSIP_SIMPLE app=pjsip-simple $@ 133 154 $(MAKE) -f $(RULES_MAK) APP=PJSUA_LIB app=pjsua-lib $@ 155 $(MAKE) -f $(RULES_MAK) APP=TEST app=pjsip-test $@ 134 156 135 157 realclean: … … 141 163 $(MAKE) -f $(RULES_MAK) APP=PJSIP_UA app=pjsip-ua $@ 142 164 $(MAKE) -f $(RULES_MAK) APP=PJSIP_SIMPLE app=pjsip-simple $@ 165 $(MAKE) -f $(RULES_MAK) APP=TEST app=pjsip-test $@ 143 166 $(MAKE) -f $(RULES_MAK) APP=PJSUA_LIB app=pjsua-lib $@ 144 167 -
pjproject/trunk/pjsip/build/test_pjsip.dsp
r547 r563 118 118 # Begin Source File 119 119 120 SOURCE="..\src\test-pjsip\transport_tcp_test.c" 121 # End Source File 122 # Begin Source File 123 120 124 SOURCE="..\src\test-pjsip\transport_test.c" 121 125 # End Source File … … 127 131 128 132 SOURCE="..\src\test-pjsip\tsx_basic_test.c" 133 # End Source File 134 # Begin Source File 135 136 SOURCE="..\src\test-pjsip\tsx_bench.c" 129 137 # End Source File 130 138 # Begin Source File -
pjproject/trunk/pjsip/include/pjsip.h
r127 r563 40 40 #include <pjsip/sip_transport_udp.h> 41 41 #include <pjsip/sip_transport_loop.h> 42 #include <pjsip/sip_transport_tcp.h> 42 43 #include <pjsip/sip_resolve.h> 43 44 -
pjproject/trunk/pjsip/include/pjsip/sip_transport.h
r550 r563 705 705 706 706 pjsip_transport_type_e type; /**< Transport type. */ 707 char type_name[8];/**< Type string name. */707 char *type_name; /**< Type string name. */ 708 708 unsigned flag; /**< Transport flag. */ 709 709 … … 722 722 int addr_len, 723 723 pjsip_transport **transport); 724 725 /** 726 * Destroy the listener. 727 */ 728 pj_status_t (*destroy)(pjsip_tpfactory *factory); 724 729 725 730 /* -
pjproject/trunk/pjsip/include/pjsip/sip_transport_tcp.h
r550 r563 39 39 40 40 /** 41 * Create, register, and start TCP transport. 41 * The TCP incoming connection backlog number. 42 * Default: 5 43 */ 44 #ifndef PJSIP_TCP_TRANSPORT_BACKLOG 45 # define PJSIP_TCP_TRANSPORT_BACKLOG 5 46 #endif 47 48 49 /** 50 * Register support for SIP TCP transport by creating TCP listener on 51 * the specified address and port. This function will create an 52 * instance of SIP TCP transport factory and register it to the 53 * transport manager. 42 54 * 43 55 * @param endpt The SIP endpoint. 44 * @param local Local address to bind. 45 * @param async_cnt Number of simultaneous async operations. 56 * @param local Optional local address to bind, or specify the 57 * address to bind the server socket to. Both IP 58 * interface address and port fields are optional. 59 * If IP interface address is not specified, socket 60 * will be bound to PJ_INADDR_ANY. If port is not 61 * specified, socket will be bound to any port 62 * selected by the operating system. 63 * @param async_cnt Number of simultaneous asynchronous accept() 64 * operations to be supported. It is recommended that 65 * the number here corresponds to the number of 66 * processors in the system (or the number of SIP 67 * worker threads). 68 * @param p_factory Optional pointer to receive the instance of the 69 * SIP TCP transport factory just created. 46 70 * 47 71 * @return PJ_SUCCESS when the transport has been successfully … … 51 75 PJ_DECL(pj_status_t) pjsip_tcp_transport_start(pjsip_endpoint *endpt, 52 76 const pj_sockaddr_in *local, 53 unsigned async_cnt); 77 unsigned async_cnt, 78 pjsip_tpfactory **p_factory); 54 79 55 80 -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
r503 r563 105 105 typedef struct transport_data 106 106 { 107 int index; 108 pjsip_transport *tp; 107 int index; 108 pjsip_transport_type_e type; 109 pjsip_host_port local_name; 110 111 union { 112 pjsip_transport *tp; 113 pjsip_tpfactory *factory; 114 void *ptr; 115 } data; 116 109 117 } transport_data; 110 118 -
pjproject/trunk/pjsip/src/pjsip/sip_transaction.c
r556 r563 1300 1300 pj_memcpy(&tsx->addr, &tsx->res_addr.addr, tsx->res_addr.addr_len); 1301 1301 tsx->addr_len = tsx->res_addr.addr_len; 1302 tsx->is_reliable = PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport); 1302 1303 } 1303 1304 … … 2131 2132 } 2132 2133 2133 /* Start timer H for transaction termination */ 2134 pjsip_endpt_schedule_timer(tsx->endpt,&tsx->timeout_timer, 2135 &timeout_timer_val); 2134 /* For INVITE, start timer H for transaction termination 2135 * regardless whether transport is reliable or not. 2136 * For non-INVITE, start timer J with the value of 64*T1 for 2137 * non-reliable transports, and zero for reliable transports. 2138 */ 2139 if (tsx->method.id == PJSIP_INVITE_METHOD) { 2140 /* Start timer H for INVITE */ 2141 pjsip_endpt_schedule_timer(tsx->endpt,&tsx->timeout_timer, 2142 &timeout_timer_val); 2143 } else if (!tsx->is_reliable) { 2144 /* Start timer J on 64*T1 seconds for non-INVITE */ 2145 pjsip_endpt_schedule_timer(tsx->endpt,&tsx->timeout_timer, 2146 &timeout_timer_val); 2147 } else { 2148 /* Start timer J on zero seconds for non-INVITE */ 2149 pj_time_val zero_time = { 0, 0 }; 2150 pjsip_endpt_schedule_timer(tsx->endpt,&tsx->timeout_timer, 2151 &zero_time); 2152 } 2136 2153 2137 2154 /* For INVITE, if unreliable transport is used, retransmission -
pjproject/trunk/pjsip/src/pjsip/sip_transport.c
r550 r563 37 37 #define THIS_FILE "sip_transport.c" 38 38 39 #if 0 40 # define TRACE_(x) PJ_LOG(5,x) 41 #else 42 # define TRACE_(x) 43 #endif 44 39 45 /* Prototype. */ 40 46 static pj_status_t mod_on_tx_msg(pjsip_tx_data *tdata); … … 602 608 pj_lock_release(mgr->lock); 603 609 610 TRACE_((THIS_FILE,"Transport %s registered: type=%s, remote=%s:%d", 611 tp->obj_name, 612 pjsip_transport_get_type_name(tp->key.type), 613 pj_inet_ntoa(((pj_sockaddr_in*)&tp->key.rem_addr)->sin_addr), 614 pj_ntohs(((pj_sockaddr_in*)&tp->key.rem_addr)->sin_port))); 615 604 616 return PJ_SUCCESS; 605 617 } … … 610 622 { 611 623 int key_len; 624 625 TRACE_((THIS_FILE, "Transport %s is being destroyed", tp->obj_name)); 612 626 613 627 pj_lock_acquire(tp->lock); … … 627 641 */ 628 642 key_len = sizeof(tp->key.type) + tp->addr_len; 643 pj_assert(pj_hash_get(mgr->table, &tp->key, key_len, NULL) != NULL); 629 644 pj_hash_set(tp->pool, mgr->table, &tp->key, key_len, 0, NULL); 630 645 … … 643 658 pjsip_tpmgr *mgr; 644 659 pj_status_t status; 660 661 TRACE_((THIS_FILE, "Transport %s shutting down", tp->obj_name)); 645 662 646 663 pj_lock_acquire(tp->lock); … … 808 825 pj_hash_iterator_t itr_val; 809 826 pj_hash_iterator_t *itr; 827 pjsip_tpfactory *factory; 810 828 pjsip_endpoint *endpt = mgr->endpt; 811 829 … … 814 832 pj_lock_acquire(mgr->lock); 815 833 834 /* 835 * Destroy all transports. 836 */ 816 837 itr = pj_hash_first(mgr->table, &itr_val); 817 838 while (itr != NULL) { … … 828 849 } 829 850 851 /* 852 * Destroy all factories/listeners. 853 */ 854 factory = mgr->factory_list.next; 855 while (factory != &mgr->factory_list) { 856 pjsip_tpfactory *next = factory->next; 857 858 factory->destroy(factory); 859 860 factory = next; 861 } 862 830 863 pj_lock_release(mgr->lock); 831 864 pj_lock_destroy(mgr->lock); … … 843 876 //pj_assert(pj_atomic_get(mgr->tdata_counter) == 0); 844 877 if (pj_atomic_get(mgr->tdata_counter) != 0) { 845 PJ_LOG( 4,(THIS_FILE, "Warning: %d transmit buffers arenot freed!",878 PJ_LOG(3,(THIS_FILE, "Warning: %d transmit buffer(s) not freed!", 846 879 pj_atomic_get(mgr->tdata_counter))); 847 880 } … … 880 913 881 914 /* Process all message fragments. */ 882 while ( total_processed < remaining_len) {915 while (remaining_len > 0) { 883 916 884 917 pjsip_msg *msg; 885 pj_size_t msg_fragment_size = 0;918 pj_size_t msg_fragment_size; 886 919 887 920 /* Initialize default fragment size. */ … … 1039 1072 pj_status_t status; 1040 1073 1074 TRACE_((THIS_FILE,"Acquiring transport type=%s, remote=%s:%d", 1075 pjsip_transport_get_type_name(type), 1076 pj_inet_ntoa(((pj_sockaddr_in*)remote)->sin_addr), 1077 pj_ntohs(((pj_sockaddr_in*)remote)->sin_port))); 1078 1041 1079 pj_lock_acquire(mgr->lock); 1042 1080 … … 1084 1122 pj_lock_release(mgr->lock); 1085 1123 *tp = transport; 1124 1125 TRACE_((THIS_FILE, "Transport %s acquired", transport->obj_name)); 1086 1126 return PJ_SUCCESS; 1087 1127 } … … 1101 1141 /* No factory can create the transport! */ 1102 1142 pj_lock_release(mgr->lock); 1143 TRACE_((THIS_FILE, "No suitable factory was found either")); 1103 1144 return PJSIP_EUNSUPTRANSPORT; 1104 1145 } 1146 1147 TRACE_((THIS_FILE, "%s, creating new one from factory", 1148 (transport?"Transport is shutdown":"No transport found"))); 1105 1149 1106 1150 /* Request factory to create transport. */ -
pjproject/trunk/pjsip/src/pjsip/sip_transport_loop.c
r315 r563 74 74 75 75 pool = pjsip_endpt_create_pool(loop->base.endpt, "rdata", 76 PJSIP_POOL_RDATA_LEN, PJSIP_POOL_RDATA_INC); 76 PJSIP_POOL_RDATA_LEN, 77 PJSIP_POOL_RDATA_INC+5); 77 78 if (!pool) 78 79 return NULL; -
pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c
r554 r563 21 21 #include <pjsip/sip_errno.h> 22 22 #include <pj/compat/socket.h> 23 #include <pj/addr_resolv.h> 23 24 #include <pj/assert.h> 24 25 #include <pj/ioqueue.h> … … 34 35 #define MAX_ASYNC_CNT 16 35 36 #define POOL_LIS_INIT 4000 36 #define POOL_LIS_INC 400 037 #define POOL_LIS_INC 4001 37 38 #define POOL_TP_INIT 4000 38 #define POOL_TP_INC 400 039 #define POOL_TP_INC 4002 39 40 40 41 … … 43 44 44 45 46 /* 47 * This structure is "descendant" of pj_ioqueue_op_key_t, and it is used to 48 * track pending/asynchronous accept() operation. TCP transport may have 49 * more than one pending accept() operations, depending on the value of 50 * async_cnt. 51 */ 45 52 struct pending_accept 46 53 { … … 53 60 }; 54 61 55 struct pending_connect 56 { 57 pj_ioqueue_op_key_t op_key; 58 struct tcp_transport *transport; 59 }; 60 61 62 63 /* 64 * This is the TCP listener, which is a "descendant" of pjsip_tpfactory (the 65 * SIP transport factory). 66 */ 62 67 struct tcp_listener 63 68 { 64 69 pjsip_tpfactory factory; 65 char name[PJ_MAX_OBJ_NAME];66 pj_bool_t active;70 char obj_name[PJ_MAX_OBJ_NAME]; 71 pj_bool_t is_registered; 67 72 pjsip_endpoint *endpt; 68 73 pjsip_tpmgr *tpmgr; … … 74 79 75 80 76 struct pending_tdata 77 { 78 PJ_DECL_LIST_MEMBER(struct pending_tdata); 81 /* 82 * This structure is used to keep delayed transmit operation in a list. 83 * A delayed transmission occurs when application sends tx_data when 84 * the TCP connect/establishment is still in progress. These delayed 85 * transmission will be "flushed" once the socket is connected (either 86 * successfully or with errors). 87 */ 88 struct delayed_tdata 89 { 90 PJ_DECL_LIST_MEMBER(struct delayed_tdata); 79 91 pjsip_tx_data_op_key *tdata_op_key; 80 92 }; 81 93 82 94 95 /* 96 * This structure describes the TCP transport, and it's descendant of 97 * pjsip_transport. 98 */ 83 99 struct tcp_transport 84 100 { 85 101 pjsip_transport base; 102 pj_bool_t is_server; 86 103 struct tcp_listener *listener; 87 104 pj_bool_t is_registered; 88 105 pj_bool_t is_closing; 106 pj_status_t close_reason; 89 107 pj_sock_t sock; 90 108 pj_ioqueue_key_t *key; 91 109 pj_bool_t has_pending_connect; 92 struct pending_connect connect_op;93 110 94 111 … … 100 117 101 118 /* Pending transmission list. */ 102 struct pending_tdata tx_list;119 struct delayed_tdata delayed_list; 103 120 }; 104 121 105 122 106 /* 107 * This callback is called when #pj_ioqueue_accept completes. 108 */ 123 /**************************************************************************** 124 * PROTOTYPES 125 */ 126 127 /* This callback is called when pending accept() operation completes. */ 109 128 static void on_accept_complete( pj_ioqueue_key_t *key, 110 129 pj_ioqueue_op_key_t *op_key, … … 112 131 pj_status_t status); 113 132 114 static pj_status_t lis_destroy(struct tcp_listener *listener); 133 /* This callback is called by transport manager to destroy listener */ 134 static pj_status_t lis_destroy(pjsip_tpfactory *factory); 135 136 /* This callback is called by transport manager to create transport */ 115 137 static pj_status_t lis_create_transport(pjsip_tpfactory *factory, 116 138 pjsip_tpmgr *mgr, … … 120 142 pjsip_transport **transport); 121 143 122 123 static pj_status_t create_tcp_transport(struct tcp_listener *listener,124 pj_sock_t sock,125 126 127 144 /* Common function to create and initialize transport */ 145 static pj_status_t tcp_create(struct tcp_listener *listener, 146 pj_sock_t sock, pj_bool_t is_server, 147 const pj_sockaddr_in *local, 148 const pj_sockaddr_in *remote, 149 struct tcp_transport **p_tcp); 128 150 129 151 … … 139 161 140 162 163 static void sockaddr_to_host_port( pj_pool_t *pool, 164 pjsip_host_port *host_port, 165 const pj_sockaddr_in *addr ) 166 { 167 host_port->host.ptr = pj_pool_alloc(pool, 48); 168 host_port->host.slen = pj_ansi_sprintf( host_port->host.ptr, "%s", 169 pj_inet_ntoa(addr->sin_addr)); 170 host_port->port = pj_ntohs(addr->sin_port); 171 } 172 173 174 175 /**************************************************************************** 176 * The TCP listener/transport factory. 177 */ 178 179 /* 180 * This is the public API to create, initialize, register, and start the 181 * TCP listener. 182 */ 141 183 PJ_DEF(pj_status_t) pjsip_tcp_transport_start( pjsip_endpoint *endpt, 142 184 const pj_sockaddr_in *local, 143 unsigned async_cnt) 185 unsigned async_cnt, 186 pjsip_tpfactory **p_factory) 144 187 { 145 188 pj_pool_t *pool; 146 189 struct tcp_listener *listener; 147 190 pj_ioqueue_callback listener_cb; 191 pj_sockaddr_in *listener_addr; 192 int addr_len; 148 193 unsigned i; 149 194 pj_status_t status; 150 195 151 196 /* Sanity check */ 152 PJ_ASSERT_RETURN(endpt && local &&async_cnt, PJ_EINVAL);197 PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL); 153 198 154 199 … … 159 204 160 205 listener = pj_pool_zalloc(pool, sizeof(struct tcp_listener)); 161 pj_ansi_sprintf(listener->name, "tcp:%d", (int)pj_ntohs(local->sin_port));162 206 listener->factory.pool = pool; 163 207 listener->factory.type = PJSIP_TRANSPORT_TCP; 164 pj_ansi_strcpy(listener->factory.type_name, "tcp");208 listener->factory.type_name = "tcp"; 165 209 listener->factory.flag = 166 210 pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_TCP); 167 211 listener->sock = PJ_INVALID_SOCKET; 212 213 pj_ansi_strcpy(listener->obj_name, "tcp"); 168 214 169 215 status = pj_lock_create_recursive_mutex(pool, "tcplis", … … 178 224 goto on_error; 179 225 180 pj_memcpy(&listener->factory.local_addr, local, sizeof(pj_sockaddr_in)); 181 status = pj_sock_bind(listener->sock, local, sizeof(*local)); 226 listener_addr = (pj_sockaddr_in*)&listener->factory.local_addr; 227 if (local) { 228 pj_memcpy(listener_addr, local, sizeof(pj_sockaddr_in)); 229 } else { 230 pj_sockaddr_in_init(listener_addr, NULL, 0); 231 } 232 233 status = pj_sock_bind(listener->sock, listener_addr, 234 sizeof(pj_sockaddr_in)); 182 235 if (status != PJ_SUCCESS) 183 236 goto on_error; 237 238 /* Retrieve the bound address */ 239 addr_len = sizeof(pj_sockaddr_in); 240 status = pj_sock_getsockname(listener->sock, listener_addr, &addr_len); 241 if (status != PJ_SUCCESS) 242 goto on_error; 243 244 /* If the address returns 0.0.0.0, use the first interface address 245 * as the transport's address. 246 */ 247 if (listener_addr->sin_addr.s_addr == 0) { 248 const pj_str_t *hostname; 249 struct pj_hostent he; 250 251 hostname = pj_gethostname(); 252 status = pj_gethostbyname(hostname, &he); 253 if (status != PJ_SUCCESS) 254 goto on_error; 255 256 listener_addr->sin_addr = *(pj_in_addr*)he.h_addr; 257 } 258 259 pj_ansi_sprintf(listener->obj_name, "tcp:%d", 260 (int)pj_ntohs(listener_addr->sin_port)); 261 262 /* Save the address name */ 263 sockaddr_to_host_port(listener->factory.pool, 264 &listener->factory.addr_name, listener_addr); 265 266 /* Start listening to the address */ 267 status = pj_sock_listen(listener->sock, PJSIP_TCP_TRANSPORT_BACKLOG); 268 if (status != PJ_SUCCESS) 269 goto on_error; 270 184 271 185 272 /* Register socket to ioqeuue */ … … 192 279 goto on_error; 193 280 194 /* Start pending accept() operation */ 281 /* Register to transport manager */ 282 listener->endpt = endpt; 283 listener->tpmgr = pjsip_endpt_get_tpmgr(endpt); 284 listener->factory.create_transport = lis_create_transport; 285 listener->factory.destroy = lis_destroy; 286 listener->is_registered = PJ_TRUE; 287 status = pjsip_tpmgr_register_tpfactory(listener->tpmgr, 288 &listener->factory); 289 if (status != PJ_SUCCESS) { 290 listener->is_registered = PJ_FALSE; 291 goto on_error; 292 } 293 294 295 /* Start pending accept() operations */ 195 296 if (async_cnt > MAX_ASYNC_CNT) async_cnt = MAX_ASYNC_CNT; 196 297 listener->async_cnt = async_cnt; … … 201 302 listener->accept_op[i].listener = listener; 202 303 203 status = pj_ioqueue_accept(listener->key, 204 &listener->accept_op[i].op_key, 205 &listener->accept_op[i].new_sock, 206 &listener->accept_op[i].local_addr, 207 &listener->accept_op[i].remote_addr, 208 &listener->accept_op[i].addr_len); 209 if (status != PJ_SUCCESS && status != PJ_EPENDING) 210 goto on_error; 211 } 212 213 /* Register to transport manager */ 214 listener->endpt = endpt; 215 listener->tpmgr = pjsip_endpt_get_tpmgr(endpt); 216 listener->factory.create_transport = lis_create_transport; 217 status = pjsip_tpmgr_register_tpfactory(listener->tpmgr, 218 &listener->factory); 219 if (status != PJ_SUCCESS) 220 goto on_error; 221 222 /* Done! */ 223 listener->active = PJ_TRUE; 224 225 PJ_LOG(4,(listener->name, 226 "SIP TCP transport listening for incoming connections at %s:%d", 227 pj_inet_ntoa(local->sin_addr), (int)pj_ntohs(local->sin_port))); 304 on_accept_complete(listener->key, &listener->accept_op[i].op_key, 305 listener->sock, PJ_EPENDING); 306 } 307 308 PJ_LOG(4,(listener->obj_name, 309 "SIP TCP listener ready for incoming connections at %s:%d", 310 pj_inet_ntoa(listener_addr->sin_addr), 311 (int)pj_ntohs(listener_addr->sin_port))); 312 313 /* Return the pointer to user */ 314 if (p_factory) *p_factory = &listener->factory; 228 315 229 316 return PJ_SUCCESS; 230 317 231 318 on_error: 232 lis_destroy( listener);319 lis_destroy(&listener->factory); 233 320 return status; 234 321 } 235 322 236 323 237 static pj_status_t lis_destroy(struct tcp_listener *listener) 238 { 239 if (listener->active) { 324 /* This callback is called by transport manager to destroy listener */ 325 static pj_status_t lis_destroy(pjsip_tpfactory *factory) 326 { 327 struct tcp_listener *listener = (struct tcp_listener *)factory; 328 329 if (listener->is_registered) { 240 330 pjsip_tpmgr_unregister_tpfactory(listener->tpmgr, &listener->factory); 241 listener-> active= PJ_FALSE;331 listener->is_registered = PJ_FALSE; 242 332 } 243 333 … … 259 349 260 350 if (listener->factory.pool) { 261 PJ_LOG(4,(listener->name, "SIP TCP transport destroyed")); 262 pj_pool_release(listener->factory.pool); 351 pj_pool_t *pool = listener->factory.pool; 352 353 PJ_LOG(4,(listener->obj_name, "SIP TCP listener destroyed")); 354 263 355 listener->factory.pool = NULL; 356 pj_pool_release(pool); 264 357 } 265 358 … … 289 382 static pj_status_t tcp_shutdown(pjsip_transport *transport); 290 383 291 /* Called by transport manager to destroy */ 292 static pj_status_t tcp_destroy(pjsip_transport *transport); 384 /* Called by transport manager to destroy transport */ 385 static pj_status_t tcp_destroy_transport(pjsip_transport *transport); 386 387 /* Utility to destroy transport */ 388 static pj_status_t tcp_destroy(pjsip_transport *transport, 389 pj_status_t reason); 293 390 294 391 /* Callback from ioqueue on incoming packet */ … … 307 404 308 405 309 static void sockaddr_to_host_port( pj_pool_t *pool,310 pjsip_host_port *host_port,311 const pj_sockaddr_in *addr )312 {313 host_port->host.ptr = pj_pool_alloc(pool, 48);314 host_port->host.slen = pj_ansi_sprintf( host_port->host.ptr, "%s",315 pj_inet_ntoa(addr->sin_addr));316 host_port->port = pj_ntohs(addr->sin_port);317 }318 319 320 406 /* 321 * Utilities to create TCP transport. 322 */ 323 static pj_status_t create_tcp_transport(struct tcp_listener *listener, 324 pj_sock_t sock, 325 const pj_sockaddr_in *local, 326 const pj_sockaddr_in *remote, 327 struct tcp_transport **p_tcp) 407 * Common function to create TCP transport, called when pending accept() and 408 * pending connect() complete. 409 */ 410 static pj_status_t tcp_create( struct tcp_listener *listener, 411 pj_sock_t sock, pj_bool_t is_server, 412 const pj_sockaddr_in *local, 413 const pj_sockaddr_in *remote, 414 struct tcp_transport **p_tcp) 328 415 { 329 416 struct tcp_transport *tcp; … … 333 420 pj_status_t status; 334 421 335 pool = pjsip_endpt_create_pool(listener->endpt, "tcp", 422 423 PJ_ASSERT_RETURN(sock != PJ_INVALID_SOCKET, PJ_EINVAL); 424 425 426 pool = pjsip_endpt_create_pool(listener->endpt, "tcp", 336 427 POOL_TP_INIT, POOL_TP_INC); 428 PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); 337 429 430 338 431 /* 339 432 * Create and initialize basic transport structure. … … 341 434 tcp = pj_pool_zalloc(pool, sizeof(*tcp)); 342 435 tcp->sock = sock; 436 tcp->is_server = is_server; 343 437 tcp->listener = listener; 344 pj_list_init(&tcp->tx_list); 345 346 347 pj_ansi_snprintf(tcp->base.obj_name, PJ_MAX_OBJ_NAME, "tcp%p", tcp); 438 pj_list_init(&tcp->delayed_list); 348 439 tcp->base.pool = pool; 349 440 441 pj_ansi_snprintf(tcp->base.obj_name, PJ_MAX_OBJ_NAME, 442 (is_server ? "tcps%p" :"tcpc%p"), tcp); 443 350 444 status = pj_atomic_create(pool, 0, &tcp->base.ref_cnt); 351 if (status != PJ_SUCCESS) 445 if (status != PJ_SUCCESS) { 352 446 goto on_error; 447 } 353 448 354 449 status = pj_lock_create_recursive_mutex(pool, "tcp", &tcp->base.lock); 355 if (status != PJ_SUCCESS) 450 if (status != PJ_SUCCESS) { 356 451 goto on_error; 452 } 357 453 358 454 tcp->base.key.type = PJSIP_TRANSPORT_TCP; … … 375 471 tcp->base.send_msg = &tcp_send_msg; 376 472 tcp->base.do_shutdown = &tcp_shutdown; 377 tcp->base.destroy = &tcp_destroy ;473 tcp->base.destroy = &tcp_destroy_transport; 378 474 379 475 … … 387 483 status = pj_ioqueue_register_sock(pool, ioqueue, sock, 388 484 tcp, &tcp_callback, &tcp->key); 389 if (status != PJ_SUCCESS) 485 if (status != PJ_SUCCESS) { 390 486 goto on_error; 487 } 391 488 392 489 /* Register transport to transport manager */ 393 490 status = pjsip_transport_register(listener->tpmgr, &tcp->base); 394 if (status != PJ_SUCCESS) 491 if (status != PJ_SUCCESS) { 395 492 goto on_error; 493 } 396 494 397 495 tcp->is_registered = PJ_TRUE; … … 400 498 *p_tcp = tcp; 401 499 500 PJ_LOG(4,(tcp->base.obj_name, "TCP %s transport created", 501 (tcp->is_server ? "server" : "client"))); 502 503 return PJ_SUCCESS; 504 402 505 on_error: 403 tcp_destroy(&tcp->base );506 tcp_destroy(&tcp->base, status); 404 507 return status; 405 508 } 406 509 407 510 408 /* Flush all pending send operations*/409 static tcp_flush_pending_tx(struct tcp_transport *tcp)511 /* Flush all delayed transmision once the socket is connected. */ 512 static void tcp_flush_pending_tx(struct tcp_transport *tcp) 410 513 { 411 514 pj_lock_acquire(tcp->base.lock); 412 while (!pj_list_empty(&tcp-> tx_list)) {413 struct pending_tdata *pending_tx;515 while (!pj_list_empty(&tcp->delayed_list)) { 516 struct delayed_tdata *pending_tx; 414 517 pjsip_tx_data *tdata; 415 518 pj_ioqueue_op_key_t *op_key; … … 417 520 pj_status_t status; 418 521 419 pending_tx = tcp-> tx_list.next;522 pending_tx = tcp->delayed_list.next; 420 523 pj_list_erase(pending_tx); 421 524 … … 437 540 438 541 542 /* Called by transport manager to destroy transport */ 543 static pj_status_t tcp_destroy_transport(pjsip_transport *transport) 544 { 545 struct tcp_transport *tcp = (struct tcp_transport*)transport; 546 547 /* Transport would have been unregistered by now since this callback 548 * is called by transport manager. 549 */ 550 tcp->is_registered = PJ_FALSE; 551 552 return tcp_destroy(transport, tcp->close_reason); 553 } 554 439 555 440 556 /* Destroy TCP transport */ 441 static pj_status_t tcp_destroy(pjsip_transport *transport) 557 static pj_status_t tcp_destroy(pjsip_transport *transport, 558 pj_status_t reason) 442 559 { 443 560 struct tcp_transport *tcp = (struct tcp_transport*)transport; 444 561 445 /* Cancel all pending transmits */ 446 while (!pj_list_empty(&tcp->tx_list)) { 447 struct pending_tdata *pending_tx; 562 if (tcp->close_reason == 0) 563 tcp->close_reason = reason; 564 565 if (tcp->is_registered) { 566 tcp->is_registered = PJ_FALSE; 567 pjsip_transport_destroy(transport); 568 569 /* pjsip_transport_destroy will recursively call this function 570 * again. 571 */ 572 return PJ_SUCCESS; 573 } 574 575 /* Mark transport as closing */ 576 tcp->is_closing = PJ_TRUE; 577 578 /* Cancel all delayed transmits */ 579 while (!pj_list_empty(&tcp->delayed_list)) { 580 struct delayed_tdata *pending_tx; 448 581 pj_ioqueue_op_key_t *op_key; 449 582 450 pending_tx = tcp-> tx_list.next;583 pending_tx = tcp->delayed_list.next; 451 584 pj_list_erase(pending_tx); 452 585 453 586 op_key = (pj_ioqueue_op_key_t*)pending_tx->tdata_op_key; 454 587 455 on_write_complete(tcp->key, op_key, 456 -PJ_RETURN_OS_ERROR(OSERR_ENOTCONN)); 457 } 458 459 if (tcp->is_registered) { 460 pjsip_transport_destroy(transport); 461 tcp->is_registered = PJ_FALSE; 588 on_write_complete(tcp->key, op_key, -reason); 462 589 } 463 590 … … 470 597 pj_ioqueue_unregister(tcp->key); 471 598 tcp->key = NULL; 599 tcp->sock = PJ_INVALID_SOCKET; 600 } 601 602 if (tcp->sock != PJ_INVALID_SOCKET) { 603 pj_sock_close(tcp->sock); 604 tcp->sock = PJ_INVALID_SOCKET; 472 605 } 473 606 … … 483 616 484 617 if (tcp->base.pool) { 485 PJ_LOG(4,(tcp->base.obj_name, "TCP transport destroyed")); 486 pj_pool_release(tcp->base.pool); 618 pj_pool_t *pool; 619 620 if (reason != PJ_SUCCESS) { 621 char errmsg[PJ_ERR_MSG_SIZE]; 622 623 pj_strerror(reason, errmsg, sizeof(errmsg)); 624 PJ_LOG(4,(tcp->base.obj_name, 625 "TCP transport destroyed with reason %d: %s", 626 reason, errmsg)); 627 628 } else { 629 630 PJ_LOG(4,(tcp->base.obj_name, 631 "TCP transport destroyed normally")); 632 633 } 634 635 pool = tcp->base.pool; 487 636 tcp->base.pool = NULL; 637 pj_pool_release(pool); 488 638 } 489 639 … … 494 644 /* 495 645 * This utility function creates receive data buffers and start 496 * asynchronous recv() operations from the socket. 646 * asynchronous recv() operations from the socket. It is called after 647 * accept() or connect() operation complete. 497 648 */ 498 649 static pj_status_t tcp_start_read(struct tcp_transport *tcp) … … 532 683 tcp->rdata.pkt_info.packet, &size, 533 684 PJ_IOQUEUE_ALWAYS_ASYNC); 534 if (status != PJ_SUCCESS ) {685 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 535 686 tcp_perror(tcp->base.obj_name, "ioqueue recv() error", status); 536 687 return status; … … 594 745 595 746 /* Create the transport descriptor */ 596 status = create_tcp_transport(listener, sock, &local_addr,597 747 status = tcp_create(listener, sock, PJ_FALSE, &local_addr, 748 (pj_sockaddr_in*)rem_addr, &tcp); 598 749 if (status != PJ_SUCCESS) 599 750 return status; 600 751 752 601 753 /* Start asynchronous connect() operation */ 602 754 tcp->has_pending_connect = PJ_TRUE; 603 pj_ioqueue_op_key_init(&tcp->connect_op.op_key,604 sizeof(tcp->connect_op.op_key));605 tcp->connect_op.transport = tcp;606 755 status = pj_ioqueue_connect(tcp->key, rem_addr, sizeof(pj_sockaddr_in)); 607 if (status != PJ_SUCCESS) { 608 tcp_destroy(&tcp->base); 756 if (status == PJ_SUCCESS) { 757 tcp->has_pending_connect = PJ_FALSE; 758 } else if (status != PJ_EPENDING) { 759 tcp_destroy(&tcp->base, status); 609 760 return status; 610 761 } … … 630 781 } 631 782 783 if (tcp->has_pending_connect) { 784 PJ_LOG(4,(tcp->base.obj_name, 785 "TCP transport %.*s:%d is connecting to %.*s:%d...", 786 (int)tcp->base.local_name.host.slen, 787 tcp->base.local_name.host.ptr, 788 tcp->base.local_name.port, 789 (int)tcp->base.remote_name.host.slen, 790 tcp->base.remote_name.host.ptr, 791 tcp->base.remote_name.port)); 792 } 793 632 794 /* Done */ 633 795 *p_transport = &tcp->base; … … 654 816 accept_op = (struct pending_accept*) op_key; 655 817 818 /* 819 * Loop while there is immediate connection or when there is error. 820 */ 656 821 do { 657 if (status != PJ_SUCCESS) { 658 tcp_perror(listener->name, "Error in accept()", status); 659 822 if (status == PJ_EPENDING) { 823 /* 824 * This can only happen when this function is called during 825 * initialization to kick off asynchronous accept(). 826 */ 827 828 } else if (status != PJ_SUCCESS) { 829 830 /* 831 * Error in accept(). 832 */ 833 tcp_perror(listener->obj_name, "Error in accept()", status); 834 835 /* 836 * Prevent endless accept() error loop by limiting the 837 * number of consecutive errors. Once the number of errors 838 * is equal to maximum, we treat this as permanent error, and 839 * we stop the accept() operation. 840 */ 660 841 ++err_cnt; 661 if (err_cnt >= 5) {662 PJ_LOG(1, (listener-> name,842 if (err_cnt >= 10) { 843 PJ_LOG(1, (listener->obj_name, 663 844 "Too many errors, listener stopping")); 664 845 } 665 846 666 goto start_next_accept; 667 } 668 669 status = create_tcp_transport( listener, sock, 670 &accept_op->local_addr, 671 &accept_op->remote_addr, &tcp); 672 if (status == PJ_SUCCESS) { 673 status = tcp_start_read(tcp); 674 if (status != PJ_SUCCESS) { 675 PJ_LOG(3,(tcp->base.obj_name, "New transport cancelled")); 676 tcp_destroy(&tcp->base); 847 } else { 848 849 if (sock == PJ_INVALID_SOCKET) { 850 sock = accept_op->new_sock; 851 PJ_LOG(4,(listener->obj_name, 852 "Warning: ioqueue reports -1 in on_accept_complete()" 853 " sock argument")); 854 } 855 856 PJ_LOG(4,(listener->obj_name, 857 "TCP listener %.*s:%d: got incoming TCP connection " 858 "from %s:%d, sock=%d", 859 (int)listener->factory.addr_name.host.slen, 860 listener->factory.addr_name.host.ptr, 861 listener->factory.addr_name.port, 862 pj_inet_ntoa(accept_op->remote_addr.sin_addr), 863 pj_ntohs(accept_op->remote_addr.sin_port), 864 sock)); 865 866 /* 867 * Incoming connections! 868 * Create TCP transport for the new socket. 869 */ 870 status = tcp_create( listener, sock, PJ_TRUE, 871 &accept_op->local_addr, 872 &accept_op->remote_addr, &tcp); 873 if (status == PJ_SUCCESS) { 874 status = tcp_start_read(tcp); 875 if (status != PJ_SUCCESS) { 876 PJ_LOG(3,(tcp->base.obj_name, "New transport cancelled")); 877 tcp_destroy(&tcp->base, status); 878 } 677 879 } 678 880 } 679 881 680 start_next_accept: 882 /* 883 * Start the next asynchronous accept() operation. 884 */ 885 accept_op->addr_len = sizeof(pj_sockaddr_in); 886 accept_op->new_sock = PJ_INVALID_SOCKET; 681 887 682 888 status = pj_ioqueue_accept(listener->key, … … 687 893 &accept_op->addr_len); 688 894 895 /* 896 * Loop while we have immediate connection or when there is error. 897 */ 898 689 899 } while (status != PJ_EPENDING); 690 900 } 691 901 692 902 693 /* Callback from ioqueue when packet is sent */ 903 /* 904 * Callback from ioqueue when packet is sent. 905 */ 694 906 static void on_write_complete(pj_ioqueue_key_t *key, 695 907 pj_ioqueue_op_key_t *op_key, 696 908 pj_ssize_t bytes_sent) 697 909 { 698 struct tcp_transport *t p = pj_ioqueue_get_user_data(key);910 struct tcp_transport *tcp = pj_ioqueue_get_user_data(key); 699 911 pjsip_tx_data_op_key *tdata_op_key = (pjsip_tx_data_op_key*)op_key; 700 912 701 913 tdata_op_key->tdata = NULL; 702 914 915 /* Check for error/closure */ 916 if (bytes_sent <= 0) { 917 pj_status_t status; 918 919 PJ_LOG(5,(tcp->base.obj_name, "TCP send() error, sent=%d", 920 bytes_sent)); 921 922 status = (bytes_sent == 0) ? PJ_RETURN_OS_ERROR(OSERR_ENOTCONN) : 923 -bytes_sent; 924 if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = status; 925 pjsip_transport_shutdown(&tcp->base); 926 } 927 703 928 if (tdata_op_key->callback) { 704 tdata_op_key->callback(&tp->base, tdata_op_key->token, bytes_sent); 705 } 706 } 707 708 709 /* This callback is called by transport manager to send SIP message */ 929 /* 930 * Notify sip_transport.c that packet has been sent. 931 */ 932 tdata_op_key->callback(&tcp->base, tdata_op_key->token, bytes_sent); 933 } 934 } 935 936 937 /* 938 * This callback is called by transport manager to send SIP message 939 */ 710 940 static pj_status_t tcp_send_msg(pjsip_transport *transport, 711 941 pjsip_tx_data *tdata, … … 719 949 struct tcp_transport *tcp = (struct tcp_transport*)transport; 720 950 pj_ssize_t size; 721 pj_status_t status; 951 pj_bool_t delayed = PJ_FALSE; 952 pj_status_t status = PJ_SUCCESS; 722 953 723 954 /* Sanity check */ … … 738 969 739 970 /* If asynchronous connect() has not completed yet, just put the 740 * transmit data in the pending transmission list. 971 * transmit data in the pending transmission list since we can not 972 * use the socket yet. 741 973 */ 742 pj_lock_acquire(tcp->base.lock);743 744 974 if (tcp->has_pending_connect) { 745 struct pending_tdata *pending_tdata; 746 747 /* Pust to list */ 748 pending_tdata = pj_pool_alloc(tdata->pool, sizeof(*pending_tdata)); 749 pending_tdata->tdata_op_key = &tdata->op_key; 750 751 pj_list_push_back(&tcp->tx_list, pending_tdata); 752 status = PJ_EPENDING; 753 754 } else { 755 /* send to ioqueue! */ 975 976 /* 977 * Looks like connect() is still in progress. Check again (this time 978 * with holding the lock) to be sure. 979 */ 980 pj_lock_acquire(tcp->base.lock); 981 982 if (tcp->has_pending_connect) { 983 struct delayed_tdata *delayed_tdata; 984 985 /* 986 * connect() is still in progress. Put the transmit data to 987 * the delayed list. 988 */ 989 delayed_tdata = pj_pool_alloc(tdata->pool, 990 sizeof(*delayed_tdata)); 991 delayed_tdata->tdata_op_key = &tdata->op_key; 992 993 pj_list_push_back(&tcp->delayed_list, delayed_tdata); 994 status = PJ_EPENDING; 995 996 /* Prevent pj_ioqueue_send() to be called below */ 997 delayed = PJ_TRUE; 998 } 999 1000 pj_lock_release(tcp->base.lock); 1001 } 1002 1003 if (!delayed) { 1004 /* 1005 * Transport is ready to go. Send the packet to ioqueue to be 1006 * sent asynchronously. 1007 */ 756 1008 size = tdata->buf.cur - tdata->buf.start; 757 1009 status = pj_ioqueue_send(tcp->key, … … 759 1011 tdata->buf.start, &size, 0); 760 1012 761 if (status != PJ_EPENDING) 1013 if (status != PJ_EPENDING) { 1014 /* Not pending (could be immediate success or error) */ 762 1015 tdata->op_key.tdata = NULL; 763 } 764 765 pj_lock_release(tcp->base.lock); 1016 1017 /* Shutdown transport on closure/errors */ 1018 if (size <= 0) { 1019 1020 PJ_LOG(5,(tcp->base.obj_name, "TCP send() error, sent=%d", 1021 size)); 1022 1023 if (status == PJ_SUCCESS) 1024 status = PJ_RETURN_OS_ERROR(OSERR_ENOTCONN); 1025 if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = status; 1026 pjsip_transport_shutdown(&tcp->base); 1027 } 1028 } 1029 } 766 1030 767 1031 return status; … … 769 1033 770 1034 771 /* This callback is called by transport manager to shutdown transport */ 1035 /* 1036 * This callback is called by transport manager to shutdown transport. 1037 * This normally is only used by UDP transport. 1038 */ 772 1039 static pj_status_t tcp_shutdown(pjsip_transport *transport) 773 1040 { … … 780 1047 781 1048 782 /* Callback from ioqueue on incoming packet */ 1049 /* 1050 * Callback from ioqueue that an incoming data is received from the socket. 1051 */ 783 1052 static void on_read_complete(pj_ioqueue_key_t *key, 784 1053 pj_ioqueue_op_key_t *op_key, … … 788 1057 pjsip_rx_data_op_key *rdata_op_key = (pjsip_rx_data_op_key*) op_key; 789 1058 pjsip_rx_data *rdata = rdata_op_key->rdata; 790 struct tcp_transport *tp = (struct tcp_transport*)rdata->tp_info.transport; 1059 struct tcp_transport *tcp = 1060 (struct tcp_transport*)rdata->tp_info.transport; 791 1061 int i; 792 1062 pj_status_t status; 793 1063 794 1064 /* Don't do anything if transport is closing. */ 795 if (t p->is_closing) {796 t p->is_closing++;1065 if (tcp->is_closing) { 1066 tcp->is_closing++; 797 1067 return; 798 1068 } … … 807 1077 pj_uint32_t flags; 808 1078 809 /* Report the packet to transport manager. */ 1079 /* Houston, we have packet! Report the packet to transport manager 1080 * to be parsed. 1081 */ 810 1082 if (bytes_read > 0) { 811 1083 pj_size_t size_eaten; … … 816 1088 pj_gettimeofday(&rdata->pkt_info.timestamp); 817 1089 1090 /* Report to transport manager. 1091 * The transport manager will tell us how many bytes of the packet 1092 * have been processed (as valid SIP message). 1093 */ 818 1094 size_eaten = 819 1095 pjsip_tpmgr_receive_packet(rdata->tp_info.transport->tpmgr, … … 834 1110 835 1111 /* Transport is closed */ 836 PJ_LOG(4,(tp->base.obj_name, "tcp connection closed")); 837 tcp_destroy(&tp->base); 1112 PJ_LOG(4,(tcp->base.obj_name, "TCP connection closed")); 1113 1114 /* We can not destroy the transport since high level objects may 1115 * still keep reference to this transport. So we can only 1116 * instruct transport manager to gracefully start the shutdown 1117 * procedure for this transport. 1118 */ 1119 if (tcp->close_reason==PJ_SUCCESS) 1120 tcp->close_reason = PJ_RETURN_OS_ERROR(OSERR_ENOTCONN); 1121 pjsip_transport_shutdown(&tcp->base); 1122 838 1123 return; 839 1124 840 } else if (bytes_read < 0) { 1125 //} else if (bytes_read < 0) { 1126 } else if (-bytes_read != PJ_STATUS_FROM_OS(OSERR_EWOULDBLOCK) && 1127 -bytes_read != PJ_STATUS_FROM_OS(OSERR_EINPROGRESS) && 1128 -bytes_read != PJ_STATUS_FROM_OS(OSERR_ECONNRESET)) 1129 { 841 1130 842 1131 /* Report error to endpoint. */ 843 1132 PJSIP_ENDPT_LOG_ERROR((rdata->tp_info.transport->endpt, 844 1133 rdata->tp_info.transport->obj_name, 845 -bytes_read, "tcp recv() error")); 846 847 /* Transport error, close transport */ 848 tcp_destroy(&tp->base); 1134 -bytes_read, "TCP recv() error")); 1135 1136 /* We can not destroy the transport since high level objects may 1137 * still keep reference to this transport. So we can only 1138 * instruct transport manager to gracefully start the shutdown 1139 * procedure for this transport. 1140 */ 1141 if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = -bytes_read; 1142 pjsip_transport_shutdown(&tcp->base); 1143 849 1144 return; 850 1145 } 851 1146 852 1147 if (i >= MAX_IMMEDIATE_PACKET) { 853 /* Force ioqueue_recv() to return PJ_EPENDING */ 1148 /* Receive quota reached. Force ioqueue_recv() to 1149 * return PJ_EPENDING 1150 */ 854 1151 flags = PJ_IOQUEUE_ALWAYS_ASYNC; 855 1152 } else { … … 868 1165 869 1166 if (status == PJ_SUCCESS) { 1167 870 1168 /* Continue loop. */ 871 1169 pj_assert(i < MAX_IMMEDIATE_PACKET); … … 880 1178 status, "tcp recv() error")); 881 1179 882 /* Transport error, close transport */ 883 tcp_destroy(&tp->base); 1180 /* We can not destroy the transport since high level objects may 1181 * still keep reference to this transport. So we can only 1182 * instruct transport manager to gracefully start the shutdown 1183 * procedure for this transport. 1184 */ 1185 if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = status; 1186 pjsip_transport_shutdown(&tcp->base); 1187 884 1188 return; 885 1189 } … … 888 1192 889 1193 890 /* Callback from ioqueue when connect completes */ 1194 /* 1195 * Callback from ioqueue when asynchronous connect() operation completes. 1196 */ 891 1197 static void on_connect_complete(pj_ioqueue_key_t *key, 892 1198 pj_status_t status) 893 1199 { 894 struct pending_connect *connect_op = (struct pending_connect *)key; 895 struct tcp_transport *tcp = connect_op->transport; 1200 struct tcp_transport *tcp; 896 1201 pj_sockaddr_in addr; 897 1202 int addrlen; 898 1203 1204 tcp = pj_ioqueue_get_user_data(key); 1205 1206 PJ_LOG(4,(tcp->base.obj_name, 1207 "TCP transport %.*s:%d is connected to %.*s:%d", 1208 (int)tcp->base.local_name.host.slen, 1209 tcp->base.local_name.host.ptr, 1210 tcp->base.local_name.port, 1211 (int)tcp->base.remote_name.host.slen, 1212 tcp->base.remote_name.host.ptr, 1213 tcp->base.remote_name.port)); 1214 899 1215 /* Mark that pending connect() operation has completed. */ 900 1216 tcp->has_pending_connect = PJ_FALSE; … … 902 1218 /* Check connect() status */ 903 1219 if (status != PJ_SUCCESS) { 1220 904 1221 tcp_perror(tcp->base.obj_name, "TCP connect() error", status); 905 tcp_destroy(&tcp->base); 1222 1223 /* We can not destroy the transport since high level objects may 1224 * still keep reference to this transport. So we can only 1225 * instruct transport manager to gracefully start the shutdown 1226 * procedure for this transport. 1227 */ 1228 if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = status; 1229 pjsip_transport_shutdown(&tcp->base); 906 1230 return; 907 1231 } … … 926 1250 status = tcp_start_read(tcp); 927 1251 if (status != PJ_SUCCESS) { 928 tcp_destroy(&tcp->base); 1252 /* We can not destroy the transport since high level objects may 1253 * still keep reference to this transport. So we can only 1254 * instruct transport manager to gracefully start the shutdown 1255 * procedure for this transport. 1256 */ 1257 if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = status; 1258 pjsip_transport_shutdown(&tcp->base); 929 1259 return; 930 1260 } -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c
r512 r563 78 78 { 79 79 pjsua_acc *acc = &pjsua_var.acc[acc_id]; 80 pjsip_transport *tp = pjsua_var.tpdata[tp_id].tp;80 struct transport_data *t = &pjsua_var.tpdata[tp_id]; 81 81 char uri[80]; 82 82 83 83 /* Transport must be valid */ 84 pj_assert(t p!= NULL);84 pj_assert(t->data.ptr != NULL); 85 85 86 86 /* Build URI for the account */ 87 87 pj_ansi_sprintf(uri, "<sip:%.*s:%d;transport=%s>", 88 (int)t p->local_name.host.slen,89 t p->local_name.host.ptr,90 t p->local_name.port,91 pjsip_transport_get_type_name(t p->key.type));88 (int)t->local_name.host.slen, 89 t->local_name.host.ptr, 90 t->local_name.port, 91 pjsip_transport_get_type_name(t->type)); 92 92 93 93 … … 145 145 146 146 PJ_TODO(attach_account_to_transport); 147 if (pjsua_var.tpdata[0]. tp)147 if (pjsua_var.tpdata[0].data.ptr) 148 148 update_acc_contact(acc_id, 0); 149 149 … … 221 221 222 222 /* Must have a transport */ 223 PJ_ASSERT_RETURN(pjsua_var.tpdata[0].tp != NULL, PJ_EINVALIDOP); 223 PJ_TODO(associate_acc_with_transport); 224 PJ_ASSERT_RETURN(pjsua_var.tpdata[0].data.ptr != NULL, PJ_EINVALIDOP); 224 225 225 226 PJSUA_LOCK(); … … 282 283 { 283 284 pjsua_acc_config cfg; 284 pjsip_transport *tp;285 struct transport_data *t = &pjsua_var.tpdata[tid]; 285 286 char uri[62]; 286 287 288 /* ID must be valid */ 289 PJ_ASSERT_RETURN(tid>=0 && tid<PJ_ARRAY_SIZE(pjsua_var.tpdata), PJ_EINVAL); 290 287 291 /* Transport must be valid */ 288 tp = pjsua_var.tpdata[tid].tp; 289 PJ_ASSERT_RETURN(tp != NULL, PJ_EINVAL); 292 PJ_ASSERT_RETURN(t->data.ptr != NULL, PJ_EINVAL); 290 293 291 294 pjsua_acc_config_default(&cfg); 292 295 293 296 /* Build URI for the account */ 294 pj_ansi_sprintf(uri, "<sip:%.*s:%d>", 295 (int)tp->local_name.host.slen, 296 tp->local_name.host.ptr, 297 tp->local_name.port); 297 pj_ansi_sprintf(uri, "<sip:%.*s:%d;transport=%s>", 298 (int)t->local_name.host.slen, 299 t->local_name.host.ptr, 300 t->local_name.port, 301 pjsip_transport_get_type_name(t->type)); 298 302 299 303 cfg.id = pj_str(uri); -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
r509 r563 730 730 /* Find empty transport slot */ 731 731 for (id=0; id < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++id) { 732 if (pjsua_var.tpdata[id]. tp== NULL)732 if (pjsua_var.tpdata[id].data.ptr == NULL) 733 733 break; 734 734 } … … 742 742 /* Create the transport */ 743 743 if (type == PJSIP_TRANSPORT_UDP) { 744 744 /* 745 * Create UDP transport. 746 */ 745 747 pjsua_transport_config config; 746 748 pj_sock_t sock = PJ_INVALID_SOCKET; … … 774 776 } 775 777 778 779 /* Save the transport */ 780 pjsua_var.tpdata[id].type = type; 781 pjsua_var.tpdata[id].local_name = tp->local_name; 782 pjsua_var.tpdata[id].data.tp = tp; 783 784 } else if (type == PJSIP_TRANSPORT_TCP) { 785 /* 786 * Create TCP transport. 787 */ 788 pjsua_transport_config config; 789 pjsip_tpfactory *tcp; 790 pj_sockaddr_in local_addr; 791 792 /* Supply default config if it's not specified */ 793 if (cfg == NULL) { 794 pjsua_transport_config_default(&config); 795 cfg = &config; 796 } 797 798 /* Init local address */ 799 pj_sockaddr_in_init(&local_addr, 0, 0); 800 801 if (cfg->port) 802 local_addr.sin_port = pj_htons((pj_uint16_t)cfg->port); 803 804 if (cfg->ip_addr.s_addr) 805 local_addr.sin_addr.s_addr = cfg->ip_addr.s_addr; 806 807 /* Create the TCP transport */ 808 status = pjsip_tcp_transport_start(pjsua_var.endpt, &local_addr, 1, 809 &tcp); 810 811 if (status != PJ_SUCCESS) { 812 pjsua_perror(THIS_FILE, "Error creating SIP TCP listener", 813 status); 814 goto on_return; 815 } 816 817 /* Save the transport */ 818 pjsua_var.tpdata[id].type = type; 819 pjsua_var.tpdata[id].local_name = tcp->addr_name; 820 pjsua_var.tpdata[id].data.factory = tcp; 821 776 822 } else { 777 823 status = PJSIP_EUNSUPTRANSPORT; … … 780 826 } 781 827 782 /* Save the transport */783 pjsua_var.tpdata[id].tp = tp;784 828 785 829 /* Return the ID */ … … 808 852 /* Find empty transport slot */ 809 853 for (id=0; id < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++id) { 810 if (pjsua_var.tpdata[id]. tp== NULL)854 if (pjsua_var.tpdata[id].data.ptr == NULL) 811 855 break; 812 856 } … … 819 863 820 864 /* Save the transport */ 821 pjsua_var.tpdata[id].tp = tp; 865 pjsua_var.tpdata[id].type = tp->key.type; 866 pjsua_var.tpdata[id].local_name = tp->local_name; 867 pjsua_var.tpdata[id].data.tp = tp; 822 868 823 869 /* Return the ID */ … … 843 889 ++i) 844 890 { 845 if (!pjsua_var.tpdata[i]. tp)891 if (!pjsua_var.tpdata[i].data.ptr) 846 892 continue; 847 893 … … 863 909 pjsua_transport_info *info) 864 910 { 865 pjsip_transport *tp;911 struct transport_data *t = &pjsua_var.tpdata[id]; 866 912 867 913 pj_memset(info, 0, sizeof(*info)); … … 871 917 872 918 /* Make sure that transport exists */ 873 PJ_ASSERT_RETURN(pjsua_var.tpdata[id]. tp!= NULL, PJ_EINVAL);919 PJ_ASSERT_RETURN(pjsua_var.tpdata[id].data.ptr != NULL, PJ_EINVAL); 874 920 875 921 PJSUA_LOCK(); 876 922 877 tp = pjsua_var.tpdata[id].tp; 878 if (tp == NULL) { 879 PJSUA_UNLOCK(); 880 return PJ_EINVALIDOP; 881 } 923 if (pjsua_var.tpdata[id].type == PJSIP_TRANSPORT_UDP) { 924 925 pjsip_transport *tp = t->data.tp; 926 927 if (tp == NULL) { 928 PJSUA_UNLOCK(); 929 return PJ_EINVALIDOP; 930 } 882 931 883 info->id = id; 884 info->type = tp->key.type; 885 info->type_name = pj_str(tp->type_name); 886 info->info = pj_str(tp->info); 887 info->flag = tp->flag; 888 info->addr_len = tp->addr_len; 889 info->local_addr = tp->local_addr; 890 info->local_name = tp->local_name; 891 info->usage_count = pj_atomic_get(tp->ref_cnt); 932 info->id = id; 933 info->type = tp->key.type; 934 info->type_name = pj_str(tp->type_name); 935 info->info = pj_str(tp->info); 936 info->flag = tp->flag; 937 info->addr_len = tp->addr_len; 938 info->local_addr = tp->local_addr; 939 info->local_name = tp->local_name; 940 info->usage_count = pj_atomic_get(tp->ref_cnt); 941 942 } else if (pjsua_var.tpdata[id].type == PJSIP_TRANSPORT_TCP) { 943 944 pjsip_tpfactory *factory = t->data.factory; 945 946 if (factory == NULL) { 947 PJSUA_UNLOCK(); 948 return PJ_EINVALIDOP; 949 } 950 951 info->id = id; 952 info->type = t->type; 953 info->type_name = pj_str("TCP"); 954 info->info = pj_str("TCP transport"); 955 info->flag = factory->flag; 956 info->addr_len = sizeof(factory->local_addr); 957 info->local_addr = factory->local_addr; 958 info->local_name = factory->addr_name; 959 info->usage_count = 0; 960 961 } 962 892 963 893 964 PJSUA_UNLOCK(); … … 907 978 908 979 /* Make sure that transport exists */ 909 PJ_ASSERT_RETURN(pjsua_var.tpdata[id]. tp!= NULL, PJ_EINVAL);980 PJ_ASSERT_RETURN(pjsua_var.tpdata[id].data.ptr != NULL, PJ_EINVAL); 910 981 911 982 … … 927 998 928 999 /* Make sure that transport exists */ 929 PJ_ASSERT_RETURN(pjsua_var.tpdata[id]. tp!= NULL, PJ_EINVAL);1000 PJ_ASSERT_RETURN(pjsua_var.tpdata[id].data.ptr != NULL, PJ_EINVAL); 930 1001 931 1002 -
pjproject/trunk/pjsip/src/test-pjsip/main.c
r111 r563 21 21 #include <string.h> 22 22 #include <stdlib.h> 23 24 extern const char *system_name; 23 25 24 26 static void usage() … … 58 60 } 59 61 log_level = atoi(*opt_arg); 62 } else if (strcmp(*opt_arg, "-s") == 0 || 63 strcmp(*opt_arg, "--system") == 0) 64 { 65 ++opt_arg; 66 if (!opt_arg) { 67 usage(); 68 return 1; 69 } 70 system_name = *opt_arg; 60 71 } else { 61 72 usage(); … … 68 79 retval = test_main(); 69 80 70 if ( argc != 1) {81 if (interractive) { 71 82 char s[10]; 72 printf("<Press ENTER to quit>\n"); 83 printf("<Press ENTER to quit>\n"); fflush(stdout); 73 84 fgets(s, sizeof(s), stdin); 74 85 } -
pjproject/trunk/pjsip/src/test-pjsip/msg_logger.c
r547 r563 28 28 { 29 29 if (msg_log_enabled) { 30 PJ_LOG(4,(THIS_FILE, "RX %d bytes %s from %s:% d:\n"31 "% s\n"30 PJ_LOG(4,(THIS_FILE, "RX %d bytes %s from %s:%s:%d:\n" 31 "%.*s\n" 32 32 "--end msg--", 33 33 rdata->msg_info.len, 34 34 pjsip_rx_data_get_info(rdata), 35 rdata->tp_info.transport->type_name, 35 36 rdata->pkt_info.src_name, 36 37 rdata->pkt_info.src_port, 38 rdata->msg_info.len, 37 39 rdata->msg_info.msg_buf)); 38 40 } … … 44 46 { 45 47 if (msg_log_enabled) { 46 PJ_LOG(4,(THIS_FILE, "TX %d bytes %s to %s:% d:\n"47 "% s\n"48 PJ_LOG(4,(THIS_FILE, "TX %d bytes %s to %s:%s:%d:\n" 49 "%.*s\n" 48 50 "--end msg--", 49 51 (tdata->buf.cur - tdata->buf.start), 50 52 pjsip_tx_data_get_info(tdata), 53 tdata->tp_info.transport->type_name, 51 54 tdata->tp_info.dst_name, 52 55 tdata->tp_info.dst_port, 56 (tdata->buf.cur - tdata->buf.start), 53 57 tdata->buf.start)); 54 58 } -
pjproject/trunk/pjsip/src/test-pjsip/msg_test.c
r127 r563 22 22 23 23 #define POOL_SIZE 8000 24 #define LOOP 10000 24 #if defined(PJ_DEBUG) && PJ_DEBUG!=0 25 # define LOOP 10000 26 #else 27 # define LOOP 100000 28 #endif 25 29 #define AVERAGE_MSG_LEN 800 26 30 #define THIS_FILE "msg_test.c" … … 35 39 #define FLAG_PARSE_ONLY 4 36 40 #define FLAG_PRINT_ONLY 8 37 38 static int flag = 0;39 41 40 42 struct test_msg … … 102 104 }; 103 105 104 static pj_highprec_t detect_len, parse_len, print_len; 105 static pj_timestamp detect_time, parse_time, print_time; 106 static struct 107 { 108 int flag; 109 pj_highprec_t detect_len, parse_len, print_len; 110 pj_timestamp detect_time, parse_time, print_time; 111 } var; 106 112 107 113 static pj_status_t test_entry( pj_pool_t *pool, struct test_msg *entry ) … … 122 128 entry->len = pj_native_strlen(entry->msg); 123 129 124 if ( flag & FLAG_PARSE_ONLY)130 if (var.flag & FLAG_PARSE_ONLY) 125 131 goto parse_msg; 126 132 127 if ( flag & FLAG_PRINT_ONLY) {133 if (var.flag & FLAG_PRINT_ONLY) { 128 134 if (print_msg == NULL) 129 135 print_msg = entry->creator(pool); … … 132 138 133 139 /* Detect message. */ 134 detect_len =detect_len + entry->len;140 var.detect_len = var.detect_len + entry->len; 135 141 pj_get_timestamp(&t1); 136 142 status = pjsip_find_msg(entry->msg, entry->len, PJ_FALSE, &msg_size); … … 149 155 pj_get_timestamp(&t2); 150 156 pj_sub_timestamp(&t2, &t1); 151 pj_add_timestamp(& detect_time, &t2);152 153 if ( flag & FLAG_DETECT_ONLY)157 pj_add_timestamp(&var.detect_time, &t2); 158 159 if (var.flag & FLAG_DETECT_ONLY) 154 160 return PJ_SUCCESS; 155 161 156 162 /* Parse message. */ 157 163 parse_msg: 158 parse_len =parse_len + entry->len;164 var.parse_len = var.parse_len + entry->len; 159 165 pj_get_timestamp(&t1); 160 166 pj_list_init(&err_list); … … 172 178 pj_get_timestamp(&t2); 173 179 pj_sub_timestamp(&t2, &t1); 174 pj_add_timestamp(& parse_time, &t2);175 176 if ( flag & FLAG_PARSE_ONLY)180 pj_add_timestamp(&var.parse_time, &t2); 181 182 if (var.flag & FLAG_PARSE_ONLY) 177 183 return PJ_SUCCESS; 178 184 … … 307 313 /* Print message. */ 308 314 print_msg: 309 print_len =print_len + entry->len;315 var.print_len = var.print_len + entry->len; 310 316 pj_get_timestamp(&t1); 311 if ( flag && FLAG_PRINT_ONLY)317 if (var.flag && FLAG_PRINT_ONLY) 312 318 ref_msg = print_msg; 313 319 len = pjsip_msg_print(ref_msg, msgbuf1, PJSIP_MAX_PKT_LEN); … … 318 324 pj_get_timestamp(&t2); 319 325 pj_sub_timestamp(&t2, &t1); 320 pj_add_timestamp(& print_time, &t2);326 pj_add_timestamp(&var.print_time, &t2); 321 327 322 328 … … 675 681 /*****************************************************************************/ 676 682 677 int msg_test(void) 683 static pj_status_t simple_test(void) 684 { 685 unsigned i; 686 pj_status_t status; 687 688 PJ_LOG(3,(THIS_FILE, " simple test..")); 689 for (i=0; i<PJ_ARRAY_SIZE(test_array); ++i) { 690 pj_pool_t *pool; 691 pool = pjsip_endpt_create_pool(endpt, NULL, POOL_SIZE, POOL_SIZE); 692 status = test_entry( pool, &test_array[i] ); 693 pjsip_endpt_release_pool(endpt, pool); 694 695 if (status != PJ_SUCCESS) 696 return status; 697 } 698 699 return PJ_SUCCESS; 700 } 701 702 703 static int msg_benchmark(unsigned *p_detect, unsigned *p_parse, 704 unsigned *p_print) 678 705 { 679 706 pj_status_t status; … … 684 711 pj_highprec_t avg_detect, avg_parse, avg_print, kbytes; 685 712 686 PJ_LOG(3,(THIS_FILE, " simple test..")); 687 for (i=0; i<PJ_ARRAY_SIZE(test_array); ++i) { 688 pool = pjsip_endpt_create_pool(endpt, NULL, POOL_SIZE, POOL_SIZE); 689 status = test_entry( pool, &test_array[i] ); 690 pjsip_endpt_release_pool(endpt, pool); 691 692 if (status != PJ_SUCCESS) 693 return status; 694 } 695 696 PJ_LOG(3,(THIS_FILE, " benchmarking..")); 697 detect_len = parse_len = print_len = 0; 698 zero.u64 = detect_time.u64 = parse_time.u64 = print_time.u64 = 0; 699 713 714 pj_memset(&var, 0, sizeof(var)); 715 zero.u64 = 0; 716 700 717 for (loop=0; loop<LOOP; ++loop) { 701 718 for (i=0; i<PJ_ARRAY_SIZE(test_array); ++i) { … … 709 726 } 710 727 711 kbytes = detect_len;728 kbytes = var.detect_len; 712 729 pj_highprec_mod(kbytes, 1000000); 713 730 pj_highprec_div(kbytes, 100000); 714 elapsed = pj_elapsed_time(&zero, & detect_time);715 avg_detect = pj_elapsed_usec(&zero, & detect_time);731 elapsed = pj_elapsed_time(&zero, &var.detect_time); 732 avg_detect = pj_elapsed_usec(&zero, &var.detect_time); 716 733 pj_highprec_mul(avg_detect, AVERAGE_MSG_LEN); 717 pj_highprec_div(avg_detect, detect_len);734 pj_highprec_div(avg_detect, var.detect_len); 718 735 avg_detect = 1000000 / avg_detect; 719 736 720 737 PJ_LOG(3,(THIS_FILE, 721 738 " %u.%u MB detected in %d.%03ds (avg=%d msg detection/sec)", 722 (unsigned)( detect_len/1000000), (unsigned)kbytes,739 (unsigned)(var.detect_len/1000000), (unsigned)kbytes, 723 740 elapsed.sec, elapsed.msec, 724 741 (unsigned)avg_detect)); 725 726 kbytes = parse_len; 742 *p_detect = (unsigned)avg_detect; 743 744 kbytes = var.parse_len; 727 745 pj_highprec_mod(kbytes, 1000000); 728 746 pj_highprec_div(kbytes, 100000); 729 elapsed = pj_elapsed_time(&zero, & parse_time);730 avg_parse = pj_elapsed_usec(&zero, & parse_time);747 elapsed = pj_elapsed_time(&zero, &var.parse_time); 748 avg_parse = pj_elapsed_usec(&zero, &var.parse_time); 731 749 pj_highprec_mul(avg_parse, AVERAGE_MSG_LEN); 732 pj_highprec_div(avg_parse, parse_len);750 pj_highprec_div(avg_parse, var.parse_len); 733 751 avg_parse = 1000000 / avg_parse; 734 752 735 753 PJ_LOG(3,(THIS_FILE, 736 754 " %u.%u MB parsed in %d.%03ds (avg=%d msg parsing/sec)", 737 (unsigned)( parse_len/1000000), (unsigned)kbytes,755 (unsigned)(var.parse_len/1000000), (unsigned)kbytes, 738 756 elapsed.sec, elapsed.msec, 739 757 (unsigned)avg_parse)); 740 741 kbytes = print_len; 758 *p_parse = (unsigned)avg_parse; 759 760 kbytes = var.print_len; 742 761 pj_highprec_mod(kbytes, 1000000); 743 762 pj_highprec_div(kbytes, 100000); 744 elapsed = pj_elapsed_time(&zero, & print_time);745 avg_print = pj_elapsed_usec(&zero, & print_time);763 elapsed = pj_elapsed_time(&zero, &var.print_time); 764 avg_print = pj_elapsed_usec(&zero, &var.print_time); 746 765 pj_highprec_mul(avg_print, AVERAGE_MSG_LEN); 747 pj_highprec_div(avg_print, print_len);766 pj_highprec_div(avg_print, var.print_len); 748 767 avg_print = 1000000 / avg_print; 749 768 750 769 PJ_LOG(3,(THIS_FILE, 751 770 " %u.%u MB printed in %d.%03ds (avg=%d msg print/sec)", 752 (unsigned)( print_len/1000000), (unsigned)kbytes,771 (unsigned)(var.print_len/1000000), (unsigned)kbytes, 753 772 elapsed.sec, elapsed.msec, 754 773 (unsigned)avg_print)); 755 774 775 *p_print = (unsigned)avg_print; 756 776 return status; 757 777 } 758 778 759 779 /*****************************************************************************/ 780 781 int msg_test(void) 782 { 783 enum { COUNT = 4, DETECT=0, PARSE=1, PRINT=2 }; 784 struct { 785 unsigned detect; 786 unsigned parse; 787 unsigned print; 788 } run[COUNT]; 789 unsigned i, max, avg_len; 790 char desc[250]; 791 pj_status_t status; 792 793 794 status = simple_test(); 795 if (status != PJ_SUCCESS) 796 return status; 797 798 for (i=0; i<COUNT; ++i) { 799 PJ_LOG(3,(THIS_FILE, " benchmarking (%d of %d)..", i+1, COUNT)); 800 status = msg_benchmark(&run[i].detect, &run[i].parse, &run[i].print); 801 if (status != PJ_SUCCESS) 802 return status; 803 } 804 805 /* Calculate average message length */ 806 for (i=0, avg_len=0; i<PJ_ARRAY_SIZE(test_array); ++i) { 807 avg_len += test_array[i].len; 808 } 809 avg_len /= PJ_ARRAY_SIZE(test_array); 810 811 812 /* Print maximum detect/sec */ 813 for (i=0, max=0; i<COUNT; ++i) 814 if (run[i].detect > max) max = run[i].detect; 815 816 PJ_LOG(3,("", " Maximum message detection/sec=%u", max)); 817 818 pj_ansi_sprintf(desc, "Number of SIP messages " 819 "can be pre-parse by <tt>pjsip_find_msg()</tt> " 820 "per second (tested with %d message sets with " 821 "average message length of " 822 "%d bytes)", PJ_ARRAY_SIZE(test_array), avg_len); 823 report_ival("msg-detect-per-sec", max, "msg/sec", desc); 824 825 /* Print maximum parse/sec */ 826 for (i=0, max=0; i<COUNT; ++i) 827 if (run[i].parse > max) max = run[i].parse; 828 829 PJ_LOG(3,("", " Maximum message parsing/sec=%u", max)); 830 831 pj_ansi_sprintf(desc, "Number of SIP messages " 832 "can be <b>parsed</b> by <tt>pjsip_parse_msg()</tt> " 833 "per second (tested with %d message sets with " 834 "average message length of " 835 "%d bytes)", PJ_ARRAY_SIZE(test_array), avg_len); 836 report_ival("msg-parse-per-sec", max, "msg/sec", desc); 837 838 /* Msg parsing bandwidth */ 839 report_ival("msg-parse-bandwidth-mb", avg_len*max/1000000, "MB/sec", 840 "Message parsing bandwidth in megabytes (number of megabytes" 841 " worth of SIP messages that can be parsed per second). " 842 "The value is derived from msg-parse-per-sec above."); 843 844 845 /* Print maximum print/sec */ 846 for (i=0, max=0; i<COUNT; ++i) 847 if (run[i].print > max) max = run[i].print; 848 849 PJ_LOG(3,("", " Maximum message print/sec=%u", max)); 850 851 pj_ansi_sprintf(desc, "Number of SIP messages " 852 "can be <b>printed</b> by <tt>pjsip_msg_print()</tt>" 853 " per second (tested with %d message sets with " 854 "average message length of " 855 "%d bytes)", PJ_ARRAY_SIZE(test_array), avg_len); 856 857 report_ival("msg-print-per-sec", max, "msg/sec", desc); 858 859 /* Msg print bandwidth */ 860 report_ival("msg-printed-bandwidth-mb", avg_len*max/1000000, "MB/sec", 861 "Message print bandwidth in megabytes (total size of " 862 "SIP messages printed per second). " 863 "The value is derived from msg-print-per-sec above."); 864 865 866 return PJ_SUCCESS; 867 } 868 -
pjproject/trunk/pjsip/src/test-pjsip/test.c
r555 r563 34 34 } while (0) 35 35 36 #define DO_TSX_TEST(test, param) \ 37 do { \ 38 PJ_LOG(3, (THIS_FILE, "Running %s(%s)...", #test, (param)->tp_type)); \ 39 rc = test(param); \ 40 PJ_LOG(3, (THIS_FILE, \ 41 "%s(%d)", \ 42 (rc ? "..ERROR" : "..success"), rc)); \ 43 if (rc!=0) goto on_return; \ 44 } while (0) 36 45 37 46 38 47 pjsip_endpoint *endpt; 39 48 int log_level = 3; 49 50 static pj_oshandle_t fd_report; 51 const char *system_name = "Unknown"; 52 static char buf[1024]; 40 53 41 54 void app_perror(const char *msg, pj_status_t rc) … … 76 89 } 77 90 91 static pj_status_t init_report(void) 92 { 93 char tmp[80]; 94 pj_time_val timestamp; 95 pj_parsed_time date_time; 96 pj_ssize_t len; 97 pj_status_t status; 98 99 pj_ansi_sprintf(tmp, "pjsip-static-bench-%s-%s.htm", PJ_OS_NAME, PJ_CC_NAME); 100 101 status = pj_file_open(NULL, tmp, PJ_O_WRONLY, &fd_report); 102 if (status != PJ_SUCCESS) 103 return status; 104 105 /* Title */ 106 len = pj_ansi_sprintf(buf, "<HTML>\n" 107 " <HEAD>\n" 108 " <TITLE>PJSIP %s (%s) - Static Benchmark</TITLE>\n" 109 " </HEAD>\n" 110 "<BODY>\n" 111 "\n", 112 PJ_VERSION, 113 (PJ_DEBUG ? "Debug" : "Release")); 114 pj_file_write(fd_report, buf, &len); 115 116 117 /* Title */ 118 len = pj_ansi_sprintf(buf, "<H1>PJSIP %s (%s) - Static Benchmark</H1>\n", 119 PJ_VERSION, 120 (PJ_DEBUG ? "Debug" : "Release")); 121 pj_file_write(fd_report, buf, &len); 122 123 len = pj_ansi_sprintf(buf, "<P>Below is the benchmark result generated " 124 "by <b>test-pjsip</b> program. The program " 125 "is single-threaded only.</P>\n"); 126 pj_file_write(fd_report, buf, &len); 127 128 129 /* Write table heading */ 130 len = pj_ansi_sprintf(buf, "<TABLE border=\"1\" cellpadding=\"4\">\n" 131 " <TR><TD bgColor=\"aqua\" align=\"center\">Variable</TD>\n" 132 " <TD bgColor=\"aqua\" align=\"center\">Value</TD>\n" 133 " <TD bgColor=\"aqua\" align=\"center\">Description</TD>\n" 134 " </TR>\n"); 135 pj_file_write(fd_report, buf, &len); 136 137 138 /* Write version */ 139 report_sval("version", PJ_VERSION, "", "PJLIB/PJSIP version"); 140 141 142 /* Debug or release */ 143 report_sval("build-type", (PJ_DEBUG ? "Debug" : "Release"), "", "Build type"); 144 145 146 /* Write timestamp */ 147 pj_gettimeofday(×tamp); 148 report_ival("timestamp", timestamp.sec, "", "System timestamp of the test"); 149 150 151 /* Write time of day */ 152 pj_time_decode(×tamp, &date_time); 153 len = pj_ansi_sprintf(tmp, "%04d-%02d-%02d %02d:%02d:%02d", 154 date_time.year, date_time.mon+1, date_time.day, 155 date_time.hour, date_time.min, date_time.sec); 156 report_sval("date-time", tmp, "", "Date/time of the test"); 157 158 159 /* Write System */ 160 report_sval("system", system_name, "", "System description"); 161 162 163 /* Write OS type */ 164 report_sval("os-family", PJ_OS_NAME, "", "Operating system family"); 165 166 167 /* Write CC name */ 168 len = pj_ansi_sprintf(tmp, "%s-%d.%d.%d", PJ_CC_NAME, 169 PJ_CC_VER_1, PJ_CC_VER_2, PJ_CC_VER_2); 170 report_sval("cc-name", tmp, "", "Compiler name and version"); 171 172 173 return PJ_SUCCESS; 174 } 175 176 void report_sval(const char *name, const char* value, const char *valname, 177 const char *desc) 178 { 179 pj_ssize_t len; 180 181 len = pj_ansi_sprintf(buf, " <TR><TD><TT>%s</TT></TD>\n" 182 " <TD align=\"right\"><B>%s %s</B></TD>\n" 183 " <TD>%s</TD>\n" 184 " </TR>\n", 185 name, value, valname, desc); 186 pj_file_write(fd_report, buf, &len); 187 } 188 189 190 void report_ival(const char *name, int value, const char *valname, 191 const char *desc) 192 { 193 pj_ssize_t len; 194 195 len = pj_ansi_sprintf(buf, " <TR><TD><TT>%s</TT></TD>\n" 196 " <TD align=\"right\"><B>%d %s</B></TD>\n" 197 " <TD>%s</TD>\n" 198 " </TR>\n", 199 name, value, valname, desc); 200 pj_file_write(fd_report, buf, &len); 201 202 } 203 204 static void close_report(void) 205 { 206 pj_ssize_t len; 207 208 if (fd_report) { 209 len = pj_ansi_sprintf(buf, "</TABLE>\n</BODY>\n</HTML>\n"); 210 pj_file_write(fd_report, buf, &len); 211 212 pj_file_close(fd_report); 213 } 214 } 215 216 78 217 int test_main(void) 79 218 { … … 81 220 pj_caching_pool caching_pool; 82 221 const char *filename; 222 unsigned i, tsx_test_cnt=0; 223 struct tsx_test_param tsx_test[10]; 224 pj_status_t status; 225 pjsip_transport *tp; 226 pjsip_tpfactory *tpfactory; 83 227 int line; 84 228 … … 93 237 return rc; 94 238 } 239 240 status = init_report(); 241 if (status != PJ_SUCCESS) 242 return status; 95 243 96 244 pj_dump_config(); … … 125 273 goto on_return; 126 274 } 275 tsx_test[tsx_test_cnt].port = 5060; 276 tsx_test[tsx_test_cnt].tp_type = "loop-dgram"; 277 tsx_test[tsx_test_cnt].type = PJSIP_TRANSPORT_LOOP_DGRAM; 278 ++tsx_test_cnt; 279 127 280 128 281 #if INCLUDE_URI_TEST … … 139 292 #endif 140 293 294 #if INCLUDE_TSX_BENCH 295 DO_TEST(tsx_bench()); 296 #endif 297 141 298 #if INCLUDE_UDP_TEST 142 299 DO_TEST(transport_udp_test()); … … 147 304 #endif 148 305 306 #if INCLUDE_TCP_TEST 307 DO_TEST(transport_tcp_test()); 308 #endif 309 310 149 311 #if INCLUDE_TSX_TEST 150 DO_TEST(tsx_basic_test()); 151 DO_TEST(tsx_uac_test()); 152 DO_TEST(tsx_uas_test()); 312 status = pjsip_udp_transport_start(endpt, NULL, NULL, 1, &tp); 313 if (status == PJ_SUCCESS) { 314 tsx_test[tsx_test_cnt].port = tp->local_name.port; 315 tsx_test[tsx_test_cnt].tp_type = "udp"; 316 tsx_test[tsx_test_cnt].type = PJSIP_TRANSPORT_UDP; 317 ++tsx_test_cnt; 318 } 319 320 status = pjsip_tcp_transport_start(endpt, NULL, 1, &tpfactory); 321 if (status == PJ_SUCCESS) { 322 tsx_test[tsx_test_cnt].port = tpfactory->addr_name.port; 323 tsx_test[tsx_test_cnt].tp_type = "tcp"; 324 tsx_test[tsx_test_cnt].type = PJSIP_TRANSPORT_TCP; 325 ++tsx_test_cnt; 326 } else { 327 app_perror("Unable to create TCP", status); 328 rc = -4; 329 goto on_return; 330 } 331 332 333 for (i=0; i<tsx_test_cnt; ++i) { 334 DO_TSX_TEST(tsx_basic_test, &tsx_test[i]); 335 DO_TSX_TEST(tsx_uac_test, &tsx_test[i]); 336 DO_TSX_TEST(tsx_uas_test, &tsx_test[i]); 337 } 153 338 #endif 154 339 155 340 156 341 on_return: 157 342 flush_events(500); 158 343 pjsip_endpt_destroy(endpt); 159 344 pj_caching_pool_destroy(&caching_pool); … … 170 355 PJ_LOG(3,(THIS_FILE, "Test completed with error(s)")); 171 356 357 report_ival("test-status", rc, "", "Overall test status/result (0==success)"); 358 close_report(); 172 359 return rc; 173 360 } -
pjproject/trunk/pjsip/src/test-pjsip/test.h
r555 r563 32 32 #define INCLUDE_TSX_GROUP 1 33 33 34 /* 35 * Include tests that normally would fail under certain gcc 36 * optimization levels. 37 */ 38 #ifndef INCLUDE_GCC_TEST 39 # define INCLUDE_GCC_TEST 0 40 #endif 34 41 35 42 … … 37 44 #define INCLUDE_MSG_TEST INCLUDE_MESSAGING_GROUP 38 45 #define INCLUDE_TXDATA_TEST INCLUDE_MESSAGING_GROUP 46 #define INCLUDE_TSX_BENCH INCLUDE_MESSAGING_GROUP 39 47 #define INCLUDE_UDP_TEST INCLUDE_TRANSPORT_GROUP 40 48 #define INCLUDE_LOOP_TEST INCLUDE_TRANSPORT_GROUP 49 #define INCLUDE_TCP_TEST INCLUDE_TRANSPORT_GROUP 41 50 #define INCLUDE_TSX_TEST INCLUDE_TSX_GROUP 42 51 … … 48 57 int msg_err_test(void); 49 58 int txdata_test(void); 59 int tsx_bench(void); 50 60 int transport_udp_test(void); 51 61 int transport_loop_test(void); 52 int tsx_basic_test(void); 53 int tsx_uac_test(void); 54 int tsx_uas_test(void); 62 int transport_tcp_test(void); 63 64 struct tsx_test_param 65 { 66 int type; 67 int port; 68 char *tp_type; 69 }; 70 71 int tsx_basic_test(struct tsx_test_param *param); 72 int tsx_uac_test(struct tsx_test_param *param); 73 int tsx_uas_test(struct tsx_test_param *param); 55 74 56 75 /* Transport test helpers (transport_test.c). */ … … 58 77 int transport_send_recv_test( pjsip_transport_type_e tp_type, 59 78 pjsip_transport *ref_tp, 60 char *target_url ); 79 char *target_url, 80 int *p_usec_rtt); 61 81 int transport_rt_test( pjsip_transport_type_e tp_type, 62 82 pjsip_transport *ref_tp, … … 69 89 /* Test utilities. */ 70 90 void app_perror(const char *msg, pj_status_t status); 71 int init_msg_logger(void);72 int msg_logger_set_enabled(pj_bool_t enabled);91 int init_msg_logger(void); 92 int msg_logger_set_enabled(pj_bool_t enabled); 73 93 void flush_events(unsigned duration); 94 95 96 void report_ival(const char *name, int value, const char *valname, const char *desc); 97 void report_sval(const char *name, const char* value, const char *valname, const char *desc); 98 74 99 75 100 /* Settings. */ -
pjproject/trunk/pjsip/src/test-pjsip/transport_loop_test.c
r127 r563 26 26 static int datagram_loop_test() 27 27 { 28 enum { LOOP = 8 }; 28 29 pjsip_transport *loop; 29 30 int i, pkt_lost; 30 31 pj_sockaddr_in addr; 31 32 pj_status_t status; 33 long ref_cnt; 34 unsigned rtt[LOOP], min_rtt; 32 35 33 36 PJ_LOG(3,(THIS_FILE, "testing datagram loop transport")); … … 41 44 } 42 45 46 /* Get initial reference counter */ 47 ref_cnt = pj_atomic_get(loop->ref_cnt); 48 43 49 /* Test basic transport attributes */ 44 50 status = generic_transport_test(loop); … … 47 53 48 54 /* Basic transport's send/receive loopback test. */ 49 for (i=0; i< 2; ++i) {55 for (i=0; i<LOOP; ++i) { 50 56 status = transport_send_recv_test(PJSIP_TRANSPORT_LOOP_DGRAM, loop, 51 "sip:bob@130.0.0.1;transport=loop-dgram"); 57 "sip:bob@130.0.0.1;transport=loop-dgram", 58 &rtt[i]); 52 59 if (status != 0) 53 60 return status; 54 61 } 62 63 min_rtt = 0xFFFFFFF; 64 for (i=0; i<LOOP; ++i) 65 if (rtt[i] < min_rtt) min_rtt = rtt[i]; 66 67 report_ival("loop-rtt-usec", min_rtt, "usec", 68 "Best Loopback transport round trip time, in microseconds " 69 "(time from sending request until response is received. " 70 "Tests were performed on local machine only)"); 71 55 72 56 73 /* Multi-threaded round-trip test. */ … … 85 102 pjsip_loop_set_delay(loop, 0); 86 103 87 /* Check that reference counter is one. */ 88 if (pj_atomic_get(loop->ref_cnt) != 1) { 89 return -50; 104 /* Check reference counter. */ 105 if (pj_atomic_get(loop->ref_cnt) != ref_cnt) { 106 PJ_LOG(3,(THIS_FILE, " error: ref counter is not %d (%d)", 107 ref_cnt, pj_atomic_get(loop->ref_cnt))); 108 return -51; 90 109 } 91 110 -
pjproject/trunk/pjsip/src/test-pjsip/transport_test.c
r547 r563 174 174 int transport_send_recv_test( pjsip_transport_type_e tp_type, 175 175 pjsip_transport *ref_tp, 176 char *target_url ) 176 char *target_url, 177 int *p_usec_rtt) 177 178 { 178 179 pj_bool_t msg_log_enabled; … … 221 222 222 223 /* Send the message (statelessly). */ 224 PJ_LOG(5,(THIS_FILE, "Sending request to %.*s", 225 (int)target.slen, target.ptr)); 223 226 status = pjsip_endpt_send_request_stateless( endpt, tdata, NULL, 224 227 &send_msg_callback); … … 229 232 } 230 233 231 /* Set the timeout ( 1 secondfrom now) */234 /* Set the timeout (2 seconds from now) */ 232 235 pj_gettimeofday(&timeout); 233 timeout.sec += 1;236 timeout.sec += 2; 234 237 235 238 /* Loop handling events until we get status */ … … 269 272 unsigned usec_rt; 270 273 usec_rt = pj_elapsed_usec(&my_send_time, &my_recv_time); 274 271 275 PJ_LOG(3,(THIS_FILE, " round-trip = %d usec", usec_rt)); 276 277 *p_usec_rtt = usec_rt; 272 278 } 273 279 … … 517 523 unsigned total_recv; 518 524 519 520 525 PJ_LOG(3,(THIS_FILE, " multithreaded round-trip test (%d threads)...", 521 526 THREADS)); -
pjproject/trunk/pjsip/src/test-pjsip/transport_udp_test.c
r550 r563 30 30 int transport_udp_test(void) 31 31 { 32 enum { SEND_RECV_LOOP = 2};32 enum { SEND_RECV_LOOP = 8 }; 33 33 pjsip_transport *udp_tp, *tp; 34 34 pj_sockaddr_in addr, rem_addr; 35 35 pj_str_t s; 36 36 pj_status_t status; 37 unsigned rtt[SEND_RECV_LOOP], min_rtt; 37 38 int i, pkt_lost; 38 39 … … 80 81 for (i=0; i<SEND_RECV_LOOP; ++i) { 81 82 status = transport_send_recv_test(PJSIP_TRANSPORT_UDP, tp, 82 "sip:alice@127.0.0.1:"TEST_UDP_PORT_STR); 83 "sip:alice@127.0.0.1:"TEST_UDP_PORT_STR, 84 &rtt[i]); 83 85 if (status != 0) 84 86 return status; 85 87 } 88 89 min_rtt = 0xFFFFFFF; 90 for (i=0; i<SEND_RECV_LOOP; ++i) 91 if (rtt[i] < min_rtt) min_rtt = rtt[i]; 92 93 report_ival("udp-rtt-usec", min_rtt, "usec", 94 "Best UDP transport round trip time, in microseconds " 95 "(time from sending request until response is received. " 96 "Tests were performed on local machine only)"); 97 86 98 87 99 /* Multi-threaded round-trip test. */ -
pjproject/trunk/pjsip/src/test-pjsip/tsx_basic_test.c
r127 r563 24 24 #define THIS_FILE "tsx_basic_test.c" 25 25 26 static char TARGET_URI[128]; 27 static char FROM_URI[128]; 28 29 26 30 /* Test transaction layer. */ 27 31 static int tsx_layer_test(void) … … 34 38 PJ_LOG(3,(THIS_FILE, " transaction layer test")); 35 39 36 target = pj_str( "sip:alice@localhost");37 from = pj_str( "sip:bob@localhost");40 target = pj_str(TARGET_URI); 41 from = pj_str(FROM_URI); 38 42 39 43 status = pjsip_endpt_create_request(endpt, &pjsip_invite_method, &target, … … 78 82 PJ_LOG(3,(THIS_FILE, " double terminate test")); 79 83 80 target = pj_str( "sip:alice@localhost;transport=loop-dgram");81 from = pj_str( "sip:bob@localhost");84 target = pj_str(TARGET_URI); 85 from = pj_str(FROM_URI); 82 86 83 87 /* Create request. */ … … 132 136 } 133 137 134 int tsx_basic_test( void)138 int tsx_basic_test(struct tsx_test_param *param) 135 139 { 136 140 int status; 141 142 pj_ansi_sprintf(TARGET_URI, "sip:bob@127.0.0.1:%d;transport=%s", 143 param->port, param->tp_type); 144 pj_ansi_sprintf(FROM_URI, "sip:alice@127.0.0.1:%d;transport=%s", 145 param->port, param->tp_type); 137 146 138 147 status = tsx_layer_test(); -
pjproject/trunk/pjsip/src/test-pjsip/tsx_uac_test.c
r555 r563 92 92 #define TEST5_RETRANSMIT_CNT 3 93 93 94 static char TARGET_URI[128]; 95 static char FROM_URI[128]; 96 static unsigned tp_flag; 97 static struct tsx_test_param *test_param; 94 98 95 99 static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e); … … 141 145 142 146 /* General timer entry to be used by tests. */ 143 static pj_timer_entry timer; 147 static struct my_timer 148 { 149 pj_timer_entry entry; 150 char key_buf[1024]; 151 pj_str_t tsx_key; 152 } timer; 144 153 145 154 /* … … 167 176 test_complete = -710; 168 177 } 178 179 180 /* If transport is reliable, then there must not be any 181 * retransmissions. 182 */ 183 if (tp_flag & PJSIP_TRANSPORT_RELIABLE) { 184 if (recv_count != 1) { 185 PJ_LOG(3,(THIS_FILE, 186 " error: there were %d (re)transmissions", 187 recv_count)); 188 test_complete = -715; 189 } 190 } else { 191 /* Check the number of transmissions, which must be 192 * 6 for INVITE and 10 for non-INVITE 193 */ 194 if (tsx->method.id==PJSIP_INVITE_METHOD && recv_count != 7) { 195 PJ_LOG(3,(THIS_FILE, 196 " error: there were %d (re)transmissions", 197 recv_count)); 198 test_complete = -716; 199 } else 200 if (tsx->method.id==PJSIP_OPTIONS_METHOD && recv_count != 11) { 201 PJ_LOG(3,(THIS_FILE, 202 " error: there were %d (re)transmissions", 203 recv_count)); 204 test_complete = -717; 205 } else 206 if (tsx->method.id!=PJSIP_INVITE_METHOD && 207 tsx->method.id!=PJSIP_OPTIONS_METHOD) 208 { 209 PJ_LOG(3,(THIS_FILE, " error: unexpected method")); 210 test_complete = -718; 211 } 212 } 169 213 } 170 214 … … 516 560 struct pj_timer_entry *entry) 517 561 { 518 pjsip_transaction *tsx = entry->user_data; 562 struct my_timer *m = (struct my_timer *)entry; 563 pjsip_transaction *tsx = pjsip_tsx_layer_find_tsx(&m->tsx_key, PJ_FALSE); 519 564 int status_code = entry->id; 520 565 … … 721 766 pjsip_transport_add_ref(r->res_addr.transport); 722 767 723 timer. cb = &send_response_callback;724 timer. user_data = r;725 pjsip_endpt_schedule_timer(endpt, &timer , &delay);768 timer.entry.cb = &send_response_callback; 769 timer.entry.user_data = r; 770 pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay); 726 771 727 772 return PJ_TRUE; … … 769 814 rdata); 770 815 771 timer.user_data = pjsip_tsx_layer_find_tsx(&key, PJ_FALSE);772 timer. id = 301;773 timer. cb = &terminate_tsx_callback;774 775 pjsip_endpt_schedule_timer(endpt, &timer , &delay);816 pj_strcpy(&timer.tsx_key, &key); 817 timer.entry.id = 301; 818 timer.entry.cb = &terminate_tsx_callback; 819 820 pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay); 776 821 } 777 822 … … 842 887 pjsip_transport_add_ref(r->res_addr.transport); 843 888 844 timer. cb = &send_response_callback;845 timer. user_data = r;846 pjsip_endpt_schedule_timer(endpt, &timer , &delay);889 timer.entry.cb = &send_response_callback; 890 timer.entry.user_data = r; 891 pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay); 847 892 848 893 } else if (method->id == PJSIP_ACK_METHOD) { … … 860 905 rdata); 861 906 862 timer.user_data = pjsip_tsx_layer_find_tsx(&key, PJ_FALSE);863 timer. id = 302;864 timer. cb = &terminate_tsx_callback;865 866 pjsip_endpt_schedule_timer(endpt, &timer , &delay);907 pj_strcpy(&timer.tsx_key, &key); 908 timer.entry.id = 302; 909 timer.entry.cb = &terminate_tsx_callback; 910 911 pjsip_endpt_schedule_timer(endpt, &timer.entry, &delay); 867 912 } 868 913 … … 981 1026 pjsip_tx_data_dec_ref(tdata); 982 1027 return test_complete; 983 } 984 985 /* Allow transaction to destroy itself */ 986 flush_events(500); 1028 1029 } else { 1030 pj_time_val now; 1031 1032 /* Allow transaction to destroy itself */ 1033 flush_events(500); 1034 1035 /* Wait until test completes */ 1036 pj_gettimeofday(&now); 1037 1038 if (PJ_TIME_VAL_LT(now, timeout)) { 1039 pj_time_val interval; 1040 interval = timeout; 1041 PJ_TIME_VAL_SUB(interval, now); 1042 flush_events(PJ_TIME_VAL_MSEC(interval)); 1043 } 1044 } 987 1045 988 1046 /* Make sure transaction has been destroyed. */ … … 1053 1111 1054 1112 /* Do the test. */ 1055 status = perform_tsx_test(-500, "sip:bob@127.0.0.1;transport=loop-dgram", 1056 "sip:alice@127.0.0.1;transport=loop-dgram", 1113 status = perform_tsx_test(-500, TARGET_URI, FROM_URI, 1057 1114 TEST1_BRANCH_ID, 1058 1115 35, sub_test[i].method); … … 1094 1151 1095 1152 status = perform_tsx_test(-800, 1096 "sip:bob@unresolved-host;transport=loop-dgram", 1097 "sip:alice@127.0.0.1;transport=loop-dgram", 1098 TEST2_BRANCH_ID, 10, 1153 "sip:bob@unresolved-host", 1154 FROM_URI, TEST2_BRANCH_ID, 10, 1099 1155 &pjsip_options_method); 1100 1156 if (status != 0) … … 1106 1162 PJ_LOG(3,(THIS_FILE, " variant b: error via callback")); 1107 1163 1108 /* Set loop transport to return delayed error. */ 1109 pjsip_loop_set_failure(loop, 2, NULL); 1110 pjsip_loop_set_send_callback_delay(loop, 10, NULL); 1111 1112 status = perform_tsx_test(-800, "sip:bob@127.0.0.1;transport=loop-dgram", 1113 "sip:alice@127.0.0.1;transport=loop-dgram", 1114 TEST2_BRANCH_ID, 2, 1115 &pjsip_options_method); 1116 if (status != 0) 1117 return status; 1118 1119 /* Restore loop transport settings. */ 1120 pjsip_loop_set_failure(loop, 0, NULL); 1121 pjsip_loop_set_send_callback_delay(loop, 0, NULL); 1164 /* This only applies to "loop-dgram" transport */ 1165 if (test_param->type == PJSIP_TRANSPORT_LOOP_DGRAM) { 1166 /* Set loop transport to return delayed error. */ 1167 pjsip_loop_set_failure(loop, 2, NULL); 1168 pjsip_loop_set_send_callback_delay(loop, 10, NULL); 1169 1170 status = perform_tsx_test(-800, TARGET_URI, FROM_URI, 1171 TEST2_BRANCH_ID, 2, 1172 &pjsip_options_method); 1173 if (status != 0) 1174 return status; 1175 1176 /* Restore loop transport settings. */ 1177 pjsip_loop_set_failure(loop, 0, NULL); 1178 pjsip_loop_set_send_callback_delay(loop, 0, NULL); 1179 } 1122 1180 1123 1181 return status; … … 1144 1202 1145 1203 /* Start the test. */ 1146 status = perform_tsx_test(-900, "sip:127.0.0.1;transport=loop-dgram", 1147 "sip:127.0.0.1;transport=loop-dgram", 1204 status = perform_tsx_test(-900, TARGET_URI, FROM_URI, 1148 1205 TEST3_BRANCH_ID, 2, &pjsip_options_method); 1149 1206 … … 1187 1244 1188 1245 /* Start the test. */ 1189 status = perform_tsx_test(-1000, "sip:127.0.0.1;transport=loop-dgram", 1190 "sip:127.0.0.1;transport=loop-dgram", 1246 status = perform_tsx_test(-1000, TARGET_URI, FROM_URI, 1191 1247 TEST4_BRANCH_ID, 6, &pjsip_options_method); 1192 1248 … … 1219 1275 1220 1276 /* Do the test. */ 1221 status = perform_tsx_test(-1100, "sip:bob@127.0.0.1;transport=loop-dgram", 1222 "sip:alice@127.0.0.1;transport=loop-dgram", 1277 status = perform_tsx_test(-1100, TARGET_URI, FROM_URI, 1223 1278 TEST5_BRANCH_ID, 1224 1279 6, &pjsip_options_method); … … 1250 1305 for (i=0; i<PJ_ARRAY_SIZE(delay); ++i) { 1251 1306 1252 PJ_LOG(3,(THIS_FILE, " variant %c: with %d ms transport delay", 1253 ('a'+i), delay[i])); 1254 1255 pjsip_loop_set_delay(loop, delay[i]); 1256 1257 status = perform_tsx_test(-1200, 1258 "sip:bob@127.0.0.1;transport=loop-dgram", 1259 "sip:alice@127.0.0.1;transport=loop-dgram", 1260 branch_id, 1261 10, method); 1307 if (test_param->type == PJSIP_TRANSPORT_LOOP_DGRAM) { 1308 PJ_LOG(3,(THIS_FILE, " variant %c: with %d ms transport delay", 1309 ('a'+i), delay[i])); 1310 1311 pjsip_loop_set_delay(loop, delay[i]); 1312 } 1313 1314 status = perform_tsx_test(-1200, TARGET_URI, FROM_URI, 1315 branch_id, 10, method); 1262 1316 if (status != 0) 1263 1317 return status; 1318 1319 if (test_param->type != PJSIP_TRANSPORT_LOOP_DGRAM) 1320 break; 1264 1321 } 1265 1322 … … 1277 1334 ***************************************************************************** 1278 1335 */ 1279 int tsx_uac_test( void)1336 int tsx_uac_test(struct tsx_test_param *param) 1280 1337 { 1281 1338 pj_sockaddr_in addr; 1282 1339 pj_status_t status; 1340 1341 timer.tsx_key.ptr = timer.key_buf; 1342 1343 test_param = param; 1344 1345 /* Get transport flag */ 1346 tp_flag = pjsip_transport_get_flag_from_type(test_param->type); 1347 1348 pj_ansi_sprintf(TARGET_URI, "sip:bob@127.0.0.1:%d;transport=%s", 1349 param->port, param->tp_type); 1350 pj_ansi_sprintf(FROM_URI, "sip:alice@127.0.0.1:%d;transport=%s", 1351 param->port, param->tp_type); 1283 1352 1284 1353 /* Check if loop transport is configured. */ … … 1317 1386 return status; 1318 1387 1319 /* TEST4_BRANCH_ID: Transport failed after several retransmissions */ 1320 status = tsx_retransmit_fail_test(); 1321 if (status != 0) 1322 return status; 1323 1324 /* TEST5_BRANCH_ID: Terminate transaction after several retransmissions */ 1325 status = tsx_terminate_after_retransmit_test(); 1326 if (status != 0) 1327 return status; 1388 /* TEST4_BRANCH_ID: Transport failed after several retransmissions. 1389 * Only applies to loop transport. 1390 */ 1391 if (test_param->type == PJSIP_TRANSPORT_LOOP_DGRAM) { 1392 status = tsx_retransmit_fail_test(); 1393 if (status != 0) 1394 return status; 1395 } 1396 1397 /* TEST5_BRANCH_ID: Terminate transaction after several retransmissions 1398 * Only applicable to non-reliable transports. 1399 */ 1400 if ((tp_flag & PJSIP_TRANSPORT_RELIABLE) == 0) { 1401 status = tsx_terminate_after_retransmit_test(); 1402 if (status != 0) 1403 return status; 1404 } 1328 1405 1329 1406 /* TEST6_BRANCH_ID: Successfull non-invite transaction */ … … 1353 1430 return status; 1354 1431 1355 1356 1432 pjsip_transport_dec_ref(loop); 1433 flush_events(500); 1434 1435 /* Unregister modules. */ 1436 status = pjsip_endpt_unregister_module(endpt, &tsx_user); 1437 if (status != PJ_SUCCESS) { 1438 app_perror(" Error: unable to unregister module", status); 1439 return -31; 1440 } 1441 status = pjsip_endpt_unregister_module(endpt, &msg_receiver); 1442 if (status != PJ_SUCCESS) { 1443 app_perror(" Error: unable to unregister module", status); 1444 return -41; 1445 } 1446 1357 1447 return 0; 1358 1448 } -
pjproject/trunk/pjsip/src/test-pjsip/tsx_uas_test.c
r555 r563 36 36 ** Test that non-INVITE transaction returns 2xx response to the correct 37 37 ** transport and correctly terminates the transaction. 38 ** This also checks that transaction is destroyed immediately after 39 ** it sends final response when reliable transport is used. 38 40 ** 39 41 ** TEST2_BRANCH_ID … … 54 56 ** TEST6_BRANCH_ID 55 57 ** As above, in COMPLETED state, with first sending provisional response. 58 ** (Only applicable for non-reliable transports). 56 59 ** 57 60 ** TEST7_BRANCH_ID … … 66 69 ** until it's terminated by user). 67 70 ** Transaction also MUST terminate in T4 seconds. 71 ** (Only applicable for non-reliable transports). 68 72 ** 69 73 ** TEST11_BRANCH_ID … … 129 133 130 134 135 static char TARGET_URI[128]; 136 static char FROM_URI[128]; 137 static struct tsx_test_param *test_param; 138 static unsigned tp_flag; 139 140 131 141 #define TEST_TIMEOUT_ERROR -30 132 142 #define MAX_ALLOWED_DIFF 150 … … 522 532 /* Check that status code is status_code. */ 523 533 if (tsx->status_code != TEST6_STATUS_CODE) { 524 PJ_LOG(3,(THIS_FILE, " error: incorrect status code")); 534 PJ_LOG(3,(THIS_FILE, " error: incorrect status code %d " 535 "(expecting %d)", tsx->status_code, 536 TEST6_STATUS_CODE)); 525 537 test_complete = -140; 526 538 } … … 576 588 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state")); 577 589 test_complete = -151; 590 } 591 592 /* Check the number of retransmissions */ 593 if (tp_flag & PJSIP_TRANSPORT_RELIABLE) { 594 595 if (tsx->retransmit_count != 0) { 596 PJ_LOG(3,(THIS_FILE, " error: should not retransmit")); 597 test_complete = -1510; 598 } 599 600 } else { 601 602 if (tsx->retransmit_count != 10) { 603 PJ_LOG(3,(THIS_FILE, 604 " error: incorrect retransmit count %d " 605 "(expecting 10)", 606 tsx->retransmit_count)); 607 test_complete = -1510; 608 } 609 578 610 } 579 611 … … 815 847 pjsip_transaction *tsx; 816 848 849 PJ_LOG(4,(THIS_FILE, " received request (probably retransmission)")); 850 817 851 status = pjsip_tsx_create_uas(&tsx_user, rdata, &tsx); 818 852 if (status != PJ_SUCCESS) { … … 831 865 832 866 } else if (pj_strcmp2(&branch_param, TEST6_BRANCH_ID) == 0) { 867 PJ_LOG(4,(THIS_FILE, " sending provisional response")); 833 868 send_response(rdata, tsx, TEST6_PROVISIONAL_CODE); 869 PJ_LOG(4,(THIS_FILE, " sending final response")); 834 870 send_response(rdata, tsx, TEST6_STATUS_CODE); 835 871 } … … 838 874 /* Verify the response received. */ 839 875 876 PJ_LOG(4,(THIS_FILE, " received response number %d", recv_count)); 877 840 878 ++recv_count; 841 879 … … 870 908 case 3: 871 909 if (code != TEST6_STATUS_CODE) { 872 PJ_LOG(3,(THIS_FILE, " error: invalid code!")); 910 PJ_LOG(3,(THIS_FILE, " error: invalid code %d " 911 "(expecting %d)", code, TEST6_STATUS_CODE)); 873 912 test_complete = -136; 874 913 } … … 1184 1223 1185 1224 /* (Re)Send the request. */ 1225 PJ_LOG(4,(THIS_FILE, " (re)sending request %d", sent_cnt)); 1226 1186 1227 status = pjsip_endpt_send_request_stateless(endpt, tdata, 0, 0); 1187 1228 if (status != PJ_SUCCESS) { … … 1256 1297 static int tsx_basic_final_response_test(void) 1257 1298 { 1299 unsigned duration; 1258 1300 int status; 1259 1301 1260 1302 PJ_LOG(3,(THIS_FILE," test1: basic sending 2xx final response")); 1261 1303 1262 status = perform_test("sip:129.0.0.1;transport=loop-dgram", 1263 "sip:129.0.0.1;transport=loop-dgram", 1264 TEST1_BRANCH_ID, 1265 33, /* Test duration must be greater than 32 secs */ 1266 &pjsip_options_method, 1, 0, 0); 1304 /* Test duration must be greater than 32 secs if unreliable transport 1305 * is used. 1306 */ 1307 duration = (tp_flag & PJSIP_TRANSPORT_RELIABLE) ? 1 : 33; 1308 1309 status = perform_test(TARGET_URI, FROM_URI, TEST1_BRANCH_ID, 1310 duration, &pjsip_options_method, 1, 0, 0); 1267 1311 if (status != 0) 1268 1312 return status; … … 1270 1314 PJ_LOG(3,(THIS_FILE," test2: basic sending non-2xx final response")); 1271 1315 1272 status = perform_test("sip:129.0.0.1;transport=loop-dgram", 1273 "sip:129.0.0.1;transport=loop-dgram", 1274 TEST2_BRANCH_ID, 1275 33, /* Test duration must be greater than 32 secs */ 1276 &pjsip_options_method, 1, 0, 0); 1316 status = perform_test(TARGET_URI, FROM_URI, TEST2_BRANCH_ID, 1317 duration, &pjsip_options_method, 1, 0, 0); 1277 1318 if (status != 0) 1278 1319 return status; … … 1290 1331 static int tsx_basic_provisional_response_test(void) 1291 1332 { 1333 unsigned duration; 1292 1334 int status; 1293 1335 1294 1336 PJ_LOG(3,(THIS_FILE," test3: basic sending 2xx final response")); 1295 1337 1296 status = perform_test("sip:129.0.0.1;transport=loop-dgram",1297 "sip:129.0.0.1;transport=loop-dgram", 1298 TEST3_BRANCH_ID, 1299 35,1338 duration = (tp_flag & PJSIP_TRANSPORT_RELIABLE) ? 1 : 33; 1339 duration += 2; 1340 1341 status = perform_test(TARGET_URI, FROM_URI, TEST3_BRANCH_ID, duration, 1300 1342 &pjsip_options_method, 1, 0, 0); 1301 1343 … … 1321 1363 PJ_LOG(3,(THIS_FILE," %s", title)); 1322 1364 1323 status = perform_test("sip:129.0.0.1;transport=loop-dgram", 1324 "sip:129.0.0.1;transport=loop-dgram", 1325 branch_id, 1326 5, 1365 status = perform_test(TARGET_URI, FROM_URI, branch_id, 5, 1327 1366 &pjsip_options_method, 1328 1367 request_cnt, 1000, 1); … … 1358 1397 " test7: INVITE non-2xx final response retransmission")); 1359 1398 1360 status = perform_test("sip:129.0.0.1;transport=loop-dgram", 1361 "sip:129.0.0.1;transport=loop-dgram", 1362 TEST7_BRANCH_ID, 1399 status = perform_test(TARGET_URI, FROM_URI, TEST7_BRANCH_ID, 1363 1400 33, /* Test duration must be greater than 32 secs */ 1364 1401 &pjsip_invite_method, 1, 0, 0); … … 1369 1406 " test8: INVITE 2xx final response retransmission")); 1370 1407 1371 status = perform_test("sip:129.0.0.1;transport=loop-dgram", 1372 "sip:129.0.0.1;transport=loop-dgram", 1373 TEST8_BRANCH_ID, 1408 status = perform_test(TARGET_URI, FROM_URI, TEST8_BRANCH_ID, 1374 1409 33, /* Test duration must be greater than 32 secs */ 1375 1410 &pjsip_invite_method, 1, 0, 0); … … 1395 1430 " test9: receiving ACK for non-2xx final response")); 1396 1431 1397 status = perform_test("sip:129.0.0.1;transport=loop-dgram", 1398 "sip:129.0.0.1;transport=loop-dgram", 1399 TEST9_BRANCH_ID, 1432 status = perform_test(TARGET_URI, FROM_URI, TEST9_BRANCH_ID, 1400 1433 20, /* allow 5 retransmissions */ 1401 1434 &pjsip_invite_method, 1, 0, 0); … … 1444 1477 pjsip_loop_set_delay(loop, tests[i].transport_delay); 1445 1478 1446 status = perform_test("sip:129.0.0.1;transport=loop-dgram", 1447 "sip:129.0.0.1;transport=loop-dgram", 1448 tests[i].branch_id, 1449 0, 1450 &pjsip_invite_method, 1, 0, 1); 1479 status = perform_test(TARGET_URI, FROM_URI, tests[i].branch_id, 1480 0, &pjsip_invite_method, 1, 0, 1); 1451 1481 if (status && status != TEST_TIMEOUT_ERROR) 1452 1482 return status; … … 1495 1525 ***************************************************************************** 1496 1526 */ 1497 int tsx_uas_test( void)1527 int tsx_uas_test(struct tsx_test_param *param) 1498 1528 { 1499 1529 pj_sockaddr_in addr; 1500 1530 pj_status_t status; 1531 1532 test_param = param; 1533 tp_flag = pjsip_transport_get_flag_from_type(param->type); 1534 1535 pj_ansi_sprintf(TARGET_URI, "sip:bob@127.0.0.1:%d;transport=%s", 1536 param->port, param->tp_type); 1537 pj_ansi_sprintf(FROM_URI, "sip:alice@127.0.0.1:%d;transport=%s", 1538 param->port, param->tp_type); 1501 1539 1502 1540 /* Check if loop transport is configured. */ … … 1505 1543 if (status != PJ_SUCCESS) { 1506 1544 PJ_LOG(3,(THIS_FILE, " Error: loop transport is not configured!")); 1507 return -1; 1508 } 1509 1545 return -10; 1546 } 1510 1547 /* Register modules. */ 1511 1548 status = pjsip_endpt_register_module(endpt, &tsx_user); … … 1551 1588 return status; 1552 1589 1553 /* TEST6_BRANCH_ID: retransmit last response in PROCEEDING state 1590 /* TEST6_BRANCH_ID: retransmit last response in COMPLETED state 1591 * This only applies to non-reliable transports, 1592 * since UAS transaction is destroyed as soon 1593 * as final response is sent for reliable transports. 1554 1594 */ 1555 status = tsx_retransmit_last_response_test(TEST6_TITLE, 1556 TEST6_BRANCH_ID, 1557 TEST6_REQUEST_COUNT, 1558 TEST6_STATUS_CODE); 1559 if (status != 0) 1560 return status; 1595 if ((tp_flag & PJSIP_TRANSPORT_RELIABLE) == 0) { 1596 status = tsx_retransmit_last_response_test(TEST6_TITLE, 1597 TEST6_BRANCH_ID, 1598 TEST6_REQUEST_COUNT, 1599 TEST6_STATUS_CODE); 1600 if (status != 0) 1601 return status; 1602 } 1561 1603 1562 1604 /* TEST7_BRANCH_ID: INVITE non-2xx final response retransmission test 1563 1605 * TEST8_BRANCH_ID: INVITE 2xx final response retransmission test 1564 1606 */ 1565 1566 1607 status = tsx_final_response_retransmission_test(); 1567 1608 if (status != 0) … … 1570 1611 /* TEST9_BRANCH_ID: retransmission of non-2xx INVITE final response must 1571 1612 * cease when ACK is received 1613 * Only applicable for non-reliable transports. 1572 1614 */ 1573 status = tsx_ack_test(); 1574 if (status != 0) 1575 return status; 1615 if ((tp_flag & PJSIP_TRANSPORT_RELIABLE) == 0) { 1616 status = tsx_ack_test(); 1617 if (status != 0) 1618 return status; 1619 } 1620 1576 1621 1577 1622 /* TEST10_BRANCH_ID: test transport failure in TRYING state. … … 1580 1625 * TEST13_BRANCH_ID: test transport failure in CONFIRMED state. 1581 1626 */ 1582 status = tsx_transport_failure_test(); 1583 if (status != 0) 1584 return status; 1585 1586 1587 pjsip_transport_dec_ref(loop); 1627 /* Only valid for loop-dgram */ 1628 if (param->type == PJSIP_TRANSPORT_LOOP_DGRAM) { 1629 status = tsx_transport_failure_test(); 1630 if (status != 0) 1631 return status; 1632 } 1633 1634 1635 /* Register modules. */ 1636 status = pjsip_endpt_unregister_module(endpt, &tsx_user); 1637 if (status != PJ_SUCCESS) { 1638 app_perror(" Error: unable to unregister module", status); 1639 return -8; 1640 } 1641 status = pjsip_endpt_unregister_module(endpt, &msg_sender); 1642 if (status != PJ_SUCCESS) { 1643 app_perror(" Error: unable to unregister module", status); 1644 return -9; 1645 } 1646 1647 1648 if (loop) 1649 pjsip_transport_dec_ref(loop); 1650 1588 1651 return 0; 1589 1590 1652 } 1591 1653 -
pjproject/trunk/pjsip/src/test-pjsip/txdata_test.c
r127 r563 22 22 #include <pjlib.h> 23 23 24 25 #define THIS_FILE "txdata_test.c" 26 27 24 28 #define HFIND(msg,h,H) ((pjsip_##h##_hdr*) pjsip_msg_find_hdr(msg, PJSIP_H_##H, NULL)) 25 29 26 #define THIS_FILE "txdata_test.c" 30 #if defined(PJ_DEBUG) && PJ_DEBUG!=0 31 # define LOOP 10000 32 #else 33 # define LOOP 100000 34 #endif 27 35 28 36 … … 323 331 return 0; 324 332 } 333 334 335 336 /* 337 * This test demonstrate the bug as reported in: 338 * http://bugzilla.pjproject.net/show_bug.cgi?id=49 339 */ 340 static int gcc_test() 341 { 342 char msgbuf[512]; 343 pj_str_t target = pj_str("sip:alice@wonderland:5061;x-param=param%201" 344 "?X-Hdr-1=Header%201" 345 "&X-Empty-Hdr="); 346 pjsip_tx_data *tdata; 347 pjsip_parser_err_report err_list; 348 pjsip_msg *msg; 349 int len; 350 pj_status_t status; 351 352 PJ_LOG(3,(THIS_FILE, " header param in URI to create request")); 353 354 /* Create request with header param in target URI. */ 355 status = pjsip_endpt_create_request(endpt, &pjsip_invite_method, &target, 356 &target, &target, &target, NULL, -1, 357 NULL, &tdata); 358 if (status != 0) { 359 app_perror(" error: Unable to create request", status); 360 return -200; 361 } 362 363 /* Print and parse the request. 364 * We'll check that header params are not present in 365 */ 366 len = pjsip_msg_print(tdata->msg, msgbuf, sizeof(msgbuf)); 367 if (len < 1) { 368 PJ_LOG(3,(THIS_FILE, " error: printing message")); 369 pjsip_tx_data_dec_ref(tdata); 370 return -250; 371 } 372 msgbuf[len] = '\0'; 373 374 PJ_LOG(5,(THIS_FILE, "%d bytes request created:--begin-msg--\n" 375 "%s\n" 376 "--end-msg--", len, msgbuf)); 377 378 /* Now parse the message. */ 379 pj_list_init(&err_list); 380 msg = pjsip_parse_msg( tdata->pool, msgbuf, len, &err_list); 381 if (msg == NULL) { 382 pjsip_parser_err_report *e; 383 384 PJ_LOG(3,(THIS_FILE, " error: parsing message message")); 385 386 e = err_list.next; 387 while (e != &err_list) { 388 PJ_LOG(3,(THIS_FILE, " %s in line %d col %d hname=%.*s", 389 pj_exception_id_name(e->except_code), 390 e->line, e->col+1, 391 (int)e->hname.slen, 392 e->hname.ptr)); 393 e = e->next; 394 } 395 396 pjsip_tx_data_dec_ref(tdata); 397 return -255; 398 } 399 400 pjsip_tx_data_dec_ref(tdata); 401 return 0; 402 } 403 325 404 326 405 /* This tests the request creating functions against the following … … 346 425 pjsip_sip_uri *uri; 347 426 pjsip_param *param; 427 pjsip_via_hdr *via; 428 pjsip_parser_err_report err_list; 348 429 pjsip_msg *msg; 349 430 int len; … … 361 442 } 362 443 444 /* Fill up the Via header to prevent syntax error on parsing */ 445 via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL); 446 via->transport = pj_str("TCP"); 447 via->sent_by.host = pj_str("127.0.0.1"); 448 363 449 /* Print and parse the request. 364 450 * We'll check that header params are not present in … … 377 463 378 464 /* Now parse the message. */ 379 msg = pjsip_parse_msg( tdata->pool, msgbuf, len, NULL); 465 pj_list_init(&err_list); 466 msg = pjsip_parse_msg( tdata->pool, msgbuf, len, &err_list); 380 467 if (msg == NULL) { 381 app_perror(" error: parsing message message", status); 382 pjsip_tx_data_dec_ref(tdata); 383 return -250; 468 pjsip_parser_err_report *e; 469 470 PJ_LOG(3,(THIS_FILE, " error: parsing message message")); 471 472 e = err_list.next; 473 while (e != &err_list) { 474 PJ_LOG(3,(THIS_FILE, " %s in line %d col %d hname=%.*s", 475 pj_exception_id_name(e->except_code), 476 e->line, e->col+1, 477 (int)e->hname.slen, 478 e->hname.ptr)); 479 e = e->next; 480 } 481 482 pjsip_tx_data_dec_ref(tdata); 483 return -256; 384 484 } 385 485 … … 513 613 } 514 614 615 616 /* 617 * create request benchmark 618 */ 619 static int create_request_bench(pj_timestamp *p_elapsed) 620 { 621 enum { COUNT = 100 }; 622 unsigned i, j; 623 pjsip_tx_data *tdata[COUNT]; 624 pj_timestamp t1, t2, elapsed; 625 pj_status_t status; 626 627 pj_str_t str_target = pj_str("sip:someuser@someprovider.com"); 628 pj_str_t str_from = pj_str("\"Local User\" <sip:localuser@serviceprovider.com>"); 629 pj_str_t str_to = pj_str("\"Remote User\" <sip:remoteuser@serviceprovider.com>"); 630 pj_str_t str_contact = str_from; 631 632 elapsed.u64 = 0; 633 634 for (i=0; i<LOOP; i+=COUNT) { 635 pj_memset(tdata, 0, sizeof(tdata)); 636 637 pj_get_timestamp(&t1); 638 639 for (j=0; j<COUNT; ++j) { 640 status = pjsip_endpt_create_request(endpt, &pjsip_invite_method, 641 &str_target, &str_from, &str_to, 642 &str_contact, NULL, -1, NULL, 643 &tdata[j]); 644 if (status != PJ_SUCCESS) { 645 app_perror(" error: unable to create request", status); 646 goto on_error; 647 } 648 } 649 650 pj_get_timestamp(&t2); 651 pj_sub_timestamp(&t2, &t1); 652 pj_add_timestamp(&elapsed, &t2); 653 654 for (j=0; j<COUNT; ++j) 655 pjsip_tx_data_dec_ref(tdata[j]); 656 } 657 658 p_elapsed->u64 = elapsed.u64; 659 return PJ_SUCCESS; 660 661 on_error: 662 for (i=0; i<COUNT; ++i) { 663 if (tdata[i]) 664 pjsip_tx_data_dec_ref(tdata[i]); 665 } 666 return -400; 667 } 668 669 670 671 /* 672 * create response benchmark 673 */ 674 static int create_response_bench(pj_timestamp *p_elapsed) 675 { 676 enum { COUNT = 100 }; 677 unsigned i, j; 678 pjsip_via_hdr *via; 679 pjsip_rx_data rdata; 680 pjsip_tx_data *request; 681 pjsip_tx_data *tdata[COUNT]; 682 pj_timestamp t1, t2, elapsed; 683 pj_status_t status; 684 685 /* Create the request first. */ 686 pj_str_t str_target = pj_str("sip:someuser@someprovider.com"); 687 pj_str_t str_from = pj_str("\"Local User\" <sip:localuser@serviceprovider.com>"); 688 pj_str_t str_to = pj_str("\"Remote User\" <sip:remoteuser@serviceprovider.com>"); 689 pj_str_t str_contact = str_from; 690 691 status = pjsip_endpt_create_request(endpt, &pjsip_invite_method, 692 &str_target, &str_from, &str_to, 693 &str_contact, NULL, -1, NULL, 694 &request); 695 if (status != PJ_SUCCESS) { 696 app_perror(" error: unable to create request", status); 697 return status; 698 } 699 700 /* Create several Via headers */ 701 via = pjsip_via_hdr_create(request->pool); 702 via->sent_by.host = pj_str("192.168.0.7"); 703 via->sent_by.port = 5061; 704 via->transport = pj_str("udp"); 705 via->rport_param = 0; 706 via->branch_param = pj_str("012345678901234567890123456789"); 707 via->recvd_param = pj_str("192.168.0.7"); 708 pjsip_msg_insert_first_hdr(request->msg, pjsip_hdr_clone(request->pool, via)); 709 pjsip_msg_insert_first_hdr(request->msg, pjsip_hdr_clone(request->pool, via)); 710 pjsip_msg_insert_first_hdr(request->msg, (pjsip_hdr*)via); 711 712 713 /* Create "dummy" rdata from the tdata */ 714 pj_memset(&rdata, 0, sizeof(pjsip_rx_data)); 715 rdata.tp_info.pool = request->pool; 716 rdata.msg_info.msg = request->msg; 717 rdata.msg_info.from = pjsip_msg_find_hdr(request->msg, PJSIP_H_FROM, NULL); 718 rdata.msg_info.to = pjsip_msg_find_hdr(request->msg, PJSIP_H_TO, NULL); 719 rdata.msg_info.cseq = pjsip_msg_find_hdr(request->msg, PJSIP_H_CSEQ, NULL); 720 rdata.msg_info.cid = pjsip_msg_find_hdr(request->msg, PJSIP_H_FROM, NULL); 721 rdata.msg_info.via = via; 722 723 /* 724 * Now benchmark create_response 725 */ 726 elapsed.u64 = 0; 727 728 for (i=0; i<LOOP; i+=COUNT) { 729 pj_memset(tdata, 0, sizeof(tdata)); 730 731 pj_get_timestamp(&t1); 732 733 for (j=0; j<COUNT; ++j) { 734 status = pjsip_endpt_create_response(endpt, &rdata, 200, NULL, &tdata[j]); 735 if (status != PJ_SUCCESS) { 736 app_perror(" error: unable to create request", status); 737 goto on_error; 738 } 739 } 740 741 pj_get_timestamp(&t2); 742 pj_sub_timestamp(&t2, &t1); 743 pj_add_timestamp(&elapsed, &t2); 744 745 for (j=0; j<COUNT; ++j) 746 pjsip_tx_data_dec_ref(tdata[j]); 747 } 748 749 p_elapsed->u64 = elapsed.u64; 750 pjsip_tx_data_dec_ref(request); 751 return PJ_SUCCESS; 752 753 on_error: 754 for (i=0; i<COUNT; ++i) { 755 if (tdata[i]) 756 pjsip_tx_data_dec_ref(tdata[i]); 757 } 758 return -400; 759 } 760 761 515 762 int txdata_test(void) 516 763 { 764 enum { REPEAT = 4 }; 765 unsigned i, msgs; 766 pj_timestamp usec[REPEAT], min, freq; 517 767 int status; 768 769 status = pj_get_timestamp_freq(&freq); 770 if (status != PJ_SUCCESS) 771 return status; 518 772 519 773 status = core_txdata_test(); … … 521 775 return status; 522 776 777 #if INCLUDE_GCC_TEST 778 status = gcc_test(); 779 if (status != 0) 780 return status; 781 #endif 523 782 524 783 status = txdata_test_uri_params(); … … 526 785 return status; 527 786 787 788 /* 789 * Benchmark create_request() 790 */ 791 PJ_LOG(3,(THIS_FILE, " benchmarking request creation:")); 792 for (i=0; i<REPEAT; ++i) { 793 PJ_LOG(3,(THIS_FILE, " test %d of %d..", 794 i+1, REPEAT)); 795 status = create_request_bench(&usec[i]); 796 if (status != PJ_SUCCESS) 797 return status; 798 } 799 800 min.u64 = PJ_UINT64(0xFFFFFFFFFFFFFFF); 801 for (i=0; i<REPEAT; ++i) { 802 if (usec[i].u64 < min.u64) min.u64 = usec[i].u64; 803 } 804 805 msgs = (unsigned)(freq.u64 * LOOP / min.u64); 806 807 PJ_LOG(3,(THIS_FILE, " Requests created at %d requests/sec", msgs)); 808 809 report_ival("create-request-per-sec", 810 msgs, "msg/sec", 811 "Number of typical request messages that can be created " 812 "per second with <tt>pjsip_endpt_create_request()</tt>"); 813 814 815 /* 816 * Benchmark create_response() 817 */ 818 PJ_LOG(3,(THIS_FILE, " benchmarking response creation:")); 819 for (i=0; i<REPEAT; ++i) { 820 PJ_LOG(3,(THIS_FILE, " test %d of %d..", 821 i+1, REPEAT)); 822 status = create_response_bench(&usec[i]); 823 if (status != PJ_SUCCESS) 824 return status; 825 } 826 827 min.u64 = PJ_UINT64(0xFFFFFFFFFFFFFFF); 828 for (i=0; i<REPEAT; ++i) { 829 if (usec[i].u64 < min.u64) min.u64 = usec[i].u64; 830 } 831 832 msgs = (unsigned)(freq.u64 * LOOP / min.u64); 833 834 PJ_LOG(3,(THIS_FILE, " Responses created at %d responses/sec", msgs)); 835 836 report_ival("create-response-per-sec", 837 msgs, "msg/sec", 838 "Number of typical response messages that can be created " 839 "per second with <tt>pjsip_endpt_create_response()</tt>"); 840 841 528 842 return 0; 529 843 } 844 -
pjproject/trunk/pjsip/src/test-pjsip/uri_test.c
r127 r563 33 33 34 34 #define POOL_SIZE 8000 35 #define LOOP_COUNT 10000 35 #if defined(PJ_DEBUG) && PJ_DEBUG!=0 36 # define LOOP_COUNT 10000 37 #else 38 # define LOOP_COUNT 40000 39 #endif 36 40 #define AVERAGE_URL_LEN 80 37 41 #define THREAD_COUNT 4 38 42 39 static pj_highprec_t parse_len, print_len, cmp_len; 40 static pj_timestamp parse_time, print_time, cmp_time; 43 static struct 44 { 45 pj_highprec_t parse_len, print_len, cmp_len; 46 pj_timestamp parse_time, print_time, cmp_time; 47 } var; 41 48 42 49 … … 687 694 /* Parse URI text. */ 688 695 pj_get_timestamp(&t1); 689 parse_len =parse_len + entry->len;696 var.parse_len = var.parse_len + entry->len; 690 697 parsed_uri = pjsip_parse_uri(pool, entry->str, entry->len, 0); 691 698 if (!parsed_uri) { … … 703 710 pj_get_timestamp(&t2); 704 711 pj_sub_timestamp(&t2, &t1); 705 pj_add_timestamp(& parse_time, &t2);712 pj_add_timestamp(&var.parse_time, &t2); 706 713 707 714 /* Create the reference URI. */ … … 721 728 s1.slen = len; 722 729 723 print_len =print_len + len;730 var.print_len = var.print_len + len; 724 731 pj_get_timestamp(&t2); 725 732 pj_sub_timestamp(&t2, &t1); 726 pj_add_timestamp(& print_time, &t2);733 pj_add_timestamp(&var.print_time, &t2); 727 734 728 735 len = pjsip_uri_print( PJSIP_URI_IN_OTHER, ref_uri, s2.ptr, PJSIP_MAX_URL_SIZE); … … 756 763 } 757 764 758 cmp_len =cmp_len + len;765 var.cmp_len = var.cmp_len + len; 759 766 pj_get_timestamp(&t2); 760 767 pj_sub_timestamp(&t2, &t1); 761 pj_add_timestamp(& cmp_time, &t2);768 pj_add_timestamp(&var.cmp_time, &t2); 762 769 763 770 /* Compare text. */ … … 786 793 } 787 794 788 int uri_test() 789 { 790 unsigned i, loop; 795 796 static int simple_uri_test(void) 797 { 798 unsigned i; 791 799 pj_pool_t *pool; 792 800 pj_status_t status; 793 pj_timestamp zero;794 pj_time_val elapsed;795 pj_highprec_t avg_parse, avg_print, avg_cmp, kbytes;796 797 zero.u32.hi = zero.u32.lo = 0;798 801 799 802 PJ_LOG(3,(THIS_FILE, " simple test")); … … 804 807 PJ_LOG(3,(THIS_FILE, " error %d when testing entry %d", 805 808 status, i)); 806 goto on_return;809 return status; 807 810 } 808 811 } 809 812 pjsip_endpt_release_pool(endpt, pool); 810 813 811 PJ_LOG(3,(THIS_FILE, " benchmarking...")); 812 parse_len = print_len = cmp_len = 0; 813 parse_time.u32.hi = parse_time.u32.lo = 0; 814 print_time.u32.hi = print_time.u32.lo = 0; 815 cmp_time.u32.hi = cmp_time.u32.lo = 0; 814 return 0; 815 } 816 817 static int uri_benchmark(unsigned *p_parse, unsigned *p_print, unsigned *p_cmp) 818 { 819 unsigned i, loop; 820 pj_pool_t *pool; 821 pj_status_t status; 822 pj_timestamp zero; 823 pj_time_val elapsed; 824 pj_highprec_t avg_parse, avg_print, avg_cmp, kbytes; 825 826 pj_memset(&var, 0, sizeof(var)); 827 828 zero.u32.hi = zero.u32.lo = 0; 829 830 var.parse_len = var.print_len = var.cmp_len = 0; 831 var.parse_time.u32.hi = var.parse_time.u32.lo = 0; 832 var.print_time.u32.hi = var.print_time.u32.lo = 0; 833 var.cmp_time.u32.hi = var.cmp_time.u32.lo = 0; 816 834 for (loop=0; loop<LOOP_COUNT; ++loop) { 817 835 pool = pjsip_endpt_create_pool(endpt, "", POOL_SIZE, POOL_SIZE); … … 828 846 } 829 847 830 kbytes = parse_len;848 kbytes = var.parse_len; 831 849 pj_highprec_mod(kbytes, 1000000); 832 850 pj_highprec_div(kbytes, 100000); 833 elapsed = pj_elapsed_time(&zero, & parse_time);834 avg_parse = pj_elapsed_usec(&zero, & parse_time);851 elapsed = pj_elapsed_time(&zero, &var.parse_time); 852 avg_parse = pj_elapsed_usec(&zero, &var.parse_time); 835 853 pj_highprec_mul(avg_parse, AVERAGE_URL_LEN); 836 pj_highprec_div(avg_parse, parse_len);854 pj_highprec_div(avg_parse, var.parse_len); 837 855 avg_parse = 1000000 / avg_parse; 838 856 839 857 PJ_LOG(3,(THIS_FILE, 840 858 " %u.%u MB of urls parsed in %d.%03ds (avg=%d urls/sec)", 841 (unsigned)( parse_len/1000000), (unsigned)kbytes,859 (unsigned)(var.parse_len/1000000), (unsigned)kbytes, 842 860 elapsed.sec, elapsed.msec, 843 861 (unsigned)avg_parse)); 844 862 845 kbytes = print_len; 863 *p_parse = (unsigned)avg_parse; 864 865 kbytes = var.print_len; 846 866 pj_highprec_mod(kbytes, 1000000); 847 867 pj_highprec_div(kbytes, 100000); 848 elapsed = pj_elapsed_time(&zero, & print_time);849 avg_print = pj_elapsed_usec(&zero, & print_time);868 elapsed = pj_elapsed_time(&zero, &var.print_time); 869 avg_print = pj_elapsed_usec(&zero, &var.print_time); 850 870 pj_highprec_mul(avg_print, AVERAGE_URL_LEN); 851 pj_highprec_div(avg_print, parse_len);871 pj_highprec_div(avg_print, var.parse_len); 852 872 avg_print = 1000000 / avg_print; 853 873 854 874 PJ_LOG(3,(THIS_FILE, 855 875 " %u.%u MB of urls printed in %d.%03ds (avg=%d urls/sec)", 856 (unsigned)( print_len/1000000), (unsigned)kbytes,876 (unsigned)(var.print_len/1000000), (unsigned)kbytes, 857 877 elapsed.sec, elapsed.msec, 858 878 (unsigned)avg_print)); 859 879 860 kbytes = cmp_len; 880 *p_print = (unsigned)avg_print; 881 882 kbytes = var.cmp_len; 861 883 pj_highprec_mod(kbytes, 1000000); 862 884 pj_highprec_div(kbytes, 100000); 863 elapsed = pj_elapsed_time(&zero, & cmp_time);864 avg_cmp = pj_elapsed_usec(&zero, & cmp_time);885 elapsed = pj_elapsed_time(&zero, &var.cmp_time); 886 avg_cmp = pj_elapsed_usec(&zero, &var.cmp_time); 865 887 pj_highprec_mul(avg_cmp, AVERAGE_URL_LEN); 866 pj_highprec_div(avg_cmp, cmp_len);888 pj_highprec_div(avg_cmp, var.cmp_len); 867 889 avg_cmp = 1000000 / avg_cmp; 868 890 869 891 PJ_LOG(3,(THIS_FILE, 870 892 " %u.%u MB of urls compared in %d.%03ds (avg=%d urls/sec)", 871 (unsigned)( cmp_len/1000000), (unsigned)kbytes,893 (unsigned)(var.cmp_len/1000000), (unsigned)kbytes, 872 894 elapsed.sec, elapsed.msec, 873 895 (unsigned)avg_cmp)); 874 896 875 PJ_LOG(3,(THIS_FILE, " multithreaded test")); 876 897 *p_cmp = (unsigned)avg_cmp; 877 898 878 899 on_return: … … 880 901 } 881 902 903 904 /*****************************************************************************/ 905 906 int uri_test(void) 907 { 908 enum { COUNT = 4, DETECT=0, PARSE=1, PRINT=2 }; 909 struct { 910 unsigned parse; 911 unsigned print; 912 unsigned cmp; 913 } run[COUNT]; 914 unsigned i, max, avg_len; 915 char desc[200]; 916 pj_status_t status; 917 918 status = simple_uri_test(); 919 if (status != PJ_SUCCESS) 920 return status; 921 922 for (i=0; i<COUNT; ++i) { 923 PJ_LOG(3,(THIS_FILE, " benchmarking (%d of %d)...", i+1, COUNT)); 924 status = uri_benchmark(&run[i].parse, &run[i].print, &run[i].cmp); 925 if (status != PJ_SUCCESS) 926 return status; 927 } 928 929 /* Calculate average URI length */ 930 for (i=0, avg_len=0; i<PJ_ARRAY_SIZE(uri_test_array); ++i) { 931 avg_len += uri_test_array[i].len; 932 } 933 avg_len /= PJ_ARRAY_SIZE(uri_test_array); 934 935 936 /* 937 * Print maximum parse/sec 938 */ 939 for (i=0, max=0; i<COUNT; ++i) 940 if (run[i].parse > max) max = run[i].parse; 941 942 PJ_LOG(3,("", " Maximum URI parse/sec=%u", max)); 943 944 pj_ansi_sprintf(desc, "Number of SIP/TEL URIs that can be <B>parsed</B> with " 945 "<tt>pjsip_parse_uri()</tt> per second " 946 "(tested with %d URI set, with average length of " 947 "%d chars)", 948 PJ_ARRAY_SIZE(uri_test_array), avg_len); 949 950 report_ival("uri-parse-per-sec", max, "URI/sec", desc); 951 952 /* URI parsing bandwidth */ 953 report_ival("uri-parse-bandwidth-mb", avg_len*max/1000000, "MB/sec", 954 "URI parsing bandwidth in megabytes (number of megabytes " 955 "worth of URI that can be parsed per second)"); 956 957 958 /* Print maximum print/sec */ 959 for (i=0, max=0; i<COUNT; ++i) 960 if (run[i].print > max) max = run[i].print; 961 962 PJ_LOG(3,("", " Maximum URI print/sec=%u", max)); 963 964 pj_ansi_sprintf(desc, "Number of SIP/TEL URIs that can be <B>printed</B> with " 965 "<tt>pjsip_uri_print()</tt> per second " 966 "(tested with %d URI set, with average length of " 967 "%d chars)", 968 PJ_ARRAY_SIZE(uri_test_array), avg_len); 969 970 report_ival("uri-print-per-sec", max, "URI/sec", desc); 971 972 /* Print maximum detect/sec */ 973 for (i=0, max=0; i<COUNT; ++i) 974 if (run[i].cmp > max) max = run[i].cmp; 975 976 PJ_LOG(3,("", " Maximum URI comparison/sec=%u", max)); 977 978 pj_ansi_sprintf(desc, "Number of SIP/TEL URIs that can be <B>compared</B> with " 979 "<tt>pjsip_uri_cmp()</tt> per second " 980 "(tested with %d URI set, with average length of " 981 "%d chars)", 982 PJ_ARRAY_SIZE(uri_test_array), avg_len); 983 984 report_ival("uri-cmp-per-sec", max, "URI/sec", desc); 985 986 return PJ_SUCCESS; 987 } 988
Note: See TracChangeset
for help on using the changeset viewer.