📄 sip_xaction.c
字号:
/* * create a transaction. */static sip_xaction_t *sip_xaction_create(sip_conn_object_t obj, _sip_msg_t *msg, char *branchid, int *error){ sip_xaction_t *trans; sip_message_type_t *sip_msg_info; int state = 0; int prev_state = 0; sip_method_t method; int ret; int timer1 = sip_timer_T1; int timer4 = sip_timer_T4; int timerd = sip_timer_TD; if (error != NULL) *error = 0; /* * Make sure we are not creating a transaction for * an ACK request. */ trans = (sip_xaction_t *)malloc(sizeof (sip_xaction_t)); if (trans == NULL) { if (error != NULL) *error = ENOMEM; return (NULL); } bzero(trans, sizeof (sip_xaction_t)); if (branchid == NULL) { trans->sip_xaction_branch_id = (char *)sip_branchid(NULL); if (trans->sip_xaction_branch_id == NULL) { free(trans); if (error != NULL) *error = ENOMEM; return (NULL); } } else { trans->sip_xaction_branch_id = (char *)malloc(strlen(branchid) + 1); if (trans->sip_xaction_branch_id == NULL) { free(trans); if (error != NULL) *error = ENOMEM; return (NULL); } (void) strncpy(trans->sip_xaction_branch_id, branchid, strlen(branchid)); trans->sip_xaction_branch_id[strlen(branchid)] = '\0'; } (void) pthread_mutex_init(&trans->sip_xaction_mutex, NULL); SIP_MSG_REFCNT_INCR(msg); trans->sip_xaction_orig_msg = msg; assert(msg->sip_msg_req_res != NULL); sip_msg_info = msg->sip_msg_req_res; if (sip_msg_info->is_request) { method = sip_msg_info->sip_req_method; } else { method = sip_get_callseq_method((sip_msg_t)msg, &ret); if (ret != 0) { free(trans->sip_xaction_branch_id); free(trans); if (error != NULL) *error = ret; return (NULL); } if (method == INVITE) state = SIPS_SRV_INV_PROCEEDING; else state = SIPS_SRV_TRYING; } trans->sip_xaction_method = method; trans->sip_xaction_state = state; /* Get connection object specific timeouts, if present */ if (sip_conn_timer1 != NULL) timer1 = sip_conn_timer1(obj); if (sip_conn_timer4 != NULL) timer4 = sip_conn_timer4(obj); if (sip_conn_timerd != NULL) timerd = sip_conn_timerd(obj); SIP_INIT_TIMER(trans->sip_xaction_TA, 2 * timer1); SIP_INIT_TIMER(trans->sip_xaction_TB, 64 * timer1) SIP_INIT_TIMER(trans->sip_xaction_TD, timerd); SIP_INIT_TIMER(trans->sip_xaction_TE, timer1); SIP_INIT_TIMER(trans->sip_xaction_TF, 64 * timer1); SIP_INIT_TIMER(trans->sip_xaction_TG, 2 * timer1); SIP_INIT_TIMER(trans->sip_xaction_TH, 64 * timer1); SIP_INIT_TIMER(trans->sip_xaction_TI, timer4); SIP_INIT_TIMER(trans->sip_xaction_TJ, 64 * timer1); SIP_INIT_TIMER(trans->sip_xaction_TK, timer4); if ((ret = sip_xaction_add(trans, branchid, msg, method)) != 0) { (void) pthread_mutex_destroy(&trans->sip_xaction_mutex); free(trans->sip_xaction_branch_id); free(trans); if (error != NULL) *error = ret; return (NULL); } if (sip_xaction_ulp_state_cb != NULL && prev_state != trans->sip_xaction_state) { sip_xaction_ulp_state_cb((sip_transaction_t)trans, (sip_msg_t)msg, prev_state, trans->sip_xaction_state); } return (trans);}/* Find a transaction, create if asked for */sip_xaction_t *sip_xaction_get(sip_conn_object_t obj, sip_msg_t msg, boolean_t create, int which, int *error){ char *branchid; sip_xaction_t *sip_trans; _sip_msg_t *_msg; sip_message_type_t *sip_msg_info; if (error != NULL) *error = 0; _msg = (_sip_msg_t *)msg; sip_msg_info = ((_sip_msg_t *)msg)->sip_msg_req_res; branchid = sip_get_branchid(msg, NULL); sip_trans = sip_xaction_find(branchid, _msg, which); if (sip_trans == NULL && create) { /* * If we are sending a request, must be conformant to RFC 3261. */ if (sip_msg_info->is_request && (branchid == NULL || strncmp(branchid, RFC_3261_BRANCH, strlen(RFC_3261_BRANCH) != 0))) { if (error != NULL) *error = EINVAL; if (branchid != NULL) free(branchid); return (NULL); } sip_trans = sip_xaction_create(obj, _msg, branchid, error); if (sip_trans != NULL) SIP_XACTION_REFCNT_INCR(sip_trans); } if (branchid != NULL) free(branchid); return (sip_trans);}/* * Delete a transaction if the reference count is 0. Passed to * sip_hash_delete(). */boolean_tsip_xaction_remove(void *obj, void *hindex, int *found){ sip_xaction_t *tmp = (sip_xaction_t *)obj; *found = 0; tmp = (sip_xaction_t *)obj; if (bcmp(tmp->sip_xaction_hash_digest, hindex, sizeof (tmp->sip_xaction_hash_digest)) == 0) { *found = 1; if (tmp->sip_xaction_ref_cnt != 0) return (B_FALSE); (void) pthread_mutex_destroy(&tmp->sip_xaction_mutex); SIP_CANCEL_TIMER(tmp->sip_xaction_TA); SIP_CANCEL_TIMER(tmp->sip_xaction_TB); SIP_CANCEL_TIMER(tmp->sip_xaction_TD); SIP_CANCEL_TIMER(tmp->sip_xaction_TE); SIP_CANCEL_TIMER(tmp->sip_xaction_TF); SIP_CANCEL_TIMER(tmp->sip_xaction_TG); SIP_CANCEL_TIMER(tmp->sip_xaction_TH); SIP_CANCEL_TIMER(tmp->sip_xaction_TI); SIP_CANCEL_TIMER(tmp->sip_xaction_TJ); SIP_CANCEL_TIMER(tmp->sip_xaction_TK); free(tmp->sip_xaction_branch_id); if (tmp->sip_xaction_last_msg != NULL) { SIP_MSG_REFCNT_DECR(tmp->sip_xaction_last_msg); tmp->sip_xaction_last_msg = NULL; } if (tmp->sip_xaction_orig_msg != NULL) { SIP_MSG_REFCNT_DECR(tmp->sip_xaction_orig_msg); tmp->sip_xaction_orig_msg = NULL; } if (tmp->sip_xaction_conn_obj != NULL) { sip_del_conn_obj_cache(tmp->sip_xaction_conn_obj, (void *)tmp); } free(tmp); return (B_TRUE); } return (B_FALSE);}/* * Delete a SIP transaction */voidsip_xaction_delete(sip_xaction_t *trans){ int hindex; hindex = SIP_DIGEST_TO_HASH(trans->sip_xaction_hash_digest); sip_hash_delete(sip_xaction_hash, trans->sip_xaction_hash_digest, hindex, sip_xaction_remove);}/* * Add a SIP transaction into the hash list. */intsip_xaction_add(sip_xaction_t *trans, char *branchid, _sip_msg_t *msg, sip_method_t method){ uint16_t hash_index[8]; if (sip_find_md5_digest(branchid, msg, hash_index, method) != 0) return (EINVAL); /* trans is not in the list as yet, so no need to hold the lock */ bcopy(hash_index, trans->sip_xaction_hash_digest, sizeof (hash_index)); if (sip_hash_add(sip_xaction_hash, (void *)trans, SIP_DIGEST_TO_HASH(hash_index)) != 0) { return (ENOMEM); } return (0);}/* Utility routine *//* Given a state, return the string - This is mostly for debug purposes */char *sip_get_xaction_state(int state){ switch (state) { case SIPS_CLNT_CALLING: return ("SIPS_CLNT_CALLING"); case SIPS_CLNT_INV_PROCEEDING: return ("SIPS_CLNT_INV_PROCEEDING"); case SIPS_CLNT_INV_TERMINATED: return ("SIPS_CLNT_INV_TERMINATED"); case SIPS_CLNT_INV_COMPLETED: return ("SIPS_CLNT_INV_COMPLETED"); case SIPS_CLNT_TRYING: return ("SIPS_CLNT_TRYING"); case SIPS_CLNT_NONINV_PROCEEDING: return ("SIPS_CLNT_NONINV_PROCEEDING"); case SIPS_CLNT_NONINV_TERMINATED: return ("SIPS_CLNT_NONINV_TERMINATED"); case SIPS_CLNT_NONINV_COMPLETED: return ("SIPS_CLNT_NONINV_COMPLETED"); case SIPS_SRV_INV_PROCEEDING: return ("SIPS_SRV_INV_PROCEEDING"); case SIPS_SRV_INV_COMPLETED: return ("SIPS_SRV_INV_COMPLETED"); case SIPS_SRV_CONFIRMED: return ("SIPS_SRV_CONFIRMED"); case SIPS_SRV_INV_TERMINATED: return ("SIPS_SRV_INV_TERMINATED"); case SIPS_SRV_TRYING: return ("SIPS_SRV_TRYING"); case SIPS_SRV_NONINV_PROCEEDING: return ("SIPS_SRV_NONINV_PROCEEDING"); case SIPS_SRV_NONINV_COMPLETED: return ("SIPS_SRV_NONINV_COMPLETED"); case SIPS_SRV_NONINV_TERMINATED: return ("SIPS_SRV_NONINV_TERMINATED"); default : return ("unknown"); }}/* * Initialize the hash table etc. */voidsip_xaction_init(int (*ulp_trans_err)(sip_transaction_t, int, void *), void (*ulp_state_cb)(sip_transaction_t, sip_msg_t, int, int)){ int cnt; for (cnt = 0; cnt < SIP_HASH_SZ; cnt++) { sip_xaction_hash[cnt].hash_count = 0; sip_xaction_hash[cnt].hash_head = NULL; sip_xaction_hash[cnt].hash_tail = NULL; (void) pthread_mutex_init( &sip_xaction_hash[cnt].sip_hash_mutex, NULL); } if (ulp_trans_err != NULL) sip_xaction_ulp_trans_err = ulp_trans_err; if (ulp_state_cb != NULL) sip_xaction_ulp_state_cb = ulp_state_cb;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -