⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sip_dialog.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 4 页
字号:
    for (index=0; index<dlg->usage_cnt; ++index) {	if (dlg->usage[index] == mod) {	    /* Module may be registered more than once in the same dialog.	     * For example, when call transfer fails, application may retry	     * call transfer on the same dialog.	     * So return PJ_SUCCESS here.	     */	    PJ_LOG(4,(dlg->obj_name, 		      "Module %.*s already registered as dialog usage, "		      "updating the data %p",		      (int)mod->name.slen, mod->name.ptr, mod_data));	    dlg->mod_data[mod->id] = mod_data;	    pjsip_dlg_dec_lock(dlg);	    return PJ_SUCCESS;	    //pj_assert(!"This module is already registered");	    //pjsip_dlg_dec_lock(dlg);	    //return PJSIP_ETYPEEXISTS;	}	if (dlg->usage[index]->priority > mod->priority)	    break;    }    /* index holds position to put the module.     * Insert module at this index.     */    pj_array_insert(dlg->usage, sizeof(dlg->usage[0]), dlg->usage_cnt,		    index, &mod);        /* Set module data. */    dlg->mod_data[mod->id] = mod_data;    /* Increment count. */    ++dlg->usage_cnt;    pjsip_dlg_dec_lock(dlg);    return PJ_SUCCESS;}/* * Attach module specific data to the dialog. Application can also set  * the value directly by accessing dlg->mod_data[module_id]. */PJ_DEF(pj_status_t) pjsip_dlg_set_mod_data( pjsip_dialog *dlg,					    int mod_id,					    void *data ){    PJ_ASSERT_RETURN(dlg, PJ_EINVAL);    PJ_ASSERT_RETURN(mod_id >= 0 && mod_id < PJSIP_MAX_MODULE,		     PJ_EINVAL);    dlg->mod_data[mod_id] = data;    return PJ_SUCCESS;}/** * Get module specific data previously attached to the dialog. Application * can also get value directly by accessing dlg->mod_data[module_id]. */PJ_DEF(void*) pjsip_dlg_get_mod_data( pjsip_dialog *dlg,				      int mod_id){    PJ_ASSERT_RETURN(dlg, NULL);    PJ_ASSERT_RETURN(mod_id >= 0 && mod_id < PJSIP_MAX_MODULE,		     NULL);    return dlg->mod_data[mod_id];}/* * Create a new request within dialog (i.e. after the dialog session has been * established). The construction of such requests follows the rule in  * RFC3261 section 12.2.1. */static pj_status_t dlg_create_request_throw( pjsip_dialog *dlg,					     const pjsip_method *method,					     int cseq,					     pjsip_tx_data **p_tdata ){    pjsip_tx_data *tdata;    pjsip_contact_hdr *contact;    pjsip_route_hdr *route, *end_list;    pj_status_t status;    /* Contact Header field.     * Contact can only be present in requests that establish dialog (in the      * core SIP spec, only INVITE).     */    if (pjsip_method_creates_dialog(method))	contact = dlg->local.contact;    else	contact = NULL;    /*     * Create the request by cloning from the headers in the     * dialog.     */    status = pjsip_endpt_create_request_from_hdr(dlg->endpt,						 method,						 dlg->target,						 dlg->local.info,						 dlg->remote.info,						 contact,						 dlg->call_id,						 cseq,						 NULL,						 &tdata);    if (status != PJ_SUCCESS)	return status;    /* Just copy dialog route-set to Route header.      * The transaction will do the processing as specified in Section 12.2.1     * of RFC 3261 in function tsx_process_route() in sip_transaction.c.     */    route = dlg->route_set.next;    end_list = &dlg->route_set;    for (; route != end_list; route = route->next ) {	pjsip_route_hdr *r;	r = pjsip_hdr_shallow_clone( tdata->pool, route );	pjsip_routing_hdr_set_route(r);	pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)r);    }    /* Copy authorization headers, if request is not ACK or CANCEL. */    if (method->id != PJSIP_ACK_METHOD && method->id != PJSIP_CANCEL_METHOD) {	status = pjsip_auth_clt_init_req( &dlg->auth_sess, tdata );	if (status != PJ_SUCCESS)	    return status;    }    /* Done. */    *p_tdata = tdata;    return PJ_SUCCESS;}/* * Create outgoing request. */PJ_DEF(pj_status_t) pjsip_dlg_create_request( pjsip_dialog *dlg,					      const pjsip_method *method,					      int cseq,					      pjsip_tx_data **p_tdata){    pj_status_t status;    pjsip_tx_data *tdata = NULL;    PJ_USE_EXCEPTION;    PJ_ASSERT_RETURN(dlg && method && p_tdata, PJ_EINVAL);    /* Lock dialog. */    pjsip_dlg_inc_lock(dlg);    /* Use outgoing CSeq and increment it by one. */    if (cseq <= 0)	cseq = dlg->local.cseq + 1;    /* Keep compiler happy */    status = PJ_EBUG;    /* Create the request. */    PJ_TRY {	status = dlg_create_request_throw(dlg, method, cseq, &tdata);    }    PJ_CATCH_ANY {	status = PJ_ENOMEM;    }    PJ_END;    /* Failed! Delete transmit data. */    if (status != PJ_SUCCESS && tdata) {	pjsip_tx_data_dec_ref( tdata );	tdata = NULL;    }    /* Unlock dialog. */    pjsip_dlg_dec_lock(dlg);    *p_tdata = tdata;    return status;}/* * Send request statefully, and update dialog'c CSeq. */PJ_DEF(pj_status_t) pjsip_dlg_send_request( pjsip_dialog *dlg,					    pjsip_tx_data *tdata,					    int mod_data_id,					    void *mod_data){    pjsip_transaction *tsx;    pjsip_msg *msg = tdata->msg;    pj_status_t status;    /* Check arguments. */    PJ_ASSERT_RETURN(dlg && tdata && tdata->msg, PJ_EINVAL);    PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_REQUEST_MSG,		     PJSIP_ENOTREQUESTMSG);    PJ_LOG(5,(dlg->obj_name, "Sending %s",	      pjsip_tx_data_get_info(tdata)));    /* Lock and increment session */    pjsip_dlg_inc_lock(dlg);    /* Update dialog's CSeq and message's CSeq if request is not     * ACK nor CANCEL.     */    if (msg->line.req.method.id != PJSIP_CANCEL_METHOD &&	msg->line.req.method.id != PJSIP_ACK_METHOD)     {	pjsip_cseq_hdr *ch;		ch = PJSIP_MSG_CSEQ_HDR(msg);	PJ_ASSERT_RETURN(ch!=NULL, PJ_EBUG);	ch->cseq = dlg->local.cseq++;	/* Force the whole message to be re-printed. */	pjsip_tx_data_invalidate_msg( tdata );    }    /* Create a new transaction if method is not ACK.     * The transaction user is the user agent module.     */    if (msg->line.req.method.id != PJSIP_ACK_METHOD) {	int tsx_count;	status = pjsip_tsx_create_uac(dlg->ua, tdata, &tsx);	if (status != PJ_SUCCESS)	    goto on_error;	/* Set transport selector */	status = pjsip_tsx_set_transport(tsx, &dlg->tp_sel);	pj_assert(status == PJ_SUCCESS);	/* Attach this dialog to the transaction, so that user agent	 * will dispatch events to this dialog.	 */	tsx->mod_data[dlg->ua->id] = dlg;	/* Copy optional caller's mod_data, if present */	if (mod_data_id >= 0 && mod_data_id < PJSIP_MAX_MODULE)	    tsx->mod_data[mod_data_id] = mod_data;	/* Increment transaction counter. */	tsx_count = ++dlg->tsx_count;	/* Send the message. */	status = pjsip_tsx_send_msg(tsx, tdata);	if (status != PJ_SUCCESS) {	    if (dlg->tsx_count == tsx_count)		pjsip_tsx_terminate(tsx, tsx->status_code);	    goto on_error;	}    } else {	/* Set transport selector */	pjsip_tx_data_set_transport(tdata, &dlg->tp_sel);	/* Send request */	status = pjsip_endpt_send_request_stateless(dlg->endpt, tdata, 						    NULL, NULL);	if (status != PJ_SUCCESS)	    goto on_error;    }    /* Unlock dialog, may destroy dialog. */    pjsip_dlg_dec_lock(dlg);    return PJ_SUCCESS;on_error:    /* Unlock dialog, may destroy dialog. */    pjsip_dlg_dec_lock(dlg);       /* Whatever happen delete the message. */    pjsip_tx_data_dec_ref( tdata );    return status;}/* Add standard headers for certain types of response */static void dlg_beautify_response(pjsip_dialog *dlg,				  pj_bool_t add_headers,				  int st_code,				  pjsip_tx_data *tdata){    pjsip_cseq_hdr *cseq;    int st_class;    const pjsip_hdr *c_hdr;    pjsip_hdr *hdr;    cseq = PJSIP_MSG_CSEQ_HDR(tdata->msg);    pj_assert(cseq != NULL);    st_class = st_code / 100;    /* Contact, Allow, Supported header. */    if (add_headers && pjsip_method_creates_dialog(&cseq->method)) {	/* Add Contact header for 1xx, 2xx, 3xx and 485 response. */	if (st_class==2 || st_class==3 || (st_class==1 && st_code != 100) ||	    st_code==485) 	{	    pj_str_t hcontact = { "Contact", 7 };	    /* Add contact header only if one is not present. */	    if (pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL) == 0 &&		pjsip_msg_find_hdr_by_name(tdata->msg, &hcontact, NULL) == 0) 	    {		hdr = pjsip_hdr_clone(tdata->pool, dlg->local.contact);		pjsip_msg_add_hdr(tdata->msg, hdr);	    }	}	/* Add Allow header in 2xx and 405 response. */	if ((st_class==2 || st_code==405) &&	    pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ALLOW, NULL)==NULL) 	{	    c_hdr = pjsip_endpt_get_capability(dlg->endpt,					       PJSIP_H_ALLOW, NULL);	    if (c_hdr) {		hdr = pjsip_hdr_clone(tdata->pool, c_hdr);		pjsip_msg_add_hdr(tdata->msg, hdr);	    }	}	/* Add Supported header in 2xx response. */	if (st_class==2 && 	    pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL)==NULL) 	{	    c_hdr = pjsip_endpt_get_capability(dlg->endpt,					       PJSIP_H_SUPPORTED, NULL);	    if (c_hdr) {		hdr = pjsip_hdr_clone(tdata->pool, c_hdr);		pjsip_msg_add_hdr(tdata->msg, hdr);	    }	}    }    /* Add To tag in all responses except 100 */    if (st_code != 100) {	pjsip_to_hdr *to;	to = PJSIP_MSG_TO_HDR(tdata->msg);	pj_assert(to != NULL);	to->tag = dlg->local.info->tag;	if (dlg->state == PJSIP_DIALOG_STATE_NULL)	    dlg->state = PJSIP_DIALOG_STATE_ESTABLISHED;    }}/* * Create response. */PJ_DEF(pj_status_t) pjsip_dlg_create_response(	pjsip_dialog *dlg,						pjsip_rx_data *rdata,						int st_code,						const pj_str_t *st_text,						pjsip_tx_data **p_tdata){    pj_status_t status;    pjsip_tx_data *tdata;    /* Create generic response.     * This will initialize response's Via, To, From, Call-ID, CSeq     * and Record-Route headers from the request.     */    status = pjsip_endpt_create_response(dlg->endpt,					 rdata, st_code, st_text, &tdata);    if (status != PJ_SUCCESS)	return status;    /* Lock the dialog. */    pjsip_dlg_inc_lock(dlg);    dlg_beautify_response(dlg, PJ_FALSE, st_code, tdata);    /* Unlock the dialog. */    pjsip_dlg_dec_lock(dlg);    /* Done. */    *p_tdata = tdata;    return PJ_SUCCESS;}/* * Modify response. */PJ_DEF(pj_status_t) pjsip_dlg_modify_response(	pjsip_dialog *dlg,						pjsip_tx_data *tdata,						int st_code,						const pj_str_t *st_text){    pjsip_hdr *hdr;    PJ_ASSERT_RETURN(dlg && tdata && tdata->msg, PJ_EINVAL);    PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_RESPONSE_MSG,		     PJSIP_ENOTRESPONSEMSG);    PJ_ASSERT_RETURN(st_code >= 100 && st_code <= 699, PJ_EINVAL);    /* Lock and increment session */    pjsip_dlg_inc_lock(dlg);    /* Replace status code and reason */    tdata->msg->line.status.code = st_code;    if (st_text) {	pj_strdup(tdata->pool, &tdata->msg->line.status.reason, st_text);    } else {	tdata->msg->line.status.reason = *pjsip_get_status_text(st_code);    }    /* Remove existing Contact header (without this, when dialog sent      * 180 and then 302, the Contact in 302 will not get updated).     */    hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL);    if (hdr)	pj_list_erase(hdr);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -