Changeset 156


Ignore:
Timestamp:
Feb 8, 2006 11:16:05 AM (18 years ago)
Author:
bennylp
Message:

Initial UAS implementation in invite session

Location:
pjproject/trunk/pjsip
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/build/pjsua.dsp

    r147 r156  
    100100 
    101101SOURCE=..\src\pjsua\main_old.c 
    102  
    103 !IF  "$(CFG)" == "pjsua - Win32 Release" 
    104  
    105 !ELSEIF  "$(CFG)" == "pjsua - Win32 Debug" 
    106  
    107102# PROP Exclude_From_Build 1 
    108  
    109 !ENDIF  
    110  
    111103# End Source File 
    112104# Begin Source File 
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c

    r145 r156  
    2727#include <pj/pool.h> 
    2828#include <pj/assert.h> 
     29#include <pj/os.h> 
    2930 
    3031#define THIS_FILE       "sip_invite_session.c" 
     
    3940static void        mod_inv_on_tsx_state(pjsip_transaction*, pjsip_event*); 
    4041 
    41 static void inv_on_state_null( pjsip_inv_session *s, pjsip_event *e); 
    42 static void inv_on_state_calling( pjsip_inv_session *s, pjsip_event *e); 
    43 static void inv_on_state_incoming( pjsip_inv_session *s, pjsip_event *e); 
    44 static void inv_on_state_early( pjsip_inv_session *s, pjsip_event *e); 
    45 static void inv_on_state_connecting( pjsip_inv_session *s, pjsip_event *e); 
    46 static void inv_on_state_confirmed( pjsip_inv_session *s, pjsip_event *e); 
    47 static void inv_on_state_disconnected( pjsip_inv_session *s, pjsip_event *e); 
    48 static void inv_on_state_terminated( pjsip_inv_session *s, pjsip_event *e); 
    49  
    50 static void (*inv_state_handler[])( pjsip_inv_session *s, pjsip_event *e) =  
     42static void inv_on_state_null( pjsip_inv_session *inv, pjsip_event *e); 
     43static void inv_on_state_calling( pjsip_inv_session *inv, pjsip_event *e); 
     44static void inv_on_state_incoming( pjsip_inv_session *inv, pjsip_event *e); 
     45static void inv_on_state_early( pjsip_inv_session *inv, pjsip_event *e); 
     46static void inv_on_state_connecting( pjsip_inv_session *inv, pjsip_event *e); 
     47static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e); 
     48static void inv_on_state_disconnected( pjsip_inv_session *inv, pjsip_event *e); 
     49 
     50static void (*inv_state_handler[])( pjsip_inv_session *inv, pjsip_event *e) =  
    5151{ 
    5252    &inv_on_state_null, 
     
    5757    &inv_on_state_confirmed, 
    5858    &inv_on_state_disconnected, 
    59     &inv_on_state_terminated, 
    6059}; 
    6160 
     
    8786 
    8887 
    89  
     88/* 
     89 * Module load() 
     90 */ 
    9091static pj_status_t mod_inv_load(pjsip_endpoint *endpt) 
    9192{ 
     
    99100} 
    100101 
     102/* 
     103 * Module unload() 
     104 */ 
    101105static pj_status_t mod_inv_unload(void) 
    102106{ 
     
    105109} 
    106110 
    107 static pj_bool_t mod_inv_on_rx_request(pjsip_rx_data *rdata) 
    108 { 
    109     pjsip_dialog *dlg; 
    110  
    111     /* Ignore requests outside dialog */ 
    112     dlg = pjsip_rdata_get_dlg(rdata); 
    113     if (dlg == NULL) 
    114         return PJ_FALSE; 
    115  
    116     /* Answer BYE with 200/OK. */ 
    117     if (rdata->msg_info.msg->line.req.method.id == PJSIP_BYE_METHOD) { 
    118         pj_status_t status; 
    119         pjsip_tx_data *tdata; 
    120  
    121         status = pjsip_dlg_create_response(dlg, rdata, 200, NULL, &tdata); 
    122         if (status == PJ_SUCCESS) 
    123             status = pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), 
    124                                              tdata); 
    125  
    126         return status==PJ_SUCCESS ? PJ_TRUE : PJ_FALSE; 
    127     } 
    128  
    129     return PJ_FALSE; 
    130 } 
    131  
    132 static pj_status_t send_ack(pjsip_inv_session *inv, pjsip_rx_data *rdata) 
     111/* 
     112 * Send ACK for 2xx response. 
     113 */ 
     114static pj_status_t inv_send_ack(pjsip_inv_session *inv, pjsip_rx_data *rdata) 
    133115{ 
    134116    pjsip_tx_data *tdata; 
     
    153135} 
    154136 
     137/* 
     138 * Module on_rx_request() 
     139 * 
     140 * This callback is called for these events: 
     141 *  - endpoint receives request which was unhandled by higher priority 
     142 *    modules (e.g. transaction layer, dialog layer). 
     143 *  - dialog distributes incoming request to its usages. 
     144 */ 
     145static pj_bool_t mod_inv_on_rx_request(pjsip_rx_data *rdata) 
     146{ 
     147    pjsip_method *method; 
     148 
     149    /* Only wants to receive request from a dialog. */ 
     150    if (pjsip_rdata_get_dlg(rdata) == NULL) 
     151        return PJ_FALSE; 
     152 
     153    /* Report to dialog that we handle INVITE, CANCEL, BYE, ACK.  
     154     * If we need to send response, it will be sent in the state 
     155     * handlers. 
     156     */ 
     157    method = &rdata->msg_info.msg->line.req.method; 
     158 
     159    if (method->id == PJSIP_INVITE_METHOD || 
     160        method->id == PJSIP_CANCEL_METHOD || 
     161        method->id == PJSIP_ACK_METHOD || 
     162        method->id == PJSIP_BYE_METHOD) 
     163    { 
     164        return PJ_TRUE; 
     165    } 
     166 
     167    return PJ_FALSE; 
     168} 
     169 
     170/* 
     171 * Module on_rx_response(). 
     172 * 
     173 * This callback is called for these events: 
     174 *  - dialog distributes incoming 2xx response to INVITE (outside 
     175 *    transaction) to its usages. 
     176 *  - endpoint distributes strayed responses. 
     177 */ 
    155178static pj_bool_t mod_inv_on_rx_response(pjsip_rx_data *rdata) 
    156179{ 
     
    176199        rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD) { 
    177200 
    178         send_ack(inv, rdata); 
     201        inv_send_ack(inv, rdata); 
    179202        return PJ_TRUE; 
    180203 
     
    185208} 
    186209 
     210/* 
     211 * Module on_tsx_state() 
     212 * 
     213 * This callback is called by dialog framework for all transactions 
     214 * inside the dialog for all its dialog usages. 
     215 */ 
    187216static void mod_inv_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e) 
    188217{ 
     
    210239} 
    211240 
     241 
     242/* 
     243 * Initialize the invite module. 
     244 */ 
    212245PJ_DEF(pj_status_t) pjsip_inv_usage_init( pjsip_endpoint *endpt, 
    213246                                          pjsip_module *app_module, 
     
    237270} 
    238271 
     272/* 
     273 * Get the instance of invite module. 
     274 */ 
    239275PJ_DEF(pjsip_module*) pjsip_inv_usage_instance(void) 
    240276{ 
     
    243279 
    244280 
     281/* 
     282 * Return the invite session for the specified dialog. 
     283 */ 
    245284PJ_DEF(pjsip_inv_session*) pjsip_dlg_get_inv_session(pjsip_dialog *dlg) 
    246285{ 
     
    248287} 
    249288 
    250 /* 
    251  * Create UAC session. 
     289 
     290/* 
     291 * Create UAC invite session. 
    252292 */ 
    253293PJ_DEF(pj_status_t) pjsip_inv_create_uac( pjsip_dialog *dlg, 
     
    349389    pj_list_init(&res_hdr_list); 
    350390 
    351     /* Check the request body, see if it's something that we support 
     391    /* Check the request body, see if it'inv something that we support 
    352392     * (i.e. SDP).  
    353393     */ 
     
    624664 
    625665/* 
    626  * Create UAS session. 
     666 * Create UAS invite session. 
    627667 */ 
    628668PJ_DEF(pj_status_t) pjsip_inv_create_uas( pjsip_dialog *dlg, 
     
    663703    inv->pool = dlg->pool; 
    664704    inv->role = PJSIP_ROLE_UAS; 
    665     inv->state = PJSIP_INV_STATE_NULL; 
     705    inv->state = PJSIP_INV_STATE_INCOMING; 
    666706    inv->dlg = dlg; 
    667707    inv->options = options; 
     
    855895    } 
    856896 
    857     /* Do we need to increment tdata's reference counter? */ 
     897    /* Do we need to increment tdata'inv reference counter? */ 
    858898    PJ_TODO(INV_ANSWER_MAY_HAVE_TO_INCREMENT_REF_COUNTER); 
    859899 
     
    10381078} 
    10391079 
    1040 static void inv_on_state_null( pjsip_inv_session *s, pjsip_event *e) 
     1080 
     1081 
     1082/* 
     1083 * Respond to incoming CANCEL request. 
     1084 */ 
     1085static void inv_respond_incoming_cancel(pjsip_inv_session *inv, 
     1086                                        pjsip_transaction *cancel_tsx, 
     1087                                        pjsip_rx_data *rdata) 
     1088{ 
     1089    pjsip_tx_data *tdata; 
     1090    pjsip_transaction *invite_tsx; 
     1091    pj_str_t key; 
     1092    pj_status_t status; 
     1093 
     1094    /* See if we have matching INVITE server transaction: */ 
     1095 
     1096    pjsip_tsx_create_key(rdata->tp_info.pool, &key, PJSIP_ROLE_UAS, 
     1097                         &pjsip_invite_method, rdata); 
     1098    invite_tsx = pjsip_tsx_layer_find_tsx(&key, PJ_TRUE); 
     1099 
     1100    if (invite_tsx == NULL) { 
     1101 
     1102        /* Invite transaction not found!  
     1103         * Respond CANCEL with 491 (RFC 3261 Section 9.2 page 42) 
     1104         */ 
     1105        status = pjsip_dlg_create_response( inv->dlg, rdata, 200, NULL,  
     1106                                            &tdata); 
     1107 
     1108    } else { 
     1109        /* Always answer CANCEL will 200 (OK) regardless of 
     1110         * the state of the INVITE transaction. 
     1111         */ 
     1112        status = pjsip_dlg_create_response( inv->dlg, rdata, 200, NULL,  
     1113                                            &tdata); 
     1114    } 
     1115 
     1116    /* See if we have created the response successfully. */ 
     1117    if (status != PJ_SUCCESS) return; 
     1118 
     1119    /* Send the CANCEL response */ 
     1120    status = pjsip_dlg_send_response(inv->dlg, cancel_tsx, tdata); 
     1121    if (status != PJ_SUCCESS) return; 
     1122 
     1123 
     1124    /* See if we need to terminate the UAS INVITE transaction 
     1125     * with 487 (Request Terminated) response.  
     1126     */ 
     1127    if (invite_tsx && invite_tsx->status_code < 200) { 
     1128 
     1129        pj_assert(invite_tsx->last_tx != NULL); 
     1130 
     1131        tdata = invite_tsx->last_tx; 
     1132 
     1133        status = pjsip_dlg_modify_response(inv->dlg, tdata, 487, NULL); 
     1134        if (status == PJ_SUCCESS) 
     1135            pjsip_dlg_send_response(inv->dlg, invite_tsx, tdata); 
     1136    } 
     1137 
     1138    if (invite_tsx) 
     1139        pj_mutex_unlock(invite_tsx->mutex); 
     1140} 
     1141 
     1142 
     1143/* 
     1144 * Respond to incoming BYE request. 
     1145 */ 
     1146static void inv_respond_incoming_bye( pjsip_inv_session *inv, 
     1147                                      pjsip_transaction *bye_tsx, 
     1148                                      pjsip_rx_data *rdata, 
     1149                                      pjsip_event *e ) 
     1150{ 
     1151    pj_status_t status; 
     1152    pjsip_tx_data *tdata; 
     1153 
     1154    /* Respond BYE with 200: */ 
     1155 
     1156    status = pjsip_dlg_create_response(inv->dlg, rdata, 200, NULL, &tdata); 
     1157    if (status != PJ_SUCCESS) return; 
     1158 
     1159    status = pjsip_dlg_send_response(inv->dlg, bye_tsx, tdata); 
     1160    if (status != PJ_SUCCESS) return; 
     1161 
     1162    /* Terminate session: */ 
     1163 
     1164    if (inv->state != PJSIP_INV_STATE_DISCONNECTED) 
     1165        inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
     1166} 
     1167 
     1168/* 
     1169 * State NULL is before anything is sent/received. 
     1170 */ 
     1171static void inv_on_state_null( pjsip_inv_session *inv, pjsip_event *e) 
    10411172{ 
    10421173    pjsip_transaction *tsx = e->body.tsx_state.tsx; 
     
    10501181 
    10511182            /* Keep the initial INVITE transaction. */ 
    1052             if (s->invite_tsx == NULL) 
    1053                 s->invite_tsx = tsx; 
     1183            if (inv->invite_tsx == NULL) 
     1184                inv->invite_tsx = tsx; 
    10541185 
    10551186            switch (tsx->state) { 
    10561187            case PJSIP_TSX_STATE_CALLING: 
    1057                 inv_set_state(s, PJSIP_INV_STATE_CALLING, e); 
     1188                inv_set_state(inv, PJSIP_INV_STATE_CALLING, e); 
    10581189                break; 
    10591190            default: 
     
    10651196            switch (tsx->state) { 
    10661197            case PJSIP_TSX_STATE_TRYING: 
    1067                 inv_set_state(s, PJSIP_INV_STATE_INCOMING, e); 
     1198                inv_set_state(inv, PJSIP_INV_STATE_INCOMING, e); 
    10681199                break; 
    10691200            default: 
     
    10771208} 
    10781209 
    1079 static void inv_on_state_calling( pjsip_inv_session *s, pjsip_event *e) 
     1210/* 
     1211 * State CALLING is after sending initial INVITE request but before 
     1212 * any response (with tag) is received. 
     1213 */ 
     1214static void inv_on_state_calling( pjsip_inv_session *inv, pjsip_event *e) 
    10801215{ 
    10811216    pjsip_transaction *tsx = e->body.tsx_state.tsx; 
     
    10851220    PJ_ASSERT_ON_FAIL(tsx && dlg, return); 
    10861221     
    1087     if (tsx == s->invite_tsx) { 
     1222    if (tsx == inv->invite_tsx) { 
    10881223 
    10891224        switch (tsx->state) { 
     
    10911226        case PJSIP_TSX_STATE_PROCEEDING: 
    10921227            if (dlg->remote.info->tag.slen) { 
    1093                 inv_set_state(s, PJSIP_INV_STATE_EARLY, e); 
     1228                inv_set_state(inv, PJSIP_INV_STATE_EARLY, e); 
    10941229            } else { 
    10951230                /* Ignore 100 (Trying) response, as it doesn't change 
     
    11061241                 */ 
    11071242                pj_assert(0); 
    1108                 inv_set_state(s, PJSIP_INV_STATE_CONNECTING, e); 
     1243                inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e); 
    11091244 
    11101245            } else if (tsx->status_code==401 || tsx->status_code==407) { 
     
    11151250                pjsip_tx_data *tdata; 
    11161251 
    1117                 status = pjsip_auth_clt_reinit_req(&s->dlg->auth_sess,  
     1252                status = pjsip_auth_clt_reinit_req(&inv->dlg->auth_sess,  
    11181253                                                   e->body.tsx_state.src.rdata, 
    11191254                                                   tsx->last_tx, 
     
    11251260                     * End the session. 
    11261261                     */ 
    1127                     inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
     1262                    inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    11281263 
    11291264                } else { 
    11301265 
    11311266                    /* Restart session. */ 
    1132                     s->state = PJSIP_INV_STATE_NULL; 
    1133                     s->invite_tsx = NULL; 
     1267                    inv->state = PJSIP_INV_STATE_NULL; 
     1268                    inv->invite_tsx = NULL; 
    11341269 
    11351270                    /* Send the request. */ 
    1136                     status = pjsip_inv_send_msg(s, tdata, NULL ); 
     1271                    status = pjsip_inv_send_msg(inv, tdata, NULL ); 
    11371272                } 
    11381273 
    11391274            } else { 
    11401275 
    1141                 inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
     1276                inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    11421277 
    11431278            } 
     
    11531288 
    11541289                /* Set state to CONNECTING */ 
    1155                 inv_set_state(s, PJSIP_INV_STATE_CONNECTING, e); 
     1290                inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e); 
    11561291 
    11571292                /* Send ACK */ 
    11581293                pj_assert(e->body.tsx_state.type == PJSIP_EVENT_RX_MSG); 
    11591294 
    1160                 send_ack(s, e->body.tsx_state.src.rdata); 
     1295                inv_send_ack(inv, e->body.tsx_state.src.rdata); 
    11611296 
    11621297            } else  { 
    1163                 inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
     1298                inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    11641299            } 
    11651300            break; 
    11661301 
    1167         default: 
    1168             pj_assert(!"Unexpected state"); 
    1169         } 
    1170  
    1171     } else { 
    1172         pj_assert(!"Unexpected transaction type"); 
    1173     } 
    1174 } 
    1175  
    1176 static void inv_on_state_incoming( pjsip_inv_session *s, pjsip_event *e) 
     1302        } 
     1303    } 
     1304} 
     1305 
     1306/* 
     1307 * State INCOMING is after we received the request, but before 
     1308 * responses with tag are sent. 
     1309 */ 
     1310static void inv_on_state_incoming( pjsip_inv_session *inv, pjsip_event *e) 
    11771311{ 
    11781312    pjsip_transaction *tsx = e->body.tsx_state.tsx; 
     
    11811315    PJ_ASSERT_ON_FAIL(tsx && dlg, return); 
    11821316 
    1183     if (tsx == s->invite_tsx) { 
     1317    if (tsx == inv->invite_tsx) { 
     1318 
     1319        /* 
     1320         * Handle the INVITE state transition. 
     1321         */ 
     1322 
    11841323        switch (tsx->state) { 
     1324 
    11851325        case PJSIP_TSX_STATE_PROCEEDING: 
     1326            /* 
     1327             * Transaction sent provisional response. 
     1328             */ 
    11861329            if (tsx->status_code > 100) 
    1187                 inv_set_state(s, PJSIP_INV_STATE_EARLY, e); 
     1330                inv_set_state(inv, PJSIP_INV_STATE_EARLY, e); 
    11881331            break; 
     1332 
     1333        case PJSIP_TSX_STATE_COMPLETED: 
     1334            /* 
     1335             * Transaction sent final response. 
     1336             */ 
     1337            if (tsx->status_code/100 == 2) 
     1338                inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e); 
     1339            else 
     1340                inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
     1341            break; 
     1342 
     1343        case PJSIP_TSX_STATE_TERMINATED: 
     1344            /*  
     1345             * This happens on transport error (e.g. failed to send 
     1346             * response) 
     1347             */ 
     1348            inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
     1349            break; 
     1350 
     1351        default: 
     1352            pj_assert(!"Unexpected INVITE state"); 
     1353            break; 
     1354        } 
     1355 
     1356    } else if (tsx->method.id == PJSIP_CANCEL_METHOD && 
     1357               tsx->role == PJSIP_ROLE_UAS && 
     1358               tsx->state < PJSIP_TSX_STATE_COMPLETED && 
     1359               e->body.tsx_state.type == PJSIP_EVENT_RX_MSG ) 
     1360    { 
     1361 
     1362        /* 
     1363         * Handle incoming CANCEL request. 
     1364         */ 
     1365 
     1366        inv_respond_incoming_cancel(inv, tsx, e->body.tsx_state.src.rdata); 
     1367 
     1368    } 
     1369} 
     1370 
     1371/* 
     1372 * State EARLY is for both UAS and UAC, after response with To tag 
     1373 * is sent/received. 
     1374 */ 
     1375static void inv_on_state_early( pjsip_inv_session *inv, pjsip_event *e) 
     1376{ 
     1377    pjsip_transaction *tsx = e->body.tsx_state.tsx; 
     1378    pjsip_dialog *dlg = pjsip_tsx_get_dlg(tsx); 
     1379 
     1380    PJ_ASSERT_ON_FAIL(tsx && dlg, return); 
     1381 
     1382    if (tsx == inv->invite_tsx) { 
     1383 
     1384        /* 
     1385         * Handle the INVITE state progress. 
     1386         */ 
     1387 
     1388        switch (tsx->state) { 
     1389 
     1390        case PJSIP_TSX_STATE_PROCEEDING: 
     1391            /* Send/received another provisional response. */ 
     1392            inv_set_state(inv, PJSIP_INV_STATE_EARLY, e); 
     1393            break; 
     1394 
    11891395        case PJSIP_TSX_STATE_COMPLETED: 
    11901396            if (tsx->status_code/100 == 2) 
    1191                 inv_set_state(s, PJSIP_INV_STATE_CONNECTING, e); 
     1397                inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e); 
    11921398            else 
    1193                 inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
    1194             break; 
    1195         case PJSIP_TSX_STATE_TERMINATED: 
    1196             /* This happens on transport error */ 
    1197             inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
    1198             break; 
    1199         default: 
    1200             pj_assert(!"Unexpected state"); 
    1201         } 
    1202     } else { 
    1203         pj_assert(!"Unexpected transaction type"); 
    1204     } 
    1205 } 
    1206  
    1207 static void inv_on_state_early( pjsip_inv_session *s, pjsip_event *e) 
    1208 { 
    1209     pjsip_transaction *tsx = e->body.tsx_state.tsx; 
    1210     pjsip_dialog *dlg = pjsip_tsx_get_dlg(tsx); 
    1211  
    1212     PJ_ASSERT_ON_FAIL(tsx && dlg, return); 
    1213  
    1214     if (tsx == s->invite_tsx) { 
    1215  
    1216         switch (tsx->state) { 
    1217  
    1218         case PJSIP_TSX_STATE_PROCEEDING: 
    1219             /* Send/received another provisional response. */ 
    1220             inv_set_state(s, PJSIP_INV_STATE_EARLY, e); 
    1221             break; 
    1222  
    1223         case PJSIP_TSX_STATE_COMPLETED: 
    1224             if (tsx->status_code/100 == 2) 
    1225                 inv_set_state(s, PJSIP_INV_STATE_CONNECTING, e); 
    1226             else 
    1227                 inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
     1399                inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    12281400            break; 
    12291401 
     
    12381410 
    12391411                /* Set state to CONNECTING */ 
    1240                 inv_set_state(s, PJSIP_INV_STATE_CONNECTING, e); 
     1412                inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e); 
    12411413 
    12421414                /* if UAC, send ACK and move state to confirmed. */ 
     
    12441416                    pj_assert(e->body.tsx_state.type == PJSIP_EVENT_RX_MSG); 
    12451417 
    1246                     send_ack(s, e->body.tsx_state.src.rdata); 
    1247  
    1248                     inv_set_state(s, PJSIP_INV_STATE_CONFIRMED, e); 
     1418                    inv_send_ack(inv, e->body.tsx_state.src.rdata); 
     1419 
     1420                    inv_set_state(inv, PJSIP_INV_STATE_CONFIRMED, e); 
    12491421                } 
    12501422 
    12511423            } else  { 
    1252                 inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
     1424                inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    12531425            } 
    12541426            break; 
    12551427 
    12561428        default: 
    1257             pj_assert(!"Unexpected state"); 
    1258         } 
    1259  
    1260     } else if (tsx->method.id == PJSIP_CANCEL_METHOD) { 
    1261  
    1262         /* Handle incoming CANCEL request. */ 
    1263         if (tsx->role == PJSIP_ROLE_UAS && s->role == PJSIP_ROLE_UAS && 
    1264             e->body.tsx_state.type == PJSIP_EVENT_RX_MSG)  
    1265         { 
    1266  
    1267             pj_status_t status; 
    1268             pjsip_tx_data *tdata; 
    1269  
    1270             /* Respond CANCEL with 200 (OK) */ 
    1271             status = pjsip_dlg_create_response(dlg, e->body.tsx_state.src.rdata, 
    1272                                                200, NULL, &tdata); 
    1273             if (status == PJ_SUCCESS) { 
    1274                 pjsip_dlg_send_response(dlg, tsx, tdata); 
    1275             } 
    1276      
    1277             /* Respond the original UAS transaction with 487 (Request  
    1278              * Terminated) response. 
    1279              */ 
    1280             pj_assert(s->invite_tsx && s->invite_tsx->last_tx); 
    1281             tdata = s->invite_tsx->last_tx; 
    1282  
    1283             status = pjsip_dlg_modify_response(dlg, tdata, 487, NULL); 
    1284             if (status == PJ_SUCCESS) { 
    1285                 pjsip_dlg_send_response(dlg, s->invite_tsx, tdata); 
    1286             } 
    1287         } 
    1288  
    1289     } else if (tsx->method.id == PJSIP_INVITE_METHOD) { 
    1290  
    1291         /* Ignore previously failed INVITE transaction event 
    1292          * (e.g. when rejected with 401/407) 
     1429            pj_assert(!"Unexpected INVITE tsx state"); 
     1430        } 
     1431 
     1432    } else if (inv->role == PJSIP_ROLE_UAS && 
     1433               tsx->role == PJSIP_ROLE_UAS && 
     1434               tsx->method.id == PJSIP_CANCEL_METHOD && 
     1435               tsx->state < PJSIP_TSX_STATE_COMPLETED && 
     1436               e->body.tsx_state.type == PJSIP_EVENT_RX_MSG ) 
     1437    { 
     1438 
     1439        /* 
     1440         * Handle incoming CANCEL request. 
    12931441         */ 
    12941442 
    1295     } else { 
    1296         pj_assert(!"Unexpected transaction type"); 
    1297     } 
    1298 } 
    1299  
    1300 static void inv_on_state_connecting( pjsip_inv_session *s, pjsip_event *e) 
     1443        inv_respond_incoming_cancel(inv, tsx, e->body.tsx_state.src.rdata); 
     1444 
     1445    } 
     1446} 
     1447 
     1448/* 
     1449 * State CONNECTING is after 2xx response to INVITE is sent/received. 
     1450 */ 
     1451static void inv_on_state_connecting( pjsip_inv_session *inv, pjsip_event *e) 
    13011452{ 
    13021453    pjsip_transaction *tsx = e->body.tsx_state.tsx; 
     
    13051456    PJ_ASSERT_ON_FAIL(tsx && dlg, return); 
    13061457 
    1307     if (tsx == s->invite_tsx) { 
    1308  
     1458    if (tsx == inv->invite_tsx) { 
     1459 
     1460        /* 
     1461         * Handle INVITE state progression. 
     1462         */ 
    13091463        switch (tsx->state) { 
    13101464 
     
    13181472             */ 
    13191473            if (tsx->status_code/100 != 2) { 
    1320                 inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
     1474                inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
    13211475            } 
    13221476            break; 
     
    13301484        } 
    13311485 
    1332     } else { 
    1333         pj_assert(!"Unexpected transaction type"); 
    1334     } 
    1335 } 
    1336  
    1337 static void inv_on_state_confirmed( pjsip_inv_session *s, pjsip_event *e) 
     1486    } else if (tsx->role == PJSIP_ROLE_UAS && 
     1487               tsx->method.id == PJSIP_BYE_METHOD && 
     1488               tsx->status_code < 200 && 
     1489               e->body.tsx_state.type == PJSIP_EVENT_RX_MSG)  
     1490    { 
     1491 
     1492        /* 
     1493         * Handle incoming BYE. 
     1494         */ 
     1495 
     1496        inv_respond_incoming_bye( inv, tsx, e->body.tsx_state.src.rdata, e ); 
     1497 
     1498    } 
     1499} 
     1500 
     1501/* 
     1502 * State CONFIRMED is after ACK is sent/received. 
     1503 */ 
     1504static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e) 
    13381505{ 
    13391506    pjsip_transaction *tsx = e->body.tsx_state.tsx; 
     
    13421509    PJ_ASSERT_ON_FAIL(tsx && dlg, return); 
    13431510 
    1344     if (tsx->method.id == PJSIP_BYE_METHOD) { 
    1345         inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
    1346  
    1347     } else if (tsx == s->invite_tsx) { 
     1511 
     1512    if (tsx->method.id == PJSIP_BYE_METHOD && 
     1513        tsx->role == PJSIP_ROLE_UAC && 
     1514        tsx->state == PJSIP_TSX_STATE_COMPLETED) 
     1515    { 
     1516        /* 
     1517         * Outgoing BYE. 
     1518         */ 
     1519        pj_status_t status; 
    13481520         
    1349         switch (tsx->state) { 
    1350         case PJSIP_TSX_STATE_TERMINATED: 
    1351         case PJSIP_TSX_STATE_DESTROYED: 
    1352             break; 
    1353         default: 
    1354             pj_assert(!"Unexpected state"); 
    1355             break; 
    1356         } 
    1357  
    1358     } else if (tsx->method.id == PJSIP_INVITE_METHOD) { 
    1359  
    1360         /* Re-INVITE */ 
    1361  
    1362     } else { 
    1363         pj_assert(!"Unexpected transaction type"); 
    1364     } 
    1365 } 
    1366  
    1367 static void inv_on_state_disconnected( pjsip_inv_session *s, pjsip_event *e) 
    1368 { 
    1369     PJ_UNUSED_ARG(s); 
    1370     PJ_UNUSED_ARG(e); 
    1371 } 
    1372  
    1373 static void inv_on_state_terminated( pjsip_inv_session *s, pjsip_event *e) 
    1374 { 
    1375     PJ_UNUSED_ARG(s); 
    1376     PJ_UNUSED_ARG(e); 
    1377 } 
    1378  
     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 
     1547            inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
     1548        } 
     1549 
     1550    } 
     1551    else if (tsx->method.id == PJSIP_BYE_METHOD && 
     1552             tsx->role == PJSIP_ROLE_UAS && 
     1553             tsx->status_code < 200 && 
     1554             e->body.tsx_state.type == PJSIP_EVENT_RX_MSG)  
     1555    { 
     1556 
     1557        /* 
     1558         * Handle incoming BYE. 
     1559         */ 
     1560 
     1561        inv_respond_incoming_bye( inv, tsx, e->body.tsx_state.src.rdata, e ); 
     1562 
     1563    } 
     1564} 
     1565 
     1566/* 
     1567 * After session has been terminated, but before dialog is destroyed 
     1568 * (because dialog has other usages, or because dialog is waiting for 
     1569 * the last transaction to terminate). 
     1570 */ 
     1571static void inv_on_state_disconnected( pjsip_inv_session *inv, pjsip_event *e) 
     1572{ 
     1573    pjsip_transaction *tsx = e->body.tsx_state.tsx; 
     1574    pjsip_dialog *dlg = pjsip_tsx_get_dlg(tsx); 
     1575 
     1576    PJ_ASSERT_ON_FAIL(tsx && dlg, return); 
     1577 
     1578    if (tsx->method.id == PJSIP_BYE_METHOD && 
     1579        tsx->role == PJSIP_ROLE_UAS && 
     1580        tsx->status_code < 200 && 
     1581        e->body.tsx_state.type == PJSIP_EVENT_RX_MSG)  
     1582    { 
     1583 
     1584        /* 
     1585         * Be nice, handle incoming BYE. 
     1586         */ 
     1587 
     1588        inv_respond_incoming_bye( inv, tsx, e->body.tsx_state.src.rdata, e ); 
     1589 
     1590    } 
     1591} 
     1592 
  • pjproject/trunk/pjsip/src/pjsip/sip_util.c

    r141 r156  
    537537    const pjsip_cseq_hdr *cseq_hdr; 
    538538    const pjsip_hdr *hdr; 
     539    pjsip_hdr *via; 
    539540    pj_status_t status; 
    540541 
     
    572573    if (status != PJ_SUCCESS) 
    573574        return status; 
     575 
     576    /* Clear Via headers in the new request. */ 
     577    while ((via=pjsip_msg_find_hdr(cancel_tdata->msg, PJSIP_H_VIA, NULL)) != NULL) 
     578        pj_list_erase(via); 
     579 
    574580 
    575581    /* Must only have single Via which matches the top-most Via in the  
Note: See TracChangeset for help on using the changeset viewer.