Changeset 212 for pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
- Timestamp:
- Feb 21, 2006 11:47:00 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
r184 r212 201 201 * move state to CONFIRMED. 202 202 */ 203 if (method->id == PJSIP_ACK_METHOD && inv && 204 inv->state != PJSIP_INV_STATE_CONFIRMED) 205 { 206 pjsip_event event; 203 if (method->id == PJSIP_ACK_METHOD && inv) { 207 204 208 205 /* Terminate INVITE transaction, if it's still present. */ … … 215 212 } 216 213 217 PJSIP_EVENT_INIT_RX_MSG(event, rdata); 218 inv_set_state(inv, PJSIP_INV_STATE_CONFIRMED, &event); 214 if (inv->state != PJSIP_INV_STATE_CONFIRMED) { 215 pjsip_event event; 216 217 PJSIP_EVENT_INIT_RX_MSG(event, rdata); 218 inv_set_state(inv, PJSIP_INV_STATE_CONFIRMED, &event); 219 } 219 220 } 220 221 … … 251 252 */ 252 253 if (msg->type == PJSIP_RESPONSE_MSG && msg->line.status.code/100==2 && 253 rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD) { 254 rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD && 255 inv->invite_tsx == NULL) 256 { 254 257 255 258 inv_send_ack(inv, rdata); … … 866 869 pjsip_tx_data *tdata; 867 870 const pjsip_hdr *hdr; 871 pj_bool_t has_sdp; 868 872 pj_status_t status; 869 873 … … 871 875 PJ_ASSERT_RETURN(inv && p_tdata, PJ_EINVAL); 872 876 873 /* State MUST be NULL. */ 874 PJ_ASSERT_RETURN(inv->state == PJSIP_INV_STATE_NULL, PJ_EINVAL); 877 /* State MUST be NULL or CONFIRMED. */ 878 PJ_ASSERT_RETURN(inv->state == PJSIP_INV_STATE_NULL || 879 inv->state == PJSIP_INV_STATE_CONFIRMED, 880 PJ_EINVALIDOP); 875 881 876 882 /* Create the INVITE request. */ … … 880 886 return status; 881 887 888 /* If this is the first INVITE, then copy the headers from inv_hdr. 889 * These are the headers parsed from the request URI when the 890 * dialog was created. 891 */ 892 if (inv->state == PJSIP_INV_STATE_NULL) { 893 hdr = inv->dlg->inv_hdr.next; 894 895 while (hdr != &inv->dlg->inv_hdr) { 896 pjsip_msg_add_hdr(tdata->msg, 897 pjsip_hdr_shallow_clone(tdata->pool, hdr)); 898 hdr = hdr->next; 899 } 900 } 901 902 /* See if we have SDP to send. */ 903 if (inv->neg) { 904 pjmedia_sdp_neg_state neg_state; 905 906 neg_state = pjmedia_sdp_neg_get_state(inv->neg); 907 908 has_sdp = (neg_state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER || 909 (neg_state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO && 910 pjmedia_sdp_neg_has_local_answer(inv->neg))); 911 912 913 } else { 914 has_sdp = PJ_FALSE; 915 } 916 882 917 /* Add SDP, if any. */ 883 if (inv->neg && 884 pjmedia_sdp_neg_get_state(inv->neg)==PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) 885 { 918 if (has_sdp) { 886 919 const pjmedia_sdp_session *offer; 887 920 … … 941 974 * Check in incoming message for SDP offer/answer. 942 975 */ 943 static voidinv_check_sdp_in_incoming_msg( pjsip_inv_session *inv,944 945 976 static pj_status_t inv_check_sdp_in_incoming_msg( pjsip_inv_session *inv, 977 pjsip_transaction *tsx, 978 pjsip_rx_data *rdata) 946 979 { 947 980 struct tsx_inv_data *tsx_inv_data; … … 964 997 965 998 if (tsx_inv_data->sdp_done) 966 return ;999 return PJ_SUCCESS; 967 1000 968 1001 /* Check if SDP is present in the message. */ … … 971 1004 if (msg->body == NULL) { 972 1005 /* Message doesn't have body. */ 973 return ;1006 return PJ_SUCCESS; 974 1007 } 975 1008 … … 978 1011 { 979 1012 /* Message body is not "application/sdp" */ 980 return ;1013 return PJMEDIA_SDP_EINSDP; 981 1014 } 982 1015 … … 990 1023 PJ_LOG(4,(THIS_FILE, "Error parsing SDP in %s: %s", 991 1024 pjsip_rx_data_get_info(rdata), errmsg)); 992 return ;1025 return PJMEDIA_SDP_EINSDP; 993 1026 } 994 1027 … … 1016 1049 PJ_LOG(4,(THIS_FILE, "Error processing SDP offer in %s: %s", 1017 1050 pjsip_rx_data_get_info(rdata), errmsg)); 1018 return ;1051 return PJMEDIA_SDP_EINSDP; 1019 1052 } 1020 1053 1021 1054 /* Inform application about remote offer. */ 1022 1055 1023 if (mod_inv.cb.on_rx_offer) 1024 (*mod_inv.cb.on_rx_offer)(inv); 1056 if (mod_inv.cb.on_rx_offer) { 1057 1058 (*mod_inv.cb.on_rx_offer)(inv, sdp); 1059 1060 } 1025 1061 1026 1062 } else if (pjmedia_sdp_neg_get_state(inv->neg) == … … 1042 1078 PJ_LOG(4,(THIS_FILE, "Error processing SDP answer in %s: %s", 1043 1079 pjsip_rx_data_get_info(rdata), errmsg)); 1044 return ;1080 return PJMEDIA_SDP_EINSDP; 1045 1081 } 1046 1082 … … 1060 1096 } 1061 1097 1062 } 1063 1064 1065 1066 /* 1067 * Answer initial INVITE. 1098 return PJ_SUCCESS; 1099 } 1100 1101 1102 /* 1103 * Process INVITE answer, for both initial and subsequent re-INVITE 1104 */ 1105 static pj_status_t process_answer( pjsip_inv_session *inv, 1106 int st_code, 1107 pjsip_tx_data *tdata ) 1108 { 1109 pj_status_t status; 1110 pjmedia_sdp_session *sdp = NULL; 1111 1112 /* Include SDP for 18x and 2xx response. 1113 * Also if SDP negotiator is ready, start negotiation. 1114 */ 1115 if (st_code/10 == 18 || st_code/10 == 20) { 1116 1117 pjmedia_sdp_neg_state neg_state; 1118 1119 neg_state = inv->neg ? pjmedia_sdp_neg_get_state(inv->neg) : 1120 PJMEDIA_SDP_NEG_STATE_NULL; 1121 1122 if (neg_state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) { 1123 1124 status = pjmedia_sdp_neg_get_neg_local(inv->neg, &sdp); 1125 1126 } else if (neg_state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO && 1127 pjmedia_sdp_neg_has_local_answer(inv->neg) ) 1128 { 1129 1130 status = inv_negotiate_sdp(inv); 1131 if (status != PJ_SUCCESS) 1132 return status; 1133 1134 status = pjmedia_sdp_neg_get_active_local(inv->neg, &sdp); 1135 } 1136 1137 } 1138 1139 1140 1141 /* Include SDP when it's available. 1142 * Subsequent response will include this SDP. 1143 */ 1144 if (sdp) { 1145 tdata->msg->body = create_sdp_body(tdata->pool, sdp); 1146 } 1147 1148 /* Remove message body if this is a non-2xx final response */ 1149 if (st_code >= 300) 1150 tdata->msg->body = NULL; 1151 1152 1153 return PJ_SUCCESS; 1154 } 1155 1156 1157 /* 1158 * Answer initial INVITE 1159 * Re-INVITE will be answered automatically, and will not use this function. 1068 1160 */ 1069 1161 PJ_DEF(pj_status_t) pjsip_inv_answer( pjsip_inv_session *inv, … … 1088 1180 * offer before. 1089 1181 */ 1090 if (local_sdp ) {1182 if (local_sdp && (st_code/100==1 || st_code/100==2)) { 1091 1183 1092 1184 if (inv->neg == NULL) { … … 1109 1201 } 1110 1202 1203 1204 1205 1206 /* Modify last response. */ 1111 1207 last_res = inv->invite_tsx->last_tx; 1112 1113 /* Modify last response. */1114 1208 status = pjsip_dlg_modify_response(inv->dlg, last_res, st_code, st_text); 1115 1209 if (status != PJ_SUCCESS) 1116 1210 return status; 1117 1211 1118 /* Include SDP for 18x and 2xx response. 1119 * Also if SDP negotiator is ready, start negotiation. 1120 */ 1121 if (st_code/10 == 18 || st_code/10 == 20) { 1122 1123 pjmedia_sdp_neg_state neg_state; 1124 1125 neg_state = inv->neg ? pjmedia_sdp_neg_get_state(inv->neg) : 1126 PJMEDIA_SDP_NEG_STATE_NULL; 1127 1128 if (neg_state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER || 1129 neg_state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO) 1130 { 1131 const pjmedia_sdp_session *local; 1132 1133 status = pjmedia_sdp_neg_get_neg_local(inv->neg, &local); 1134 if (status == PJ_SUCCESS) 1135 last_res->msg->body = create_sdp_body(last_res->pool, local); 1136 } 1137 1138 /* Start negotiation, if ready. */ 1139 if (neg_state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO) { 1140 status = inv_negotiate_sdp(inv); 1141 if (status != PJ_SUCCESS) { 1142 pjsip_tx_data_dec_ref(last_res); 1143 return status; 1144 } 1145 } 1146 } 1212 1213 /* Process SDP in answer */ 1214 status = process_answer(inv, st_code, last_res); 1215 if (status != PJ_SUCCESS) 1216 return status; 1147 1217 1148 1218 … … 1150 1220 1151 1221 return PJ_SUCCESS; 1222 } 1223 1224 1225 /* 1226 * Set SDP answer. 1227 */ 1228 PJ_DEF(pj_status_t) pjsip_inv_set_sdp_answer( pjsip_inv_session *inv, 1229 const pjmedia_sdp_session *sdp ) 1230 { 1231 pj_status_t status; 1232 1233 PJ_ASSERT_RETURN(inv && sdp, PJ_EINVAL); 1234 1235 pjsip_dlg_inc_lock(inv->dlg); 1236 status = pjmedia_sdp_neg_set_local_answer( inv->pool, inv->neg, sdp); 1237 pjsip_dlg_dec_lock(inv->dlg); 1238 1239 return status; 1152 1240 } 1153 1241 … … 1206 1294 PJ_ASSERT_RETURN(tdata != NULL, PJ_EINVALIDOP); 1207 1295 1208 status = pjsip_dlg_modify_response(inv->dlg, tdata, st_code, 1209 st_text); 1296 //status = pjsip_dlg_modify_response(inv->dlg, tdata, st_code, 1297 // st_text); 1298 status = pjsip_inv_answer(inv, st_code, st_text, NULL, &tdata); 1210 1299 } 1211 1300 break; … … 1248 1337 pjsip_tx_data **p_tdata ) 1249 1338 { 1250 PJ_UNUSED_ARG(inv); 1251 PJ_UNUSED_ARG(new_contact); 1252 PJ_UNUSED_ARG(new_offer); 1253 PJ_UNUSED_ARG(p_tdata); 1254 1255 PJ_TODO(CREATE_REINVITE_REQUEST); 1256 return PJ_ENOTSUP; 1339 pj_status_t status; 1340 pjsip_contact_hdr *contact_hdr = NULL; 1341 1342 /* Check arguments. */ 1343 PJ_ASSERT_RETURN(inv && p_tdata, PJ_EINVAL); 1344 1345 /* Must NOT have a pending INVITE transaction */ 1346 PJ_ASSERT_RETURN(inv->invite_tsx==NULL, PJ_EINVALIDOP); 1347 1348 1349 pjsip_dlg_inc_lock(inv->dlg); 1350 1351 if (new_contact) { 1352 pj_str_t tmp; 1353 const pj_str_t STR_CONTACT = { "Contact", 7 }; 1354 1355 pj_strdup_with_null(inv->dlg->pool, &tmp, new_contact); 1356 contact_hdr = pjsip_parse_hdr(inv->dlg->pool, &STR_CONTACT, 1357 tmp.ptr, tmp.slen, NULL); 1358 if (!contact_hdr) { 1359 status = PJSIP_EINVALIDURI; 1360 goto on_return; 1361 } 1362 } 1363 1364 1365 if (new_offer) { 1366 if (!inv->neg) { 1367 status = pjmedia_sdp_neg_create_w_local_offer(inv->pool, new_offer, 1368 &inv->neg); 1369 if (status != PJ_SUCCESS) 1370 goto on_return; 1371 1372 } else switch (pjmedia_sdp_neg_get_state(inv->neg)) { 1373 1374 case PJMEDIA_SDP_NEG_STATE_NULL: 1375 pj_assert(!"Unexpected SDP neg state NULL"); 1376 status = PJ_EBUG; 1377 goto on_return; 1378 1379 case PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER: 1380 PJ_LOG(4,(inv->obj_name, 1381 "pjsip_inv_reinvite: already have an offer, new " 1382 "offer is ignored")); 1383 break; 1384 1385 case PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER: 1386 status = pjmedia_sdp_neg_set_local_answer(inv->pool, inv->neg, 1387 new_offer); 1388 if (status != PJ_SUCCESS) 1389 goto on_return; 1390 break; 1391 1392 case PJMEDIA_SDP_NEG_STATE_WAIT_NEGO: 1393 PJ_LOG(4,(inv->obj_name, 1394 "pjsip_inv_reinvite: SDP in WAIT_NEGO state, new " 1395 "offer is ignored")); 1396 break; 1397 1398 case PJMEDIA_SDP_NEG_STATE_DONE: 1399 status = pjmedia_sdp_neg_modify_local_offer(inv->pool,inv->neg, 1400 new_offer); 1401 if (status != PJ_SUCCESS) 1402 goto on_return; 1403 break; 1404 } 1405 } 1406 1407 if (contact_hdr) 1408 inv->dlg->local.contact = contact_hdr; 1409 1410 status = pjsip_inv_invite(inv, p_tdata); 1411 1412 on_return: 1413 pjsip_dlg_dec_lock(inv->dlg); 1414 return status; 1257 1415 } 1258 1416 … … 1909 2067 1910 2068 } 2069 else if (tsx->method.id == PJSIP_INVITE_METHOD && 2070 tsx->role == PJSIP_ROLE_UAS) 2071 { 2072 2073 /* 2074 * Handle incoming re-INVITE 2075 */ 2076 if (tsx->state == PJSIP_TSX_STATE_TRYING) { 2077 2078 pjsip_rx_data *rdata = e->body.tsx_state.src.rdata; 2079 pjsip_tx_data *tdata; 2080 pj_status_t status; 2081 2082 /* Check if we have INVITE pending. */ 2083 if (inv->invite_tsx && inv->invite_tsx!=tsx) { 2084 2085 /* Can not receive re-INVITE while another one is pending. */ 2086 status = pjsip_dlg_create_response( inv->dlg, rdata, 500, NULL, 2087 &tdata); 2088 if (status != PJ_SUCCESS) 2089 return; 2090 2091 status = pjsip_dlg_send_response( inv->dlg, tsx, tdata); 2092 2093 2094 return; 2095 } 2096 2097 /* Save the invite transaction. */ 2098 inv->invite_tsx = tsx; 2099 2100 /* Process SDP in incoming message. */ 2101 status = inv_check_sdp_in_incoming_msg(inv, tsx, rdata); 2102 2103 if (status != PJ_SUCCESS) { 2104 2105 /* Not Acceptable */ 2106 const pjsip_hdr *accept; 2107 2108 status = pjsip_dlg_create_response(inv->dlg, rdata, 2109 488, NULL, &tdata); 2110 if (status != PJ_SUCCESS) 2111 return; 2112 2113 2114 accept = pjsip_endpt_get_capability(dlg->endpt, PJSIP_H_ACCEPT, 2115 NULL); 2116 if (accept) { 2117 pjsip_msg_add_hdr(tdata->msg, 2118 pjsip_hdr_clone(tdata->pool, accept)); 2119 } 2120 2121 status = pjsip_dlg_send_response(dlg, tsx, tdata); 2122 2123 return; 2124 } 2125 2126 /* Create 2xx ANSWER */ 2127 status = pjsip_dlg_create_response(dlg, rdata, 200, NULL, &tdata); 2128 if (status != PJ_SUCCESS) 2129 return; 2130 2131 /* Process SDP in the answer */ 2132 status = process_answer(inv, 200, tdata); 2133 if (status != PJ_SUCCESS) 2134 return; 2135 2136 status = pjsip_inv_send_msg(inv, tdata, NULL); 2137 2138 } 2139 2140 } 2141 else if (tsx->method.id == PJSIP_INVITE_METHOD && 2142 tsx->role == PJSIP_ROLE_UAC) 2143 { 2144 /* 2145 * Handle outgoing re-INVITE 2146 */ 2147 if (tsx->state == PJSIP_TSX_STATE_TERMINATED && 2148 tsx->status_code/100 == 2) 2149 { 2150 2151 /* Re-INVITE was accepted. */ 2152 2153 /* Process SDP */ 2154 inv_check_sdp_in_incoming_msg(inv, tsx, 2155 e->body.tsx_state.src.rdata); 2156 2157 /* Send ACK */ 2158 inv_send_ack(inv, e->body.tsx_state.src.rdata); 2159 2160 } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED && 2161 (tsx->status_code==401 || tsx->status_code==407)) 2162 { 2163 pjsip_tx_data *tdata; 2164 pj_status_t status; 2165 2166 /* Handle authentication challenge. */ 2167 status = pjsip_auth_clt_reinit_req( &dlg->auth_sess, 2168 e->body.tsx_state.src.rdata, 2169 tsx->last_tx, 2170 &tdata); 2171 if (status != PJ_SUCCESS) 2172 return; 2173 2174 /* Send re-INVITE */ 2175 status = pjsip_inv_send_msg( inv, tdata, NULL); 2176 2177 } else if (tsx->status_code==PJSIP_SC_CALL_TSX_DOES_NOT_EXIST || 2178 tsx->status_code==PJSIP_SC_REQUEST_TIMEOUT || 2179 tsx->status_code >= 700) 2180 { 2181 /* 2182 * Handle responses that terminates dialog. 2183 */ 2184 inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 2185 } 2186 } 1911 2187 } 1912 2188
Note: See TracChangeset
for help on using the changeset viewer.