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

📄 sip_transaction.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * called before tsx_send_msg() has completed.	 */	PJ_ASSERT_RETURN(event->type == PJSIP_EVENT_TX_MSG, PJ_EBUG);	/* Get the txdata */	tdata = event->body.tx_msg.tdata;	/* Save the message for retransmission. */	if (tsx->last_tx && tsx->last_tx != tdata) {	    pjsip_tx_data_dec_ref(tsx->last_tx);	    tsx->last_tx = NULL;	}	if (tsx->last_tx != tdata) {	    tsx->last_tx = tdata;	    pjsip_tx_data_add_ref(tdata);	}	/* Send the message. */        status = tsx_send_msg( tsx, tdata);	if (status != PJ_SUCCESS) {	    return status;	}	/* Start Timer B (or called timer F for non-INVITE) for transaction 	 * timeout.	 */	pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, 				    &timeout_timer_val);	/* Start Timer A (or timer E) for retransmission only if unreliable 	 * transport is being used.	 */	if (!tsx->is_reliable)  {	    tsx->retransmit_count = 0;	    if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) {		tsx->transport_flag |= TSX_HAS_PENDING_RESCHED;	    } else {		pjsip_endpt_schedule_timer(tsx->endpt, &tsx->retransmit_timer,					   &t1_timer_val);	    }	}	/* Move state. */	tsx_set_state( tsx, PJSIP_TSX_STATE_CALLING,                        PJSIP_EVENT_TX_MSG, tdata);    }    return PJ_SUCCESS;}/* * State Calling is for UAC after it sends request but before any responses * is received. */static pj_status_t tsx_on_state_calling( pjsip_transaction *tsx, 				         pjsip_event *event ){    pj_assert(tsx->state == PJSIP_TSX_STATE_CALLING);    pj_assert(tsx->role == PJSIP_ROLE_UAC);    if (event->type == PJSIP_EVENT_TIMER && 	event->body.timer.entry == &tsx->retransmit_timer)     {        pj_status_t status;	/* Retransmit the request. */        status = tsx_retransmit( tsx, 1 );	if (status != PJ_SUCCESS) {	    return status;	}    } else if (event->type == PJSIP_EVENT_TIMER && 	       event->body.timer.entry == &tsx->timeout_timer)     {	/* Cancel retransmission timer. */	if (tsx->retransmit_timer._timer_id != -1) {	    pjsip_endpt_cancel_timer(tsx->endpt, &tsx->retransmit_timer);	    tsx->retransmit_timer._timer_id = -1;	}	tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED);	/* Set status code */	tsx_set_status_code(tsx, PJSIP_SC_TSX_TIMEOUT, NULL);	/* Inform TU. */	tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,                        PJSIP_EVENT_TIMER, &tsx->timeout_timer);	/* Transaction is destroyed */	//return PJSIP_ETSXDESTROYED;    } else if (event->type == PJSIP_EVENT_RX_MSG) {	pjsip_msg *msg;	int code;	/* Get message instance */	msg = event->body.rx_msg.rdata->msg_info.msg;	/* Better be a response message. */	if (msg->type != PJSIP_RESPONSE_MSG)	    return PJSIP_ENOTRESPONSEMSG;	code = msg->line.status.code;	/* If the response is final, cancel both retransmission and timeout	 * timer.	 */	if (code >= 200) {	    if (tsx->retransmit_timer._timer_id != -1) {		pjsip_endpt_cancel_timer(tsx->endpt, &tsx->retransmit_timer);		tsx->retransmit_timer._timer_id = -1;	    }	    if (tsx->timeout_timer._timer_id != -1) {		pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer);		tsx->timeout_timer._timer_id = -1;	    }	} else {	    /* Cancel retransmit timer (for non-INVITE transaction, the	     * retransmit timer will be rescheduled at T2.	     */	    if (tsx->retransmit_timer._timer_id != -1) {		pjsip_endpt_cancel_timer(tsx->endpt, &tsx->retransmit_timer);		tsx->retransmit_timer._timer_id = -1;	    }	    /* For provisional response, only cancel retransmit when this	     * is an INVITE transaction. For non-INVITE, section 17.1.2.1	     * of RFC 3261 says that:	     *	- retransmit timer is set to T2	     *	- timeout timer F is not deleted.	     */	    if (tsx->method.id == PJSIP_INVITE_METHOD) {		/* Cancel timeout timer */		pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer);	    } else {		if (!tsx->is_reliable) {		    pjsip_endpt_schedule_timer(tsx->endpt, 					       &tsx->retransmit_timer,					       &t2_timer_val);		}	    }	}	 	tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED);	/* Discard retransmission message if it is not INVITE.	 * The INVITE tdata is needed in case we have to generate ACK for	 * the final response.	 */	/* Keep last_tx for authorization. */	//blp: always keep last_tx until transaction is destroyed	//code = msg->line.status.code;	//if (tsx->method.id != PJSIP_INVITE_METHOD && code!=401 && code!=407) {	//    pjsip_tx_data_dec_ref(tsx->last_tx);	//    tsx->last_tx = NULL;	//}	/* Processing is similar to state Proceeding. */	tsx_on_state_proceeding_uac( tsx, event);    } else {	pj_assert(!"Unexpected event");        return PJ_EBUG;    }    return PJ_SUCCESS;}/* * State Trying is for UAS after it received request but before any responses * is sent. * Note: this is different than RFC3261, which can use Trying state for *	 non-INVITE client transaction (bug in RFC?). */static pj_status_t tsx_on_state_trying( pjsip_transaction *tsx,                                         pjsip_event *event){    pj_status_t status;    pj_assert(tsx->state == PJSIP_TSX_STATE_TRYING);    /* This state is only for UAS */    pj_assert(tsx->role == PJSIP_ROLE_UAS);    /* Better be transmission of response message.     * If we've got request retransmission, this means that the TU hasn't     * transmitted any responses within 500 ms, which is not allowed. If     * this happens, just ignore the event (we couldn't retransmit last     * response because we haven't sent any!).     */    if (event->type != PJSIP_EVENT_TX_MSG) {	return PJ_SUCCESS;    }    /* The rest of the processing of the event is exactly the same as in     * "Proceeding" state.     */    status = tsx_on_state_proceeding_uas( tsx, event);    /* Inform the TU of the state transision if state is still State_Trying */    if (status==PJ_SUCCESS && tsx->state == PJSIP_TSX_STATE_TRYING) {	tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING,                        PJSIP_EVENT_TX_MSG, event->body.tx_msg.tdata);    }    return status;}/* * Handler for events in Proceeding for UAS * This state happens after the TU sends provisional response. */static pj_status_t tsx_on_state_proceeding_uas( pjsip_transaction *tsx,                                                pjsip_event *event){    pj_assert(tsx->state == PJSIP_TSX_STATE_PROCEEDING || 	      tsx->state == PJSIP_TSX_STATE_TRYING);    /* This state is only for UAS. */    pj_assert(tsx->role == PJSIP_ROLE_UAS);    /* Receive request retransmission. */    if (event->type == PJSIP_EVENT_RX_MSG) {        pj_status_t status;	/* Must have last response sent. */	PJ_ASSERT_RETURN(tsx->last_tx != NULL, PJ_EBUG);	/* Send last response */	if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) {	    tsx->transport_flag |= TSX_HAS_PENDING_SEND;	} else {	    status = tsx_send_msg(tsx, tsx->last_tx);	    if (status != PJ_SUCCESS)		return status;	}	    } else if (event->type == PJSIP_EVENT_TX_MSG ) {	pjsip_tx_data *tdata = event->body.tx_msg.tdata;        pj_status_t status;	/* The TU sends response message to the request. Save this message so	 * that we can retransmit the last response in case we receive request	 * retransmission.	 */	pjsip_msg *msg = tdata->msg;	/* This can only be a response message. */	PJ_ASSERT_RETURN(msg->type==PJSIP_RESPONSE_MSG, PJSIP_ENOTRESPONSEMSG);	/* Update last status */	tsx_set_status_code(tsx, msg->line.status.code, 			    &msg->line.status.reason);	/* Discard the saved last response (it will be updated later as	 * necessary).	 */	if (tsx->last_tx && tsx->last_tx != tdata) {	    pjsip_tx_data_dec_ref( tsx->last_tx );	    tsx->last_tx = NULL;	}	/* Send the message. */        status = tsx_send_msg(tsx, tdata);	if (status != PJ_SUCCESS) {	    return status;	}	// Update To tag header for RFC2543 transaction.	// TODO:	/* Update transaction state */	if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 100)) {	    if (tsx->last_tx != tdata) {		tsx->last_tx = tdata;		pjsip_tx_data_add_ref( tdata );	    }	    tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING,                            PJSIP_EVENT_TX_MSG, tdata );	} else if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 200)) {	    if (tsx->method.id == PJSIP_INVITE_METHOD && tsx->handle_200resp==0) {		/* 2xx class message is not saved, because retransmission                  * is handled by TU.		 */		tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,                                PJSIP_EVENT_TX_MSG, tdata );		/* Transaction is destroyed. */		//return PJSIP_ETSXDESTROYED;	    } else {		pj_time_val timeout;		if (tsx->method.id == PJSIP_INVITE_METHOD) {		    tsx->retransmit_count = 0;		    if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) {			tsx->transport_flag |= TSX_HAS_PENDING_RESCHED;		    } else {			pjsip_endpt_schedule_timer( tsx->endpt, 						    &tsx->retransmit_timer,						    &t1_timer_val);		    }		}		/* Save last response sent for retransmission when request 		 * retransmission is received.		 */		if (tsx->last_tx != tdata) {		    tsx->last_tx = tdata;		    pjsip_tx_data_add_ref(tdata);		}		/* Setup timeout timer: */				if (tsx->method.id == PJSIP_INVITE_METHOD) {		    		    /* Start Timer H at 64*T1 for INVITE server transaction,		     * regardless of transport.		     */		    timeout = timeout_timer_val;		    		} else if (PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)==0) {		    		    /* For non-INVITE, start timer J at 64*T1 for unreliable		     * transport.		     */		    timeout = timeout_timer_val;		    		} else {		    		    /* Transaction terminates immediately for non-INVITE when		     * reliable transport is used.		     */		    timeout.sec = timeout.msec = 0;		}		pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,                                             &timeout);		/* Set state to "Completed" */		tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED,                                PJSIP_EVENT_TX_MSG, tdata );	    }	} else if (tsx->status_code >= 300) {	    /* 3xx-6xx class message causes transaction to move to              * "Completed" state.              */	    if (tsx->last_tx != tdata) {		tsx->last_tx = tdata;		pjsip_tx_data_add_ref( tdata );	    }	    /* For INVITE, start timer H for transaction termination 	     * regardless whether transport is reliable or not.	     * For non-INVITE, start timer J with the value of 64*T1 for	     * non-reliable transports, and zero for reliable transports.	     */	    if (tsx->method.id == PJSIP_INVITE_METHOD) {		/* Start timer H for INVITE */		pjsip_endpt_schedule_timer(tsx->endpt,&tsx->timeout_timer,					   &timeout_timer_val);	    } else if (!tsx->is_reliable) {		/* Start timer J on 64*T1 seconds for non-INVITE */		pjsip_endpt_schedule_timer(tsx->endpt,&tsx->timeout_timer,					   &timeout_timer_val);	    } else {		/* Start timer J on zero seconds for non-INVITE */		pj_time_val zero_time = { 0, 0 };		pjsip_endpt_schedule_timer(tsx->endpt,&tsx->timeout_timer,					   &zero_time);	    }	    /* For INVITE, if unreliable transport is used, retransmission 	     * timer G will be scheduled (retransmission).	     */	    if (!tsx->is_reliable) {		pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr( msg, PJSIP_H_CSEQ,                                                           NULL);		if (cseq->method.id == PJSIP_INVITE_METHOD) {		    tsx->retransmit_count = 0;		    if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) {			tsx->transport_flag |= TSX_HAS_PENDING_RESCHED;		    } else {			pjsip_endpt_schedule_timer(tsx->endpt, 						   &tsx->retransmit_timer, 						   &t1_timer_val);		    }		}	    }	    /* Inform TU */	    tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED,                            PJSIP_EVENT_TX_MSG, tdata );	} else {	    pj_assert(0);	}    } else if (event->type == PJSIP_EVENT_TIMER && 	       event->body.timer.entry == &tsx->retransmit_timer) {	/* Retransmission timer elapsed. */        pj_status_t status;	/* Must not be triggered while transport is pending. */	pj_assert((tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) == 0);	/* Must have last response to retransmit. */	pj_assert(tsx->last_tx != NULL);	/* Retransmit the last response. */        status = tsx_retransmit( tsx, 1 );	if (status != PJ_SUCCESS) {	    return status;	}    } else if (event->type == PJSIP_EVENT_TIMER && 	       event->body.timer.entry == &tsx->timeout_timer) {	/* Timeout timer. should not happen? */	pj_assert(!"Should not happen(?)");	tsx_set_status_code(tsx, PJSIP_SC_TSX_TIMEOUT, NULL);	tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,                        PJSIP_EVENT_TIMER, &tsx->timeout_timer);	return PJ_EBUG;    } else {	pj_assert(!"Unexpected event");        return PJ_EBUG;    }    return PJ_SUCCESS;}/* * Handler for events in Proceeding for UAC * This state happens after provisional response(s) has been received from * UAS. */static pj_status_t tsx_on_state_proceeding_uac(pjsip_transaction *tsx,                                                pjsip_event *event){    pj_asser

⌨️ 快捷键说明

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