📄 sip_dialog.c
字号:
} if (error != 0) return (NULL); callid = sip_get_callid((sip_msg_t)sip_msg, &error); if (error != 0 || remtag == NULL || localtag == NULL || callid == NULL) { return (NULL); } sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len, remtag->sip_str_ptr, remtag->sip_str_len, callid->sip_str_ptr, callid->sip_str_len, NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest); dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_hash, (void *)digest, SIP_DIGEST_TO_HASH(digest), sip_dialog_match); if (dialog == NULL) { sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len, NULL, 0, callid->sip_str_ptr, callid->sip_str_len, NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest); dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_phash, (void *)digest, SIP_DIGEST_TO_HASH(digest), sip_dialog_match); } return ((sip_dialog_t)dialog);}/* * We keep this partial dialog for the duration of the INVITE * transaction timeout duration, i.e. Timer B. */voidsip_dlg_self_destruct(void *args){ sip_dialog_timer_obj_t *tim_obj = (sip_dialog_timer_obj_t *)args; _sip_dialog_t *dialog = (_sip_dialog_t *)tim_obj->dialog; int index; if (dialog->sip_dlg_type == SIP_UAC_DIALOG) SIP_DLG_REFCNT_DECR(dialog); (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); assert(dialog->sip_dlg_state == SIP_DLG_NEW); dialog->sip_dlg_state = SIP_DLG_DESTROYED; (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); if (dialog->sip_dlg_type == SIP_UAC_DIALOG) { index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id); sip_hash_delete(sip_dialog_phash, (void *)dialog->sip_dlg_id, index, sip_dialog_dontfree); } if (tim_obj->func != NULL) tim_obj->func(dialog, NULL, NULL); sip_release_dialog_res(dialog); free(tim_obj);}/* Terminate a dialog */voidsip_dialog_terminate(_sip_dialog_t *dialog, sip_msg_t sip_msg){ int prev_state; (void) pthread_mutex_lock(&dialog->sip_dlg_mutex); prev_state = dialog->sip_dlg_state; dialog->sip_dlg_state = SIP_DLG_DESTROYED; (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex); if (sip_dlg_ulp_state_cb != NULL) { sip_dlg_ulp_state_cb((sip_dialog_t)dialog, sip_msg, prev_state, dialog->sip_dlg_state); } SIP_DLG_REFCNT_DECR(dialog);}/* Delete a dialog */voidsip_dialog_delete(_sip_dialog_t *dialog){ int index; index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id); sip_hash_delete(sip_dialog_hash, (void *)dialog->sip_dlg_id, index, sip_dialog_free);}/* Process an incoming request/response *//* ARGSUSED */intsip_dialog_process(_sip_msg_t *sip_msg, sip_dialog_t *sip_dialog, void (*func)(sip_dialog_t, sip_msg_t, void *)){ boolean_t request; _sip_dialog_t *_dialog; int error; request = sip_msg_is_request((sip_msg_t)sip_msg, &error); if (error != 0) return (EINVAL); _dialog = (_sip_dialog_t *)*sip_dialog; if (request) { uint32_t cseq; (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); cseq = sip_get_callseq_num(sip_msg, &error); if (error != 0 || ((_dialog->sip_dlg_remote_cseq != 0) && (SIP_CSEQ_LT(cseq, _dialog->sip_dlg_remote_cseq)))) { (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); /* Send CALL_NON_EXISTANT response?? */ return (EPROTO); } _dialog->sip_dlg_remote_cseq = cseq; (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); } else { int resp_code; sip_method_t method; int error; resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error); if (error == 0) { method = sip_get_callseq_method((sip_msg_t)sip_msg, &error); } if (error != 0) return (error); (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); assert(_dialog->sip_dlg_state == SIP_DLG_EARLY || _dialog->sip_dlg_state == SIP_DLG_CONFIRMED); /* * Let the user delete the dialog if it is not a 1XX/2XX resp * for an early INVITE dialog. */ if (SIP_OK_RESP(resp_code)) { if (method == INVITE) { if (_dialog->sip_dlg_state == SIP_DLG_EARLY) { _dialog->sip_dlg_state = SIP_DLG_CONFIRMED; (void) pthread_mutex_unlock( &_dialog->sip_dlg_mutex); (void) sip_dlg_recompute_rset(_dialog, sip_msg, SIP_UAC_DIALOG); if (sip_dlg_ulp_state_cb != NULL) { sip_dlg_ulp_state_cb( (sip_dialog_t)_dialog, sip_msg, SIP_DLG_EARLY, _dialog->sip_dlg_state); } return (0); } } } (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); } return (0);}/* Copy partial dialog to create a complete dialog */_sip_dialog_t *sip_copy_partial_dialog(_sip_dialog_t *dialog){ _sip_dialog_t *new_dlg; new_dlg = calloc(1, sizeof (_sip_dialog_t)); if (new_dlg == NULL) return (NULL); if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) { new_dlg->sip_dlg_req_uri.sip_str_ptr = malloc(dialog->sip_dlg_req_uri.sip_str_len + 1); if (new_dlg->sip_dlg_req_uri.sip_str_ptr == NULL) { free(new_dlg); return (NULL); } (void) strncpy(new_dlg->sip_dlg_req_uri.sip_str_ptr, dialog->sip_dlg_req_uri.sip_str_ptr, dialog->sip_dlg_req_uri.sip_str_len); new_dlg->sip_dlg_req_uri.sip_str_ptr[ dialog->sip_dlg_req_uri.sip_str_len] = '\0'; new_dlg->sip_dlg_req_uri.sip_str_len = dialog->sip_dlg_req_uri.sip_str_len; } if (dialog->sip_dlg_route_set != NULL) { assert(dialog->sip_dlg_rset.sip_str_ptr != NULL); new_dlg->sip_dlg_rset.sip_str_ptr = malloc(dialog->sip_dlg_rset.sip_str_len + 1); if (new_dlg->sip_dlg_rset.sip_str_ptr == NULL) { if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL) free(new_dlg->sip_dlg_req_uri.sip_str_ptr); free(new_dlg); return (NULL); } (void) strncpy(new_dlg->sip_dlg_rset.sip_str_ptr, dialog->sip_dlg_rset.sip_str_ptr, dialog->sip_dlg_rset.sip_str_len); new_dlg->sip_dlg_rset.sip_str_ptr[ dialog->sip_dlg_rset.sip_str_len] = '\0'; new_dlg->sip_dlg_rset.sip_str_len = dialog->sip_dlg_rset.sip_str_len; new_dlg->sip_dlg_route_set = sip_dup_header(dialog->sip_dlg_route_set); if (new_dlg->sip_dlg_route_set == NULL) { free(new_dlg->sip_dlg_rset.sip_str_ptr); if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL) free(new_dlg->sip_dlg_req_uri.sip_str_ptr); free(new_dlg); return (NULL); } } if ((new_dlg->sip_dlg_local_uri_tag = sip_dup_header(dialog->sip_dlg_local_uri_tag)) == NULL || (new_dlg->sip_dlg_remote_target = sip_dup_header(dialog->sip_dlg_remote_target)) == NULL || (new_dlg->sip_dlg_call_id = sip_dup_header(dialog->sip_dlg_call_id)) == NULL) { sip_release_dialog_res(new_dlg); return (NULL); } if (dialog->sip_dlg_event != NULL) { new_dlg->sip_dlg_event = sip_dup_header(dialog->sip_dlg_event); if (new_dlg->sip_dlg_event == NULL) { sip_release_dialog_res(new_dlg); return (NULL); } } new_dlg->sip_dlg_local_cseq = dialog->sip_dlg_local_cseq; new_dlg->sip_dlg_type = dialog->sip_dlg_type; new_dlg->sip_dlg_on_fork = B_FALSE; (void) pthread_mutex_init(&new_dlg->sip_dlg_mutex, NULL); return (new_dlg);}/* * Update the dialog using the response */sip_dialog_tsip_update_dialog(sip_dialog_t dialog, _sip_msg_t *sip_msg, void (*func)(sip_dialog_t, sip_msg_t, void *)){ _sip_dialog_t *_dialog; boolean_t isreq; sip_method_t method; int resp_code = 0; int prev_state; boolean_t decr_ref = B_FALSE; int error; isreq = sip_msg_is_request((sip_msg_t)sip_msg, &error); if (error != 0) return (dialog); _dialog = (_sip_dialog_t *)dialog; (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex); if (isreq) { method = sip_get_request_method((sip_msg_t)sip_msg, &error); if (error != 0 || _dialog->sip_dlg_method != SUBSCRIBE || method != NOTIFY) { (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); return (dialog); } } else { resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error); if (error != 0) { (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); return (dialog); } } prev_state = _dialog->sip_dlg_state; if (_dialog->sip_dlg_state == SIP_DLG_CONFIRMED) { (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); } else if (_dialog->sip_dlg_state == SIP_DLG_EARLY) { /* * Let the user delete the dialog if it is not a 1XX/2XX resp * for an early dialog. */ assert(!isreq); if (SIP_OK_RESP(resp_code)) { _dialog->sip_dlg_state = SIP_DLG_CONFIRMED; (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); (void) sip_dlg_recompute_rset(_dialog, sip_msg, SIP_UAS_DIALOG); if (sip_dlg_ulp_state_cb != NULL) { sip_dlg_ulp_state_cb(dialog, (sip_msg_t)sip_msg, prev_state, dialog->sip_dlg_state); } } else { (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); } } else if (_dialog->sip_dlg_state == SIP_DLG_NEW) { if (!isreq && _dialog->sip_dlg_method == SUBSCRIBE && SIP_PROVISIONAL_RESP(resp_code)) { (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); return (dialog); } if (_dialog->sip_dlg_type == SIP_UAC_DIALOG) { _sip_dialog_t *new_dlg; if (_dialog->sip_dlg_on_fork) { new_dlg = sip_copy_partial_dialog(_dialog); if (new_dlg == NULL) { (void) pthread_mutex_unlock( &_dialog->sip_dlg_mutex); return (dialog); } /* * This decr/incr dance is because the caller * has incremented the ref on the partial * dialog, we release it here and incr the * ref on the new dialog which will be * released by the caller. */ (void) pthread_mutex_unlock( &_dialog->sip_dlg_mutex); SIP_DLG_REFCNT_DECR(_dialog); _dialog = new_dlg; (void) pthread_mutex_lock( &_dialog->sip_dlg_mutex); SIP_DLG_REFCNT_INCR(_dialog); } else { int index; /* * take it out of the list so that further * responses will not result in a dialog. * We will have an extra refcount when we * come back from sip_complete_dialog(), i.e. * one when the partial dialog was created - * in sip_seed_dialog(), one held by the caller * and one that will be added by * sip_complete_dialog(). We need to release * the one added by the sip_seed_dialog(), * since the one in sip_complete_dialog() * is for the same purpose. */ /* Cancel the timer */ if (SIP_IS_TIMER_RUNNING( _dialog->sip_dlg_timer)) { SIP_CANCEL_TIMER( dialog->sip_dlg_timer); } index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id); (void) pthread_mutex_unlock( &_dialog->sip_dlg_mutex); sip_hash_delete(sip_dialog_phash, (void *)_dialog->sip_dlg_id, index, sip_dialog_dontfree); (void) pthread_mutex_lock( &_dialog->sip_dlg_mutex); decr_ref = B_TRUE; } } (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); if ((dialog = sip_complete_dialog(sip_msg, _dialog, func)) == NULL) { return (NULL); } if (decr_ref) SIP_DLG_REFCNT_DECR(_dialog); } else { (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex); } return (dialog);}/* Initialize the hash table */voidsip_dialog_init(void (*ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int)){ int cnt; for (cnt = 0; cnt < SIP_HASH_SZ; cnt++) { sip_dialog_hash[cnt].hash_count = 0; sip_dialog_hash[cnt].hash_head = NULL; sip_dialog_hash[cnt].hash_tail = NULL; (void) pthread_mutex_init( &sip_dialog_hash[cnt].sip_hash_mutex, NULL); sip_dialog_phash[cnt].hash_count = 0; sip_dialog_phash[cnt].hash_head = NULL; sip_dialog_phash[cnt].hash_tail = NULL; (void) pthread_mutex_init( &sip_dialog_phash[cnt].sip_hash_mutex, NULL); } if (ulp_state_cb != NULL) sip_dlg_ulp_state_cb = ulp_state_cb;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -