Files
svc.ems/plat/sip/src/sip_transaction.c
2024-09-27 15:39:34 +08:00

1003 lines
38 KiB
C

#include "./include/sip_pub.h"
#include "./include/sip.h"
#include "./include/sip_const.h"
#include "./include/sip_struct.h"
#include "./include/sip_ext.h"
#include "./include/sip_transport.h"
#include "./include/sip_msg.h"
int sip_create_trans_branch(WORD transId, SIP_GEN_PARA *branch)
{
branch->paraName = SIP_API_PNAME_BRANCH;
branch->paraType = SIP_API_PTYPE_STRING;
sprintf(branch->para.paraStr, "z9hG4bk-%d-%ld", SIP_BRANCH_BASE_TRANS_ID + transId, time(NULL));
return 0;
}
DWORD sip_min(DWORD A, DWORD B)
{
if (A <= B)
return A;
return B;
}
void sip_trans_init(WORD trans_id)
{
memset((BYTE *)&sipTrans[trans_id], 0, sizeof(SIP_TRANSACTION));
}
int sip_request_uri_match(SIP_URI *uriFirst, SIP_URI *uriSecond)
{
if (strcmp(uriFirst->userName, uriSecond->userName) != 0)
return -1;
if (strcmp(uriFirst->host.addr.domain, uriSecond->host.addr.domain) != 0)
return -1;
return 0;
}
int sip_call_id_match(SIP_HDR_CALL_ID *callIdFirst, SIP_HDR_CALL_ID *callIdSecond)
{
if (strcmp(callIdFirst->value, callIdSecond->value) !=0)
return -1;
if (strcmp(callIdFirst->host, callIdSecond->host) != 0)
return -1;
return 0;
}
int sip_top_via_match(SIP_HDR_VIA *viaFirst, SIP_HDR_VIA *viaSecond)
{
if (strcmp(viaFirst->url.domain, viaSecond->url.domain) != 0)
return -1;
return 0;
}
WORD sip_request_match_server_trans(SIP_API_STRUCT *recvMsg)
{
WORD transId;
char *branchRecvd, *branchCreated;
char *sentByRecvd, *sentByCreated;
char methodRecvd, methodCreated;
SIP_MSG *sipMsgRecvd;
SIP_CR_MSG *sipMsgCreated;
SIP_URI *requestUriRecvd, *requestUriCreated;
char *toTagRecvd, *toTagCreated;//, *toTagResponse;//improve
char *fromTagRecvd, *fromTagCreated;
SIP_HDR_CALL_ID *callIdRecvd, *callIdCreated;
SIP_HDR_CSEQ *cseqRecvd, *cseqCreated;
SIP_HDR_VIA *viaRecvd, *viaCreated;
sipMsgRecvd = &recvMsg->sipApiMsg.sipMsg;
methodRecvd = sipMsgRecvd->sipStartLine.sipMethod;
viaRecvd = &sipMsgRecvd->sipHdrVias.vias[1];
branchRecvd = viaRecvd->params.para[0].para.paraStr;
if (strncmp(branchRecvd, "z9hG4bK", 7) == 0)
{ // RFC 3261
sentByRecvd = sipMsgRecvd->sipHdrVias.vias[1].url.domain;
for (transId = 0; transId < SIP_MAX_NUM_OF_TRANS; transId++)
{
if ((sipTrans[transId].flag != 1) ||
(sipTrans[transId].client != SIP_TRANS_SERVER))
continue;
sipMsgCreated = &sipTrans[transId].crMsg;
branchCreated = sipMsgCreated->sipCrHdrVia.params.para[0].para.paraStr;
sentByCreated = sipMsgCreated->sipCrHdrVia.url.domain;
methodCreated = sipMsgCreated->sipCrStartLine.sipMethod;
if ((strcmp(branchRecvd, branchCreated) == 0) &&
(strcmp(sentByRecvd, sentByCreated) == 0))//
{
if (methodRecvd == SIP_METHOD_ACK)
return transId;
else if (methodRecvd == methodCreated)
return transId;
}
}
}
// RFC 2543
requestUriRecvd = &sipMsgRecvd->sipStartLine.requestUri;
toTagRecvd = sipMsgRecvd->sipHdrTo.params.para[0].para.paraStr;
fromTagRecvd = sipMsgRecvd->sipHdrFrom.params.para[0].para.paraStr;
callIdRecvd = &sipMsgRecvd->sipHdrCallId;
cseqRecvd = &sipMsgRecvd->sipHdrCseq;
for (transId = 0; transId < SIP_MAX_NUM_OF_TRANS; transId++)
{
if ((sipTrans[transId].flag != 1) ||
(sipTrans[transId].client != SIP_TRANS_SERVER))
continue;
sipMsgCreated = &sipTrans[transId].crMsg;
requestUriCreated = &sipMsgCreated->sipCrStartLine.requestUri;
toTagCreated = sipMsgCreated->sipCrHdrTo.params.para[0].para.paraStr;
// toTagResponse = sipTrans[transId].sdMsg.sipApiMsg.sipMsg.sipHdrTo.params.para[0].para.paraStr;//improve
fromTagCreated = sipMsgCreated->sipCrHdrFrom.params.para[0].para.paraStr;
callIdCreated = &sipMsgCreated->sipCrHdrCallId;
cseqCreated = &sipMsgCreated->sipCrHdrCseq;
viaCreated = &sipMsgCreated->sipCrHdrVia;
if ((sip_request_uri_match(requestUriRecvd, requestUriCreated) == 0) &&
(strcmp(fromTagRecvd, fromTagCreated) == 0) &&
(sip_call_id_match(callIdRecvd, callIdCreated) == 0) &&
(cseqRecvd->value == cseqCreated->value) &&
(sip_top_via_match(viaRecvd, viaCreated) == 0))
{
if (methodRecvd == SIP_METHOD_ACK)
{
if (strcmp(toTagRecvd, toTagCreated) == 0)//if (strcmp(toTagRecvd, toTagResponse) == 0)//improve
return transId;
}
else
{
if ((strcmp(toTagRecvd, toTagCreated) == 0) &&
(cseqRecvd->method == cseqCreated->method))
return transId;
}
}
}
return SIP_MAX_NUM_OF_TRANS;
}
WORD sip_response_match_client_trans(SIP_API_STRUCT *recvMsg)
{
char *first;
char *second;
char tmp[8] = "";
char *branchRecvd, *branchCreated;
BYTE methodRecvd, methodCreated;
WORD transId;
branchRecvd = recvMsg->sipApiMsg.sipMsg.sipHdrVias.vias[1].params.para[0].para.paraStr;
first = strchr(branchRecvd, '-');
if (first == NULL)
return SIP_MAX_NUM_OF_TRANS;
second = strchr(first + 1, '-');
if (second == NULL)
return SIP_MAX_NUM_OF_TRANS;
if ((second - first - 1) != SIP_BRANCH_BASE_TRANS_ID_LEN)
return SIP_MAX_NUM_OF_TRANS;
strncpy(tmp, first + 1, SIP_BRANCH_BASE_TRANS_ID_LEN);
transId = atol(tmp);
transId = transId - SIP_BRANCH_BASE_TRANS_ID;
if (transId >= SIP_MAX_NUM_OF_TRANS)
return SIP_MAX_NUM_OF_TRANS;
methodRecvd = recvMsg->sipApiMsg.sipMsg.sipHdrCseq.method;
methodCreated = sipTrans[transId].crMsg.sipCrHdrCseq.method;
branchCreated = sipTrans[transId].crMsg.sipCrHdrVia.params.para[0].para.paraStr;
if ((strcmp(branchRecvd, branchCreated) == 0) &&
(methodRecvd == methodCreated))
return transId;
else
{
for (transId = 0; transId < SIP_MAX_NUM_OF_TRANS; transId++)
{
if ((sipTrans[transId].flag != 1) ||
(sipTrans[transId].client != SIP_TRANS_CLIENT))
continue;
methodCreated = sipTrans[transId].crMsg.sipCrHdrCseq.method;
branchCreated = sipTrans[transId].crMsg.sipCrHdrVia.params.para[0].para.paraStr;
if ((strcmp(branchRecvd, branchCreated) == 0) &&
(methodRecvd == methodCreated))
return transId;
}
}
return SIP_MAX_NUM_OF_TRANS;
}
int sip_trans_srv_non_inv_proc(WORD transId)
{
SIP_TRANSACTION *sipTransPtr;
WORD sdCmd;
WORD rvCmd;
SIP_USER *sipUser;
sipTransPtr = &sipTrans[transId];
sdCmd = sipTransPtr->sdCmd;
rvCmd = sipTransPtr->rvCmd;
sipUser = &sipUsers.sipUsers[sipTransPtr->userIndex].sipUser;
switch (sipTransPtr->state)
{
case SIP_TRANS_STATE_IDLE:
// Request received, pass to TU
sipTransPtr->state = SIP_TRANS_STATE_TRYING;
sipTransPtr->timer = (18 * SIP_TIMER_T4);
return sip_trans_srv_non_inv_proc(transId);
case SIP_TRANS_STATE_TRYING:
if (sdCmd != SIP_COMMAND_IDLE)
{
sipTransPtr->sdCmd = SIP_COMMAND_IDLE;
if ((sdCmd >= 100) && (sdCmd <= 199))
{ // If 1XX from TU, send response
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
sipTransPtr->state = SIP_TRANS_STATE_PROCEEDING;
sipTransPtr->timer = (18 * SIP_TIMER_T4);
}
else if ((sdCmd >= 200) && (sdCmd <= 699))
{ // If 200-699 from TU, send response
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
sipTransPtr->state = SIP_TRANS_STATE_COMPLETED;
sipTransPtr->timer = SIP_TIMER_J;
}
}
if ((SIP_TRANS_STATE_TRYING == sipTransPtr->state) && (sipTransPtr->timer > 0))
{
if (--sipTransPtr->timer == 0)
{
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
}
break;
case SIP_TRANS_STATE_PROCEEDING:
if (sdCmd != SIP_COMMAND_IDLE)
{
sipTransPtr->sdCmd = SIP_COMMAND_IDLE;
if ((sdCmd >= 100) && (sdCmd <= 199))
{ // If 1XX from TU, send response
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
}
else if ((sdCmd >= 200) && (sdCmd <= 699))
{ // If 200-699 from TU, send response
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
sipTransPtr->state = SIP_TRANS_STATE_COMPLETED;
sipTransPtr->timer = SIP_TIMER_J;
return 0;
}
}
if (rvCmd != SIP_COMMAND_IDLE)
{
sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
if (rvCmd == SIP_TRANSPORT_ERROR)
{ // If transport error, inform TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
else
{ // If request, send response
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
}
}
if ((SIP_TRANS_STATE_PROCEEDING == sipTransPtr->state) && (sipTransPtr->timer > 0))
{
if (--sipTransPtr->timer == 0)
{
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
}
break;
case SIP_TRANS_STATE_COMPLETED:
if (rvCmd != SIP_COMMAND_IDLE)
{
sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
// Request, send response
if (rvCmd == SIP_TRANSPORT_ERROR)
{ // If transport error, inform TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
else
{ // If request, send response
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
}
}
if (sipTransPtr->timer > 0)
sipTransPtr->timer--;
if (sipTransPtr->timer == 0)
{ // if timer J fires
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
break;
default:
sipTransPtr->state = SIP_TRANS_STATE_IDLE;
break;
}
return 0;
}
int sip_trans_srv_inv_proc(WORD transId)
{
SIP_TRANSACTION *sipTransPtr;
WORD sdCmd;
WORD rvCmd;
SIP_USER *sipUser;
sipTransPtr = &sipTrans[transId];
sdCmd = sipTransPtr->sdCmd;
rvCmd = sipTransPtr->rvCmd;
sipUser = &sipUsers.sipUsers[sipTransPtr->userIndex].sipUser;
switch (sipTransPtr->state)
{
case SIP_TRANS_STATE_IDLE:
// INVITE received, pass to TU
sipTransPtr->timer2= SIP_TIMER_200MS;
sipTransPtr->timer = (18 * SIP_TIMER_T4);
sipTransPtr->state = SIP_TRANS_STATE_PROCEEDING;
return sip_trans_srv_inv_proc(transId);
break;
case SIP_TRANS_STATE_PROCEEDING:
if (sdCmd != SIP_COMMAND_IDLE)
{
sipTransPtr->sdCmd = SIP_COMMAND_IDLE;
if ((sdCmd >= 101) && (sdCmd <= 199))
{ // if 101-199 from TU, send response
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
sipTransPtr->timer2 = 0;
}
else if ((sdCmd >= 200) && (sdCmd <= 299))
{ // if 2xx from TU, send response
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
sipTransPtr->timer2 = 0;
sipTransPtr->timer = 0;
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
else if ((sdCmd >= 300) && (sdCmd <= 699))
{ // if 300-699 from TU, send response
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
sipTransPtr->state = SIP_TRANS_STATE_COMPLETED;
sipTransPtr->timer2 = SIP_TIMER_G;
sipTransPtr->timer = SIP_TIMER_H;
return 0;
}
}
if (rvCmd != SIP_COMMAND_IDLE)
{
sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
if (rvCmd == SIP_TRANSPORT_ERROR)
{ // If transport error, inform TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
else if (rvCmd == SIP_METHOD_INVITE)
{ // If INVITE, send response
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
}
}
if ((SIP_TRANS_STATE_PROCEEDING == sipTransPtr->state) && (sipTransPtr->timer2 > 0))
{
if (--sipTransPtr->timer2== 0)
sip_send_100(&sipTransPtr->crMsg, sipTransPtr);
}
if ((SIP_TRANS_STATE_PROCEEDING == sipTransPtr->state) && (sipTransPtr->timer > 0))
{
if (--sipTransPtr->timer == 0)
{
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
}
break;
case SIP_TRANS_STATE_COMPLETED:
if (rvCmd != SIP_COMMAND_IDLE)
{
sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
if (rvCmd == SIP_TRANSPORT_ERROR)
{ // If transport error, inform TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
else if (rvCmd == SIP_METHOD_ACK)
{ // If ACK
sipTransPtr->state = SIP_TRANS_STATE_CONFIRMED;
sipTransPtr->timer = SIP_TIMER_I;
return 0;
}
else if (rvCmd == SIP_METHOD_INVITE)
{ // If INVITE, send response
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
}
}
if ((SIP_TRANS_STATE_COMPLETED == sipTransPtr->state) && (sipTransPtr->timer2 > 0))
{
if (--sipTransPtr->timer2 == 0)
{// If timer G fires, send response
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
sipTransPtr->retransTimes++;
sipTransPtr->timer2 = sip_min((1 << sipTransPtr->retransTimes) * SIP_TIMER_E_INITIAL, SIP_TIMER_T2);
}
}
if ((SIP_TRANS_STATE_COMPLETED == sipTransPtr->state) && (sipTransPtr->timer > 0))
{
if (--sipTransPtr->timer == 0)
{ // If timer H fires
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
}
break;
case SIP_TRANS_STATE_CONFIRMED:
if (sipTransPtr->timer > 0)
sipTransPtr->timer--;
if (sipTransPtr->timer == 0)
{ // If timer I fires
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
break;
default:
sipTransPtr->state = SIP_TRANS_STATE_IDLE;
break;
}
return 0;
}
int sip_trans_clt_non_inv_proc(WORD transId)
{
SIP_TRANSACTION *sipTransPtr;
SIP_USER *sipUser;
WORD sdCmd;
WORD rvCmd;
sipTransPtr = &sipTrans[transId];
sdCmd = sipTransPtr->sdCmd;
rvCmd = sipTransPtr->rvCmd;
sipUser = &sipUsers.sipUsers[sipTransPtr->userIndex].sipUser;
switch (sipTransPtr->state)
{
case SIP_TRANS_STATE_IDLE:
if (sdCmd != SIP_COMMAND_IDLE)
{
sipTransPtr->sdCmd = SIP_COMMAND_IDLE;
if (sdCmd != SIP_METHOD_INVITE)
{ // Request from TU, send request
// sip_fill_cr_msg(&sipTransPtr->crMsg, &sipTransPtr->sdMsg);//improve
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
if (sdCmd == SIP_METHOD_ACK)
{
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
else
{
sipTransPtr->timer = SIP_TIMER_F;
sipTransPtr->timer2 = SIP_TIMER_E_INITIAL;
sipTransPtr->retransTimes = 0;
sipTransPtr->state = SIP_TRANS_STATE_TRYING;
}
}
else
return 1;
}
break;
case SIP_TRANS_STATE_TRYING:
if (rvCmd != SIP_COMMAND_IDLE)
{
sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
if ((rvCmd >= 200) & (rvCmd <= 699))
{ // 200-699, resp. to TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_COMPLETED;
sipTransPtr->timer = SIP_TIMER_K;
return 0;
}
else if (rvCmd == SIP_TRANSPORT_ERROR)
{ // Transport error, inform TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
else if ((rvCmd >= 100) & (rvCmd <= 199))
{ // 1xx, 1xx to TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_PROCEEDING;
sipTransPtr->timer = SIP_TIMER_F;
// sipTransPtr->timer2 = SIP_TIMER_T2;//??
return 0;
}
}
if ((SIP_TRANS_STATE_TRYING == sipTransPtr->state) && (sipTransPtr->timer2 > 0))
{
if (--sipTransPtr->timer2 == 0)
{// Timer E fires, send request
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
sipTransPtr->retransTimes++;
sipTransPtr->timer2 = sip_min((1 << sipTransPtr->retransTimes) * SIP_TIMER_E_INITIAL, SIP_TIMER_T2);
}
}
if ((SIP_TRANS_STATE_TRYING == sipTransPtr->state) && (sipTransPtr->timer > 0))
{
if (--sipTransPtr->timer == 0)
{// If timer F fires, inform TU
/* memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
memcpy(&sipToUpMsg, &sipTransPtr->sdMsg, sizeof(SIP_API_STRUCT));
sipToUpMsg.sipApiType = SIP_API_RES_MSG;
sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
*///improve
memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
sip_fill_msg_with_cr(&sipToUpMsg.sipApiMsg.sipMsg, &sipTransPtr->crMsg);
sipToUpMsg.sipApiType = SIP_API_RES_MSG;
sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
}
break;
case SIP_TRANS_STATE_PROCEEDING:
if (rvCmd != SIP_COMMAND_IDLE)
{
sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
if ((rvCmd >= 200) & (rvCmd <= 699))
{ // 100-699, resp. to TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_COMPLETED;
sipTransPtr->timer = SIP_TIMER_K;
return 0;
}
else if (rvCmd == SIP_TRANSPORT_ERROR)
{ // Transport error, inform TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
else if ((rvCmd >= 100) & (rvCmd <= 199))
{ // 1xx, 1xx to TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
}
}
if ((SIP_TRANS_STATE_PROCEEDING == sipTransPtr->state) && (sipTransPtr->timer2 > 0))
{
if (--sipTransPtr->timer2 == 0)
{// Timer E fires, send request
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
sipTransPtr->retransTimes++;
sipTransPtr->timer2 = SIP_TIMER_T2;
}
}
if ((SIP_TRANS_STATE_PROCEEDING == sipTransPtr->state) && (sipTransPtr->timer > 0))
{
if (--sipTransPtr->timer == 0)
{// If timer F fires, inform TU
/* memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
memcpy(&sipToUpMsg, &sipTransPtr->sdMsg, sizeof(SIP_API_STRUCT));
sipToUpMsg.sipApiType = SIP_API_RES_MSG;
sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
*///improve
memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
sip_fill_msg_with_cr(&sipToUpMsg.sipApiMsg.sipMsg, &sipTransPtr->crMsg);
sipToUpMsg.sipApiType = SIP_API_RES_MSG;
sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
}
break;
case SIP_TRANS_STATE_COMPLETED:
if (sipTransPtr->timer > 0)
sipTransPtr->timer--;
if (sipTransPtr->timer == 0)
{ // if timer K fires
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
break;
default:
sipTransPtr->state = SIP_TRANS_STATE_IDLE;
break;
}
return 0;
}
int sip_trans_clt_inv_proc(WORD transId)
{
SIP_TRANSACTION *sipTransPtr;
SIP_USER *sipUser;
WORD sdCmd;
WORD rvCmd;
sipTransPtr = &sipTrans[transId];
sdCmd = sipTransPtr->sdCmd;
rvCmd = sipTransPtr->rvCmd;
sipUser = &sipUsers.sipUsers[sipTransPtr->userIndex].sipUser;
switch (sipTransPtr->state)
{
case SIP_TRANS_STATE_IDLE:
if (sdCmd != SIP_COMMAND_IDLE)
{
sipTransPtr->sdCmd = SIP_COMMAND_IDLE;
if ((sdCmd == SIP_METHOD_INVITE) || (sdCmd == SIP_METHOD_RE_INVITE))
{ // INVITE from TU, INVITE sent
// sip_fill_cr_msg(&sipTransPtr->crMsg, &sipTransPtr->sdMsg);//improve
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
sipTransPtr->timer = SIP_TIMER_B;
sipTransPtr->timer2 = SIP_TIMER_A;
sipTransPtr->state = SIP_TRANS_STATE_CALLING;
}
else
return 1;
}
break;
case SIP_TRANS_STATE_CALLING:
if (rvCmd != SIP_COMMAND_IDLE)
{
sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
if ((rvCmd >= 300) & (rvCmd <= 699))
{ // 300-699, ACK sent, resp. to TU
sip_send_ack(&sipRecvMsg, sipTransPtr);
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_COMPLETED;
sipTransPtr->timer = SIP_TIMER_D;
sipTransPtr->timer2 = 0;
return 0;
}
else if ((rvCmd >= 200) & (rvCmd <= 299))
{ // 2xx, 2xx to TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
sipTransPtr->timer2 = 0;
return 1;
}
else if ((rvCmd >= 100) & (rvCmd <= 199))
{ // 1xx, 1xx to TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_PROCEEDING;
sipTransPtr->timer2 = 0;
sipTransPtr->timer = (7 * SIP_TIMER_T4);
return 0;
}
else if (rvCmd == SIP_TRANSPORT_ERROR)
{ // transport error, inform TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
sipTransPtr->timer2 = 0;
return 1;
}
}
if (sipTransPtr->timer2 > 0)
{
if (--sipTransPtr->timer2 == 0)
{ // If timer A fires, reset A, INVITE sent
sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
// sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
sipTransPtr->retransTimes++;
sipTransPtr->timer2 = sip_min((1 << sipTransPtr->retransTimes) * SIP_TIMER_E_INITIAL, SIP_TIMER_B);
}
}
if ((SIP_TRANS_STATE_CALLING == sipTransPtr->state) && (sipTransPtr->timer > 0))
{
if (--sipTransPtr->timer == 0)
{// If timer B fires, inform TU
/* memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
memcpy(&sipToUpMsg, &sipTransPtr->sdMsg, sizeof(SIP_API_STRUCT));
sipToUpMsg.sipApiType = SIP_API_RES_MSG;
sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
*///improve
memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
sip_fill_msg_with_cr(&sipToUpMsg.sipApiMsg.sipMsg, &sipTransPtr->crMsg);
sipToUpMsg.sipApiType = SIP_API_RES_MSG;
sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
}
break;
case SIP_TRANS_STATE_PROCEEDING:
if (rvCmd != SIP_COMMAND_IDLE)
{
sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
if ((rvCmd >= 300) & (rvCmd <= 699))
{ // 300-699, ACK sent, resp. to TU
sip_send_ack(&sipRecvMsg, sipTransPtr);
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_COMPLETED;
sipTransPtr->timer = SIP_TIMER_D;
}
else if ((rvCmd >= 200) & (rvCmd <= 299))
{ // 2xx, 2xx to TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
else if ((rvCmd >= 100) & (rvCmd <= 199))
{ // 1xx, 1xx to TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
}
}
if ((SIP_TRANS_STATE_PROCEEDING == sipTransPtr->state) && (sipTransPtr->timer > 0))
{
if (-- sipTransPtr->timer == 0)
{
/* memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
memcpy(&sipToUpMsg, &sipTransPtr->sdMsg, sizeof(SIP_API_STRUCT));
sipToUpMsg.sipApiType = SIP_API_RES_MSG;
sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
*///improve
memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
sip_fill_msg_with_cr(&sipToUpMsg.sipApiMsg.sipMsg, &sipTransPtr->crMsg);
sipToUpMsg.sipApiType = SIP_API_RES_MSG;
sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
}
break;
case SIP_TRANS_STATE_COMPLETED:
if (rvCmd != SIP_COMMAND_IDLE)
{
sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
if ((rvCmd >= 300) & (rvCmd <= 699))
{ // 300-699, ACK sent
sip_send_ack(&sipRecvMsg, sipTransPtr);
}
else if (rvCmd == SIP_TRANSPORT_ERROR)
{ // if transport error, inform TU
sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
}
if (sipTransPtr->timer > 0)
sipTransPtr->timer--;
if (sipTransPtr->timer == 0)
{ // if timer D fires
sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
return 1;
}
break;
default:
sipTransPtr->state = SIP_TRANS_STATE_IDLE;
break;
}
return 0;
}
void sip_transaction_proc(WORD transid)
{
switch (sipTrans[transid].mainState)
{
case SIP_TRANS_MAIN_STATE_INIT:
sip_trans_init(transid);
break;
case SIP_TRANS_MAIN_STATE_SVR_NON_INV:
switch (sip_trans_srv_non_inv_proc(transid))
{
case 0:
break;
case 1:
sipTrans[transid].mainState = SIP_TRANS_MAIN_STATE_INIT;
sip_transaction_proc(transid);
break;
default:
break;
}
break;
case SIP_TRANS_MAIN_STATE_SVR_INV:
switch (sip_trans_srv_inv_proc(transid))
{
case 0:
break;
case 1:
sipTrans[transid].mainState = SIP_TRANS_MAIN_STATE_INIT;
sip_transaction_proc(transid);
break;
default:
break;
}
break;
case SIP_TRANS_MAIN_STATE_CLT_NON_INV:
switch (sip_trans_clt_non_inv_proc(transid))
{
case 0:
break;
case 1:
sipTrans[transid].mainState = SIP_TRANS_MAIN_STATE_INIT;
sip_transaction_proc(transid);
break;
default:
break;
}
break;
case SIP_TRANS_MAIN_STATE_CLT_INV:
switch (sip_trans_clt_inv_proc(transid))
{
case 0:
break;
case 1:
sipTrans[transid].mainState = SIP_TRANS_MAIN_STATE_INIT;
sip_transaction_proc(transid);
break;
default:
break;
}
break;
default:
sipTrans[transid].mainState = SIP_TRANS_MAIN_STATE_INIT;
break;
}
}
int sip_msg_transport_to_transaction(SIP_API_STRUCT *recvMsg, WORD transId)
{
SIP_TRANSACTION *sipTransPtr = &sipTrans[transId];
if (recvMsg->sipApiType == SIP_API_TYPE_RESPONSE)
sipTransPtr->rvCmd = recvMsg->sipApiMsg.sipMsg.sipStartLine.statusCode;
else if (recvMsg->sipApiType == SIP_API_TYPE_REQUEST)
sipTransPtr->rvCmd = recvMsg->sipApiMsg.sipMsg.sipStartLine.sipMethod;
sip_transaction_proc(transId);
return 0;
}
int sip_set_trans_send_cmd(SIP_TRANSACTION *trans, SIP_API_STRUCT *sipApiMsg)
{
SIP_START_LINE *startLine;
startLine = &sipApiMsg->sipApiMsg.sipMsg.sipStartLine;
if (sipApiMsg->sipApiType == SIP_API_REQ_MSG)
trans->sdCmd = startLine->sipMethod;
else if (sipApiMsg->sipApiType == SIP_API_RES_MSG)
trans->sdCmd = startLine->statusCode;
else
return -1;
return 0;
}
int sip_create_transaction(BYTE client, BYTE method, BYTE userIndex, WORD upPort, SIP_API_STRUCT *msg)
{
WORD i;
WORD transId = sipTransHead;
SIP_TRANSACTION *trans;
if (msg == NULL)
{
// sip_trans_init(transId);
return -1;
}//improve
if (transId>= SIP_MAX_NUM_OF_TRANS)
{
transId = 0;
}
for (i = 0; i < SIP_MAX_NUM_OF_TRANS; i++)
{
trans = &sipTrans[transId];
if (trans->flag != 0)
{
if (++transId >= SIP_MAX_NUM_OF_TRANS)
{
transId = 0;
}
continue;
}
else
{
sip_trans_init(transId);
trans->flag = 1;
trans->client = client;
trans->method = method;
trans->userIndex = userIndex;
trans->upPort = upPort;
/* if (client == SIP_TRANS_SERVER)
{
if (msg == NULL)
{
sip_trans_init(transId);
return -1;
}
sip_fill_cr_msg(&trans->crMsg, msg);
}
*///improve
sipTransHead = (transId+ 1) & SIP_MAX_NUM_OF_TRANS_1;
if (client == SIP_TRANS_SERVER)
{
if (method == SIP_TRANS_NON_INVITE)
trans->mainState = SIP_TRANS_MAIN_STATE_SVR_NON_INV;
else
trans->mainState = SIP_TRANS_MAIN_STATE_SVR_INV;
}
else
{
if (method == SIP_TRANS_NON_INVITE)
trans->mainState = SIP_TRANS_MAIN_STATE_CLT_NON_INV;
else
trans->mainState = SIP_TRANS_MAIN_STATE_CLT_INV;
if (msg->sipApiMsg.sipMsg.sipStartLine.sipMethod != SIP_METHOD_CANCEL)
{
sip_create_trans_branch(transId, &msg->sipApiMsg.sipMsg.sipHdrVias.vias[msg->sipApiMsg.sipMsg.sipHdrVias.head].params.para[0]);
msg->sipApiMsg.sipMsg.sipHdrVias.vias[msg->sipApiMsg.sipMsg.sipHdrVias.head].params.paraNum++;
}
}
trans->state = SIP_TRANS_STATE_IDLE;
sip_fill_cr_msg(&trans->crMsg, msg);//improve
return transId;
}
}
return SIP_MAX_NUM_OF_TRANS;
}