📄 sip_xaction_state_mc.c
字号:
sip_trans->sip_xaction_last_msg = NULL; } SIP_MSG_REFCNT_INCR(msg); sip_trans->sip_xaction_last_msg = msg; (void) sip_add_conn_obj_cache(conn_obj, (void *)sip_trans); if (SIP_PROVISIONAL_RESP(resp_code)) { break; } else if (SIP_FINAL_RESP(resp_code)) { /* For unreliable transports, start Timer J */ if (!isreliable) { timer_obj_J = sip_setup_timer( conn_obj, sip_trans, NULL, sip_trans->sip_xaction_TJ, SIP_XACTION_TIMER_J); if (timer_obj_J == NULL) { (void) pthread_mutex_unlock(& sip_trans-> sip_xaction_mutex); return (ENOMEM); } SIP_SCHED_TIMER( sip_trans->sip_xaction_TJ, timer_obj_J, sip_xaction_state_timer_fire); if (!SIP_IS_TIMER_RUNNING( sip_trans->sip_xaction_TJ)) { (void) pthread_mutex_unlock(& sip_trans-> sip_xaction_mutex); free(timer_obj_J); return (ENOMEM); } sip_trans->sip_xaction_state = SIPS_SRV_NONINV_COMPLETED; } else { sip_trans->sip_xaction_state = SIPS_SRV_NONINV_TERMINATED; } } break; default: (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (EPROTO); } (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex); if (prev_state != sip_trans->sip_xaction_state && sip_xaction_ulp_state_cb != NULL) { sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans, (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state); } return (0);}/* * -------------------------- Input Routines --------------------------- *//* Process an incoming SIP message Request or Response */intsip_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans, _sip_msg_t **sip_msg){ sip_message_type_t *sip_msg_info; int ret; sip_msg_info = (*sip_msg)->sip_msg_req_res; if (sip_msg_info->is_request) ret = sip_srv_xaction_input(conn_obj, sip_trans, sip_msg); else ret = sip_clnt_xaction_input(conn_obj, sip_trans, sip_msg); return (ret);}/* Process a Request from the transport */static intsip_srv_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans, _sip_msg_t **sip_msg){ sip_message_type_t *sip_msg_info; _sip_msg_t *msg = *sip_msg; int prev_state; boolean_t isreliable; sip_msg_info = msg->sip_msg_req_res; isreliable = sip_is_conn_reliable(conn_obj); /* * Cancel if the original transaction has not yet got a final * response and send a 487 response. */ if (sip_msg_info->sip_req_method == ACK) { _sip_msg_t *sip_last_resp; const sip_str_t *resp_to_tag; const sip_str_t *req_to_tag; int error; sip_message_type_t *last_msg_info; (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex); if (sip_trans->sip_xaction_last_msg != NULL) sip_last_resp = sip_trans->sip_xaction_last_msg; else sip_last_resp = sip_trans->sip_xaction_orig_msg; last_msg_info = sip_last_resp->sip_msg_req_res; if (last_msg_info->is_request) { (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (0); } req_to_tag = sip_get_to_tag((sip_msg_t)msg, &error); if (req_to_tag == NULL || error != 0) { (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (0); } resp_to_tag = sip_get_to_tag((sip_msg_t)sip_last_resp, &error); if (req_to_tag == NULL || error != 0) { (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (0); } if (resp_to_tag->sip_str_len != req_to_tag->sip_str_len || strncmp(resp_to_tag->sip_str_ptr, req_to_tag->sip_str_ptr, req_to_tag->sip_str_len) != 0) { (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (0); } prev_state = sip_trans->sip_xaction_state; if (sip_trans->sip_xaction_state == SIPS_SRV_INV_COMPLETED) { sip_xaction_time_obj_t *timer_obj_I = NULL; SIP_CANCEL_TIMER(sip_trans->sip_xaction_TG); /* * Cancel Timer H and goto TERMINATED state for * reliable transports. */ if (isreliable) { SIP_CANCEL_TIMER( sip_trans->sip_xaction_TH); sip_trans->sip_xaction_state = SIPS_SRV_INV_TERMINATED; (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); if (sip_xaction_ulp_state_cb != NULL) { sip_xaction_ulp_state_cb( (sip_transaction_t)sip_trans, (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state); } return (0); } /* * For unreliable transports, start TIMER I and * transition to CONFIRMED state. */ timer_obj_I = sip_setup_timer(conn_obj, sip_trans, NULL, sip_trans->sip_xaction_TI, SIP_XACTION_TIMER_I); if (timer_obj_I == NULL) { (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (ENOMEM); } SIP_SCHED_TIMER(sip_trans->sip_xaction_TI, timer_obj_I, sip_xaction_state_timer_fire); if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TI)) { (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); free(timer_obj_I); return (ENOMEM); } sip_trans->sip_xaction_state = SIPS_SRV_CONFIRMED; } (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex); if (prev_state != sip_trans->sip_xaction_state && sip_xaction_ulp_state_cb != NULL) { sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans, (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state); } return (0); } else if (sip_msg_info->sip_req_method == CANCEL) { if (sip_trans->sip_xaction_method == INVITE) { (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (0); } } if (sip_msg_info->sip_req_method == INVITE) { (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex); assert(sip_trans->sip_xaction_method == INVITE); /* Retransmitted invite */ switch (sip_trans->sip_xaction_state) { case SIPS_SRV_INV_PROCEEDING: case SIPS_SRV_INV_COMPLETED: if (sip_trans->sip_xaction_last_msg != NULL) { _sip_msg_t *new_msg; new_msg = sip_trans->sip_xaction_last_msg; (void) sip_stack_send(conn_obj, new_msg->sip_msg_buf, new_msg->sip_msg_len); } break; default: (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (EPROTO); } (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex); sip_free_msg((sip_msg_t)msg); *sip_msg = NULL; return (0); } /* Retransmitted request */ assert(sip_trans->sip_xaction_method != INVITE); (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex); switch (sip_trans->sip_xaction_state) { case SIPS_SRV_NONINV_PROCEEDING: case SIPS_SRV_NONINV_COMPLETED: if (sip_trans->sip_xaction_last_msg != NULL) { _sip_msg_t *new_msg; new_msg = sip_trans->sip_xaction_last_msg; (void) sip_stack_send(conn_obj, new_msg->sip_msg_buf, new_msg->sip_msg_len); } break; default: (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (EPROTO); } (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex); sip_free_msg((sip_msg_t)msg); *sip_msg = NULL; return (0);}/* Process a Response */static intsip_clnt_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans, _sip_msg_t **msg){ int ret; if (sip_trans->sip_xaction_method == INVITE) ret = sip_clnt_xaction_inv_res(conn_obj, sip_trans, msg); else ret = sip_clnt_xaction_noninv_res(conn_obj, sip_trans, msg); return (ret);}static intsip_create_send_nonOKack(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans, _sip_msg_t *msg, boolean_t copy){ _sip_msg_t *ack_msg; int ret = 0; ack_msg = (_sip_msg_t *)sip_new_msg(); if (ack_msg == NULL) return (ENOMEM); if ((ret = sip_create_nonOKack( (sip_msg_t)sip_trans->sip_xaction_orig_msg, (sip_msg_t)msg, (sip_msg_t)ack_msg)) != 0) { sip_free_msg((sip_msg_t)ack_msg); return (ret); } if ((ret = sip_stack_send(conn_obj, ack_msg->sip_msg_buf, ack_msg->sip_msg_len)) != 0) { sip_free_msg((sip_msg_t)ack_msg); return (ret); } if (copy) { SIP_MSG_REFCNT_INCR(ack_msg); if (sip_trans->sip_xaction_last_msg != NULL) { SIP_MSG_REFCNT_DECR(sip_trans->sip_xaction_last_msg); sip_trans->sip_xaction_last_msg = NULL; } sip_trans->sip_xaction_last_msg = ack_msg; } sip_free_msg((sip_msg_t)ack_msg); return (0);}/* Process a INVITE Response */static intsip_clnt_xaction_inv_res(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans, _sip_msg_t **sip_msg){ int resp_code; _sip_msg_t *msg = *sip_msg; sip_xaction_time_obj_t *timer_obj_D = NULL; sip_message_type_t *sip_msg_info; int prev_state; boolean_t isreliable; assert(msg->sip_msg_req_res != NULL); sip_msg_info = msg->sip_msg_req_res; resp_code = sip_msg_info->sip_resp_code; isreliable = sip_is_conn_reliable(conn_obj); (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex); prev_state = sip_trans->sip_xaction_state; switch (sip_trans->sip_xaction_state) { case SIPS_CLNT_CALLING: if (SIP_PROVISIONAL_RESP(resp_code)) { /* * sip_trans->sip_xaction_last_msg ? */ SIP_CANCEL_TIMER( sip_trans->sip_xaction_TA); sip_trans->sip_xaction_state = SIPS_CLNT_INV_PROCEEDING; } else if (SIP_OK_RESP(resp_code)) { /* * sip_trans->sip_xaction_last_msg ? */ SIP_CANCEL_TIMER( sip_trans->sip_xaction_TA); SIP_CANCEL_TIMER( sip_trans->sip_xaction_TB); sip_trans->sip_xaction_state = SIPS_CLNT_INV_TERMINATED; } else if (SIP_NONOK_FINAL_RESP(resp_code)) { int ret; /* * sip_trans->sip_xaction_last_msg ? */ SIP_CANCEL_TIMER( sip_trans->sip_xaction_TA); SIP_CANCEL_TIMER( sip_trans->sip_xaction_TB); if ((ret = sip_create_send_nonOKack(conn_obj, sip_trans, msg, B_FALSE)) != 0) { (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (ret); } /* * start timer D for unreliable transports */ if (!isreliable) { timer_obj_D = sip_setup_timer( conn_obj, sip_trans, NULL, sip_trans->sip_xaction_TD, SIP_XACTION_TIMER_D); if (timer_obj_D == NULL) { (void) pthread_mutex_unlock( &sip_trans-> sip_xaction_mutex); return (ENOMEM); } SIP_SCHED_TIMER( sip_trans->sip_xaction_TD, timer_obj_D, sip_xaction_state_timer_fire); if (!SIP_IS_TIMER_RUNNING( sip_trans->sip_xaction_TD)) { (void) pthread_mutex_unlock( &sip_trans-> sip_xaction_mutex); free(timer_obj_D); return (ENOMEM); } sip_trans->sip_xaction_state = SIPS_CLNT_INV_COMPLETED; } else { sip_trans->sip_xaction_state = SIPS_CLNT_INV_TERMINATED; } } else { /* Invalid resp_code */ (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (EPROTO); } break; case SIPS_CLNT_INV_PROCEEDING: if (SIP_PROVISIONAL_RESP(resp_code)) { break; } else if (SIP_OK_RESP(resp_code)) { SIP_CANCEL_TIMER( sip_trans->sip_xaction_TB); sip_trans->sip_xaction_state = SIPS_CLNT_INV_TERMINATED; } else if (SIP_NONOK_FINAL_RESP(resp_code)) { int ret; SIP_CANCEL_TIMER( sip_trans->sip_xaction_TB); if ((ret = sip_create_send_nonOKack(conn_obj, sip_trans, msg, B_FALSE)) != 0) { (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (ret); } /* * start timer D for unreliable transports */ if (!isreliable) { timer_obj_D = sip_setup_timer( conn_obj, sip_trans, NULL, sip_trans->sip_xaction_TD, SIP_XACTION_TIMER_D); if (timer_obj_D == NULL) { (void) pthread_mutex_unlock( &sip_trans-> sip_xaction_mutex); return (ENOMEM); } SIP_SCHED_TIMER( sip_trans->sip_xaction_TD, timer_obj_D, sip_xaction_state_timer_fire); if (!SIP_IS_TIMER_RUNNING( sip_trans->sip_xaction_TD)) { (void) pthread_mutex_unlock( &sip_trans-> sip_xaction_mutex); free(timer_obj_D); return (ENOMEM); } sip_trans->sip_xaction_state = SIPS_CLNT_INV_COMPLETED; } else { sip_trans->sip_xaction_state = SIPS_CLNT_INV_TERMINATED; } } else { (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (EPROTO); } break; case SIPS_CLNT_INV_COMPLETED: /* * Transport error takes it to * SIPS_CLNT_INV_TERMINATED */ if (SIP_NONOK_FINAL_RESP(resp_code)) { int ret; if ((ret = sip_create_send_nonOKack(conn_obj, sip_trans, msg, B_FALSE)) != 0) { (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (ret); } } else { /* Invalid resp_code */ (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (EPROTO); } break; default: (void) pthread_mutex_unlock( &sip_trans->sip_xaction_mutex); return (EPROTO); } (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex); if (prev_state != sip_trans->sip_xaction_state && sip_xaction_ulp_state_cb != NULL) { sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans, (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state); } return (0);}/* Process a NON-INVITE Response */static intsip_clnt_xaction_noninv_res(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans, _sip_msg_t **sip_msg){ int resp_code;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -