- Timestamp:
- Apr 2, 2007 11:23:09 AM (18 years ago)
- Location:
- pjproject/branches/pjproject-0.5-stable/pjsip-apps/src/samples
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/pjproject-0.5-stable/pjsip-apps/src/samples/proxy.h
r1121 r1123 54 54 puts("Options:\n" 55 55 "\n" 56 " -p, --port N Set local listener port to N\n" 57 " -R, --rr Perform record routing\n" 58 " -h, --help Show this help screen\n" 56 " --port N Set local listener port to N\n" 57 " --rr Perform record routing\n" 58 " --log-level N Set log level to N (default: 4)\n" 59 " --help Show this help screen\n" 59 60 ); 60 61 } … … 64 65 { 65 66 struct pj_getopt_option long_opt[] = { 66 { "port",1, 0, 'p'}, 67 { "rr", 1, 0, 'R'}, 68 { "help",1, 0, 'h'}, 67 { "port", 1, 0, 'p'}, 68 { "rr", 0, 0, 'R'}, 69 { "log-level", 1, 0, 'L'}, 70 { "help", 0, 0, 'h'}, 69 71 }; 70 72 int c; … … 72 74 73 75 pj_optind = 0; 74 while((c=pj_getopt_long(argc, argv, " pRh", long_opt, &opt_ind))!=-1) {76 while((c=pj_getopt_long(argc, argv, "", long_opt, &opt_ind))!=-1) { 75 77 switch (c) { 76 78 case 'p': … … 84 86 break; 85 87 88 case 'L': 89 pj_log_set_level(atoi(pj_optarg)); 90 break; 91 86 92 case 'h': 87 93 usage(); … … 89 95 90 96 default: 91 puts("Unknown option ignored");92 break;97 puts("Unknown option. Run with --help for help."); 98 return -1; 93 99 } 94 100 } … … 96 102 return PJ_SUCCESS; 97 103 } 104 105 106 /***************************************************************************** 107 * This is a very simple PJSIP module, whose sole purpose is to display 108 * incoming and outgoing messages to log. This module will have priority 109 * higher than transport layer, which means: 110 * 111 * - incoming messages will come to this module first before reaching 112 * transaction layer. 113 * 114 * - outgoing messages will come to this module last, after the message 115 * has been 'printed' to contiguous buffer by transport layer and 116 * appropriate transport instance has been decided for this message. 117 * 118 */ 119 120 /* Notification on incoming messages */ 121 static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata) 122 { 123 PJ_LOG(5,(THIS_FILE, "RX %d bytes %s from %s %s:%d:\n" 124 "%.*s\n" 125 "--end msg--", 126 rdata->msg_info.len, 127 pjsip_rx_data_get_info(rdata), 128 rdata->tp_info.transport->type_name, 129 rdata->pkt_info.src_name, 130 rdata->pkt_info.src_port, 131 (int)rdata->msg_info.len, 132 rdata->msg_info.msg_buf)); 133 134 /* Always return false, otherwise messages will not get processed! */ 135 return PJ_FALSE; 136 } 137 138 /* Notification on outgoing messages */ 139 static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata) 140 { 141 142 /* Important note: 143 * tp_info field is only valid after outgoing messages has passed 144 * transport layer. So don't try to access tp_info when the module 145 * has lower priority than transport layer. 146 */ 147 148 PJ_LOG(5,(THIS_FILE, "TX %d bytes %s to %s %s:%d:\n" 149 "%.*s\n" 150 "--end msg--", 151 (tdata->buf.cur - tdata->buf.start), 152 pjsip_tx_data_get_info(tdata), 153 tdata->tp_info.transport->type_name, 154 tdata->tp_info.dst_name, 155 tdata->tp_info.dst_port, 156 (int)(tdata->buf.cur - tdata->buf.start), 157 tdata->buf.start)); 158 159 /* Always return success, otherwise message will not get sent! */ 160 return PJ_SUCCESS; 161 } 162 163 /* The module instance. */ 164 static pjsip_module mod_msg_logger = 165 { 166 NULL, NULL, /* prev, next. */ 167 { "mod-msg-logger", 14 }, /* Name. */ 168 -1, /* Id */ 169 PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority */ 170 NULL, /* load() */ 171 NULL, /* start() */ 172 NULL, /* stop() */ 173 NULL, /* unload() */ 174 &logging_on_rx_msg, /* on_rx_request() */ 175 &logging_on_rx_msg, /* on_rx_response() */ 176 &logging_on_tx_msg, /* on_tx_request. */ 177 &logging_on_tx_msg, /* on_tx_response() */ 178 NULL, /* on_tsx_state() */ 179 180 }; 98 181 99 182 … … 142 225 global.pool = pj_pool_create(&global.cp.factory, "proxyapp", 143 226 4000, 4000, NULL); 227 228 /* Register the logger module */ 229 pjsip_endpt_register_module(global.endpt, &mod_msg_logger); 144 230 145 231 return PJ_SUCCESS; … … 413 499 414 500 /* We're not interested to receive request destined to us, so 415 * respond with 404/Not Found. 416 */ 417 pjsip_endpt_respond_stateless(global.endpt, rdata, 418 PJSIP_SC_NOT_FOUND, NULL, 419 NULL, NULL); 501 * respond with 404/Not Found (only if request is not ACK!). 502 */ 503 if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) { 504 pjsip_endpt_respond_stateless(global.endpt, rdata, 505 PJSIP_SC_NOT_FOUND, NULL, 506 NULL, NULL); 507 } 420 508 421 509 /* Delete the request since we're not forwarding it */ -
pjproject/branches/pjproject-0.5-stable/pjsip-apps/src/samples/stateful_proxy.c
r1121 r1123 24 24 25 25 26 /* Callback to be called to handle incoming requests. */ 27 static pj_bool_t on_rx_request( pjsip_rx_data *rdata ); 28 29 /* Callback to be called to handle incoming response. */ 30 static pj_bool_t on_rx_response( pjsip_rx_data *rdata ); 31 32 33 /* This is the data that is attached to the UAC transaction */ 34 struct tsx_data 35 { 36 pjsip_transaction *uas_tsx; 37 pj_timer_entry timer; 38 }; 39 26 /* 27 * mod_stateful_proxy is the module to receive SIP request and 28 * response message that is outside any transaction context. 29 */ 30 static pj_bool_t proxy_on_rx_request(pjsip_rx_data *rdata ); 31 static pj_bool_t proxy_on_rx_response(pjsip_rx_data *rdata ); 40 32 41 33 static pjsip_module mod_stateful_proxy = 42 34 { 43 NULL, NULL, 35 NULL, NULL, /* prev, next. */ 44 36 { "mod-stateful-proxy", 18 }, /* Name. */ 45 -1, 46 PJSIP_MOD_PRIORITY_ APPLICATION,/* Priority */37 -1, /* Id */ 38 PJSIP_MOD_PRIORITY_UA_PROXY_LAYER, /* Priority */ 47 39 NULL, /* load() */ 48 40 NULL, /* start() */ 49 41 NULL, /* stop() */ 50 42 NULL, /* unload() */ 51 & on_rx_request,/* on_rx_request() */52 & on_rx_response,/* on_rx_response() */43 &proxy_on_rx_request, /* on_rx_request() */ 44 &proxy_on_rx_response, /* on_rx_response() */ 53 45 NULL, /* on_tx_request. */ 54 46 NULL, /* on_tx_response() */ … … 57 49 58 50 51 /* 52 * mod_tu (tu=Transaction User) is the module to receive notification 53 * from transaction when the transaction state has changed. 54 */ 55 static void tu_on_tsx_state(pjsip_transaction *tsx, pjsip_event *event); 56 57 static pjsip_module mod_tu = 58 { 59 NULL, NULL, /* prev, next. */ 60 { "mod-transaction-user", 20 }, /* Name. */ 61 -1, /* Id */ 62 PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */ 63 NULL, /* load() */ 64 NULL, /* start() */ 65 NULL, /* stop() */ 66 NULL, /* unload() */ 67 NULL, /* on_rx_request() */ 68 NULL, /* on_rx_response() */ 69 NULL, /* on_tx_request. */ 70 NULL, /* on_tx_response() */ 71 &tu_on_tsx_state, /* on_tsx_state() */ 72 }; 73 74 75 /* This is the data that is attached to the UAC transaction */ 76 struct uac_data 77 { 78 pjsip_transaction *uas_tsx; 79 pj_timer_entry timer; 80 }; 81 82 83 /* This is the data that is attached to the UAS transaction */ 84 struct uas_data 85 { 86 pjsip_transaction *uac_tsx; 87 }; 88 89 90 59 91 static pj_status_t init_stateful_proxy(void) 60 92 { 61 93 pj_status_t status; 62 94 63 /* Register our module to receive incoming requests. */64 95 status = pjsip_endpt_register_module( global.endpt, &mod_stateful_proxy); 65 96 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 66 97 98 status = pjsip_endpt_register_module( global.endpt, &mod_tu); 99 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 100 67 101 return PJ_SUCCESS; 68 102 } 69 103 70 104 71 /* Callback to be called to handle incoming requests. */72 static pj_bool_t on_rx_request( pjsip_rx_data *rdata )105 /* Callback to be called to handle new incoming requests. */ 106 static pj_bool_t proxy_on_rx_request( pjsip_rx_data *rdata ) 73 107 { 74 108 pjsip_transaction *uas_tsx, *uac_tsx; 75 struct tsx_data *tsx_data; 109 struct uac_data *uac_data; 110 struct uas_data *uas_data; 76 111 pjsip_tx_data *tdata; 77 112 pj_status_t status; 78 113 79 /* Verify incoming request */ 80 status = proxy_verify_request(rdata); 81 if (status != PJ_SUCCESS) { 82 app_perror("RX invalid request", status); 83 return PJ_TRUE; 84 } 85 86 /* 87 * Request looks sane, next clone the request to create transmit data. 88 */ 89 status = pjsip_endpt_create_request_fwd(global.endpt, rdata, NULL, 90 NULL, 0, &tdata); 91 if (status != PJ_SUCCESS) { 92 pjsip_endpt_respond_stateless(global.endpt, rdata, 93 PJSIP_SC_INTERNAL_SERVER_ERROR, NULL, 94 NULL, NULL); 95 return PJ_TRUE; 96 } 97 98 99 /* Process routing */ 100 status = proxy_process_routing(tdata); 101 if (status != PJ_SUCCESS) { 102 app_perror("Error processing route", status); 103 return PJ_TRUE; 104 } 105 106 /* Calculate target */ 107 status = proxy_calculate_target(rdata, tdata); 108 if (status != PJ_SUCCESS) { 109 app_perror("Error calculating target", status); 110 return PJ_TRUE; 111 } 112 113 /* Everything is set to forward the request. */ 114 115 /* If this is an ACK request, forward statelessly */ 116 if (tdata->msg->line.req.method.id == PJSIP_ACK_METHOD) { 117 status = pjsip_endpt_send_request_stateless(global.endpt, tdata, 118 NULL, NULL); 119 if (status != PJ_SUCCESS) { 120 app_perror("Error forwarding request", status); 121 return PJ_TRUE; 122 } 123 124 return PJ_TRUE; 125 } 126 127 /* Create UAC transaction for forwarding the request */ 128 status = pjsip_tsx_create_uac(&mod_stateful_proxy, tdata, &uac_tsx); 129 if (status != PJ_SUCCESS) { 130 pjsip_tx_data_dec_ref(tdata); 131 pjsip_endpt_respond_stateless(global.endpt, rdata, 132 PJSIP_SC_INTERNAL_SERVER_ERROR, NULL, 133 NULL, NULL); 134 return PJ_TRUE; 135 } 136 137 /* Create UAS transaction to handle incoming request */ 138 status = pjsip_tsx_create_uas(&mod_stateful_proxy, rdata, &uas_tsx); 139 if (status != PJ_SUCCESS) { 140 pjsip_tx_data_dec_ref(tdata); 141 pjsip_endpt_respond_stateless(global.endpt, rdata, 142 PJSIP_SC_INTERNAL_SERVER_ERROR, NULL, 143 NULL, NULL); 144 pjsip_tsx_terminate(uac_tsx, PJSIP_SC_INTERNAL_SERVER_ERROR); 145 return PJ_TRUE; 146 } 147 148 /* Feed the request to the UAS transaction to drive it's state 149 * out of NULL state. 150 */ 151 pjsip_tsx_recv_msg(uas_tsx, rdata); 152 153 /* Attach a data to the UAC transaction, to be used to find the 154 * UAS transaction when we receive response in the UAC side. 155 */ 156 tsx_data = pj_pool_alloc(uac_tsx->pool, sizeof(struct tsx_data)); 157 tsx_data->uas_tsx = uas_tsx; 158 159 uac_tsx->mod_data[mod_stateful_proxy.id] = (void*)tsx_data; 160 161 /* Everything is setup, forward the request */ 162 status = pjsip_tsx_send_msg(uac_tsx, tdata); 163 if (status != PJ_SUCCESS) { 164 pjsip_tx_data *err_res; 165 166 /* Fail to send request, for some reason */ 167 168 /* Destroy UAC transaction */ 169 pjsip_tx_data_dec_ref(tdata); 170 pjsip_tsx_terminate(uac_tsx, PJSIP_SC_INTERNAL_SERVER_ERROR); 171 172 /* Send 500/Internal Server Error to UAS transaction */ 173 status = pjsip_endpt_create_response(global.endpt, rdata, 174 PJSIP_SC_INTERNAL_SERVER_ERROR, 175 NULL, &err_res); 176 if (status == PJ_SUCCESS) 114 if (rdata->msg_info.msg->line.req.method.id != PJSIP_CANCEL_METHOD) { 115 116 /* Verify incoming request */ 117 status = proxy_verify_request(rdata); 118 if (status != PJ_SUCCESS) { 119 app_perror("RX invalid request", status); 120 return PJ_TRUE; 121 } 122 123 /* 124 * Request looks sane, next clone the request to create transmit data. 125 */ 126 status = pjsip_endpt_create_request_fwd(global.endpt, rdata, NULL, 127 NULL, 0, &tdata); 128 if (status != PJ_SUCCESS) { 129 pjsip_endpt_respond_stateless(global.endpt, rdata, 130 PJSIP_SC_INTERNAL_SERVER_ERROR, 131 NULL, NULL, NULL); 132 return PJ_TRUE; 133 } 134 135 136 /* Process routing */ 137 status = proxy_process_routing(tdata); 138 if (status != PJ_SUCCESS) { 139 app_perror("Error processing route", status); 140 return PJ_TRUE; 141 } 142 143 /* Calculate target */ 144 status = proxy_calculate_target(rdata, tdata); 145 if (status != PJ_SUCCESS) { 146 app_perror("Error calculating target", status); 147 return PJ_TRUE; 148 } 149 150 /* Everything is set to forward the request. */ 151 152 /* If this is an ACK request, forward statelessly. 153 * This happens if the proxy records route and this ACK 154 * is sent for 2xx response. An ACK that is sent for non-2xx 155 * final response will be absorbed by transaction layer, and 156 * it will not be received by on_rx_request() callback. 157 */ 158 if (tdata->msg->line.req.method.id == PJSIP_ACK_METHOD) { 159 status = pjsip_endpt_send_request_stateless(global.endpt, tdata, 160 NULL, NULL); 161 if (status != PJ_SUCCESS) { 162 app_perror("Error forwarding request", status); 163 return PJ_TRUE; 164 } 165 166 return PJ_TRUE; 167 } 168 169 /* Create UAC transaction for forwarding the request. 170 * Set our module as the transaction user to receive further 171 * events from this transaction. 172 */ 173 status = pjsip_tsx_create_uac(&mod_tu, tdata, &uac_tsx); 174 if (status != PJ_SUCCESS) { 175 pjsip_tx_data_dec_ref(tdata); 176 pjsip_endpt_respond_stateless(global.endpt, rdata, 177 PJSIP_SC_INTERNAL_SERVER_ERROR, 178 NULL, NULL, NULL); 179 return PJ_TRUE; 180 } 181 182 /* Create UAS transaction to handle incoming request */ 183 status = pjsip_tsx_create_uas(&mod_tu, rdata, &uas_tsx); 184 if (status != PJ_SUCCESS) { 185 pjsip_tx_data_dec_ref(tdata); 186 pjsip_endpt_respond_stateless(global.endpt, rdata, 187 PJSIP_SC_INTERNAL_SERVER_ERROR, 188 NULL, NULL, NULL); 189 pjsip_tsx_terminate(uac_tsx, PJSIP_SC_INTERNAL_SERVER_ERROR); 190 return PJ_TRUE; 191 } 192 193 /* Feed the request to the UAS transaction to drive it's state 194 * out of NULL state. 195 */ 196 pjsip_tsx_recv_msg(uas_tsx, rdata); 197 198 /* Attach a data to the UAC transaction, to be used to find the 199 * UAS transaction when we receive response in the UAC side. 200 */ 201 uac_data = (struct uac_data*) 202 pj_pool_alloc(uac_tsx->pool, sizeof(struct uac_data)); 203 uac_data->uas_tsx = uas_tsx; 204 uac_tsx->mod_data[mod_tu.id] = (void*)uac_data; 205 206 /* Attach data to the UAS transaction, to find the UAC transaction 207 * when cancelling INVITE request. 208 */ 209 uas_data = (struct uas_data*) 210 pj_pool_alloc(uas_tsx->pool, sizeof(struct uas_data)); 211 uas_data->uac_tsx = uac_tsx; 212 uas_tsx->mod_data[mod_tu.id] = (void*)uas_data; 213 214 /* Everything is setup, forward the request */ 215 status = pjsip_tsx_send_msg(uac_tsx, tdata); 216 if (status != PJ_SUCCESS) { 217 pjsip_tx_data *err_res; 218 219 /* Fail to send request, for some reason */ 220 221 /* Destroy transmit data */ 222 pjsip_tx_data_dec_ref(tdata); 223 224 /* I think UAC transaction should have been destroyed when 225 * it fails to send request, so no need to destroy it. 226 pjsip_tsx_terminate(uac_tsx, PJSIP_SC_INTERNAL_SERVER_ERROR); 227 */ 228 229 /* Send 500/Internal Server Error to UAS transaction */ 230 pjsip_endpt_create_response(global.endpt, rdata, 231 500, NULL, &err_res); 177 232 pjsip_tsx_send_msg(uas_tsx, err_res); 178 else 179 pjsip_tsx_terminate(uac_tsx, PJSIP_SC_INTERNAL_SERVER_ERROR); 180 181 return PJ_TRUE; 233 234 return PJ_TRUE; 235 } 236 237 /* Send 100/Trying if this is an INVITE */ 238 if (rdata->msg_info.msg->line.req.method.id == PJSIP_INVITE_METHOD) { 239 pjsip_tx_data *res100; 240 241 pjsip_endpt_create_response(global.endpt, rdata, 100, NULL, 242 &res100); 243 pjsip_tsx_send_msg(uas_tsx, res100); 244 } 245 246 } else { 247 /* This is CANCEL request */ 248 pjsip_transaction *invite_uas; 249 struct uas_data *uas_data; 250 pj_str_t key; 251 252 /* Find the UAS INVITE transaction */ 253 pjsip_tsx_create_key(rdata->tp_info.pool, &key, PJSIP_UAS_ROLE, 254 &pjsip_invite_method, rdata); 255 invite_uas = pjsip_tsx_layer_find_tsx(&key, PJ_TRUE); 256 if (!invite_uas) { 257 /* Invite transaction not found, respond CANCEL with 481 */ 258 pjsip_endpt_respond_stateless(global.endpt, rdata, 481, NULL, 259 NULL, NULL); 260 return PJ_TRUE; 261 } 262 263 /* Respond 200 OK to CANCEL */ 264 pjsip_endpt_respond(global.endpt, NULL, rdata, 200, NULL, NULL, 265 NULL, NULL); 266 267 /* Send CANCEL to cancel the UAC transaction. 268 * The UAS INVITE transaction will get final response when 269 * we receive final response from the UAC INVITE transaction. 270 */ 271 uas_data = (struct uas_data*) invite_uas->mod_data[mod_tu.id]; 272 if (uas_data->uac_tsx) { 273 pjsip_tx_data *cancel; 274 275 pj_mutex_lock(uas_data->uac_tsx->mutex); 276 277 pjsip_endpt_create_cancel(global.endpt, uas_data->uac_tsx->last_tx, 278 &cancel); 279 pjsip_endpt_send_request(global.endpt, cancel, -1, NULL, NULL); 280 281 pj_mutex_unlock(uas_data->uac_tsx->mutex); 282 } 283 284 /* Unlock UAS tsx because it is locked in find_tsx() */ 285 pj_mutex_unlock(invite_uas->mutex); 182 286 } 183 287 … … 186 290 187 291 188 /* Callback to be called to handle incoming response. */ 189 static pj_bool_t on_rx_response( pjsip_rx_data *rdata ) 190 { 191 pjsip_transaction *uac_tsx; 292 /* Callback to be called to handle incoming response outside 293 * any transactions. This happens for example when 2xx/OK 294 * for INVITE is received and transaction will be destroyed 295 * immediately, so we need to forward the subsequent 2xx/OK 296 * retransmission statelessly. 297 */ 298 static pj_bool_t proxy_on_rx_response( pjsip_rx_data *rdata ) 299 { 192 300 pjsip_tx_data *tdata; 193 301 pjsip_response_addr res_addr; … … 213 321 pj_bzero(&res_addr, sizeof(res_addr)); 214 322 res_addr.dst_host.type = PJSIP_TRANSPORT_UDP; 215 res_addr.dst_host.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP); 323 res_addr.dst_host.flag = 324 pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP); 216 325 217 326 /* Destination address is Via's received param */ … … 222 331 } 223 332 224 /* Destination port is the rpo t */333 /* Destination port is the rport */ 225 334 if (hvia->rport_param != 0 && hvia->rport_param != -1) 226 335 res_addr.dst_host.addr.port = hvia->rport_param; … … 233 342 } 234 343 235 uac_tsx = pjsip_rdata_get_tsx(rdata); 236 237 if (!uac_tsx) { 238 /* UAC transaction not found (it may have been destroyed). 239 * Forward response statelessly. 240 */ 241 status = pjsip_endpt_send_response(global.endpt, &res_addr, tdata, 242 NULL, NULL); 243 if (status != PJ_SUCCESS) { 244 app_perror("Error forwarding response", status); 245 return PJ_TRUE; 246 } 247 } else { 248 struct tsx_data *tsx_data; 249 250 tsx_data = (struct tsx_data*) uac_tsx->mod_data[mod_stateful_proxy.id]; 344 /* Forward response */ 345 status = pjsip_endpt_send_response(global.endpt, &res_addr, tdata, 346 NULL, NULL); 347 if (status != PJ_SUCCESS) { 348 app_perror("Error forwarding response", status); 349 return PJ_TRUE; 350 } 351 352 return PJ_TRUE; 353 } 354 355 356 /* Callback to be called to handle transaction state changed. */ 357 static void tu_on_tsx_state(pjsip_transaction *tsx, pjsip_event *event) 358 { 359 struct uac_data *uac_data; 360 pj_status_t status; 361 362 if (tsx->role == PJSIP_ROLE_UAS) { 363 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) { 364 struct uas_data *uas_data; 365 366 uas_data = (struct uas_data*) tsx->mod_data[mod_tu.id]; 367 if (uas_data->uac_tsx) { 368 uac_data = (struct uac_data*) 369 uas_data->uac_tsx->mod_data[mod_tu.id]; 370 uac_data->uas_tsx = NULL; 371 } 372 373 } 374 return; 375 } 376 377 /* Get the data that we attached to the UAC transaction previously */ 378 uac_data = (struct uac_data*) tsx->mod_data[mod_tu.id]; 379 380 381 /* Handle incoming response */ 382 if (event->body.tsx_state.type == PJSIP_EVENT_RX_MSG) { 383 384 pjsip_rx_data *rdata; 385 pjsip_response_addr res_addr; 386 pjsip_via_hdr *hvia; 387 pjsip_tx_data *tdata; 388 389 rdata = event->body.tsx_state.src.rdata; 390 391 /* Do not forward 100 response for INVITE (we already responded 392 * INVITE with 100) 393 */ 394 if (tsx->method.id == PJSIP_INVITE_METHOD && 395 rdata->msg_info.msg->line.status.code == 100) 396 { 397 return; 398 } 399 400 /* Create response to be forwarded upstream 401 * (Via will be stripped here) 402 */ 403 status = pjsip_endpt_create_response_fwd(global.endpt, rdata, 0, 404 &tdata); 405 if (status != PJ_SUCCESS) { 406 app_perror("Error creating response", status); 407 return; 408 } 409 410 /* Get topmost Via header of the new response */ 411 hvia = (pjsip_via_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, 412 NULL); 413 if (hvia == NULL) { 414 /* Invalid response! Just drop it */ 415 pjsip_tx_data_dec_ref(tdata); 416 return; 417 } 418 419 /* Calculate the address to forward the response */ 420 pj_bzero(&res_addr, sizeof(res_addr)); 421 res_addr.dst_host.type = PJSIP_TRANSPORT_UDP; 422 res_addr.dst_host.flag = 423 pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP); 424 425 /* Destination address is Via's received param */ 426 res_addr.dst_host.addr.host = hvia->recvd_param; 427 if (res_addr.dst_host.addr.host.slen == 0) { 428 /* Someone has messed up our Via header! */ 429 res_addr.dst_host.addr.host = hvia->sent_by.host; 430 } 431 432 /* Destination port is the rport */ 433 if (hvia->rport_param != 0 && hvia->rport_param != -1) 434 res_addr.dst_host.addr.port = hvia->rport_param; 435 436 if (res_addr.dst_host.addr.port == 0) { 437 /* Ugh, original sender didn't put rport! 438 * At best, can only send the response to the port in Via. 439 */ 440 res_addr.dst_host.addr.port = hvia->sent_by.port; 441 } 251 442 252 443 /* Forward response with the UAS transaction */ 253 pjsip_tsx_send_msg(tsx_data->uas_tsx, tdata); 254 255 /* Special case for pjsip: 256 * if response is 2xx for INVITE transaction, terminate the UAS 257 * transaction (otherwise it will retransmit the response). 258 */ 259 if (tsx_data->uas_tsx->method.id == PJSIP_INVITE_METHOD && 260 rdata->msg_info.msg->line.status.code/100 == 2) 261 { 262 pjsip_tsx_terminate(tsx_data->uas_tsx, 263 rdata->msg_info.msg->line.status.code); 264 tsx_data->uas_tsx = NULL; 265 } 266 } 267 268 return PJ_TRUE; 444 pjsip_tsx_send_msg(uac_data->uas_tsx, tdata); 445 446 } 447 448 /* If UAC transaction is terminated, terminate the UAS as well. 449 * This could happen because of: 450 * - timeout on the UAC side 451 * - receipt of 2xx response to INVITE 452 */ 453 if (tsx->state == PJSIP_TSX_STATE_TERMINATED && uac_data->uas_tsx) { 454 455 pjsip_transaction *uas_tsx; 456 struct uas_data *uas_data; 457 458 uas_tsx = uac_data->uas_tsx; 459 uas_data = (struct uas_data*) uas_tsx->mod_data[mod_tu.id]; 460 uas_data->uac_tsx = NULL; 461 462 if (event->body.tsx_state.type == PJSIP_EVENT_TIMER) { 463 464 /* Send 408/Timeout if this is an INVITE transaction, since 465 * we must have sent provisional response before. For non 466 * INVITE transaction, just destroy it. 467 */ 468 if (tsx->method.id == PJSIP_INVITE_METHOD) { 469 470 pjsip_tx_data *tdata = uas_tsx->last_tx; 471 472 tdata->msg->line.status.code = PJSIP_SC_REQUEST_TIMEOUT; 473 tdata->msg->line.status.reason = pj_str("Request timed out"); 474 tdata->msg->body = NULL; 475 476 pjsip_tx_data_add_ref(tdata); 477 pjsip_tx_data_invalidate_msg(tdata); 478 479 pjsip_tsx_send_msg(uas_tsx, tdata); 480 481 } else { 482 /* For non-INVITE, just destroy the UAS transaction */ 483 pjsip_tsx_terminate(uas_tsx, PJSIP_SC_REQUEST_TIMEOUT); 484 } 485 486 } else if (event->body.tsx_state.type == PJSIP_EVENT_RX_MSG) { 487 488 if (uas_tsx->state < PJSIP_TSX_STATE_TERMINATED) { 489 pjsip_msg *msg; 490 int code; 491 492 msg = event->body.tsx_state.src.rdata->msg_info.msg; 493 code = msg->line.status.code; 494 495 uac_data->uas_tsx = NULL; 496 pjsip_tsx_terminate(uas_tsx, code); 497 } 498 } 499 } 269 500 } 270 501 … … 280 511 global.record_route = 0; 281 512 513 pj_log_set_level(4); 514 282 515 status = init_options(argc, argv); 283 516 if (status != PJ_SUCCESS) 284 517 return 1; 285 286 pj_log_set_level(4);287 518 288 519 status = init_stack(); -
pjproject/branches/pjproject-0.5-stable/pjsip-apps/src/samples/stateless_proxy.c
r1121 r1123 35 35 static pjsip_module mod_stateless_proxy = 36 36 { 37 NULL, NULL, /* prev, next.*/38 { "mod-stateless-proxy", 19 }, /* Name. */39 -1, /* Id*/40 PJSIP_MOD_PRIORITY_ APPLICATION,/* Priority */41 NULL, /* load() */42 NULL, /* start() */43 NULL, /* stop() */44 NULL, /* unload() */45 &on_rx_request, /* on_rx_request() */46 &on_rx_response, 47 NULL, /* on_tx_request. */48 NULL, /* on_tx_response() */49 NULL, /* on_tsx_state() */37 NULL, NULL, /* prev, next. */ 38 { "mod-stateless-proxy", 19 }, /* Name. */ 39 -1, /* Id */ 40 PJSIP_MOD_PRIORITY_UA_PROXY_LAYER, /* Priority */ 41 NULL, /* load() */ 42 NULL, /* start() */ 43 NULL, /* stop() */ 44 NULL, /* unload() */ 45 &on_rx_request, /* on_rx_request() */ 46 &on_rx_response, /* on_rx_response() */ 47 NULL, /* on_tx_request. */ 48 NULL, /* on_tx_response() */ 49 NULL, /* on_tsx_state() */ 50 50 }; 51 51 … … 179 179 180 180 global.port = 5060; 181 pj_log_set_level(4); 181 182 182 183 status = init_options(argc, argv); 183 184 if (status != PJ_SUCCESS) 184 185 return 1; 185 186 pj_log_set_level(4);187 186 188 187 status = init_stack();
Note: See TracChangeset
for help on using the changeset viewer.