- Timestamp:
- Feb 8, 2006 10:44:25 PM (19 years ago)
- Location:
- pjproject/trunk/pjsip
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/include/pjsip/sip_dialog.h
r141 r160 50 50 51 51 /** 52 * Dialog state. 53 */ 54 enum pjsip_dialog_state 55 { 56 PJSIP_DIALOG_STATE_NULL, 57 PJSIP_DIALOG_STATE_ESTABLISHED, 58 }; 59 60 /** 52 61 * This structure describes the dialog structure. 53 62 */ … … 68 77 69 78 /* Dialog's session properties. */ 70 pj_bool_t established;/**< Dialog is established?*/79 enum pjsip_dialog_state state; /**< Dialog state. */ 71 80 pjsip_uri *target; /**< Current target. */ 72 81 pjsip_dlg_party local; /**< Local party info. */ -
pjproject/trunk/pjsip/include/pjsip/sip_event.h
r139 r160 125 125 { 126 126 pjsip_tx_data *tdata; /**< The transmit data buffer. */ 127 pjsip_transaction *tsx; /**< The transaction. */128 127 129 128 } tx_msg; … … 140 139 { 141 140 pjsip_rx_data *rdata; /**< The receive data buffer. */ 142 pjsip_transaction *tsx; /**< The transaction. */143 141 } rx_msg; 144 142 … … 179 177 * Init tx msg event. 180 178 */ 181 #define PJSIP_EVENT_INIT_TX_MSG(event,pt sx,ptdata) \179 #define PJSIP_EVENT_INIT_TX_MSG(event,ptdata) \ 182 180 do { \ 183 181 (event).type = PJSIP_EVENT_TX_MSG; \ 184 (event).body.tx_msg.tsx = ptsx; \185 182 (event).body.tx_msg.tdata = ptdata; \ 186 183 } while (0) … … 189 186 * Init rx msg event. 190 187 */ 191 #define PJSIP_EVENT_INIT_RX_MSG(event,p tsx,prdata) \188 #define PJSIP_EVENT_INIT_RX_MSG(event,prdata) \ 192 189 do { \ 193 190 (event).type = PJSIP_EVENT_RX_MSG; \ 194 (event).body.rx_msg.tsx = ptsx; \195 191 (event).body.rx_msg.rdata = prdata; \ 196 192 } while (0) -
pjproject/trunk/pjsip/include/pjsip/sip_transaction.h
r127 r160 176 176 /** 177 177 * Create, initialize, and register a new transaction as UAS from the 178 * specified incoming request in \c rdata. 178 * specified incoming request in \c rdata. After calling this function, 179 * application MUST call #pjsip_tsx_recv_msg() so that transaction 180 * moves from state NULL. 179 181 * 180 182 * @param tsx_user Module to be registered as transaction user of the new … … 190 192 pjsip_transaction **p_tsx ); 191 193 194 195 /** 196 * Call this function to manually feed a message to the transaction. 197 * For UAS transaction, application MUST call this function after 198 * UAS transaction has been created. 199 * 200 * This function SHOULD only be called to pass initial request message 201 * to UAS transaction. Before this function returns, on_tsx_state() 202 * callback of the transaction user will be called. If response message 203 * is passed to this function, then on_rx_response() will also be called 204 * before on_tsx_state(). 205 * 206 * @param tsx The transaction. 207 * @param rdata The message. 208 */ 209 PJ_DECL(void) pjsip_tsx_recv_msg( pjsip_transaction *tsx, 210 pjsip_rx_data *rdata); 211 192 212 /** 193 213 * Transmit message in tdata with this transaction. It is possible to -
pjproject/trunk/pjsip/include/pjsip/sip_types.h
r127 r160 134 134 typedef struct pjsip_dialog pjsip_dialog; 135 135 136 /** 137 * Dialog state (sip_dialog.h). 138 */ 139 enum pjsip_dialog_state pjsip_dialog_state; 136 140 137 141 /** -
pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
r156 r160 110 110 111 111 /* 112 * Set session state. 113 */ 114 void inv_set_state(pjsip_inv_session *inv, pjsip_inv_state state, 115 pjsip_event *e) 116 { 117 inv->state = state; 118 if (mod_inv.cb.on_state_changed) 119 (*mod_inv.cb.on_state_changed)(inv, e); 120 121 if (inv->state == PJSIP_INV_STATE_DISCONNECTED) 122 pjsip_dlg_dec_session(inv->dlg); 123 } 124 125 126 /* 112 127 * Send ACK for 2xx response. 113 128 */ … … 146 161 { 147 162 pjsip_method *method; 163 pjsip_dialog *dlg; 164 pjsip_inv_session *inv; 148 165 149 166 /* Only wants to receive request from a dialog. */ 150 if (pjsip_rdata_get_dlg(rdata) == NULL) 167 dlg = pjsip_rdata_get_dlg(rdata); 168 if (dlg == NULL) 151 169 return PJ_FALSE; 170 171 inv = dlg->mod_data[mod_inv.mod.id]; 152 172 153 173 /* Report to dialog that we handle INVITE, CANCEL, BYE, ACK. … … 159 179 if (method->id == PJSIP_INVITE_METHOD || 160 180 method->id == PJSIP_CANCEL_METHOD || 161 method->id == PJSIP_ACK_METHOD ||162 181 method->id == PJSIP_BYE_METHOD) 163 182 { 164 183 return PJ_TRUE; 184 } 185 186 /* On receipt ACK request, when state is CONNECTING, 187 * move state to CONFIRMED. 188 */ 189 if (method->id == PJSIP_ACK_METHOD && inv && 190 inv->state == PJSIP_INV_STATE_CONFIRMED) 191 { 192 pjsip_event event; 193 194 PJSIP_EVENT_INIT_RX_MSG(event, rdata); 195 inv_set_state(inv, PJSIP_INV_STATE_CONFIRMED, &event); 165 196 } 166 197 … … 703 734 inv->pool = dlg->pool; 704 735 inv->role = PJSIP_ROLE_UAS; 705 inv->state = PJSIP_INV_STATE_ INCOMING;736 inv->state = PJSIP_INV_STATE_NULL; 706 737 inv->dlg = dlg; 707 738 inv->options = options; … … 1067 1098 1068 1099 1069 void inv_set_state(pjsip_inv_session *inv, pjsip_inv_state state,1070 pjsip_event *e)1071 {1072 inv->state = state;1073 if (mod_inv.cb.on_state_changed)1074 (*mod_inv.cb.on_state_changed)(inv, e);1075 1076 if (inv->state == PJSIP_INV_STATE_DISCONNECTED)1077 pjsip_dlg_dec_session(inv->dlg);1078 }1079 1080 1081 1082 1100 /* 1083 1101 * Respond to incoming CANCEL request. … … 1164 1182 if (inv->state != PJSIP_INV_STATE_DISCONNECTED) 1165 1183 inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 1184 } 1185 1186 /* 1187 * Respond to BYE request. 1188 */ 1189 static void inv_handle_bye_response( pjsip_inv_session *inv, 1190 pjsip_transaction *tsx, 1191 pjsip_rx_data *rdata, 1192 pjsip_event *e ) 1193 { 1194 pj_status_t status; 1195 1196 if (e->body.tsx_state.type != PJSIP_EVENT_RX_MSG) { 1197 inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 1198 return; 1199 } 1200 1201 /* Handle 401/407 challenge. */ 1202 if (tsx->status_code == 401 || tsx->status_code == 407) { 1203 1204 pjsip_tx_data *tdata; 1205 1206 status = pjsip_auth_clt_reinit_req( &inv->dlg->auth_sess, 1207 rdata, 1208 tsx->last_tx, 1209 &tdata); 1210 1211 if (status != PJ_SUCCESS) { 1212 1213 /* Does not have proper credentials. 1214 * End the session anyway. 1215 */ 1216 inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 1217 1218 } else { 1219 /* Re-send BYE. */ 1220 status = pjsip_inv_send_msg(inv, tdata, NULL ); 1221 } 1222 1223 } else { 1224 1225 /* End the session. */ 1226 1227 inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 1228 } 1229 1166 1230 } 1167 1231 … … 1197 1261 case PJSIP_TSX_STATE_TRYING: 1198 1262 inv_set_state(inv, PJSIP_INV_STATE_INCOMING, e); 1263 break; 1264 case PJSIP_TSX_STATE_PROCEEDING: 1265 inv_set_state(inv, PJSIP_INV_STATE_INCOMING, e); 1266 if (tsx->status_code > 100) 1267 inv_set_state(inv, PJSIP_INV_STATE_EARLY, e); 1199 1268 break; 1200 1269 default: … … 1464 1533 1465 1534 case PJSIP_TSX_STATE_CONFIRMED: 1535 if (tsx->status_code/100 == 2) 1536 inv_set_state(inv, PJSIP_INV_STATE_CONFIRMED, e); 1466 1537 break; 1467 1538 … … 1496 1567 inv_respond_incoming_bye( inv, tsx, e->body.tsx_state.src.rdata, e ); 1497 1568 1498 } 1569 } else if (tsx->method.id == PJSIP_BYE_METHOD && 1570 tsx->role == PJSIP_ROLE_UAC && 1571 tsx->state == PJSIP_TSX_STATE_COMPLETED) 1572 { 1573 1574 /* 1575 * Outgoing BYE 1576 */ 1577 inv_handle_bye_response( inv, tsx, e->body.tsx_state.src.rdata, e); 1578 1579 } 1580 1499 1581 } 1500 1582 … … 1514 1596 tsx->state == PJSIP_TSX_STATE_COMPLETED) 1515 1597 { 1598 1516 1599 /* 1517 * Outgoing BYE .1600 * Outgoing BYE 1518 1601 */ 1519 pj_status_t status; 1520 1521 /* Handle 401/407 challenge. */ 1522 if (tsx->status_code == 401 || tsx->status_code == 407) { 1523 1524 pjsip_tx_data *tdata; 1525 1526 status = pjsip_auth_clt_reinit_req( &inv->dlg->auth_sess, 1527 e->body.tsx_state.src.rdata, 1528 tsx->last_tx, 1529 &tdata); 1530 1531 if (status != PJ_SUCCESS) { 1532 1533 /* Does not have proper credentials. 1534 * End the session anyway. 1535 */ 1536 inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 1537 1538 } else { 1539 /* Re-send BYE. */ 1540 status = pjsip_inv_send_msg(inv, tdata, NULL ); 1541 } 1542 1543 } else { 1544 1545 /* End the session. */ 1546 1602 1603 if (e->body.tsx_state.type == PJSIP_EVENT_RX_MSG) 1604 inv_handle_bye_response( inv, tsx, e->body.tsx_state.src.rdata, e); 1605 else 1547 1606 inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 1548 }1549 1607 1550 1608 } -
pjproject/trunk/pjsip/src/pjsip/sip_dialog.c
r141 r160 75 75 dlg->ua = ua; 76 76 dlg->endpt = endpt; 77 dlg->state = PJSIP_DIALOG_STATE_NULL; 77 78 78 79 status = pj_mutex_create_recursive(pool, "dlg%p", &dlg->mutex); … … 375 376 PJ_TODO(DIALOG_APP_TIMER); 376 377 378 /* Feed the first request to the transaction. */ 379 pjsip_tsx_recv_msg(tsx, rdata); 380 377 381 /* Done. */ 378 382 *p_dlg = dlg; … … 408 412 PJSIP_ENOTRESPONSEMSG); 409 413 414 /* Status code MUST be 1xx (but not 100), or 2xx */ 415 status = rdata->msg_info.msg->line.status.code; 416 PJ_ASSERT_RETURN( (status/100==1 && status!=100) || 417 (status/100==2), PJ_EBUG); 418 410 419 /* To tag must present in the response. */ 411 420 PJ_ASSERT_RETURN(rdata->msg_info.to->tag.slen != 0, PJSIP_EMISSINGTAG); … … 444 453 /* Initial role is UAC. */ 445 454 dlg->role = PJSIP_ROLE_UAC; 455 456 /* Dialog state depends on the response. */ 457 status = rdata->msg_info.msg->line.status.code/100; 458 if (status == 1 || status == 2) 459 dlg->state = PJSIP_DIALOG_STATE_ESTABLISHED; 460 else { 461 pj_assert(!"Invalid status code"); 462 dlg->state = PJSIP_DIALOG_STATE_NULL; 463 } 446 464 447 465 /* Secure? */ … … 463 481 } 464 482 465 /* Initclient authentication session. */483 /* Clone client authentication session. */ 466 484 status = pjsip_auth_clt_clone(dlg->pool, &dlg->auth_sess, 467 485 &first_dlg->auth_sess); … … 850 868 } 851 869 870 /* Add standard headers for certain types of response */ 871 static void dlg_beautify_response(pjsip_dialog *dlg, 872 int st_code, 873 pjsip_tx_data *tdata) 874 { 875 pjsip_cseq_hdr *cseq; 876 int st_class; 877 const pjsip_hdr *c_hdr; 878 pjsip_hdr *hdr; 879 880 cseq = PJSIP_MSG_CSEQ_HDR(tdata->msg); 881 pj_assert(cseq != NULL); 882 883 st_class = st_code / 100; 884 885 /* Contact, Allow, Supported header. */ 886 if (pjsip_method_creates_dialog(&cseq->method)) { 887 /* Add Contact header for 1xx, 2xx, 3xx and 485 response. */ 888 if (st_class==2 || st_class==3 || (st_class==1 && st_code != 100) || 889 st_code==485) 890 { 891 /* Add contact header only if one is not present. */ 892 if (pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL) == 0) { 893 hdr = pjsip_hdr_clone(tdata->pool, dlg->local.contact); 894 pjsip_msg_add_hdr(tdata->msg, hdr); 895 } 896 } 897 898 /* Add Allow header in 2xx and 405 response. */ 899 if ((st_class==2 || st_code==405) && 900 pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ALLOW, NULL)==NULL) 901 { 902 c_hdr = pjsip_endpt_get_capability(dlg->endpt, 903 PJSIP_H_ALLOW, NULL); 904 if (c_hdr) { 905 hdr = pjsip_hdr_clone(tdata->pool, c_hdr); 906 pjsip_msg_add_hdr(tdata->msg, hdr); 907 } 908 } 909 910 /* Add Supported header in 2xx response. */ 911 if (st_class==2 && 912 pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL)==NULL) 913 { 914 c_hdr = pjsip_endpt_get_capability(dlg->endpt, 915 PJSIP_H_SUPPORTED, NULL); 916 if (c_hdr) { 917 hdr = pjsip_hdr_clone(tdata->pool, c_hdr); 918 pjsip_msg_add_hdr(tdata->msg, hdr); 919 } 920 } 921 922 } 923 924 /* Add To tag in all responses except 100 */ 925 if (st_code != 100) { 926 pjsip_to_hdr *to; 927 928 to = PJSIP_MSG_TO_HDR(tdata->msg); 929 pj_assert(to != NULL); 930 931 to->tag = dlg->local.info->tag; 932 } 933 } 934 852 935 853 936 /* … … 861 944 { 862 945 pj_status_t status; 863 pjsip_cseq_hdr *cseq;864 946 pjsip_tx_data *tdata; 865 int st_class; 866 867 /* Create generic response. */ 947 948 /* Create generic response. 949 * This will initialize response's Via, To, From, Call-ID, CSeq 950 * and Record-Route headers from the request. 951 */ 868 952 status = pjsip_endpt_create_response(dlg->endpt, 869 953 rdata, st_code, st_text, &tdata); … … 874 958 pj_mutex_lock(dlg->mutex); 875 959 876 /* Special treatment for 2xx response to request that establishes 877 * dialog. 878 * 879 * RFC 3261 Section 12.1.1 880 * 881 * When a UAS responds to a request with a response that establishes 882 * a dialog (such as a 2xx to INVITE): 883 * - MUST copy all Record-Route header field values from the request 884 * into the response (including the URIs, URI parameters, and any 885 * Record-Route header field parameters, whether they are known or 886 * unknown to the UAS) and MUST maintain the order of those values. 887 * - The Contact header field contains an address where the UAS would 888 * like to be contacted for subsequent requests in the dialog. 889 * 890 * Also from Table 3, page 119. 891 */ 892 cseq = PJSIP_MSG_CSEQ_HDR(tdata->msg); 893 pj_assert(cseq != NULL); 894 895 st_class = st_code / 100; 896 897 if (cseq->cseq == dlg->remote.first_cseq && 898 (st_class==1 || st_class==2) && st_code != 100) 899 { 900 pjsip_hdr *rr, *hdr; 901 902 /* Duplicate Record-Route header from the request. */ 903 rr = (pjsip_hdr*) rdata->msg_info.record_route; 904 while (rr) { 905 hdr = pjsip_hdr_clone(tdata->pool, rr); 906 pjsip_msg_add_hdr(tdata->msg, hdr); 907 908 rr = rr->next; 909 if (rr == &rdata->msg_info.msg->hdr) 910 break; 911 rr = pjsip_msg_find_hdr(rdata->msg_info.msg, 912 PJSIP_H_RECORD_ROUTE, rr); 913 } 914 } 915 916 /* Contact header. */ 917 if (pjsip_method_creates_dialog(&cseq->method)) { 918 /* Add Contact header for 1xx, 2xx, 3xx and 485 response. */ 919 if (st_class==2 || st_class==3 || (st_class==1 && st_code != 100) || 920 st_code==485) 921 { 922 /* Add contact header. */ 923 pjsip_hdr *hdr = pjsip_hdr_clone(tdata->pool, dlg->local.contact); 924 pjsip_msg_add_hdr(tdata->msg, hdr); 925 } 926 927 /* Add Allow header in 2xx and 405 response. */ 928 if (st_class==2 || st_code==405) { 929 const pjsip_hdr *c_hdr; 930 c_hdr = pjsip_endpt_get_capability(dlg->endpt, 931 PJSIP_H_ALLOW, NULL); 932 if (c_hdr) { 933 pjsip_hdr *hdr = pjsip_hdr_clone(tdata->pool, c_hdr); 934 pjsip_msg_add_hdr(tdata->msg, hdr); 935 } 936 } 937 938 /* Add Supported header in 2xx response. */ 939 if (st_class==2) { 940 const pjsip_hdr *c_hdr; 941 c_hdr = pjsip_endpt_get_capability(dlg->endpt, 942 PJSIP_H_SUPPORTED, NULL); 943 if (c_hdr) { 944 pjsip_hdr *hdr = pjsip_hdr_clone(tdata->pool, c_hdr); 945 pjsip_msg_add_hdr(tdata->msg, hdr); 946 } 947 } 948 949 } 950 951 /* Add To tag in all responses except 100 */ 952 if (st_code != 100 && rdata->msg_info.to->tag.slen == 0) { 953 pjsip_to_hdr *to; 954 955 to = PJSIP_MSG_TO_HDR(tdata->msg); 956 pj_assert(to != NULL); 957 958 to->tag = dlg->local.info->tag; 959 } 960 dlg_beautify_response(dlg, st_code, tdata); 960 961 961 962 /* Unlock the dialog. */ … … 981 982 PJ_ASSERT_RETURN(st_code >= 100 && st_code <= 699, PJ_EINVAL); 982 983 984 pj_mutex_lock(dlg->mutex); 985 986 /* Replace status code and reason */ 983 987 tdata->msg->line.status.code = st_code; 984 988 if (st_text) { … … 987 991 tdata->msg->line.status.reason = *pjsip_get_status_text(st_code); 988 992 } 993 994 dlg_beautify_response(dlg, st_code, tdata); 995 996 997 /* Must add reference counter, since tsx_send_msg() will decrement it */ 998 pjsip_tx_data_add_ref(tdata); 999 1000 /* Force to re-print message. */ 1001 pjsip_tx_data_invalidate_msg(tdata); 1002 1003 pj_mutex_unlock(dlg->mutex); 989 1004 990 1005 return PJ_SUCCESS; … … 1058 1073 { 1059 1074 pj_status_t status; 1060 pjsip_transaction *tsx ;1075 pjsip_transaction *tsx = NULL; 1061 1076 unsigned i; 1062 1077 … … 1065 1080 1066 1081 /* Check CSeq */ 1067 if (rdata->msg_info.cseq->cseq <= dlg->remote.cseq) { 1082 if (rdata->msg_info.cseq->cseq <= dlg->remote.cseq && 1083 rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD && 1084 rdata->msg_info.msg->line.req.method.id != PJSIP_CANCEL_METHOD) 1085 { 1068 1086 /* Invalid CSeq. 1069 1087 * Respond statelessly with 500 (Internal Server Error) 1070 1088 */ 1071 1089 pj_mutex_unlock(dlg->mutex); 1090 pj_assert(pjsip_rdata_get_tsx(rdata) == NULL); 1072 1091 pjsip_endpt_respond_stateless(dlg->endpt, 1073 1092 rdata, 500, NULL, NULL, NULL); … … 1079 1098 1080 1099 /* Create UAS transaction for this request. */ 1081 status = pjsip_tsx_create_uas(dlg->ua, rdata, &tsx); 1082 PJ_ASSERT_ON_FAIL(status==PJ_SUCCESS,{goto on_return;}); 1083 1084 /* Put this dialog in the transaction data. */ 1085 tsx->mod_data[dlg->ua->id] = dlg; 1086 1087 /* Add transaction count. */ 1088 ++dlg->tsx_count; 1100 if (pjsip_rdata_get_tsx(rdata) == NULL) { 1101 status = pjsip_tsx_create_uas(dlg->ua, rdata, &tsx); 1102 PJ_ASSERT_ON_FAIL(status==PJ_SUCCESS,{goto on_return;}); 1103 1104 /* Put this dialog in the transaction data. */ 1105 tsx->mod_data[dlg->ua->id] = dlg; 1106 1107 /* Add transaction count. */ 1108 ++dlg->tsx_count; 1109 } 1089 1110 1090 1111 /* Report the request to dialog usages. */ … … 1101 1122 } 1102 1123 1103 if (i==dlg->usage_cnt) { 1104 pjsip_tx_data *tdata; 1105 1106 PJ_LOG(4,(dlg->obj_name, 1107 "%s is unhandled by dialog usages. " 1108 "Dialog will response with 500 (Internal Server Error)", 1109 pjsip_rx_data_get_info(rdata))); 1110 status = pjsip_endpt_create_response(dlg->endpt, 1111 rdata, 1112 PJSIP_SC_INTERNAL_SERVER_ERROR, 1113 NULL, &tdata); 1114 if (status == PJ_SUCCESS) 1115 status = pjsip_tsx_send_msg(tsx, tdata); 1116 1117 if (status != PJ_SUCCESS) { 1118 char errmsg[PJSIP_ERR_MSG_SIZE]; 1119 pj_strerror(status, errmsg, sizeof(errmsg)); 1120 PJ_LOG(4,(dlg->obj_name,"Error sending %s: %s", 1121 pjsip_tx_data_get_info(tdata), errmsg)); 1122 pjsip_tsx_terminate(tsx, 500); 1123 } 1124 } 1124 /* Feed the first request to the transaction. */ 1125 if (tsx) 1126 pjsip_tsx_recv_msg(tsx, rdata); 1125 1127 1126 1128 on_return: … … 1143 1145 pj_assert(pjsip_rdata_get_dlg(rdata) == dlg); 1144 1146 1145 /* Update the remote tag if it is different. */1146 if (pj_strcmp(&dlg->remote.info->tag, &rdata->msg_info.to->tag) != 0) {1147 1148 pj_strdup(dlg->pool, &dlg->remote.info->tag, &rdata->msg_info.to->tag);1149 1150 /* No need to update remote's tag_hval since its never used. */1151 }1152 1153 1147 /* Keep the response's status code */ 1154 1148 res_code = rdata->msg_info.msg->line.status.code; 1155 1149 1156 /* When we receive response that establishes dialog, update the route1157 * set and dialog target.1158 */ 1159 if ( !dlg->established&&1150 /* When we receive response that establishes dialog, update To tag, 1151 * route set and dialog target. 1152 */ 1153 if (dlg->state == PJSIP_DIALOG_STATE_NULL && 1160 1154 pjsip_method_creates_dialog(&rdata->msg_info.cseq->method) && 1161 1155 (res_code > 100 && res_code < 300) && 1162 1156 rdata->msg_info.to->tag.slen) 1163 1157 { 1158 pjsip_hdr *hdr, *end_hdr; 1159 pjsip_contact_hdr *contact; 1160 1161 /* Update To tag. */ 1162 pj_strdup(dlg->pool, &dlg->remote.info->tag, &rdata->msg_info.to->tag); 1163 /* No need to update remote's tag_hval since its never used. */ 1164 1165 1164 1166 /* RFC 3271 Section 12.1.2: 1165 1167 * The route set MUST be set to the list of URIs in the Record-Route … … 1170 1172 * route set for future requests in this dialog. 1171 1173 */ 1172 pjsip_hdr *hdr, *end_hdr;1173 pjsip_contact_hdr *contact;1174 1175 1174 pj_list_init(&dlg->route_set); 1176 1175 … … 1195 1194 } 1196 1195 1197 dlg-> established = 1;1196 dlg->state = PJSIP_DIALOG_STATE_ESTABLISHED; 1198 1197 } 1199 1198 … … 1252 1251 --dlg->tsx_count; 1253 1252 1253 /* Increment session to prevent usages from destroying dialog. */ 1254 ++dlg->sess_count; 1255 1254 1256 /* Pass to dialog usages. */ 1255 1257 for (i=0; i<dlg->usage_cnt; ++i) { … … 1260 1262 (*dlg->usage[i]->on_tsx_state)(tsx, e); 1261 1263 } 1264 1265 /* Decrement temporary session. */ 1266 --dlg->sess_count; 1262 1267 1263 1268 if (tsx->state == PJSIP_TSX_STATE_TERMINATED && dlg->tsx_count == 0 && -
pjproject/trunk/pjsip/src/pjsip/sip_transaction.c
r152 r160 171 171 static int tsx_send_msg( pjsip_transaction *tsx, 172 172 pjsip_tx_data *tdata); 173 static void tsx_on_rx_msg( pjsip_transaction *tsx,174 pjsip_rx_data *rdata );175 173 176 174 … … 698 696 /* Race condition! 699 697 * Transaction may gets deleted before we have chance to lock it 700 * in tsx_on_rx_msg().698 * in pjsip_tsx_recv_msg(). 701 699 */ 702 700 PJ_TODO(FIX_RACE_CONDITION_HERE); 703 701 704 702 /* Pass the message to the transaction. */ 705 tsx_on_rx_msg(tsx, rdata );703 pjsip_tsx_recv_msg(tsx, rdata ); 706 704 707 705 return PJ_TRUE; … … 746 744 /* Race condition! 747 745 * Transaction may gets deleted before we have chance to lock it 748 * in tsx_on_rx_msg().746 * in pjsip_tsx_recv_msg(). 749 747 */ 750 748 PJ_TODO(FIX_RACE_CONDITION_HERE); 751 749 752 750 /* Pass the message to the transaction. */ 753 tsx_on_rx_msg(tsx, rdata );751 pjsip_tsx_recv_msg(tsx, rdata ); 754 752 755 753 return PJ_TRUE; … … 966 964 pj_assert(rdata != NULL); 967 965 968 if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG && 969 tsx->tsx_user->on_rx_request) 970 { 971 (*tsx->tsx_user->on_rx_request)(rdata); 972 973 } else if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG && 966 if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG && 974 967 tsx->tsx_user->on_rx_response) 975 968 { … … 1240 1233 1241 1234 1242 /* Begin with state TRYING.1235 /* Begin with state NULL. 1243 1236 * Manually set-up the state becase we don't want to call the callback. 1244 1237 */ 1245 tsx->state = PJSIP_TSX_STATE_ TRYING;1246 tsx->state_handler = &tsx_on_state_ trying;1238 tsx->state = PJSIP_TSX_STATE_NULL; 1239 tsx->state_handler = &tsx_on_state_null; 1247 1240 1248 1241 /* Get response address. */ … … 1328 1321 state_str[tsx->state])); 1329 1322 1330 PJSIP_EVENT_INIT_TX_MSG(event, t sx, tdata);1323 PJSIP_EVENT_INIT_TX_MSG(event, tdata); 1331 1324 1332 1325 /* Dispatch to transaction. */ … … 1350 1343 * transaction is received. 1351 1344 */ 1352 static void tsx_on_rx_msg( pjsip_transaction *tsx, pjsip_rx_data *rdata) 1345 PJ_DEF(void) pjsip_tsx_recv_msg( pjsip_transaction *tsx, 1346 pjsip_rx_data *rdata) 1353 1347 { 1354 1348 pjsip_event event; … … 1363 1357 1364 1358 /* Init event. */ 1365 PJSIP_EVENT_INIT_RX_MSG(event, tsx,rdata);1359 PJSIP_EVENT_INIT_RX_MSG(event, rdata); 1366 1360 1367 1361 /* Dispatch to transaction. */ … … 1717 1711 if (tsx->role == PJSIP_ROLE_UAS) { 1718 1712 1719 /* UAS doesn't have STATE_NULL. 1720 * State has moved from NULL after transaction is initialized. 1721 */ 1722 pj_assert(!"Bug bug bug!!"); 1723 return PJ_EBUG; 1713 /* Set state to Trying. */ 1714 pj_assert(event->type == PJSIP_EVENT_RX_MSG && 1715 event->body.rx_msg.rdata->msg_info.msg->type == 1716 PJSIP_REQUEST_MSG); 1717 tsx_set_state( tsx, PJSIP_TSX_STATE_TRYING, PJSIP_EVENT_RX_MSG, 1718 event->body.rx_msg.rdata); 1724 1719 1725 1720 } else { -
pjproject/trunk/pjsip/src/pjsip/sip_ua_layer.c
r145 r160 475 475 pjsip_dialog *dlg; 476 476 477 /* Optimized path: bail out early if request doesn't have To tag */ 478 if (rdata->msg_info.to->tag.slen == 0) 477 /* Optimized path: bail out early if request is not CANCEL and it doesn't 478 * have To tag 479 */ 480 if (rdata->msg_info.to->tag.slen == 0 && 481 rdata->msg_info.msg->line.req.method.id != PJSIP_CANCEL_METHOD) 482 { 479 483 return PJ_FALSE; 484 } 480 485 481 486 /* Lock user agent before looking up the dialog hash table. */ … … 625 630 626 631 if (rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD) { 627 //pj_str_t *to_tag = &rdata->msg_info.to->tag; 632 633 int st_code = rdata->msg_info.msg->line.status.code; 634 pj_str_t *to_tag = &rdata->msg_info.to->tag; 628 635 629 636 /* Must hold UA mutex before accessing dialog set. */ … … 632 639 dlg = dlg_set->dlg_list.next; 633 640 634 /* Forking handling is temporarily disabled. */635 PJ_TODO(UA_LAYER_HANDLE_FORKING);636 637 #if 0638 641 while (dlg != (pjsip_dialog*)&dlg_set->dlg_list) { 639 642 … … 653 656 654 657 /* If no dialog with matching remote tag is found, this must be 655 * a forked response. 658 * a forked response. Respond to this ONLY when response is non-100 659 * provisional response OR a 2xx response. 656 660 */ 657 if (dlg == (pjsip_dialog*)&dlg_set->dlg_list) { 661 if (dlg == (pjsip_dialog*)&dlg_set->dlg_list && 662 ((st_code/100==1 && st_code!=100) || st_code/100==2)) 663 { 658 664 /* Report to application about forked condition. 659 665 * Application can either create a dialog or ignore the response. … … 678 684 return PJ_TRUE; 679 685 } 686 687 } else if (dlg == (pjsip_dialog*)&dlg_set->dlg_list) { 688 689 /* For 100 or non-2xx response which has different To tag, 690 * pass the response to the first dialog. 691 */ 692 693 dlg = dlg_set->dlg_list.next; 694 680 695 } 681 #endif682 696 683 697 /* Done with the dialog set. */ -
pjproject/trunk/pjsip/src/pjsip/sip_util.c
r156 r160 1304 1304 } 1305 1305 1306 /* Feed the request to the transaction. */ 1307 pjsip_tsx_recv_msg(tsx, rdata); 1308 1306 1309 /* Send the message. */ 1307 1310 status = pjsip_tsx_send_msg(tsx, tdata); -
pjproject/trunk/pjsip/src/pjsua/main.c
r147 r160 19 19 #include "pjsua.h" 20 20 #include "getopt.h" 21 22 23 /* For debugging, disable threading. */ 24 //#define NO_WORKER_THREAD 25 26 #ifdef NO_WORKER_THREAD 27 #include <conio.h> 28 #endif 21 #include <stdlib.h> 22 29 23 30 24 #define THIS_FILE "main.c" … … 69 63 puts("Console keys:"); 70 64 puts(" m Make a call"); 65 puts(" a Answer incoming call"); 71 66 puts(" h Hangup current call"); 72 67 puts(" q Quit"); … … 75 70 } 76 71 72 static pj_bool_t input(const char *title, char *buf, pj_size_t len) 73 { 74 char *p; 75 76 printf("%s (empty to cancel): ", title); fflush(stdout); 77 fgets(buf, len, stdin); 78 79 /* Remove trailing newlines. */ 80 for (p=buf; ; ++p) { 81 if (*p=='\r' || *p=='\n') *p='\0'; 82 else if (!*p) break; 83 } 84 85 if (!*buf) 86 return PJ_FALSE; 87 88 return PJ_TRUE; 89 } 90 77 91 static void ui_console_main(void) 78 92 { 79 char keyin[10];80 93 char buf[128]; 81 char *p;82 94 pjsip_inv_session *inv; 83 95 … … 86 98 for (;;) { 87 99 88 #ifdef NO_WORKER_THREAD89 pj_time_val timeout = { 0, 10 };90 pjsip_endpt_handle_events (pjsua.endpt, &timeout);91 92 if (kbhit())93 fgets(keyin, sizeof(keyin), stdin);94 #else95 100 ui_help(); 96 fgets(keyin, sizeof(keyin), stdin); 97 #endif 98 99 switch (keyin[0]) { 101 fgets(buf, sizeof(buf), stdin); 102 103 switch (buf[0]) { 100 104 101 105 case 'm': … … 107 111 108 112 #if 1 109 printf("Enter URL to call: "); fflush(stdout); 110 fgets(buf, sizeof(buf), stdin); 111 112 if (buf[0]=='\r' || buf[0]=='\n') { 113 /* Cancelled. */ 114 puts("<cancelled>"); 113 /* Make call! : */ 114 if (!input("Enter URL to call", buf, sizeof(buf))) 115 continue; 116 pjsua_invite(buf, &inv); 117 118 #else 119 120 pjsua_invite("sip:localhost:5061", &inv); 121 #endif 122 break; 123 124 125 case 'a': 126 127 if (inv_session == NULL || inv_session->role != PJSIP_ROLE_UAS || 128 inv_session->state >= PJSIP_INV_STATE_CONNECTING) 129 { 130 puts("No pending incoming call"); 115 131 fflush(stdout); 116 132 continue; 117 } 118 119 /* Remove trailing newlines. */ 120 for (p=buf; ; ++p) { 121 if (*p=='\r' || *p=='\n') *p='\0'; 122 else if (!*p) break; 123 } 124 /* Make call! : */ 125 126 pjsua_invite(buf, &inv); 127 128 #else 129 130 pjsua_invite("sip:localhost:5061", &inv); 131 #endif 132 break; 133 133 134 } else { 135 pj_status_t status; 136 pjsip_tx_data *tdata; 137 138 if (!input("Answer with code (100-699)", buf, sizeof(buf))) 139 continue; 140 141 status = pjsip_inv_answer(inv_session, atoi(buf), NULL, NULL, 142 &tdata); 143 if (status == PJ_SUCCESS) 144 status = pjsip_inv_send_msg(inv_session, tdata, NULL); 145 146 if (status != PJ_SUCCESS) 147 pjsua_perror("Unable to create/send response", status); 148 } 149 150 break; 134 151 135 152 case 'h': … … 673 690 674 691 675 #ifdef NO_WORKER_THREAD676 pjsua.thread_cnt = 0;677 #endif678 679 680 692 /* Initialize pjsua (to create pool etc). 681 693 */ -
pjproject/trunk/pjsip/src/pjsua/pjsua_core.c
r147 r160 102 102 static pj_bool_t mod_pjsua_on_rx_request(pjsip_rx_data *rdata) 103 103 { 104 PJ_UNUSED_ARG(rdata); 105 PJ_TODO(IMPLEMENT_UAS); 104 pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata); 105 pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata); 106 pjsip_msg *msg = rdata->msg_info.msg; 107 108 /* 109 * Handle incoming INVITE outside dialog. 110 */ 111 if (dlg == NULL && tsx == NULL && 112 msg->line.req.method.id == PJSIP_INVITE_METHOD) 113 { 114 pj_status_t status; 115 pjsip_tx_data *response = NULL; 116 unsigned options = 0; 117 118 /* Verify that we can handle the request. */ 119 status = pjsip_inv_verify_request(rdata, &options, NULL, NULL, 120 pjsua.endpt, &response); 121 if (status != PJ_SUCCESS) { 122 123 /* 124 * No we can't handle the incoming INVITE request. 125 */ 126 127 if (response) { 128 pjsip_response_addr res_addr; 129 130 pjsip_get_response_addr(response->pool, rdata, &res_addr); 131 pjsip_endpt_send_response(pjsua.endpt, &res_addr, response, 132 NULL, NULL); 133 134 } else { 135 136 /* Respond with 500 (Internal Server Error) */ 137 pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL, 138 NULL, NULL); 139 } 140 141 } else { 142 /* 143 * Yes we can handle the incoming INVITE request. 144 */ 145 pjsip_inv_session *inv; 146 pjmedia_sdp_session *answer; 147 148 /* Create dummy SDP answer: */ 149 150 151 status = pjmedia_sdp_parse(pjsua.pool, PJSUA_DUMMY_SDP_ANSWER, 152 pj_native_strlen(PJSUA_DUMMY_SDP_ANSWER), 153 &answer); 154 if (status != PJ_SUCCESS) { 155 156 pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL, 157 NULL, NULL); 158 return PJ_TRUE; 159 } 160 161 /* Create dialog: */ 162 163 status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata, 164 &pjsua.contact_uri, &dlg); 165 if (status != PJ_SUCCESS) 166 return PJ_TRUE; 167 168 169 /* Create invite session: */ 170 171 status = pjsip_inv_create_uas( dlg, rdata, answer, 0, &inv); 172 if (status != PJ_SUCCESS) { 173 174 status = pjsip_dlg_create_response( dlg, rdata, 500, NULL, 175 &response); 176 if (status == PJ_SUCCESS) 177 status = pjsip_dlg_send_response(dlg, 178 pjsip_rdata_get_tsx(rdata), 179 response); 180 return PJ_TRUE; 181 182 } 183 184 /* Answer with 100 (using the dialog, not invite): */ 185 186 status = pjsip_dlg_create_response(dlg, rdata, 100, NULL, &response); 187 if (status == PJ_SUCCESS) 188 status = pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), response); 189 } 190 191 /* This INVITE request has been handled. */ 192 return PJ_TRUE; 193 } 194 195 196 106 197 return PJ_FALSE; 107 198 } … … 122 213 { 123 214 PJ_UNUSED_ARG(rdata); 124 PJ_TODO(IMPLEMENT_UAS);125 215 return PJ_FALSE; 126 216 } -
pjproject/trunk/pjsip/src/test-pjsip/tsx_uas_test.c
r127 r160 710 710 return PJ_TRUE; 711 711 } 712 pjsip_tsx_recv_msg(tsx, rdata); 712 713 713 714 save_key(tsx); … … 750 751 return PJ_TRUE; 751 752 } 753 pjsip_tsx_recv_msg(tsx, rdata); 752 754 753 755 save_key(tsx); … … 802 804 } 803 805 806 pjsip_tsx_recv_msg(tsx, rdata); 804 807 save_key(tsx); 805 808 … … 883 886 } 884 887 888 pjsip_tsx_recv_msg(tsx, rdata); 885 889 save_key(tsx); 886 890 … … 967 971 } 968 972 973 pjsip_tsx_recv_msg(tsx, rdata); 969 974 save_key(tsx); 970 975 send_response(rdata, tsx, TEST9_STATUS_CODE); … … 1077 1082 } 1078 1083 1084 pjsip_tsx_recv_msg(tsx, rdata); 1079 1085 save_key(tsx); 1080 1086
Note: See TracChangeset
for help on using the changeset viewer.