transacmng.c

来自「mgcp协议源代码和测试程序,还有一个编译器」· C语言 代码 · 共 1,780 行 · 第 1/5 页

C
1,780
字号
    
    /* If piggybacked command number is 0, move this transaction command into
       none piggybacking command list */
    if (pCmdPiggy->pCmdOut->wPiggyCmdNum == 0)
    {
      SListAppend(&pMsgList->CmdSentList, pCmdPiggy);
      SListDelCurNode(&pMsgList->CmdSentPiggybackList);
    }
    else
      SListNextNode(&pMsgList->CmdSentPiggybackList);
  }

  SListReset(&pMsgList->RspSentPiggybackList);
  while((pRspPiggy = SListGetCurData(&pMsgList->RspSentPiggybackList))!= NULL)
  {
    Assert(pRspPiggy->pRspOut->wPiggyCmdNum > 0);
    for (i = 0; i < pRspPiggy->pRspOut->wPiggyCmdNum; i++)
    {
      if (pRspPiggy->pRspOut->PiggybackCmdIDTable[i] == dwCommandID)
      {
        WORD j;

        /* Advance the following command IDs after the found Command ID */
        for (j = i+1; j < pRspPiggy->pRspOut->wPiggyCmdNum; j++)
        {          
          pRspPiggy->pRspOut->PiggybackCmdIDTable[i] =
                                   pRspPiggy->pRspOut->PiggybackCmdIDTable[j];
        }

        pRspPiggy->pRspOut->wPiggyCmdNum--;
        break;
      }
    }
    
    /* If piggybacked command number is 0, move this transaction response into
       none piggybacking response list */
    if (pRspPiggy->pRspOut->wPiggyCmdNum == 0)
    {
      SListAppend(&pMsgList->RspSentList, pRspPiggy);
      SListDelCurNode(&pMsgList->RspSentPiggybackList);
    }
    else
      SListNextNode(&pMsgList->RspSentPiggybackList);
  }

  SListReset(&pMsgList->RspSentPiggyWaitAckList);
  while((pRspPiggyWaitAck = SListGetCurData(&pMsgList->RspSentPiggyWaitAckList))!= NULL)
  {
    Assert(pRspPiggyWaitAck->pRspOut->wPiggyCmdNum > 0);
    for (i = 0; i < pRspPiggyWaitAck->pRspOut->wPiggyCmdNum; i++)
    {
      if (pRspPiggyWaitAck->pRspOut->PiggybackCmdIDTable[i] == dwCommandID)
      {
        WORD j;
        
        /* Advance the following command IDs after the found Command ID */
        for (j = i+1; j < pRspPiggy->pRspOut->wPiggyCmdNum; j++)
        {          
          pRspPiggyWaitAck->pRspOut->PiggybackCmdIDTable[i] =
                             pRspPiggyWaitAck->pRspOut->PiggybackCmdIDTable[j];
        }

        pRspPiggyWaitAck->pRspOut->wPiggyCmdNum--;
        break;
      }
    }
    
    /* If piggybacked response waiting ack number is 0, move this transaction
        response into none piggybacking response waiting ack list */
    if (pRspPiggyWaitAck->pRspOut->wPiggyCmdNum == 0)
    {
      SListAppend(&pMsgList->RspSentWaitAckList, pRspPiggyWaitAck);
      SListDelCurNode(&pMsgList->RspSentPiggyWaitAckList);
    }
    else
      SListNextNode(&pMsgList->RspSentPiggyWaitAckList);
  }
}
/******************************************************************************
 * Function          : SendProvisonalResponse
 *
 * Description       : Construct a Mgcp provisonal response and send out
 *                     
 * Input parameters  : dwTransactionId - Transaction ID of the response
 *                     dwRspCode - Response code of the response
 *                     iSocket_fd - Socket to send this response 
 *                     dwDesAddress - Destination IP address of the response
 *                     wDesPort - Destination port of the response
 *
 * Output parameters : 
 *
 * Return value      : None
 *
 * Comments          : 
 *
 * History           :
 *  2005/09/03       : Creation
 *
 * Date              : Sep 03 2005, Frank Zhang
 ******************************************************************************/
void SendProvisonalResponse(DWORD dwTransactionId, DWORD dwRspCode,
                            int iSocket_fd, DWORD dwDesAddress,
                            WORD wDesPort)
{
  TMGCPMsgList AbnfMsgList;
  TMGCPResponse *pRsp = NULL;
  TCtx ctx;
  char EnBuffer[ABNF_ENCODE_BUF_LEN];
  char *pcRspString;

  struct sockaddr_in DesAddress;
  socklen_t SocketLen = sizeof(struct sockaddr);

  memset(&AbnfMsgList, 0, sizeof(TMGCPMsgList));
  memset(EnBuffer, 0, sizeof(EnBuffer));
  CtxInitial(&ctx, EnBuffer, ABNF_ENCODE_BUF_LEN);
  
  AbnfMsgList.MGCPMessage.iNum = 1;
  AbnfMsgList.MGCPMessage.pNode = calloc(1, sizeof(TMGCPMessage));
  Assert(AbnfMsgList.MGCPMessage.pNode);

//  memset(AbnfMsgList.MGCPMessage.pNode, 0, sizeof(TMGCPMessage));
  
  ((TMGCPMessage*)AbnfMsgList.MGCPMessage.pNode)->iType = MGCPMessage_MGCPResponse;
  pRsp = &((TMGCPMessage*)AbnfMsgList.MGCPMessage.pNode)->u.MGCPResponse;
  
  /* Response code */
  StrClone(&pRsp->MGCPResponseLine.responseCode, Ultoa(dwRspCode));

  /* Transaction ID */
  StrClone(&pRsp->MGCPResponseLine.transaction_id, Ultoa(dwTransactionId));

  /* Response string */
  if ((pcRspString = FindRspStringByCode(dwRspCode)) != NULL)
  {
    pRsp->MGCPResponseLine.responseString.flag = 1;
    StrClone((char**)&pRsp->MGCPResponseLine.responseString.pRuleData,
             pcRspString);
  }

  if (EN_MGCPMsgList(&ctx, &AbnfMsgList) == OK)
  {
    DesAddress.sin_family = AF_INET;
    DesAddress.sin_port = htons(wDesPort);
    DesAddress.sin_addr.s_addr = htonl(dwDesAddress);
    
    sendto(iSocket_fd, ctx.pHead, ctx.pCur-ctx.pHead, 0,
           (struct sockaddr*)&DesAddress, SocketLen);
  }

  /* Free the AbnfMessages */
  Free_MGCPMsgList(&AbnfMsgList);  
}
/******************************************************************************
 * Function          : ProcessTransacIncomingMgcpCmd
 *
 * Description       : Process the transaction incoming mgcp command, if the
 *                     command is a old, resend the response or ignor it; if it
 *                     is a new one, add it into incoming command list and send
 *                     it to EndpointCtrl for further process
 *                     
 * Input parameters  : H_MGCP_TRANSAC_MANAGER - TransactionManager handle 
 *                     pMgcpCmd - pointer to Mgcp incoming command to be processed
 *
 * Output parameters : 
 *
 * Return value      : None
 *
 * Comments          : 
 *
 * History           :
 *  2005/09/03       : Creation
 *
 * Date              : Sep 03 2005, Frank Zhang
 ******************************************************************************/
void ProcessTransacIncomingMgcpCmd(H_MGCP_TRANSAC_MANAGER pTransacMng,
                                   MGCP_INCOMING_COMMAND *pMgcpCmd)
{
	TRANSAC_CMD_IN *pTransCmd;
	TRANSAC_RSP_OUT *pTransRsp;
	TRANSAC_RSP_WAIT_ACK *pTransRspWaitAck;
	
	Assert(pTransacMng);
	Assert(pMgcpCmd);
	
	/* Check command type validity */
	if (pMgcpCmd->eType == MGCP_CMD_RSIP || pMgcpCmd->eType == MGCP_CMD_NTFY)
	{
		DEBUG(LogMSG(LOG_ERROR, "\nUnsupported incoming cmd for MG, it is outgoing cmd!");)
		return;
	}
	
	/* Search the CmdInProcess queue to check if this command is being processed */
	if (SListFind(&pTransacMng->MsgList.CmdInProcessList,
				  &pMgcpCmd->dwTransacId, FindMgcpCmdInByTranID) != NULL)
	{
		DWORD dwRspCode = pTransacMng->MsgList.bQueueIsFull ?
						  RSP_TRANSACTION_QUEUED : RSP_TRANSACTION_IN_PROGRESS;
						  
		/* Send provisional response */
		if (pTransacMng->MsgList.bQueueIsFull)
		{
			SendProvisonalResponse(pMgcpCmd->dwTransacId, dwRspCode,
								   pTransacMng->iSocket_fd, pMgcpCmd->dwSrcIpAddr,
								   pMgcpCmd->wSrcPort);        
		}
		/* Set the provisional response sent flag of this command */
		pTransCmd = SListGetCurData(&pTransacMng->MsgList.CmdInProcessList);
		Assert(pTransCmd);
		pTransCmd->bProvisionalRspOut = TRUE;
	}
	/* Check if the command has been responsed */
	else if (SListFind(&pTransacMng->MsgList.RspSentList,
					 &pMgcpCmd->dwTransacId, FindMgcpRspOutByTranID) != NULL)
	{
		/* Re-Send the response */
		pTransRsp = SListGetCurData(&pTransacMng->MsgList.RspSentList);
		Assert(pTransRsp);
		SendMgcpRspOut(pTransacMng, pTransRsp->pRspOut, FALSE);		// 该反馈不需要确认
	}
	// 检查命令是否已经被响应, 响应消息是以附带在命令上的方式发送给对方的
	/* Check if the command has been responsed with piggybacking commands */		// piggyback : 附带
	else if (SListFind(&pTransacMng->MsgList.RspSentPiggybackList,
					   &pMgcpCmd->dwTransacId, FindMgcpRspOutByTranID) != NULL)
	{
		/* Re-Send the response */
		pTransRsp = SListGetCurData(&pTransacMng->MsgList.RspSentPiggybackList);
		Assert(pTransRsp);
		SendMgcpRspOut(pTransacMng, pTransRsp->pRspOut, FALSE);		// 该反馈不需要确认
	}
	/* Check if the command has been responsed and waiting ack */
	else if (SListFind(&pTransacMng->MsgList.RspSentWaitAckList,
					   &pMgcpCmd->dwTransacId, FindMgcpRspOutWaitAckByTranID) != NULL)
	{
		/* Re-Send the response waiting ack */
		pTransRspWaitAck = SListGetCurData(&pTransacMng->MsgList.RspSentWaitAckList);
		Assert(pTransRspWaitAck);
		SendMgcpRspOut(pTransacMng, pTransRspWaitAck->pRspOut, TRUE);	// 该反馈需要确认
	}
	/* Check if the command has been responsed with piggybacking commands
	 and waiting ack */
	else if (SListFind(&pTransacMng->MsgList.RspSentPiggyWaitAckList,
					   &pMgcpCmd->dwTransacId, FindMgcpRspOutWaitAckByTranID) != NULL)
	{
		/* Re-Send the piggybacking response waiting ack */
		pTransRspWaitAck = SListGetCurData(&pTransacMng->MsgList.RspSentPiggyWaitAckList);
		Assert(pTransRspWaitAck);
		SendMgcpRspOut(pTransacMng, pTransRspWaitAck->pRspOut, TRUE);	// 该反馈需要确认
	}
	/* Check if the command has been responsed and response has been acked */
	else if (SListFind(&pTransacMng->MsgList.RspAckReceivedList,
					   &pMgcpCmd->dwTransacId, FindMgcpRspACKByTranID) != NULL)
	{
		/* Response ack has been received, need no process */
	}
	else /* New incoming command */
	{
		MGCP_STACK_MSG Msg;
		MGCP_CMD_IN *pNewMgcpCmd  = NULL;
		
		if (pMgcpCmd->eType == MGCP_CMD_EXPR &&
			(StrCaseCmp(pMgcpCmd->u.pExprCmd->pcCmdName, "Auth") == 0))
		{
			MGCP_RSP_OUT MgcpRspOut;
			memset(&MgcpRspOut, 0, sizeof(MGCP_RSP_OUT));
			
			MgcpRspOut.wRspCode = 200;
			MgcpRspOut.pcRspString = "Frank ZHANG@2006";
			MgcpRspOut.dwTransacId = pMgcpCmd->dwTransacId;
			MgcpRspOut.dwDesIpAddr = pMgcpCmd->dwSrcIpAddr;
			MgcpRspOut.wDesPort = pMgcpCmd->wSrcPort;
			SendMgcpRspOut(pTransacMng, &MgcpRspOut, FALSE);	// 该反馈不需要确认
			return;
		}
		
		pNewMgcpCmd  = (MGCP_CMD_IN*)calloc(1, sizeof(MGCP_CMD_IN));
		Assert(pNewMgcpCmd);
		
		/* Create a new transaction command */
		pTransCmd = (TRANSAC_CMD_IN*)calloc(1, sizeof(TRANSAC_CMD_IN));
		Assert(pTransCmd);
		
		pTransCmd->dwTransacId = pMgcpCmd->dwTransacId;
		pTransCmd->bProvisionalRspOut = FALSE;
		
		/* Add this new command into incoming command queue */
		SListAppend(&pTransacMng->MsgList.CmdInProcessList, pTransCmd);
	    
		/* If the incoming command queue length reach the high water mark, send
		provisional response out */
	    if (pTransacMng->MsgList.bQueueIsFull ||
			(pTransacMng->MsgList.CmdInProcessList.count >=
			pTransacMng->MsgList.wHighWaterMark))
	    {
			SendProvisonalResponse(pMgcpCmd->dwTransacId, RSP_TRANSACTION_QUEUED,
								   pTransacMng->iSocket_fd, pMgcpCmd->dwSrcIpAddr,
								   pMgcpCmd->wSrcPort);
			
			pTransCmd->bProvisionalRspOut = TRUE;
			pTransacMng->MsgList.bQueueIsFull = TRUE;
	    }
		
		/* Construct a new stack message and send to EndpointCtrl */
		/* Transaction ID */
		pNewMgcpCmd->dwTransacId = pMgcpCmd->dwTransacId;
		
		/* Endpoint name */
		pNewMgcpCmd->EndpointName.pcLocalName = pMgcpCmd->EndpointName.pcLocalName;
		pMgcpCmd->EndpointName.pcLocalName = NULL;		// 防止指针悬空
		pNewMgcpCmd->EndpointName.pcDomainName = pMgcpCmd->EndpointName.pcDomainName;
		pMgcpCmd->EndpointName.pcDomainName = NULL;		// 防止指针悬空
		
		/* Source address and port of this command*/
		pNewMgcpCmd->dwSrcIpAddr =  pMgcpCmd->dwSrcIpAddr;
		pNewMgcpCmd->wSrcPort =  pMgcpCmd->wSrcPort;
		
		/* Command type and data */
		pNewMgcpCmd->eType = pMgcpCmd->eType;
		pNewMgcpCmd->u.pEpcfCmd = pMgcpCmd->u.pEpcfCmd;
		pMgcpCmd->u.pEpcfCmd = NULL;	// 防止指针悬空
		
		/* Construct the stack message to EndpointCtrl */
		memset(&Msg, 0, sizeof(MGCP_STACK_MSG));
		Msg.eMsgCode = M_INCOMING_CMD;
		Msg.pMsgData = pNewMgcpCmd;
		
	    /* Must use none block like mode to send message because of mutex useage */
	    SendMsgToEndpointCtrl((H_MGCP_ENDPOINT_CONTROL)
	                          pTransacMng->pStack->pEndpointCtl, &Msg);
	}
}

/******************************************************************************
 * Function          : ProcessTransacIncomingMgcpRsp
 *
 * Description       : Process the transaction incoming mgcp response, if it is
 *                     a response ack, find the response waiting this ack and
 *                     process it; if it is a old one and need ack, resend the
 *                     ack response; if it is a new, find the outgoing command
 *                     associating this response and process, after process,
 *                     send it to EndpointCtrl for further process.
 *                     
 * Input parameters  : H_MGCP_TRANSAC_MANAGER - TransactionManager handle 
 *                     pMgcpRsp - pointer to Mgcp incoming response to be processed
 *
 * Output parameters : 
 *
 * Return value      : None
 *
 * Comments          : 
 *
 * History           :
 *  2005/09/05       : Creation
 *
 * Date              : Sep 05 2005, Frank Zhang
 ******************************************************************************/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?