Files
gb28181/GB28181Device/sip/sip_trans.cpp
2024-12-15 20:42:32 +08:00

280 lines
7.4 KiB
C++

/***************************************************************************************
*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
*
* By downloading, copying, installing or using the software you agree to this license.
* If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Copyright (C) 2014-2022, Happytimesoft Corporation, all rights reserved.
*
* Redistribution and use in binary forms, with or without modification, are permitted.
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*
****************************************************************************************/
#include "sys_inc.h"
#include "hsip.h"
#include "sip_parse.h"
#include "sip_trans.h"
/***************************************************************************************/
extern HSIP_CLASS hsip;
/***************************************************************************************/
STRANSN * sip_trans_get_idle(STRANS * thiz, BOOL b_sig)
{
STRANSN * p_trans =(STRANSN *)pps_fl_pop(thiz->trans_fl);
if (p_trans)
{
memset(p_trans, 0, sizeof(STRANSN));
// Set the global ID of this call
sprintf(p_trans->callid, "%u%u@%s", (uint32)rand(), sys_os_get_uptime(), hsip.local_ipstr);
if (b_sig == TRUE)
{
p_trans->p_wait_sig = sys_os_create_sig();
}
// Set default retransmission parameters
p_trans->state_retx_count = 0;
p_trans->state_timer_interval = 1;
p_trans->state_retx_max_times = 5;
pps_ctx_ul_add(thiz->trans_ul, p_trans); // Add to UsedList for easy management
}
else
{
// pps_ctx_show(thiz->trans_fl);
}
return p_trans;
}
BOOL sip_trans_set_msg(STRANSN * p_trans, void * p_msg)
{
if (p_trans == NULL || p_msg == NULL)
{
return FALSE;
}
HSIP_MSG * tx_msg = (HSIP_MSG *)p_msg;
char cseq[16];
if (sip_get_user_name(tx_msg, "From", p_trans->from, sizeof(p_trans->from)) == FALSE)
{
return FALSE;
}
if (sip_get_user_name(tx_msg, "To", p_trans->to, sizeof(p_trans->to)) == FALSE)
{
return FALSE;
}
if (sip_get_msg_call_id(tx_msg, p_trans->callid, sizeof(p_trans->callid)) == FALSE)
{
return FALSE;
}
if (sip_get_msg_cseq(tx_msg, cseq, sizeof(cseq)) == FALSE)
{
return FALSE;
}
p_trans->seq = (uint32)atoi(cseq);
p_trans->tx_msg = tx_msg;
p_trans->state = 1;
log_print(HT_LOG_INFO, "%s, from[%s] to[%s] callid[%s] seq[%u]\r\n",
__FUNCTION__, p_trans->from, p_trans->to, p_trans->callid, p_trans->seq);
return TRUE;
}
void sip_trans_set_idle(STRANS * thiz, STRANSN * p_trans)
{
sip_trans_hash_del(thiz, p_trans);
sys_os_destroy_sig_mutex(p_trans->p_wait_sig);
memset(p_trans, 0, sizeof(STRANSN));
pps_fl_push_tail(thiz->trans_fl, p_trans);
}
void sip_trans_free_used(STRANS * thiz, STRANSN * p_trans)
{
pps_ctx_ul_del(thiz->trans_ul, p_trans);
sip_trans_set_idle(thiz, p_trans);
}
STRANSN * sip_trans_lookup_start(STRANS * thiz)
{
return (STRANSN *)pps_lookup_start(thiz->trans_ul);
}
STRANSN * sip_trans_lookup_next(STRANS * thiz, STRANSN * p_trans)
{
return (STRANSN *)pps_lookup_next(thiz->trans_ul, p_trans);
}
void sip_trans_lookup_stop(STRANS * thiz)
{
pps_lookup_end(thiz->trans_ul);
}
/*******************************************************\
Get the index value of the corresponding PTRANS transaction entry
\*******************************************************/
uint32 sip_trans_get_index(STRANS * thiz, STRANSN * p_trans)
{
return pps_get_index(thiz->trans_fl, p_trans);
}
STRANSN * sip_trans_get_by_index(STRANS * thiz, uint32 index)
{
return (STRANSN *)pps_get_node_by_index(thiz->trans_fl, index);
}
/*******************************************************\
PTRANS transaction table entry HASH operation
\*******************************************************/
void sip_trans_hash_add(STRANS * thiz, STRANSN * p_trans)
{
snprintf(p_trans->hash_key, sizeof(p_trans->hash_key)-1, "%s%s%s%u", p_trans->callid, p_trans->from, p_trans->to, p_trans->seq);
ihash_add(thiz->trans_hash, p_trans->hash_key, sip_trans_get_index(thiz, p_trans), 0);
}
void sip_trans_hash_del(STRANS * thiz, STRANSN * p_trans)
{
ihash_del(thiz->trans_hash, p_trans->hash_key, sip_trans_get_index(thiz, p_trans));
}
STRANSN * sip_trans_hash_find(STRANS * thiz, const char * hash_key)
{
uint32 trans_index = (uint32) ihash_find_index_from_keystr(thiz->trans_hash, hash_key);
if (trans_index == 0xFFFFFFFF || trans_index >= thiz->trans_num)
{
return NULL;
}
return sip_trans_get_by_index(thiz, trans_index);
}
/*******************************************************\
Transaction timer, check retransmission requirements
\*******************************************************/
void sip_trans_timer(STRANS * thiz, uint32 cur_t)
{
uint32 i;
STRANSN * p_trans;
for (i = 0; i < thiz->trans_num; i++)
{
p_trans = sip_trans_get_by_index(thiz, i);
if (p_trans == NULL || p_trans->last_tx_time == 0 || p_trans->state != 1)
{
continue;
}
if ((cur_t - p_trans->last_tx_time) > p_trans->state_timer_interval)
{
if (p_trans->state_retx_count > p_trans->state_retx_max_times)
{
p_trans->state = 4;
if (p_trans->p_wait_sig)
{
sys_os_sig_sign(p_trans->p_wait_sig); // Notify the caller, the caller checks the state unit to determine whether it is successful or not
}
continue;
}
// sip_user_send_msg(&g_user, p_trans->tx_msg);
p_trans->last_tx_time = sys_os_get_uptime();
p_trans->state_retx_count++;
}
}
}
/*******************************************************\
Response packet receiving processing
\*******************************************************/
STRANSN * sip_trans_rly_find(STRANS * thiz, const char * callid, const char * from, const char * to, uint32 seq)
{
char hash_key[128];
snprintf(hash_key, sizeof(hash_key)-1, "%s%s%s%u", callid, from, to, seq);
STRANSN * p_trans = sip_trans_hash_find(thiz, hash_key);
if (p_trans == NULL)
{
return NULL;
}
if ((strcasecmp(p_trans->from, from) != 0) || (strcasecmp(p_trans->to, to) != 0) || p_trans->seq != seq)
{
log_print(HT_LOG_ERR, "%s, hash err!!!\r\n", __FUNCTION__);
return NULL;
}
p_trans->state = 2;
return p_trans;
}
/*******************************************************\
Transaction request response waiting
\*******************************************************/
int sip_trans_wait(STRANSN * p_trans, int ms)
{
return sys_os_sig_wait_timeout(p_trans->p_wait_sig, ms);
}
/*******************************************************\
Transaction initialization function
\*******************************************************/
void sip_trans_init(STRANS * thiz, int num)
{
memset(thiz, 0, sizeof(STRANS));
thiz->trans_num = num;
thiz->trans_fl = pps_ctx_fl_init(num, sizeof(STRANSN), TRUE);
thiz->trans_ul = pps_ctx_ul_init(thiz->trans_fl, TRUE);
thiz->trans_hash = ihash_init(num, num);
}
void sip_trans_uninit(STRANS * thiz)
{
if (thiz->trans_hash)
{
ihash_uninit(thiz->trans_hash);
thiz->trans_hash = NULL;
}
if (thiz->trans_ul)
{
pps_ul_free(thiz->trans_ul);
thiz->trans_ul = NULL;
}
if (thiz->trans_fl)
{
pps_fl_free(thiz->trans_fl);
thiz->trans_fl = NULL;
}
}