Changeset 160 for pjproject/trunk/pjsip/src/pjsip/sip_dialog.c
- Timestamp:
- Feb 8, 2006 10:44:25 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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 &&
Note: See TracChangeset
for help on using the changeset viewer.