Ignore:
Timestamp:
Feb 8, 2006 10:44:25 PM (18 years ago)
Author:
bennylp
Message:

Finished invite session UAS implementation

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsip/sip_dialog.c

    r141 r160  
    7575    dlg->ua = ua; 
    7676    dlg->endpt = endpt; 
     77    dlg->state = PJSIP_DIALOG_STATE_NULL; 
    7778 
    7879    status = pj_mutex_create_recursive(pool, "dlg%p", &dlg->mutex); 
     
    375376    PJ_TODO(DIALOG_APP_TIMER); 
    376377 
     378    /* Feed the first request to the transaction. */ 
     379    pjsip_tsx_recv_msg(tsx, rdata); 
     380 
    377381    /* Done. */ 
    378382    *p_dlg = dlg; 
     
    408412                     PJSIP_ENOTRESPONSEMSG); 
    409413 
     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 
    410419    /* To tag must present in the response. */ 
    411420    PJ_ASSERT_RETURN(rdata->msg_info.to->tag.slen != 0, PJSIP_EMISSINGTAG); 
     
    444453    /* Initial role is UAC. */ 
    445454    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    } 
    446464 
    447465    /* Secure? */ 
     
    463481    } 
    464482 
    465     /* Init client authentication session. */ 
     483    /* Clone client authentication session. */ 
    466484    status = pjsip_auth_clt_clone(dlg->pool, &dlg->auth_sess,  
    467485                                  &first_dlg->auth_sess); 
     
    850868} 
    851869 
     870/* Add standard headers for certain types of response */ 
     871static 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 
    852935 
    853936/* 
     
    861944{ 
    862945    pj_status_t status; 
    863     pjsip_cseq_hdr *cseq; 
    864946    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     */ 
    868952    status = pjsip_endpt_create_response(dlg->endpt, 
    869953                                         rdata, st_code, st_text, &tdata); 
     
    874958    pj_mutex_lock(dlg->mutex); 
    875959 
    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); 
    960961 
    961962    /* Unlock the dialog. */ 
     
    981982    PJ_ASSERT_RETURN(st_code >= 100 && st_code <= 699, PJ_EINVAL); 
    982983 
     984    pj_mutex_lock(dlg->mutex); 
     985 
     986    /* Replace status code and reason */ 
    983987    tdata->msg->line.status.code = st_code; 
    984988    if (st_text) { 
     
    987991        tdata->msg->line.status.reason = *pjsip_get_status_text(st_code); 
    988992    } 
     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); 
    9891004 
    9901005    return PJ_SUCCESS; 
     
    10581073{ 
    10591074    pj_status_t status; 
    1060     pjsip_transaction *tsx; 
     1075    pjsip_transaction *tsx = NULL; 
    10611076    unsigned i; 
    10621077 
     
    10651080 
    10661081    /* 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    { 
    10681086        /* Invalid CSeq. 
    10691087         * Respond statelessly with 500 (Internal Server Error) 
    10701088         */ 
    10711089        pj_mutex_unlock(dlg->mutex); 
     1090        pj_assert(pjsip_rdata_get_tsx(rdata) == NULL); 
    10721091        pjsip_endpt_respond_stateless(dlg->endpt, 
    10731092                                      rdata, 500, NULL, NULL, NULL); 
     
    10791098 
    10801099    /* 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    } 
    10891110 
    10901111    /* Report the request to dialog usages. */ 
     
    11011122    } 
    11021123 
    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); 
    11251127 
    11261128on_return: 
     
    11431145    pj_assert(pjsip_rdata_get_dlg(rdata) == dlg); 
    11441146 
    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  
    11531147    /* Keep the response's status code */ 
    11541148    res_code = rdata->msg_info.msg->line.status.code; 
    11551149 
    1156     /* When we receive response that establishes dialog, update the route 
    1157      * 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 &&  
    11601154        pjsip_method_creates_dialog(&rdata->msg_info.cseq->method) && 
    11611155        (res_code > 100 && res_code < 300) && 
    11621156        rdata->msg_info.to->tag.slen) 
    11631157    { 
     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 
    11641166        /* RFC 3271 Section 12.1.2: 
    11651167         * The route set MUST be set to the list of URIs in the Record-Route 
     
    11701172         * route set for future requests in this dialog. 
    11711173         */ 
    1172         pjsip_hdr *hdr, *end_hdr; 
    1173         pjsip_contact_hdr *contact; 
    1174  
    11751174        pj_list_init(&dlg->route_set); 
    11761175 
     
    11951194        } 
    11961195 
    1197         dlg->established = 1; 
     1196        dlg->state = PJSIP_DIALOG_STATE_ESTABLISHED; 
    11981197    } 
    11991198 
     
    12521251        --dlg->tsx_count; 
    12531252 
     1253    /* Increment session to prevent usages from destroying dialog. */ 
     1254    ++dlg->sess_count; 
     1255 
    12541256    /* Pass to dialog usages. */ 
    12551257    for (i=0; i<dlg->usage_cnt; ++i) { 
     
    12601262        (*dlg->usage[i]->on_tsx_state)(tsx, e); 
    12611263    } 
     1264 
     1265    /* Decrement temporary session. */ 
     1266    --dlg->sess_count; 
    12621267 
    12631268    if (tsx->state == PJSIP_TSX_STATE_TERMINATED && dlg->tsx_count == 0 &&  
Note: See TracChangeset for help on using the changeset viewer.