mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	........ Merged revisions 430996 from http://svn.asterisk.org/svn/asterisk/branches/11 ........ Merged revisions 430998 from http://svn.asterisk.org/svn/asterisk/branches/13 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@431000 65c4cc65-6c06-0410-ace0-fbb531ad65f3
		
			
				
	
	
		
			4711 lines
		
	
	
		
			175 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			4711 lines
		
	
	
		
			175 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2004-2005 by Objective Systems, Inc.
 | |
|  *
 | |
|  * This software is furnished under an open source license and may be 
 | |
|  * used and copied only in accordance with the terms of this license. 
 | |
|  * The text of the license may generally be found in the root 
 | |
|  * directory of this installation in the COPYING file.  It 
 | |
|  * can also be viewed online at the following URL:
 | |
|  *
 | |
|  *   http://www.obj-sys.com/open/license.html
 | |
|  *
 | |
|  * Any redistributions of this file including modified versions must 
 | |
|  * maintain this copyright notice.
 | |
|  *
 | |
|  *****************************************************************************/
 | |
| #include "asterisk.h"
 | |
| #include "asterisk/lock.h"
 | |
| #include "ooh245.h"
 | |
| #include "ooq931.h"
 | |
| #include "ooCalls.h"
 | |
| #include "printHandler.h"
 | |
| #include "ooh323ep.h"
 | |
| #include "ooCapability.h"
 | |
| #include "ooTimer.h"
 | |
| #ifdef _WIN32
 | |
| #include <stdlib.h>
 | |
| #include <process.h>
 | |
| #define getpid _getpid
 | |
| #endif
 | |
| #include <time.h>
 | |
| 
 | |
| /** Global endpoint structure */
 | |
| extern ooEndPoint gH323ep;
 | |
| 
 | |
| static ASN1OBJID gh245ProtocolID = {
 | |
|   6, { 0, 0, 8, 245, 0, 8 }
 | |
| };
 | |
| 
 | |
| int ooCreateH245Message(OOH323CallData* call, H245Message **pph245msg, int type)
 | |
| {
 | |
|    /* OOCTXT* pctxt = &gH323ep.msgctxt; */
 | |
|    OOCTXT* pctxt = call->msgctxt;
 | |
| 
 | |
|    *pph245msg = (H245Message*) memAlloc (pctxt, sizeof(H245Message));
 | |
| 
 | |
|    if(!(*pph245msg))
 | |
|    {
 | |
|       OOTRACEERR1("ERROR:Failed to allocate memory for h245 message\n");
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       (*pph245msg)->h245Msg.t = type;
 | |
|       (*pph245msg)->logicalChannelNo = 0;
 | |
|       switch(type)
 | |
|       {
 | |
|          case  T_H245MultimediaSystemControlMessage_request:
 | |
|             (*pph245msg)->h245Msg.u.request = (H245RequestMessage*) 
 | |
|             memAllocZ (pctxt, sizeof(H245RequestMessage));
 | |
| 
 | |
|             /*Check for successful mem allocation, and if successful initialize
 | |
|               mem to zero*/
 | |
|             if(!(*pph245msg)->h245Msg.u.request)
 | |
|             {
 | |
|                OOTRACEERR1("ERROR:Memory allocation for H.245 request"
 | |
|                                      " message failed\n");
 | |
|                return OO_FAILED;
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|          case T_H245MultimediaSystemControlMessage_response:
 | |
|             (*pph245msg)->h245Msg.u.response = (H245ResponseMessage*)
 | |
|             memAllocZ (pctxt, sizeof(H245ResponseMessage));
 | |
| 
 | |
|             /*Check for successful mem allocation, and if successful initialize
 | |
|               mem to zero*/
 | |
|             if(!(*pph245msg)->h245Msg.u.response)
 | |
|             {
 | |
|                OOTRACEERR1("ERROR:Memory allocation for H.245 response"
 | |
|                                      " message failed\n");
 | |
|                return OO_FAILED;
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|          case T_H245MultimediaSystemControlMessage_command:
 | |
|             (*pph245msg)->h245Msg.u.command = (H245CommandMessage*)
 | |
|             memAllocZ (pctxt, sizeof(H245CommandMessage));
 | |
| 
 | |
|             /*Check for successful mem allocation, and if successful initialize
 | |
|               mem to zero*/
 | |
|             if(!(*pph245msg)->h245Msg.u.command)
 | |
|             {
 | |
|                OOTRACEERR1("ERROR:Memory allocation for H.245 command"
 | |
|                                      " message failed\n");
 | |
|                return OO_FAILED;
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|          case T_H245MultimediaSystemControlMessage_indication:
 | |
|             (*pph245msg)->h245Msg.u.indication = (H245IndicationMessage*)
 | |
|             memAllocZ (pctxt, sizeof(H245IndicationMessage));
 | |
| 
 | |
|             /*Check for successful mem allocation, and if successful initialize
 | |
|               mem to zero*/
 | |
|             if(!(*pph245msg)->h245Msg.u.indication)
 | |
|             {
 | |
|                OOTRACEERR1("ERROR:Memory allocation for H.245 indication"
 | |
|                                      " message failed\n");
 | |
|                return OO_FAILED;
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|          default:
 | |
|             OOTRACEERR1("ERROR: H245 message type not supported\n");
 | |
|       }
 | |
| 
 | |
|       return OO_OK;
 | |
|    }
 | |
| }
 | |
| 
 | |
| int ooFreeH245Message(OOH323CallData *call, H245Message *pmsg)
 | |
| {
 | |
|   /* In case of tunneling, memory is freed when corresponding Q931 message is freed.*/
 | |
|    OOTRACEDBGC1("msgCtxt Reset?");
 | |
|    if (0 != pmsg) {
 | |
|      if(!OO_TESTFLAG (call->flags, OO_M_TUNNELING)){
 | |
|          /* memReset (&gH323ep.msgctxt); */
 | |
|          memReset (call->msgctxt);
 | |
|          OOTRACEDBGC3(" Done (%s, %s)\n", call->callType, call->callToken);
 | |
|          return OO_OK;
 | |
|      }
 | |
|    }
 | |
|    OOTRACEDBGC3("Not Done (%s, %s)\n", call->callType, call->callToken);
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| #ifndef _COMPACT
 | |
| static void ooPrintH245Message 
 | |
|    (OOH323CallData* call, ASN1OCTET* msgbuf, ASN1UINT msglen)
 | |
| {
 | |
|    OOCTXT ctxt;
 | |
|    H245MultimediaSystemControlMessage mmMsg;
 | |
|    int ret;
 | |
| 
 | |
|    initContext (&ctxt);
 | |
| 
 | |
|    setPERBuffer (&ctxt, msgbuf, msglen, TRUE);
 | |
| 
 | |
|    initializePrintHandler(&printHandler, "Sending H.245 Message");
 | |
| 
 | |
|    /* Set event handler */
 | |
|    setEventHandler (&ctxt, &printHandler);
 | |
| 
 | |
|    ret = asn1PD_H245MultimediaSystemControlMessage(&ctxt, &mmMsg);
 | |
|    if(ret != ASN_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error decoding H245 message (%s, %s)\n", 
 | |
|                   call->callType, call->callToken);
 | |
|       OOTRACEERR1 (errGetText (&ctxt));
 | |
|    }
 | |
|    finishPrint();
 | |
|    freeContext(&ctxt);   
 | |
| }
 | |
| #endif
 | |
| 
 | |
| int ooEncodeH245Message
 | |
|    (OOH323CallData *call, H245Message *ph245Msg, char *msgbuf, int size)
 | |
| {
 | |
|    int len=0, encodeLen=0, i=0;
 | |
|    int stat=0;
 | |
|    ASN1OCTET* encodePtr=NULL;
 | |
|    H245MultimediaSystemControlMessage *multimediaMsg;
 | |
|    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
 | |
|    OOCTXT *pctxt = call->msgctxt;
 | |
|    multimediaMsg = &(ph245Msg->h245Msg);
 | |
| 
 | |
|    if(!msgbuf || size<200)
 | |
|    {
 | |
|       OOTRACEERR3("Error: Invalid message buffer/size for "
 | |
|                   "ooEncodeH245Message. (%s, %s)\n", 
 | |
|                    call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
| 
 | |
|    msgbuf[i++] = ph245Msg->msgType;
 | |
|    msgbuf[i++] = (ph245Msg->logicalChannelNo>>8);
 | |
|    msgbuf[i++] = ph245Msg->logicalChannelNo;
 | |
|    /* This will contain the total length of the encoded message */
 | |
|    msgbuf[i++] = 0;
 | |
|    msgbuf[i++] = 0;
 | |
|    
 | |
|    if(!OO_TESTFLAG (call->flags, OO_M_TUNNELING))
 | |
|    {
 | |
|       /* Populate message buffer to be returned */
 | |
|       len =  4;
 | |
|       msgbuf[i++] = 3; /* TPKT version */
 | |
|       msgbuf[i++] = 0; /* TPKT resevred */
 | |
|       /* 1st octet of length, will be populated once len is determined */
 | |
|       msgbuf[i++] = 0; 
 | |
|       /* 2nd octet of length, will be populated once len is determined */
 | |
|       msgbuf[i++] = 0;
 | |
|    }
 | |
|    
 | |
|    setPERBuffer (pctxt, (unsigned char*) msgbuf+i, (size-i), TRUE);
 | |
| 
 | |
|    /* stat = asn1PE_H245MultimediaSystemControlMessage (&gH323ep.msgctxt,  */
 | |
|    stat = asn1PE_H245MultimediaSystemControlMessage (call->msgctxt, 
 | |
|                                                             multimediaMsg);
 | |
| 
 | |
|    if (stat != ASN_OK) {
 | |
|       OOTRACEERR3 ("ERROR: H245 Message encoding failed (%s, %s)\n", 
 | |
|                    call->callType, call->callToken);
 | |
|       /* OOTRACEERR1 (errGetText (&gH323ep.msgctxt)); */
 | |
|       OOTRACEERR1 (errGetText (call->msgctxt));
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    
 | |
|    encodePtr = encodeGetMsgPtr(pctxt, &encodeLen);
 | |
|    len +=encodeLen;
 | |
|    msgbuf[3] = (len>>8);
 | |
|    msgbuf[4] = len;
 | |
|    if(!OO_TESTFLAG (call->flags, OO_M_TUNNELING))
 | |
|    {
 | |
|       msgbuf[7] = len>>8;
 | |
|       msgbuf[8] = len;
 | |
|    }
 | |
| #ifndef _COMPACT
 | |
|    ooPrintH245Message (call, encodePtr, encodeLen);
 | |
| #endif
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| int ooSendH245Msg(OOH323CallData *call, H245Message *msg)
 | |
| {
 | |
|    int iRet=0,  len=0, msgType=0, logicalChannelNo = 0;
 | |
|    ASN1OCTET * encodebuf;
 | |
| 
 | |
| 
 | |
|    if(!call)
 | |
|       return OO_FAILED;
 | |
| 
 | |
|    encodebuf = (ASN1OCTET*) memAlloc (call->pctxt, MAXMSGLEN);
 | |
|    if(!encodebuf)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to allocate memory for encoding H245 "
 | |
|                   "message(%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    iRet = ooEncodeH245Message(call, msg, (char*) encodebuf, MAXMSGLEN);
 | |
| 
 | |
|    if(iRet != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to encode H245 message. (%s, %s)\n", 
 | |
|                                              call->callType, call->callToken);
 | |
|       memFreePtr (call->pctxt, encodebuf);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    if(!call->pH245Channel)
 | |
|    {
 | |
|       call->pH245Channel =  
 | |
|               (OOH323Channel*) memAllocZ (call->pctxt, sizeof(OOH323Channel));
 | |
|       if(!call->pH245Channel)
 | |
|       {
 | |
|          OOTRACEERR3("Error:Failed to allocate memory for H245Channel "
 | |
|                      "structure. (%s, %s)\n", call->callType, call->callToken);
 | |
|          memFreePtr (call->pctxt, encodebuf);
 | |
|          return OO_FAILED;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    /* We need to send EndSessionCommand immediately.*/      
 | |
|    if(!OO_TESTFLAG(call->flags, OO_M_TUNNELING)){
 | |
|       if(encodebuf[0]== OOEndSessionCommand) /* High priority message */
 | |
|       {
 | |
|          dListFreeAll(call->pctxt, &call->pH245Channel->outQueue);
 | |
|          dListAppend (call->pctxt, &call->pH245Channel->outQueue, encodebuf);
 | |
|          ooSendMsg(call, OOH245MSG);
 | |
|       }
 | |
|       else{
 | |
|          dListAppend (call->pctxt, &call->pH245Channel->outQueue, encodebuf);
 | |
|          OOTRACEDBGC4("Queued H245 messages %d. (%s, %s)\n", 
 | |
|          call->pH245Channel->outQueue.count, 
 | |
|          call->callType, call->callToken);   
 | |
|       }
 | |
|    }
 | |
|    else{
 | |
|       msgType = encodebuf[0];
 | |
| 
 | |
|       logicalChannelNo = encodebuf[1];
 | |
|       logicalChannelNo = logicalChannelNo << 8;
 | |
|       logicalChannelNo = (logicalChannelNo | encodebuf[2]);
 | |
| 
 | |
|       len = encodebuf[3];
 | |
|       len = len<<8;
 | |
|       len = (len | encodebuf[4]);
 | |
| 
 | |
|       iRet = ooSendAsTunneledMessage
 | |
|          (call, encodebuf+5,len,msgType, logicalChannelNo);
 | |
| 
 | |
|       if(iRet != OO_OK)
 | |
|       {
 | |
|          memFreePtr (call->pctxt, encodebuf);
 | |
|          OOTRACEERR3("ERROR:Failed to tunnel H.245 message (%s, %s)\n",
 | |
|                       call->callType, call->callToken);
 | |
|          if(call->callState < OO_CALL_CLEAR)
 | |
|          {
 | |
|             call->callEndReason = OO_REASON_INVALIDMESSAGE;
 | |
|             call->callState = OO_CALL_CLEAR;
 | |
|          }
 | |
|          return OO_FAILED;
 | |
|       }
 | |
|       memFreePtr (call->pctxt, encodebuf);
 | |
|       return OO_OK;
 | |
|    }
 | |
| 
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| int ooSendTermCapMsg(OOH323CallData *call)
 | |
| {
 | |
|    int ret;
 | |
|    H245RequestMessage *request=NULL;
 | |
|    OOCTXT *pctxt=NULL;
 | |
|    ooH323EpCapability *epCap=NULL;
 | |
|    H245TerminalCapabilitySet *termCap=NULL;
 | |
|    H245AudioCapability *audioCap=NULL;
 | |
|    H245DataApplicationCapability *t38Cap, *rtdCap = NULL;
 | |
|    H245AudioTelephonyEventCapability *ateCap=NULL;
 | |
|    H245UserInputCapability *userInputCap = NULL;
 | |
|    H245CapabilityTableEntry *entry=NULL;
 | |
|    H245AlternativeCapabilitySet *altSetAudio=NULL, *altSetVideo=NULL, *altSetDtmf=NULL;
 | |
|    H245CapabilityDescriptor *capDesc=NULL;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    H245VideoCapability *videoCap=NULL;
 | |
| 
 | |
|    int i=0,k=0;
 | |
|    if(call->localTermCapState == OO_LocalTermCapSetSent)
 | |
|    {
 | |
|       OOTRACEINFO3("TerminalCapabilitySet exchange procedure already in "
 | |
|                    "progress. (%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_OK;
 | |
|    }
 | |
|  
 | |
|    ret = ooCreateH245Message(call, &ph245msg,  
 | |
|                              T_H245MultimediaSystemControlMessage_request);
 | |
|  
 | |
|    if(ret == OO_FAILED)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to create H245 message for Terminal "
 | |
|                   "CapabilitySet (%s, %s)\n", call->callType,call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
| 
 | |
|   /* Set request type as TerminalCapabilitySet */
 | |
|    request = ph245msg->h245Msg.u.request;
 | |
|    /* pctxt = &gH323ep.msgctxt; */
 | |
|    pctxt = call->msgctxt;
 | |
|    ph245msg->msgType = OOTerminalCapabilitySet;
 | |
|    memset(request, 0, sizeof(H245RequestMessage));
 | |
|    if(request == NULL)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR: No memory allocated for request message (%s, %s)\n",
 | |
|                    call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    
 | |
|    request->t = T_H245RequestMessage_terminalCapabilitySet;
 | |
|    request->u.terminalCapabilitySet = (H245TerminalCapabilitySet*)
 | |
|                   memAlloc(pctxt, sizeof(H245TerminalCapabilitySet)); 
 | |
|    termCap = request->u.terminalCapabilitySet;
 | |
|    memset(termCap, 0, sizeof(H245TerminalCapabilitySet));
 | |
|    termCap->m.multiplexCapabilityPresent = 0;
 | |
|    termCap->m.capabilityTablePresent = 1;
 | |
|    termCap->m.capabilityDescriptorsPresent = 1;
 | |
|    termCap->sequenceNumber = ++(call->localTermCapSeqNo);  
 | |
|    termCap->protocolIdentifier = gh245ProtocolID; /* protocol id */
 | |
| 
 | |
|    /* Initialize alternate sets */
 | |
|    altSetAudio = (H245AlternativeCapabilitySet*)
 | |
|              memAlloc(pctxt, sizeof(H245AlternativeCapabilitySet));
 | |
|    altSetVideo = (H245AlternativeCapabilitySet*)
 | |
|             memAlloc(pctxt, sizeof(H245AlternativeCapabilitySet));
 | |
|    altSetDtmf = (H245AlternativeCapabilitySet*)
 | |
|             memAlloc(pctxt, sizeof(H245AlternativeCapabilitySet));
 | |
|    if(!altSetAudio || !altSetVideo || !altSetDtmf)
 | |
|    {
 | |
|     OOTRACEERR3("Error:Memory - ooSendTermCapMsg - altSet."
 | |
|                 "(%s, %s)\n", call->callType, call->callToken);
 | |
|     return OO_FAILED;
 | |
|    }
 | |
|    memset(altSetDtmf, 0, sizeof(H245AlternativeCapabilitySet));
 | |
|    memset(altSetVideo, 0, sizeof(H245AlternativeCapabilitySet));
 | |
|    memset(altSetAudio, 0, sizeof(H245AlternativeCapabilitySet));
 | |
| 
 | |
| 
 | |
|    /* Add audio Capabilities */
 | |
|  
 | |
|    dListInit(&(termCap->capabilityTable));
 | |
|    for(k=0; k<(int)call->capPrefs.index; k++)
 | |
|    {
 | |
|       if(call->ourCaps)
 | |
|          epCap = call->ourCaps;
 | |
|       else
 | |
|          epCap = gH323ep.myCaps;
 | |
|       while(epCap) { 
 | |
|          if(epCap->cap == call->capPrefs.order[k]) 
 | |
|             break;
 | |
|          epCap = epCap->next;
 | |
|       }
 | |
|       if(!epCap)
 | |
|       {
 | |
|          OOTRACEWARN4("WARN:Preferred capability %d not supported.(%s, %s)\n",
 | |
|                      call->capPrefs.order[k],call->callType, call->callToken);
 | |
|          continue;
 | |
|       }
 | |
| 
 | |
|       if(epCap->capType == OO_CAP_TYPE_AUDIO)
 | |
|       {
 | |
| 
 | |
|          /* Create audio capability. If capability supports receive, we only 
 | |
|             add it as receive capability in TCS. However, if it supports only 
 | |
|             transmit, we add it as transmit capability in TCS.
 | |
|          */
 | |
|          if((epCap->dir & OORX))
 | |
|          {
 | |
| 
 | |
|             OOTRACEDBGC4("Sending receive capability %s in TCS.(%s, %s)\n",
 | |
|                 ooGetCapTypeText(epCap->cap), call->callType, call->callToken);
 | |
| 
 | |
|             audioCap = ooCapabilityCreateAudioCapability(epCap, pctxt, OORX);
 | |
|             if(!audioCap)
 | |
|             {
 | |
|                OOTRACEWARN4("WARN:Failed to create audio capability %s "
 | |
|                             "(%s, %s)\n", ooGetCapTypeText(epCap->cap), 
 | |
|                             call->callType, call->callToken);
 | |
|                continue;
 | |
|             }
 | |
|          }
 | |
|          else if(epCap->dir & OOTX)
 | |
|          {
 | |
|             OOTRACEDBGC4("Sending transmit capability %s in TCS.(%s, %s)\n",
 | |
|                 ooGetCapTypeText(epCap->cap), call->callType, call->callToken);
 | |
|             audioCap = ooCapabilityCreateAudioCapability(epCap, pctxt, OOTX);
 | |
|             if(!audioCap)
 | |
|             {
 | |
|                OOTRACEWARN4("WARN:Failed to create audio capability %s "
 | |
|                             "(%s, %s)\n", ooGetCapTypeText(epCap->cap),
 | |
|                             call->callType, call->callToken);
 | |
|                continue;
 | |
|             }     
 | |
|          }
 | |
|          else{
 | |
|             OOTRACEWARN3("Warn:Capability is not RX/TX/RXANDTX. Symmetric "
 | |
|                          "capabilities are not supported.(%s, %s)\n", 
 | |
|                          call->callType, call->callToken);
 | |
|             continue;
 | |
|          }
 | |
|          /* Add  Capabilities to Capability Table */
 | |
|          entry = (H245CapabilityTableEntry*) memAlloc(pctxt,
 | |
|                          sizeof(H245CapabilityTableEntry));
 | |
|          if(!entry)
 | |
|          {
 | |
|             OOTRACEERR3("Error:Memory - ooSendTermCapMsg - entry(audio Cap)."
 | |
|                         "(%s, %s)\n", call->callType, call->callToken);
 | |
|             return OO_FAILED;
 | |
|          }
 | |
|          memset(entry, 0, sizeof(H245CapabilityTableEntry));
 | |
|          entry->m.capabilityPresent = 1;
 | |
|          if((epCap->dir & OORX))
 | |
|          {
 | |
|             entry->capability.t = T_H245Capability_receiveAudioCapability;
 | |
|             entry->capability.u.receiveAudioCapability = audioCap;
 | |
|          }
 | |
|          else{
 | |
|             entry->capability.t = T_H245Capability_transmitAudioCapability;
 | |
|             entry->capability.u.transmitAudioCapability = audioCap;
 | |
|          }
 | |
|          entry->capabilityTableEntryNumber = i+1;
 | |
|          dListAppend(pctxt , &(termCap->capabilityTable), entry);
 | |
| 	 altSetAudio->elem[altSetAudio->n] = i+1;
 | |
| 	 altSetAudio->n++;
 | |
|          i++;
 | |
|       }
 | |
|       else if(epCap->capType == OO_CAP_TYPE_DATA)
 | |
|       {
 | |
| 
 | |
|          /* Create t.38 capability. If capability supports receive, we only 
 | |
|             add it as receive capability in TCS. However, if it supports only 
 | |
|             transmit, we add it as transmit capability in TCS.
 | |
|          */
 | |
|          if((epCap->dir & OORX) && !(epCap->dir & OOTX))
 | |
|          {
 | |
| 
 | |
|             OOTRACEDBGC3("Sending receive capability t38 in TCS.(%s, %s)\n",
 | |
|                 call->callType, call->callToken);
 | |
| 
 | |
|             t38Cap = ooCapabilityCreateT38Capability(epCap, pctxt, OORX);
 | |
|             if(!t38Cap)
 | |
|             {
 | |
|                OOTRACEWARN3("WARN:Failed to create t38 capability for"
 | |
|                             "%s, %s\n",
 | |
|                             call->callType, call->callToken);
 | |
|                continue;
 | |
|             }
 | |
|          }
 | |
|          else if((epCap->dir & OOTX) && !(epCap->dir & OORX))
 | |
|          {
 | |
|             OOTRACEDBGC3("Sending transmit capability t38 in TCS.(%s, %s)\n",
 | |
|                 call->callType, call->callToken);
 | |
|             t38Cap = ooCapabilityCreateT38Capability(epCap, pctxt, OOTX);
 | |
|             if(!t38Cap)
 | |
|             {
 | |
|                OOTRACEWARN3("WARN:Failed to create capability t38 "
 | |
|                             "(%s, %s)\n",
 | |
|                             call->callType, call->callToken);
 | |
|                continue;
 | |
|             }     
 | |
|          }
 | |
|          else{
 | |
|             OOTRACEDBGC3("Sending transmit&recevie capability t38 in TCS.(%s, %s)\n",
 | |
|                 call->callType, call->callToken);
 | |
|             t38Cap = ooCapabilityCreateT38Capability(epCap, pctxt, OOTX&OORX);
 | |
|             if(!t38Cap)
 | |
|             {
 | |
|                OOTRACEWARN3("WARN:Failed to create capability t38 "
 | |
|                             "(%s, %s)\n",
 | |
|                             call->callType, call->callToken);
 | |
|                continue;
 | |
|             }     
 | |
|          }
 | |
|          /* Add  Capabilities to Capability Table */
 | |
|          entry = (H245CapabilityTableEntry*) memAlloc(pctxt,
 | |
|                          sizeof(H245CapabilityTableEntry));
 | |
|          if(!entry)
 | |
|          {
 | |
|             OOTRACEERR3("Error:Memory - ooSendTermCapMsg - entry(audio Cap)."
 | |
|                         "(%s, %s)\n", call->callType, call->callToken);
 | |
|             return OO_FAILED;
 | |
|          }
 | |
|          memset(entry, 0, sizeof(H245CapabilityTableEntry));
 | |
|          entry->m.capabilityPresent = 1;
 | |
|          if((epCap->dir & OORX) && (epCap->dir & OOTX)) {
 | |
|             entry->capability.t = T_H245Capability_receiveAndTransmitDataApplicationCapability;
 | |
|             entry->capability.u.receiveAndTransmitDataApplicationCapability = t38Cap;
 | |
|          } else if((epCap->dir & OORX)) {
 | |
|             entry->capability.t = T_H245Capability_receiveDataApplicationCapability;
 | |
|             entry->capability.u.receiveDataApplicationCapability = t38Cap;
 | |
|          }else{
 | |
|             entry->capability.t = T_H245Capability_transmitDataApplicationCapability;
 | |
|             entry->capability.u.transmitDataApplicationCapability = t38Cap;
 | |
|          }
 | |
|          entry->capabilityTableEntryNumber = i+1;
 | |
|          dListAppend(pctxt , &(termCap->capabilityTable), entry);
 | |
| 	 altSetAudio->elem[altSetAudio->n] = i+1;
 | |
| 	 altSetAudio->n++;
 | |
|          i++;
 | |
|       }
 | |
|       else if(epCap->capType == OO_CAP_TYPE_VIDEO)
 | |
|       {
 | |
|          if((epCap->dir & OORX))
 | |
|          {
 | |
|             OOTRACEDBGC4("Sending receive capability %s in TCS.(%s, %s)\n",
 | |
|                 ooGetCapTypeText(epCap->cap), call->callType, call->callToken);
 | |
|             videoCap = ooCapabilityCreateVideoCapability(epCap, pctxt, OORX);
 | |
|             if(!videoCap)
 | |
|             {
 | |
|                OOTRACEWARN4("WARN:Failed to create Video capability %s "
 | |
|                             "(%s, %s)\n", ooGetCapTypeText(epCap->cap),
 | |
|                            call->callType, call->callToken);
 | |
|                continue;
 | |
|             }
 | |
|          }
 | |
|          else if(epCap->dir & OOTX)
 | |
|          {
 | |
|             OOTRACEDBGC4("Sending transmit capability %s in TCS.(%s, %s)\n",
 | |
|                 ooGetCapTypeText(epCap->cap), call->callType, call->callToken);
 | |
|             videoCap = ooCapabilityCreateVideoCapability(epCap, pctxt, OOTX);
 | |
|             if(!videoCap)
 | |
|             {
 | |
|                OOTRACEWARN4("WARN:Failed to create video capability %s "
 | |
|                             "(%s, %s)\n", ooGetCapTypeText(epCap->cap),
 | |
|                            call->callType, call->callToken);
 | |
|                continue;
 | |
|             }     
 | |
|          }
 | |
|          else{
 | |
|             OOTRACEWARN3("Warn:Capability is not RX/TX/RXANDTX. Symmetric "
 | |
|                          "capabilities are not supported.(%s, %s)\n", 
 | |
|                          call->callType, call->callToken);
 | |
|             continue;
 | |
|          }
 | |
|          /* Add Video capabilities to Capability Table */
 | |
|          entry = (H245CapabilityTableEntry*) memAlloc(pctxt,
 | |
|                             sizeof(H245CapabilityTableEntry));
 | |
|          if(!entry)
 | |
|          {
 | |
|             OOTRACEERR3("Error:Memory - ooSendTermCapMsg - entry(video Cap)."
 | |
|                         "(%s, %s)\n", call->callType, call->callToken);
 | |
|             return OO_FAILED;
 | |
|          }
 | |
|          memset(entry, 0, sizeof(H245CapabilityTableEntry));
 | |
|          entry->m.capabilityPresent = 1;
 | |
|          if((epCap->dir & OORX))
 | |
|          {
 | |
|             entry->capability.t = T_H245Capability_receiveVideoCapability;
 | |
|             entry->capability.u.receiveVideoCapability = videoCap;
 | |
|          }
 | |
|          else{
 | |
|             entry->capability.t = T_H245Capability_transmitVideoCapability;
 | |
|             entry->capability.u.transmitVideoCapability = videoCap;
 | |
|          }
 | |
|          entry->capabilityTableEntryNumber = i+1;
 | |
|          dListAppend(pctxt , &(termCap->capabilityTable), entry);
 | |
| 	 altSetVideo->elem[altSetVideo->n] = i+1;
 | |
| 	 altSetVideo->n++;
 | |
|          i++;
 | |
|       }
 | |
|    }
 | |
|    /* Add dtmf capability, if any */
 | |
|    if(call->dtmfmode & OO_CAP_DTMF_RFC2833)
 | |
|    {
 | |
|       ateCap = (H245AudioTelephonyEventCapability*)
 | |
|                   ooCapabilityCreateDTMFCapability(OO_CAP_DTMF_RFC2833, call->dtmfcodec, pctxt);
 | |
|       if(!ateCap)
 | |
|       {
 | |
|          OOTRACEWARN3("WARN:Failed to add RFC2833 cap to TCS(%s, %s)\n",
 | |
|                      call->callType, call->callToken);
 | |
|       }
 | |
|       else {
 | |
|          entry = (H245CapabilityTableEntry*) memAlloc(pctxt,
 | |
|                       sizeof(H245CapabilityTableEntry));
 | |
|          if(!entry)
 | |
|          {
 | |
|             OOTRACEERR3("Error:Failed to allocate memory for new capability "
 | |
|                         "table entry. (%s, %s)\n", call->callType, 
 | |
|                         call->callToken);
 | |
|             ooFreeH245Message(call, ph245msg);
 | |
|             return OO_FAILED;
 | |
|          }
 | |
|             
 | |
|          memset(entry, 0, sizeof(H245CapabilityTableEntry));
 | |
|          entry->m.capabilityPresent = 1;
 | |
| 
 | |
|          entry->capability.t = T_H245Capability_receiveRTPAudioTelephonyEventCapability;
 | |
|          entry->capability.u.receiveRTPAudioTelephonyEventCapability = ateCap;
 | |
|       
 | |
|          entry->capabilityTableEntryNumber = i+1;
 | |
|          dListAppend(pctxt , &(termCap->capabilityTable), entry);
 | |
| 	 altSetDtmf->elem[altSetDtmf->n] = i+1;
 | |
| 	 altSetDtmf->n++;
 | |
| 
 | |
|          i++;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if(call->dtmfmode & OO_CAP_DTMF_CISCO)
 | |
|    {
 | |
|       rtdCap = (H245DataApplicationCapability*)
 | |
|                   ooCapabilityCreateDTMFCapability(OO_CAP_DTMF_CISCO, call->dtmfcodec, pctxt);
 | |
|       if(!rtdCap)
 | |
|       {
 | |
|          OOTRACEWARN3("WARN:Failed to add RTP/CISCO DTMF cap to TCS(%s, %s)\n",
 | |
|                      call->callType, call->callToken);
 | |
|       }
 | |
|       else {
 | |
|          entry = (H245CapabilityTableEntry*) memAlloc(pctxt,
 | |
|                       sizeof(H245CapabilityTableEntry));
 | |
|          if(!entry)
 | |
|          {
 | |
|             OOTRACEERR3("Error:Failed to allocate memory for new capability "
 | |
|                         "table entry. (%s, %s)\n", call->callType, 
 | |
|                         call->callToken);
 | |
|             ooFreeH245Message(call, ph245msg);
 | |
|             return OO_FAILED;
 | |
|          }
 | |
|             
 | |
|          memset(entry, 0, sizeof(H245CapabilityTableEntry));
 | |
|          entry->m.capabilityPresent = 1;
 | |
| 
 | |
|          entry->capability.t = T_H245Capability_receiveDataApplicationCapability;
 | |
|          entry->capability.u.receiveDataApplicationCapability = rtdCap;
 | |
|       
 | |
|          entry->capabilityTableEntryNumber = i+1;
 | |
|          dListAppend(pctxt , &(termCap->capabilityTable), entry);
 | |
| 	 altSetDtmf->elem[altSetDtmf->n] = i+1;
 | |
| 	 altSetDtmf->n++;
 | |
| 
 | |
|          i++;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if(call->dtmfmode & OO_CAP_DTMF_H245_alphanumeric)
 | |
|    {
 | |
|       userInputCap = (H245UserInputCapability*)ooCapabilityCreateDTMFCapability
 | |
|                                         (OO_CAP_DTMF_H245_alphanumeric, 0, pctxt);
 | |
|       if(!userInputCap)
 | |
|       {
 | |
|          OOTRACEWARN3("WARN:Failed to add H245(alphanumeric) cap to "
 | |
|                       "TCS(%s, %s)\n", call->callType, call->callToken);
 | |
|       }
 | |
|       else {
 | |
|          entry = (H245CapabilityTableEntry*) memAlloc(pctxt,
 | |
|                       sizeof(H245CapabilityTableEntry));
 | |
|          if(!entry)
 | |
|          {
 | |
|             OOTRACEERR3("Error:Failed to allocate memory for new capability "
 | |
|                         "table entry. (%s, %s)\n", call->callType, 
 | |
|                         call->callToken);
 | |
|             ooFreeH245Message(call, ph245msg);
 | |
|             return OO_FAILED;
 | |
|          }
 | |
|             
 | |
|          memset(entry, 0, sizeof(H245CapabilityTableEntry));
 | |
|          entry->m.capabilityPresent = 1;
 | |
| 
 | |
|          entry->capability.t = T_H245Capability_receiveAndTransmitUserInputCapability;
 | |
|          entry->capability.u.receiveAndTransmitUserInputCapability = userInputCap;
 | |
|       
 | |
|          entry->capabilityTableEntryNumber = i+1;
 | |
|          dListAppend(pctxt , &(termCap->capabilityTable), entry);
 | |
| 	 altSetDtmf->elem[altSetDtmf->n] = i+1;
 | |
| 	 altSetDtmf->n++;
 | |
| 
 | |
|          i++;
 | |
|       }
 | |
|    }
 | |
|    userInputCap = NULL;
 | |
|    if(call->dtmfmode & OO_CAP_DTMF_H245_signal)
 | |
|    {
 | |
|       userInputCap = (H245UserInputCapability*)ooCapabilityCreateDTMFCapability
 | |
|                                         (OO_CAP_DTMF_H245_signal, 0, pctxt);
 | |
|       if(!userInputCap)
 | |
|       {
 | |
|          OOTRACEWARN3("WARN:Failed to add H245(signal) cap to "
 | |
|                       "TCS(%s, %s)\n", call->callType, call->callToken);
 | |
|       }
 | |
|       else {
 | |
|          entry = (H245CapabilityTableEntry*) memAlloc(pctxt,
 | |
|                       sizeof(H245CapabilityTableEntry));
 | |
|          if(!entry)
 | |
|          {
 | |
|             OOTRACEERR3("Error:Failed to allocate memory for new capability "
 | |
|                         "table entry. (%s, %s)\n", call->callType, 
 | |
|                         call->callToken);
 | |
|             ooFreeH245Message(call, ph245msg);
 | |
|             return OO_FAILED;
 | |
|          }
 | |
|             
 | |
|          memset(entry, 0, sizeof(H245CapabilityTableEntry));
 | |
|          entry->m.capabilityPresent = 1;
 | |
| 
 | |
|          entry->capability.t = T_H245Capability_receiveAndTransmitUserInputCapability;
 | |
|          entry->capability.u.receiveAndTransmitUserInputCapability = userInputCap;
 | |
|       
 | |
|          entry->capabilityTableEntryNumber = i+1;
 | |
|          dListAppend(pctxt , &(termCap->capabilityTable), entry);
 | |
| 	 altSetDtmf->elem[altSetDtmf->n] = i+1;
 | |
| 	 altSetDtmf->n++;
 | |
| 
 | |
|          i++;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|           
 | |
|    /*TODO:Add Video and Data capabilities, if required*/
 | |
|    if(i==0)
 | |
|    {
 | |
|       OOTRACEERR3("Error:No capabilities found to send in TCS message."
 | |
|                   " (%s, %s)\n", call->callType, call->callToken);
 | |
|       ooFreeH245Message(call,ph245msg);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|       
 | |
|    /* Define capability descriptior */
 | |
|    capDesc = (H245CapabilityDescriptor*)
 | |
|              memAlloc(pctxt, sizeof(H245CapabilityDescriptor));
 | |
|    memset(capDesc, 0, sizeof(H245CapabilityDescriptor));
 | |
|    capDesc->m.simultaneousCapabilitiesPresent = 1;
 | |
|    capDesc->capabilityDescriptorNumber = 1;
 | |
|    dListInit(&(capDesc->simultaneousCapabilities));
 | |
|    /* Add Alternative Capability Set.
 | |
|       TODO: Right now all capabilities are added in separate
 | |
|             alternate capabilities set. Need a way for application
 | |
|             developer to specify the alternative capability sets.
 | |
|    */
 | |
|    /* for(j=0; j<i; j++)
 | |
|    {
 | |
|       altSet = (H245AlternativeCapabilitySet*)
 | |
|                memAlloc(pctxt, sizeof(H245AlternativeCapabilitySet));
 | |
|       memset(altSet, 0, sizeof(H245AlternativeCapabilitySet));
 | |
|       altSet->n = 1;
 | |
|       altSet->elem[0] = j+1;
 | |
|    
 | |
|       dListAppend(pctxt, &(capDesc->simultaneousCapabilities), altSet);
 | |
|    } */
 | |
| 
 | |
|    if (altSetAudio->n) dListAppend(pctxt, &(capDesc->simultaneousCapabilities), altSetAudio);
 | |
|    if (altSetVideo->n) dListAppend(pctxt, &(capDesc->simultaneousCapabilities), altSetVideo);
 | |
|    if (altSetDtmf->n) dListAppend(pctxt, &(capDesc->simultaneousCapabilities), altSetDtmf);
 | |
| 
 | |
|    dListInit(&(termCap->capabilityDescriptors));
 | |
|    dListAppend(pctxt, &(termCap->capabilityDescriptors), capDesc);
 | |
| 
 | |
|    OOTRACEDBGA3("Built terminal capability set message (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to enqueue TCS message to outbound queue. "
 | |
|                   "(%s, %s)\n", call->callType, call->callToken);
 | |
|    }
 | |
|    else {
 | |
|       call->localTermCapState = OO_LocalTermCapSetSent;
 | |
|    }
 | |
| 
 | |
|    ooFreeH245Message(call,ph245msg);
 | |
| 
 | |
|    return ret;
 | |
| }
 | |
| int ooSendEmptyTermCapMsg(OOH323CallData *call)
 | |
| {
 | |
|    int ret;
 | |
|    H245RequestMessage *request = NULL;
 | |
|    OOCTXT *pctxt = NULL;
 | |
|    H245TerminalCapabilitySet *termCap = NULL;
 | |
|    H245Message *ph245msg = NULL;
 | |
| 
 | |
|    ret = ooCreateH245Message(call, &ph245msg,
 | |
| 				T_H245MultimediaSystemControlMessage_request);
 | |
| 
 | |
|    if (ret == OO_FAILED) {
 | |
|       OOTRACEERR3("Error:Failed to create H245 message for Terminal "
 | |
|                   "CapabilitySet (%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
| 
 | |
|   /* Set request type as TerminalCapabilitySet */
 | |
|    request = ph245msg->h245Msg.u.request;
 | |
|    pctxt = call->msgctxt;
 | |
|    ph245msg->msgType = OOTerminalCapabilitySet;
 | |
|    memset(request, 0, sizeof(H245RequestMessage));
 | |
| 
 | |
|    request->t = T_H245RequestMessage_terminalCapabilitySet;
 | |
|    request->u.terminalCapabilitySet = (H245TerminalCapabilitySet*)
 | |
|                   memAlloc(pctxt, sizeof(H245TerminalCapabilitySet));
 | |
|    termCap = request->u.terminalCapabilitySet;
 | |
|    memset(termCap, 0, sizeof(H245TerminalCapabilitySet));
 | |
|    termCap->m.multiplexCapabilityPresent = 0;
 | |
|    termCap->m.capabilityTablePresent = 0;
 | |
|    termCap->m.capabilityDescriptorsPresent = 0;
 | |
|    termCap->sequenceNumber = ++(call->localTermCapSeqNo);
 | |
|    termCap->protocolIdentifier = gh245ProtocolID; /* protocol id */
 | |
| 
 | |
|    OOTRACEDBGA3("Built empty terminal capability set message (%s, %s)\n",
 | |
|                  call->callType, call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if (ret != OO_OK) {
 | |
|       OOTRACEERR3("Error:Failed to enqueue empty TCS message to outbound queue. "
 | |
|                   "(%s, %s)\n", call->callType, call->callToken);
 | |
|    }
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
| 
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| ASN1UINT ooGenerateStatusDeterminationNumber()
 | |
| {
 | |
|    ASN1UINT statusDeterminationNumber;
 | |
|    ASN1UINT random_factor = getpid();
 | |
| 
 | |
| #ifdef _WIN32
 | |
|    SYSTEMTIME systemTime;
 | |
|    GetLocalTime(&systemTime);
 | |
|    srand((systemTime.wMilliseconds ^ systemTime.wSecond) + random_factor);
 | |
| #else
 | |
|    struct timeval tv;
 | |
|    gettimeofday(&tv, NULL);
 | |
|    srand((tv.tv_usec ^ tv.tv_sec) + random_factor );
 | |
| #endif
 | |
| 
 | |
|    statusDeterminationNumber = rand()%16777215;
 | |
|    return statusDeterminationNumber;
 | |
| }
 | |
| /* TODO: Should Send MasterSlave Release when no response from 
 | |
|          Remote endpoint after MasterSlaveDetermination sent within
 | |
|          timeout.
 | |
| */
 | |
| int ooHandleMasterSlave(OOH323CallData *call, void * pmsg, 
 | |
|                           int msgType)
 | |
| {
 | |
|    H245MasterSlaveDetermination *masterSlave;
 | |
|    H245MasterSlaveDeterminationAck *masterSlaveAck;
 | |
|    ASN1UINT statusDeterminationNumber, moduloDiff;
 | |
| 
 | |
|    switch(msgType)
 | |
|    {
 | |
|       case OOMasterSlaveDetermination:
 | |
|          OOTRACEINFO3("Master Slave Determination received (%s, %s)\n",
 | |
|                        call->callType, call->callToken);
 | |
|          
 | |
|          masterSlave = (H245MasterSlaveDetermination*)pmsg;
 | |
| 
 | |
| 	 if(call->masterSlaveState != OO_MasterSlave_DetermineSent && 
 | |
| 	    OO_TESTFLAG(gH323ep.flags, OO_M_TRYBEMASTER))
 | |
|          {
 | |
|             ooSendMasterSlaveDeterminationAck(call, "slave");
 | |
|             call->masterSlaveState =  OO_MasterSlave_Master;
 | |
|             OOTRACEINFO3("MasterSlaveDetermination done - Master(%s, %s)\n",
 | |
|                              call->callType, call->callToken);
 | |
|             return OO_OK;
 | |
| 	 }
 | |
|          if(masterSlave->terminalType < gH323ep.termType)
 | |
|          {
 | |
|             ooSendMasterSlaveDeterminationAck(call, "slave");
 | |
|             call->masterSlaveState =  OO_MasterSlave_Master;
 | |
|             OOTRACEINFO3("MasterSlaveDetermination done - Master(%s, %s)\n",
 | |
|                              call->callType, call->callToken);
 | |
|             return OO_OK;
 | |
|          }
 | |
|          if(masterSlave->terminalType > gH323ep.termType)
 | |
|          {
 | |
|             ooSendMasterSlaveDeterminationAck(call, "master");
 | |
|             call->masterSlaveState =  OO_MasterSlave_Slave;
 | |
|             OOTRACEINFO3("MasterSlaveDetermination done - Slave(%s, %s)\n",
 | |
|                              call->callType, call->callToken);
 | |
|             return OO_OK;
 | |
|          }
 | |
|          /* Since term types are same, master slave determination will
 | |
|             be done based on statusdetermination number
 | |
|          */
 | |
|          
 | |
|          OOTRACEDBGA3("Determining master-slave based on StatusDetermination"
 | |
|                       "Number (%s, %s)\n", call->callType, call->callToken);
 | |
|          if(call->masterSlaveState == OO_MasterSlave_DetermineSent)
 | |
|             statusDeterminationNumber = call->statusDeterminationNumber;
 | |
|          else
 | |
| 	    if (OO_TESTFLAG(gH323ep.flags, OO_M_TRYBEMASTER)) 
 | |
|             	statusDeterminationNumber = masterSlave->statusDeterminationNumber - 1;
 | |
| 	    else
 | |
|             	statusDeterminationNumber = ooGenerateStatusDeterminationNumber();
 | |
| 
 | |
| 	 moduloDiff = (masterSlave->statusDeterminationNumber - statusDeterminationNumber)
 | |
| 			&0xffffff;
 | |
|          
 | |
|          /* if(masterSlave->statusDeterminationNumber > 
 | |
|                        statusDeterminationNumber) */
 | |
| 	 if (moduloDiff < 0x800000 && moduloDiff != 0)
 | |
|          {
 | |
|             ooSendMasterSlaveDeterminationAck(call, "slave");
 | |
|             call->masterSlaveState =  OO_MasterSlave_Master;
 | |
|             OOTRACEINFO3("MasterSlaveDetermination done - Master(%s, %s)\n",
 | |
|                              call->callType, call->callToken);
 | |
|             return OO_OK;
 | |
|          }
 | |
|          /* if(masterSlave->statusDeterminationNumber < 
 | |
|                          statusDeterminationNumber) */
 | |
| 	 if (moduloDiff > 0x800000)
 | |
|          {
 | |
|             ooSendMasterSlaveDeterminationAck(call, "master");
 | |
|             call->masterSlaveState =  OO_MasterSlave_Slave;
 | |
|             OOTRACEINFO3("MasterSlaveDetermination done - Slave(%s, %s)\n",
 | |
|                              call->callType, call->callToken);
 | |
|             return OO_OK;
 | |
|          }
 | |
|          /* if(masterSlave->statusDeterminationNumber == 
 | |
|                          statusDeterminationNumber) */
 | |
| 	 if (moduloDiff == 0 || moduloDiff == 0x800000)
 | |
|          {
 | |
|             ooSendMasterSlaveDeterminationReject (call);
 | |
| 
 | |
|             OOTRACEERR3("ERROR:MasterSlaveDetermination failed- identical "
 | |
|                         "numbers (%s, %s)\n", call->callType, call->callToken);
 | |
|          }
 | |
|          break;
 | |
| 
 | |
|       case OOMasterSlaveAck:
 | |
|          masterSlaveAck = (H245MasterSlaveDeterminationAck*)pmsg;
 | |
|          if(call->masterSlaveState == OO_MasterSlave_DetermineSent)
 | |
|          {
 | |
|             if(masterSlaveAck->decision.t == 
 | |
|                T_H245MasterSlaveDeterminationAck_decision_master)
 | |
|             {
 | |
|                ooSendMasterSlaveDeterminationAck(call, "slave");
 | |
|                call->masterSlaveState =  OO_MasterSlave_Master;
 | |
|                OOTRACEINFO3("MasterSlaveDetermination done - Master(%s, %s)\n",
 | |
|                              call->callType, call->callToken);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                ooSendMasterSlaveDeterminationAck(call, "master");
 | |
|                call->masterSlaveState = OO_MasterSlave_Slave;
 | |
|                OOTRACEINFO3("MasterSlaveDetermination done - Slave(%s, %s)\n",
 | |
|                              call->callType, call->callToken);
 | |
|             }
 | |
|          }
 | |
| 
 | |
| 	 call->msAckStatus = OO_msAck_remoteReceived;
 | |
|          
 | |
|          if(call->localTermCapState == OO_LocalTermCapSetAckRecvd &&
 | |
|             call->remoteTermCapState == OO_RemoteTermCapSetAckSent)
 | |
|          {
 | |
|             /*Since Cap exchange and MasterSlave Procedures are done */
 | |
|             if(gH323ep.h323Callbacks.openLogicalChannels)
 | |
|                gH323ep.h323Callbacks.openLogicalChannels(call);
 | |
| 
 | |
|    	    /* ooSendStatusInquiry(call); */
 | |
| 
 | |
|             if(!ooGetTransmitLogicalChannel(call))
 | |
|                ooOpenLogicalChannels(call);
 | |
| #if 0
 | |
|             if(!call->logicalChans){
 | |
|                if(!gH323ep.h323Callbacks.openLogicalChannels)
 | |
|                   ooOpenLogicalChannels(call);
 | |
|                else
 | |
|                   gH323ep.h323Callbacks.openLogicalChannels(call);
 | |
|             }
 | |
| #endif
 | |
|          }
 | |
|          else
 | |
|             OOTRACEDBGC1("Not opening logical channels as Cap exchange "
 | |
|                          "remaining\n");
 | |
|          break;
 | |
|        default:
 | |
|           OOTRACEWARN3("Warn:Unhandled Master Slave message received - %s - "
 | |
|                        "%s\n", call->callType, call->callToken);
 | |
|    }
 | |
|    return OO_OK;      
 | |
| }
 | |
| 
 | |
| int ooSendMasterSlaveDetermination(OOH323CallData *call)
 | |
| {
 | |
|    int ret;
 | |
|    H245Message* ph245msg=NULL;
 | |
|    H245RequestMessage *request;
 | |
|    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
 | |
|    OOCTXT *pctxt=call->msgctxt;
 | |
|    H245MasterSlaveDetermination* pMasterSlave;
 | |
| 
 | |
|    /* Check whether Master Slave Determination already in progress */
 | |
|    if(call->masterSlaveState != OO_MasterSlave_Idle)
 | |
|    {
 | |
|       OOTRACEINFO3("MasterSlave determination already in progress (%s, %s)\n",
 | |
|                    call->callType, call->callToken);
 | |
|       return OO_OK;
 | |
|    }
 | |
| 
 | |
|    ret = ooCreateH245Message(call, &ph245msg,
 | |
|                    T_H245MultimediaSystemControlMessage_request);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error: creating H245 message - MasterSlave Determination "
 | |
|                   "(%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OOMasterSlaveDetermination;
 | |
|    request = ph245msg->h245Msg.u.request;
 | |
|    request->t = T_H245RequestMessage_masterSlaveDetermination;
 | |
|    request->u.masterSlaveDetermination = (H245MasterSlaveDetermination*)
 | |
|             ASN1MALLOC(pctxt, sizeof(H245MasterSlaveDetermination));
 | |
| 
 | |
|    
 | |
|    pMasterSlave = request->u.masterSlaveDetermination;
 | |
|    memset(pMasterSlave, 0, sizeof(H245MasterSlaveDetermination));   
 | |
|    pMasterSlave->terminalType = gH323ep.termType; 
 | |
|    pMasterSlave->statusDeterminationNumber = 
 | |
|                        ooGenerateStatusDeterminationNumber();
 | |
|    call->statusDeterminationNumber = pMasterSlave->statusDeterminationNumber;
 | |
| 
 | |
|    OOTRACEDBGA3("Built MasterSlave Determination (%s, %s)\n", call->callType,
 | |
|                  call->callToken); 
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
| 
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to enqueue MasterSlaveDetermination message to"
 | |
|                   " outbound queue. (%s, %s)\n", call->callType, 
 | |
|                   call->callToken);
 | |
|    }
 | |
|    else
 | |
|       call->masterSlaveState = OO_MasterSlave_DetermineSent;
 | |
|    
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
| 
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| int ooSendMasterSlaveDeterminationAck(OOH323CallData* call,
 | |
|                                       char * status)
 | |
| {
 | |
|    int ret=0;
 | |
|    H245ResponseMessage * response=NULL;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
 | |
|    OOCTXT *pctxt=call->msgctxt;
 | |
| 
 | |
|    ret = ooCreateH245Message(call, &ph245msg, 
 | |
|                       T_H245MultimediaSystemControlMessage_response);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:H245 message creation failed for - MasterSlave "
 | |
|                   "Determination Ack (%s, %s)\n",call->callType, 
 | |
|                   call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OOMasterSlaveAck;
 | |
|    response = ph245msg->h245Msg.u.response;
 | |
|    memset(response, 0, sizeof(H245ResponseMessage));
 | |
|    response->t = T_H245ResponseMessage_masterSlaveDeterminationAck;
 | |
|    response->u.masterSlaveDeterminationAck = (H245MasterSlaveDeterminationAck*)
 | |
|                    ASN1MALLOC(pctxt, sizeof(H245MasterSlaveDeterminationAck));
 | |
|    memset(response->u.masterSlaveDeterminationAck, 0, 
 | |
|                              sizeof(H245MasterSlaveDeterminationAck));
 | |
|    if(!strcmp("master", status))
 | |
|       response->u.masterSlaveDeterminationAck->decision.t = 
 | |
|                          T_H245MasterSlaveDeterminationAck_decision_master;
 | |
|    else
 | |
|       response->u.masterSlaveDeterminationAck->decision.t = 
 | |
|                          T_H245MasterSlaveDeterminationAck_decision_slave;
 | |
|    
 | |
|    OOTRACEDBGA3("Built MasterSlave determination Ack (%s, %s)\n", 
 | |
|                 call->callType, call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to enqueue MasterSlaveDeterminationAck message"
 | |
|                   " to outbound queue. (%s, %s)\n", call->callType, 
 | |
|                   call->callToken);
 | |
|    }
 | |
|    
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
|    call->msAckStatus = OO_msAck_localSent;
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| int ooSendMasterSlaveDeterminationReject (OOH323CallData* call)
 | |
| {
 | |
|    int ret=0;
 | |
|    H245ResponseMessage* response=NULL;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
 | |
|    OOCTXT *pctxt=call->msgctxt;
 | |
| 
 | |
|    ret = ooCreateH245Message
 | |
|       (call, &ph245msg, T_H245MultimediaSystemControlMessage_response);
 | |
| 
 | |
|    if (ret != OO_OK) {
 | |
|       OOTRACEERR3("Error:H245 message creation failed for - MasterSlave "
 | |
|                   "Determination Reject (%s, %s)\n",call->callType, 
 | |
|                   call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OOMasterSlaveReject;
 | |
|    response = ph245msg->h245Msg.u.response;
 | |
| 
 | |
|    response->t = T_H245ResponseMessage_masterSlaveDeterminationReject;
 | |
| 
 | |
|    response->u.masterSlaveDeterminationReject = 
 | |
|       (H245MasterSlaveDeterminationReject*)
 | |
|       memAlloc (pctxt, sizeof(H245MasterSlaveDeterminationReject));
 | |
| 
 | |
|    response->u.masterSlaveDeterminationReject->cause.t =
 | |
|       T_H245MasterSlaveDeterminationReject_cause_identicalNumbers;
 | |
| 
 | |
|    OOTRACEDBGA3 ("Built MasterSlave determination reject (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);
 | |
| 
 | |
|    ret = ooSendH245Msg (call, ph245msg);
 | |
| 
 | |
|    if (ret != OO_OK) {
 | |
|       OOTRACEERR3 
 | |
|          ("Error:Failed to enqueue MasterSlaveDeterminationReject "
 | |
|           "message to outbound queue.(%s, %s)\n", call->callType, 
 | |
|           call->callToken);
 | |
|    }
 | |
|    
 | |
|    ooFreeH245Message (call, ph245msg);
 | |
| 
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| int ooSendMasterSlaveDeterminationRelease(OOH323CallData * call)
 | |
| {
 | |
|    int ret=0;
 | |
|    H245IndicationMessage* indication=NULL;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
 | |
|    OOCTXT *pctxt=call->msgctxt;
 | |
| 
 | |
|    ret = ooCreateH245Message
 | |
|       (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication);
 | |
| 
 | |
|    if (ret != OO_OK) {
 | |
|       OOTRACEERR3("Error:H245 message creation failed for - MasterSlave "
 | |
|                   "Determination Release (%s, %s)\n",call->callType, 
 | |
|                   call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OOMasterSlaveRelease;
 | |
|    indication = ph245msg->h245Msg.u.indication;
 | |
| 
 | |
|    indication->t = T_H245IndicationMessage_masterSlaveDeterminationRelease;
 | |
| 
 | |
|    indication->u.masterSlaveDeterminationRelease = 
 | |
|       (H245MasterSlaveDeterminationRelease*)
 | |
|       memAlloc (pctxt, sizeof(H245MasterSlaveDeterminationRelease));
 | |
| 
 | |
|    if(!indication->u.masterSlaveDeterminationRelease)
 | |
|    {
 | |
|       OOTRACEERR3("Error: Failed to allocate memory for MSDRelease message."
 | |
|                   " (%s, %s)\n", call->callType, call->callToken);
 | |
|       ooFreeH245Message(call, ph245msg);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    OOTRACEDBGA3 ("Built MasterSlave determination Release (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);
 | |
| 
 | |
|    ret = ooSendH245Msg (call, ph245msg);
 | |
| 
 | |
|    if (ret != OO_OK) {
 | |
|       OOTRACEERR3 
 | |
|         ("Error:Failed to enqueue MasterSlaveDeterminationRelease "
 | |
|         "message to outbound queue.(%s, %s)\n", call->callType, 
 | |
|         call->callToken);
 | |
|    }
 | |
|    
 | |
|    ooFreeH245Message (call, ph245msg);
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| int ooHandleMasterSlaveReject
 | |
|    (OOH323CallData *call, H245MasterSlaveDeterminationReject* reject)
 | |
| {
 | |
|    if(call->msdRetries < DEFAULT_MAX_RETRIES)
 | |
|    {
 | |
|       call->msdRetries++;
 | |
|       OOTRACEDBGA3("Retrying MasterSlaveDetermination. (%s, %s)\n", 
 | |
|                     call->callType, call->callToken);
 | |
|       call->masterSlaveState = OO_MasterSlave_Idle;
 | |
|       ooSendMasterSlaveDetermination(call);
 | |
|       return OO_OK;
 | |
|    }
 | |
|    OOTRACEERR3("Error:Failed to complete MasterSlaveDetermination - "
 | |
|                "Ending call. (%s, %s)\n", call->callType, call->callToken);
 | |
|    if(call->callState < OO_CALL_CLEAR)
 | |
|    {
 | |
|       call->callEndReason = OO_REASON_LOCAL_CLEARED;
 | |
|       call->callState = OO_CALL_CLEAR;
 | |
|    }
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| /* handling requestmode routines */
 | |
| 
 | |
| int ooSendRequestModeAck(OOH323CallData* call,
 | |
|                                       H245SequenceNumber sequenceNumber)
 | |
| {
 | |
|    int ret=0;
 | |
|    H245ResponseMessage* response=NULL;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    OOCTXT *pctxt=call->msgctxt;
 | |
| 
 | |
|    ret = ooCreateH245Message(call, &ph245msg, 
 | |
|                       T_H245MultimediaSystemControlMessage_response);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:H245 message creation failed for - RequestMode "
 | |
|                   "Ack (%s, %s)\n",call->callType, 
 | |
|                   call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OORequestModeAck;
 | |
|    response = ph245msg->h245Msg.u.response;
 | |
|    memset(response, 0, sizeof(H245ResponseMessage));
 | |
|    response->t = T_H245ResponseMessage_requestModeAck;
 | |
|    response->u.requestModeAck = (H245RequestModeAck *)
 | |
|                    ASN1MALLOC(pctxt, sizeof(H245RequestModeAck));
 | |
|    memset(response->u.requestModeAck, 0, 
 | |
|                              sizeof(H245RequestModeAck));
 | |
| 
 | |
|    response->u.requestModeAck->sequenceNumber = sequenceNumber;
 | |
|    response->u.requestModeAck->response.t = 
 | |
| 	T_H245RequestModeAck_response_willTransmitMostPreferredMode;
 | |
| 
 | |
|    OOTRACEDBGA3("Built RequestModeAck (%s, %s)\n", 
 | |
|                 call->callType, call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to enqueue RequestModeAck message"
 | |
|                   " to outbound queue. (%s, %s)\n", call->callType, 
 | |
|                   call->callToken);
 | |
|    }
 | |
|    
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| int ooSendRequestModeReject(OOH323CallData* call,
 | |
|                                       H245SequenceNumber sequenceNumber)
 | |
| {
 | |
|    int ret=0;
 | |
|    H245ResponseMessage* response=NULL;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    OOCTXT *pctxt=call->msgctxt;
 | |
| 
 | |
|    ret = ooCreateH245Message(call, &ph245msg, 
 | |
|                       T_H245MultimediaSystemControlMessage_response);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:H245 message creation failed for - RequstMode "
 | |
|                   "Reject (%s, %s)\n",call->callType, 
 | |
|                   call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OORequestModeReject;
 | |
|    response = ph245msg->h245Msg.u.response;
 | |
|    memset(response, 0, sizeof(H245ResponseMessage));
 | |
|    response->t = T_H245ResponseMessage_requestModeReject;
 | |
|    response->u.requestModeReject = (H245RequestModeReject *)
 | |
|                    ASN1MALLOC(pctxt, sizeof(H245RequestModeReject));
 | |
|    memset(response->u.requestModeReject, 0, 
 | |
|                              sizeof(H245RequestModeReject));
 | |
| 
 | |
|    response->u.requestModeReject->sequenceNumber = sequenceNumber;
 | |
|    response->u.requestModeReject->cause.t = 
 | |
| 		T_H245RequestModeReject_cause_modeUnavailable;
 | |
| 
 | |
|    OOTRACEDBGA3("Built RequestModeReject (%s, %s)\n", 
 | |
|                 call->callType, call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to enqueue RequestModeReject message"
 | |
|                   " to outbound queue. (%s, %s)\n", call->callType, 
 | |
|                   call->callToken);
 | |
|    }
 | |
|    
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| int ooSendRequestMode(OOH323CallData* call,
 | |
|                                       int isT38Mode)
 | |
| {
 | |
|    int ret=0;
 | |
|    H245RequestMessage *request;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    OOCTXT *pctxt=call->msgctxt;
 | |
| 
 | |
| 
 | |
|    H245ModeDescription pModeDesc;
 | |
|    H245ModeElement pModeElem;
 | |
| 
 | |
|    if (isT38Mode && !OO_TESTFLAG(call->flags, OO_M_T38SUPPORTED)) /* t38 req but we dont support */
 | |
| 	return OO_OK;
 | |
| 
 | |
|    ret = ooCreateH245Message(call, &ph245msg, 
 | |
|                       T_H245MultimediaSystemControlMessage_request);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:H245 message creation failed for - RequstMode "
 | |
|                   "(%s, %s)\n",call->callType, 
 | |
|                   call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OORequestMode;
 | |
|    request = ph245msg->h245Msg.u.request;
 | |
|    memset(request, 0, sizeof(H245RequestMessage));
 | |
|    request->t = T_H245RequestMessage_requestMode;
 | |
| 
 | |
|    request->u.requestMode = (H245RequestMode *)
 | |
|                    ASN1MALLOC(pctxt, sizeof(H245RequestMode));
 | |
|    memset(request->u.requestMode, 0, 
 | |
|                              sizeof(H245RequestMode));
 | |
| 
 | |
|    call->requestSequence++;
 | |
|    call->reqFlags = (isT38Mode) ? OO_M_DATASESSION : OO_M_AUDIOSESSION;
 | |
| 
 | |
|    request->u.requestMode->sequenceNumber = call->requestSequence;
 | |
|    memset(&pModeElem, 0, sizeof(pModeElem));
 | |
|    memset(&pModeDesc, 0, sizeof(pModeDesc));
 | |
|    dListInit(&(request->u.requestMode->requestedModes));
 | |
|    dListInit(&pModeDesc);
 | |
| 
 | |
|    if (isT38Mode) {
 | |
| 
 | |
|    	pModeElem.type.t = T_H245ModeElementType_dataMode;
 | |
|    	pModeElem.type.u.dataMode = (H245DataMode *) memAllocZ(pctxt, sizeof(H245DataMode));
 | |
|    	pModeElem.type.u.dataMode->bitRate = 144;
 | |
|    	if (!ooCreateT38ApplicationData(pctxt,&(pModeElem.type.u.dataMode->application))) {
 | |
|        		OOTRACEERR3("Error:Memory - ooCapabilityCreateT38Capability - (%s, %s)\n",
 | |
| 						call->callType, 
 | |
| 						call->callToken);
 | |
|    	}
 | |
|    } else {
 | |
| 	pModeElem.type.t = T_H245ModeElementType_audioMode;
 | |
| 	pModeElem.type.u.audioMode = (H245AudioMode *) memAllocZ(pctxt, sizeof(H245AudioMode));
 | |
| 	pModeElem.type.u.audioMode->t = T_H245AudioMode_genericAudioMode;
 | |
| 	pModeElem.type.u.audioMode->u.genericAudioMode = (H245GenericCapability *)
 | |
| 					memAllocZ(pctxt, sizeof(H245GenericCapability));
 | |
|         pModeElem.type.u.audioMode->u.genericAudioMode->capabilityIdentifier.t =
 | |
| 					 T_H245CapabilityIdentifier_domainBased;
 | |
| 	pModeElem.type.u.audioMode->u.genericAudioMode->capabilityIdentifier.u.domainBased =
 | |
| 					 "H.323";
 | |
|         pModeElem.type.u.audioMode->u.genericAudioMode->m.maxBitRatePresent = TRUE;
 | |
|         pModeElem.type.u.audioMode->u.genericAudioMode->maxBitRate = 144;
 | |
|    }
 | |
| 
 | |
|    dListAppend(pctxt, &pModeDesc, &pModeElem);
 | |
|    dListAppend(pctxt, &(request->u.requestMode->requestedModes), &pModeDesc);
 | |
| 
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to enqueue RequestMode message"
 | |
|                   " to outbound queue. (%s, %s)\n", call->callType, 
 | |
|                   call->callToken);
 | |
|    }
 | |
|    
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| void ooOnReceivedRequestModeAck(OOH323CallData* call, H245RequestModeAck * requestModeAck)
 | |
| {
 | |
| 	int t38mode;
 | |
| 
 | |
| 	if (!call->reqFlags) return;
 | |
| 
 | |
| 	if (OO_TESTFLAG(call->reqFlags, OO_M_AUDIOSESSION)) {
 | |
|  		OO_SETFLAG(call->flags, OO_M_AUDIOSESSION);
 | |
| 		OO_CLRFLAG(call->flags, OO_M_DATASESSION);
 | |
| 		t38mode = 0;
 | |
| 	} else {
 | |
|  		OO_CLRFLAG(call->flags, OO_M_AUDIOSESSION);
 | |
| 		OO_SETFLAG(call->flags, OO_M_DATASESSION);
 | |
| 		t38mode = 1;
 | |
| 	}
 | |
| 
 | |
| 	call->reqFlags = 0; /* don't handle duplicate ack packet */
 | |
| 
 | |
| 	ooCloseAllLogicalChannels(call, "transmit");
 | |
| 	if(gH323ep.h323Callbacks.onModeChanged) {
 | |
| 		OOTRACEDBGA3("Handle RequestModeAck: (%s, %s), calling "
 | |
| 			"callback onModeChanged\n", call->callType, call->callToken);
 | |
| 		gH323ep.h323Callbacks.onModeChanged(call, t38mode);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int ooHandleRequestMode(OOH323CallData* call,
 | |
| 				H245RequestMode *requestMode)
 | |
| {
 | |
|   
 | |
|   H245ModeDescription** pModeRef;
 | |
|   H245ModeElement** pModeElem;
 | |
|   H245ModeElementType* pMode;
 | |
| 
 | |
|   pModeRef = (H245ModeDescription**)dListFindByIndex(&requestMode->requestedModes, 0);
 | |
|   pModeElem = (H245ModeElement **) dListFindByIndex(*pModeRef, 0);
 | |
|   pMode = &((*pModeElem)->type);
 | |
|   OOTRACEDBGA5("Handle RequestMode: "
 | |
|                   " modetype: %d/%d for (%s, %s)\n", pMode->t, pMode->u.dataMode->application.t,
 | |
| 		  call->callType, 
 | |
|                   call->callToken);
 | |
|   switch (pMode->t) {
 | |
| 	case T_H245ModeElementType_dataMode:
 | |
| 		if (pMode->u.dataMode->application.t == T_H245DataMode_application_t38fax &&
 | |
| 		    OO_TESTFLAG(call->flags, OO_M_T38SUPPORTED)) {
 | |
| 			if (ooSendRequestModeAck(call, requestMode->sequenceNumber) == OO_OK &&
 | |
| 				OO_TESTFLAG(call->flags, OO_M_AUDIOSESSION)) {
 | |
| 
 | |
| 				OO_CLRFLAG(call->flags, OO_M_AUDIOSESSION);
 | |
| 				OO_SETFLAG(call->flags, OO_M_DATASESSION);
 | |
| 				if(gH323ep.h323Callbacks.onModeChanged) {
 | |
| 					OOTRACEDBGA3("Handle RequestMode: (%s, %s), calling "
 | |
| 					"callback onModeChanged\n", call->callType, call->callToken);
 | |
| 					gH323ep.h323Callbacks.onModeChanged(call, 1);
 | |
| 				}
 | |
| 			}
 | |
| 		} else {
 | |
| 			ooSendRequestModeReject(call, requestMode->sequenceNumber);
 | |
| 		}
 | |
| 		break;
 | |
| 	case T_H245ModeElementType_audioMode:
 | |
| 		if (ooSendRequestModeAck(call, requestMode->sequenceNumber) == OO_OK && 
 | |
| 			OO_TESTFLAG(call->flags, OO_M_DATASESSION)) {
 | |
| 
 | |
| 			OO_CLRFLAG(call->flags, OO_M_DATASESSION);
 | |
| 			OO_SETFLAG(call->flags, OO_M_AUDIOSESSION);
 | |
| 			if(gH323ep.h323Callbacks.onModeChanged) {
 | |
| 				OOTRACEDBGA3("Handle RequestMode: (%s, %s), calling "
 | |
| 				"callback onModeChanged\n", call->callType, call->callToken);
 | |
| 				gH323ep.h323Callbacks.onModeChanged(call, 0);
 | |
| 			}
 | |
| 		}
 | |
| 		break;
 | |
| 	default:
 | |
| 		;
 | |
|   }
 | |
|   return OO_OK;
 | |
|   
 | |
| }
 | |
| 
 | |
| int ooHandleOpenLogicalChannel(OOH323CallData* call, 
 | |
|                                  H245OpenLogicalChannel *olc)
 | |
| {
 | |
| 
 | |
|    H245OpenLogicalChannel_forwardLogicalChannelParameters *flcp =
 | |
|     &(olc->forwardLogicalChannelParameters);
 | |
|    
 | |
| #if 0
 | |
|    if(!call->logicalChans)
 | |
|       ooOpenLogicalChannels(call);
 | |
| #endif
 | |
| 
 | |
|    /* Check whether channel type is supported. Only supported channel 
 | |
|       type for now is g711ulaw audio channel.
 | |
|    */
 | |
|    switch(flcp->dataType.t)
 | |
|    {
 | |
|    case T_H245DataType_nonStandard:
 | |
|       OOTRACEWARN3("Warn:Media channel data type "
 | |
|                    "'T_H245DataType_nonStandard' not supported (%s, %s)\n",
 | |
|                    call->callType, call->callToken);
 | |
|       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
 | |
|              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
 | |
|       break;
 | |
|    case T_H245DataType_nullData:
 | |
|       OOTRACEWARN3("Warn:Media channel data type "
 | |
|                    "'T_H245DataType_nullData' not supported (%s, %s)\n",
 | |
|                    call->callType, call->callToken);
 | |
|       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
 | |
|              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
 | |
|       break;
 | |
|    case T_H245DataType_videoData:
 | |
|    case T_H245DataType_audioData:
 | |
|    case T_H245DataType_data:
 | |
|       ooHandleOpenLogicalChannel_helper(call, olc);
 | |
|       break;
 | |
|    case T_H245DataType_encryptionData:
 | |
|       OOTRACEWARN3("Warn:Media channel data type "
 | |
|                    "'T_H245DataType_encryptionData' not supported (%s, %s)\n",
 | |
|                    call->callType, call->callToken);
 | |
|       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
 | |
|              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
 | |
|       break;
 | |
|    case T_H245DataType_h235Control:
 | |
|       OOTRACEWARN3("Warn:Media channel data type "
 | |
|                    "'T_H245DataType_h235Control' not supported (%s, %s)\n",
 | |
|                    call->callType, call->callToken);
 | |
|       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
 | |
|              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
 | |
|       break;
 | |
|    case T_H245DataType_h235Media:
 | |
|       OOTRACEWARN3("Warn:Media channel data type "
 | |
|                    "'T_H245DataType_h235Media' not supported (%s, %s)\n",
 | |
|                    call->callType, call->callToken);
 | |
|       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
 | |
|              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
 | |
|       break;
 | |
|    case T_H245DataType_multiplexedStream:
 | |
|       OOTRACEWARN3("Warn:Media channel data type "
 | |
|                   "'T_H245DataType_multiplexedStream' not supported(%s, %s)\n",
 | |
|                    call->callType, call->callToken);
 | |
|       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
 | |
|              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
 | |
|       break;
 | |
|    case T_H245DataType_redundancyEncoding:
 | |
|       OOTRACEWARN3("Warn:Media channel data type "
 | |
|                 "'T_H245DataType_redundancyEncoding' not supported (%s, %s)\n",
 | |
|                   call->callType, call->callToken);
 | |
|       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
 | |
|              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
 | |
|       break;
 | |
|    case T_H245DataType_multiplePayloadStream:
 | |
|       OOTRACEWARN3("Warn:Media channel data type "
 | |
|              "'T_H245DataType_multiplePayloadStream' not supported (%s, %s)\n",
 | |
|                    call->callType, call->callToken);
 | |
|       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
 | |
|              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
 | |
|       break;
 | |
|    case T_H245DataType_fec:
 | |
|       OOTRACEWARN3("Warn:Media channel data type 'T_H245DataType_fec' not "
 | |
|                    "supported (%s, %s)\n", call->callType, call->callToken);
 | |
|       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
 | |
|              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
 | |
|       break;
 | |
|    default:
 | |
|       OOTRACEERR3("ERROR:Unknown media channel data type (%s, %s)\n", 
 | |
|                    call->callType, call->callToken);
 | |
|       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
 | |
|              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
 | |
|    }
 | |
|    
 | |
|    return OO_OK;
 | |
| }       
 | |
| 
 | |
| /*TODO: Need to clean logical channel in case of failure after creating one */
 | |
| int ooHandleOpenLogicalChannel_helper(OOH323CallData *call, 
 | |
|                                     H245OpenLogicalChannel*olc)
 | |
| {
 | |
|    int ret=0;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    H245ResponseMessage *response;
 | |
|    H245OpenLogicalChannelAck *olcAck;
 | |
|    ooH323EpCapability *epCap=NULL;
 | |
|    H245H2250LogicalChannelAckParameters *h2250lcap=NULL;
 | |
|    OOCTXT *pctxt;
 | |
|    H245UnicastAddress *unicastAddrs, *unicastAddrs1;
 | |
|    H245UnicastAddress_iPAddress *iPAddress = NULL, *iPAddress1 = NULL;
 | |
|    H245UnicastAddress_iP6Address *iP6Address = NULL, *iP6Address1 = NULL;
 | |
|    ooLogicalChannel *pLogicalChannel = NULL;
 | |
|    H245H2250LogicalChannelParameters *h2250lcp=NULL;
 | |
|    H245OpenLogicalChannel_forwardLogicalChannelParameters *flcp =
 | |
|     &(olc->forwardLogicalChannelParameters);
 | |
| 
 | |
|    if(!flcp || flcp->multiplexParameters.t != T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
 | |
|    {
 | |
|       OOTRACEERR3("Error:ooHandleOpenLogicalChannel_helper - invalid forward "
 | |
|                  "logical channel parameters. (%s, %s)\n", call->callType, 
 | |
|                  call->callToken);
 | |
|       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
 | |
|           T_H245OpenLogicalChannelReject_cause_unspecified);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
| 
 | |
|    h2250lcp = flcp->multiplexParameters.u.h2250LogicalChannelParameters;
 | |
| 
 | |
|    if(!(epCap=ooIsDataTypeSupported(call, &flcp->dataType, OORX)))
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:HandleOpenLogicalChannel_helper - capability not "
 | |
|                   "supported (%s, %s)\n", call->callType, call->callToken);
 | |
|       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
 | |
|           T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    /* Generate an Ack for the open channel request */
 | |
|    ret = ooCreateH245Message(call, &ph245msg,
 | |
|                              T_H245MultimediaSystemControlMessage_response);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error: H245 message creation failed for - "
 | |
|                   "OpenLogicalChannel Ack (%s, %s)\n", call->callType, 
 | |
|                   call->callToken);
 | |
|       memFreePtr(call->pctxt, epCap);
 | |
|       epCap = NULL;
 | |
|       return OO_FAILED;
 | |
|    }
 | |
| 
 | |
|    ph245msg->msgType = OOOpenLogicalChannelAck;
 | |
|    ph245msg->logicalChannelNo = olc->forwardLogicalChannelNumber;
 | |
|    response = ph245msg->h245Msg.u.response;
 | |
|    /* pctxt = &gH323ep.msgctxt; */
 | |
|    pctxt = call->msgctxt;
 | |
|    memset(response, 0, sizeof(H245ResponseMessage));
 | |
|    response->t = T_H245ResponseMessage_openLogicalChannelAck;
 | |
|    response->u.openLogicalChannelAck = (H245OpenLogicalChannelAck*)
 | |
|                    memAlloc(pctxt, sizeof(H245OpenLogicalChannelAck));   
 | |
|    olcAck = response->u.openLogicalChannelAck;
 | |
|    memset(olcAck, 0, sizeof(H245OpenLogicalChannelAck));
 | |
|    olcAck->forwardLogicalChannelNumber = olc->forwardLogicalChannelNumber;
 | |
| 
 | |
|    olcAck->m.forwardMultiplexAckParametersPresent = 1;
 | |
|    olcAck->forwardMultiplexAckParameters.t = 
 | |
|      T_H245OpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters;
 | |
|    olcAck->forwardMultiplexAckParameters.u.h2250LogicalChannelAckParameters = 
 | |
|                       (H245H2250LogicalChannelAckParameters*)ASN1MALLOC(pctxt, 
 | |
|                       sizeof(H245H2250LogicalChannelAckParameters));
 | |
|    h2250lcap = 
 | |
|       olcAck->forwardMultiplexAckParameters.u.h2250LogicalChannelAckParameters;
 | |
|    memset(h2250lcap, 0, sizeof(H245H2250LogicalChannelAckParameters));
 | |
| 
 | |
|    h2250lcap->m.mediaChannelPresent = 1;
 | |
|    h2250lcap->m.mediaControlChannelPresent = 1;
 | |
|    h2250lcap->m.sessionIDPresent = 1;
 | |
| 
 | |
|    if(h2250lcp->sessionID == 0)
 | |
|       h2250lcap->sessionID = ooCallGenerateSessionID(call, epCap->capType, "receive");
 | |
|    else
 | |
|       h2250lcap->sessionID = h2250lcp->sessionID;
 | |
|    
 | |
|    h2250lcap->mediaChannel.t = 
 | |
|                          T_H245TransportAddress_unicastAddress;
 | |
|    h2250lcap->mediaChannel.u.unicastAddress =  (H245UnicastAddress*)
 | |
|                          ASN1MALLOC(pctxt, sizeof(H245UnicastAddress));
 | |
| 
 | |
|    unicastAddrs = h2250lcap->mediaChannel.u.unicastAddress;
 | |
|    memset(unicastAddrs, 0, sizeof(H245UnicastAddress));
 | |
| 
 | |
|    if (call->versionIP == 6) {
 | |
|    	unicastAddrs->t = T_H245UnicastAddress_iP6Address;
 | |
|    	unicastAddrs->u.iP6Address = (H245UnicastAddress_iP6Address*)
 | |
|                memAlloc(pctxt, sizeof(H245UnicastAddress_iP6Address));
 | |
|    	iP6Address = unicastAddrs->u.iP6Address;
 | |
|    	memset(iP6Address, 0, sizeof(H245UnicastAddress_iP6Address));
 | |
|    } else {
 | |
|    	unicastAddrs->t = T_H245UnicastAddress_iPAddress;
 | |
|    	unicastAddrs->u.iPAddress = (H245UnicastAddress_iPAddress*)
 | |
|                memAlloc(pctxt, sizeof(H245UnicastAddress_iPAddress));
 | |
|    	iPAddress = unicastAddrs->u.iPAddress;
 | |
|    	memset(iPAddress, 0, sizeof(H245UnicastAddress_iPAddress));
 | |
|    }
 | |
| 
 | |
|    pLogicalChannel = ooAddNewLogicalChannel(call, 
 | |
|                         olc->forwardLogicalChannelNumber, h2250lcap->sessionID,
 | |
|                         "receive", epCap);
 | |
|    if(!pLogicalChannel)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Failed to add new logical channel entry to call " 
 | |
|                   "(%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
| 
 | |
|    if (call->versionIP == 6) {
 | |
| 	inet_pton(AF_INET6, pLogicalChannel->localIP, iP6Address->network.data);
 | |
|    	iP6Address->network.numocts = 16;
 | |
|    	iP6Address->tsapIdentifier = pLogicalChannel->localRtpPort;
 | |
|    } else {
 | |
| 	inet_pton(AF_INET, pLogicalChannel->localIP, iPAddress->network.data);
 | |
|    	iPAddress->network.numocts = 4;
 | |
|    	iPAddress->tsapIdentifier = pLogicalChannel->localRtpPort;
 | |
|    }
 | |
| 
 | |
|    /* media contrcol channel */
 | |
|    h2250lcap->mediaControlChannel.t = 
 | |
|                                  T_H245TransportAddress_unicastAddress;
 | |
|    h2250lcap->mediaControlChannel.u.unicastAddress =  (H245UnicastAddress*)
 | |
|                          ASN1MALLOC(pctxt, sizeof(H245UnicastAddress));
 | |
| 
 | |
|    unicastAddrs1 = h2250lcap->mediaControlChannel.u.unicastAddress;
 | |
| 
 | |
|    memset(unicastAddrs1, 0, sizeof(H245UnicastAddress));
 | |
|    if (call->versionIP == 6) {
 | |
|    	unicastAddrs1->t = T_H245UnicastAddress_iP6Address;
 | |
|    	unicastAddrs1->u.iP6Address = (H245UnicastAddress_iP6Address*)
 | |
|                memAlloc(pctxt, sizeof(H245UnicastAddress_iP6Address));
 | |
|    	iP6Address1 = unicastAddrs1->u.iP6Address;
 | |
|    	memset(iP6Address1, 0, sizeof(H245UnicastAddress_iP6Address));
 | |
| 	inet_pton(AF_INET6, pLogicalChannel->localIP, iP6Address1->network.data);
 | |
|    	iP6Address1->network.numocts = 16;
 | |
|    	iP6Address1->tsapIdentifier = pLogicalChannel->localRtcpPort;
 | |
|    } else {
 | |
|    	unicastAddrs1->t = T_H245UnicastAddress_iPAddress;
 | |
|    	unicastAddrs1->u.iPAddress = (H245UnicastAddress_iPAddress*)
 | |
|                	memAlloc(pctxt, sizeof(H245UnicastAddress_iPAddress));
 | |
|    	iPAddress1 = unicastAddrs1->u.iPAddress;
 | |
|    	memset(iPAddress1, 0, sizeof(H245UnicastAddress_iPAddress));
 | |
| 
 | |
| 	inet_pton(AF_INET, pLogicalChannel->localIP, iPAddress1->network.data);
 | |
|    	iPAddress1->network.numocts = 4;
 | |
|    	iPAddress1->tsapIdentifier = pLogicalChannel->localRtcpPort;
 | |
|    }
 | |
| 
 | |
|    OOTRACEDBGA3("Built OpenLogicalChannelAck (%s, %s)\n", call->callType, 
 | |
|                  call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to enqueue OpenLogicalChannelAck message to "
 | |
|                   "outbound queue. (%s, %s)\n", call->callType, 
 | |
|                   call->callToken);
 | |
|    }
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
| 
 | |
| 
 | |
|    if(epCap->startReceiveChannel)
 | |
|    {
 | |
|       epCap->startReceiveChannel(call, pLogicalChannel);      
 | |
|       OOTRACEINFO6("Receive channel of type %s started at %s:%d(%s, %s)\n", 
 | |
|                     ooGetCapTypeText(epCap->cap), pLogicalChannel->localIP,
 | |
|                     pLogicalChannel->localRtpPort, call->callType, 
 | |
|                     call->callToken);
 | |
|    }
 | |
|    else{
 | |
|       OOTRACEERR3("ERROR:No callback registered to start receive audio "
 | |
|                   "channel (%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    pLogicalChannel->state = OO_LOGICALCHAN_ESTABLISHED;
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| int ooSendOpenLogicalChannelReject
 | |
|    (OOH323CallData *call, ASN1UINT channelNum, ASN1UINT cause)
 | |
| {
 | |
|    int ret=0;
 | |
|    H245ResponseMessage* response=NULL;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
 | |
|    OOCTXT *pctxt=call->msgctxt;
 | |
| 
 | |
|    ret = ooCreateH245Message
 | |
|       (call, &ph245msg, T_H245MultimediaSystemControlMessage_response);
 | |
| 
 | |
|    if (ret != OO_OK) {
 | |
|       OOTRACEERR3("Error:H245 message creation failed for - OpenLogicalChannel"
 | |
|                   "Reject (%s, %s)\n",call->callType, 
 | |
|                   call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OOOpenLogicalChannelReject;
 | |
|    response = ph245msg->h245Msg.u.response;
 | |
| 
 | |
|    response->t = T_H245ResponseMessage_openLogicalChannelReject;
 | |
| 
 | |
|    response->u.openLogicalChannelReject = 
 | |
|       (H245OpenLogicalChannelReject*)
 | |
|       memAlloc (pctxt, sizeof(H245OpenLogicalChannelReject));
 | |
| 
 | |
|    if(!response->u.openLogicalChannelReject)
 | |
|    {
 | |
|       OOTRACEERR3("Error: Failed to allocate memory for OpenLogicalChannel"
 | |
|                   "Reject message. (%s, %s)\n", call->callType, 
 | |
|                   call->callToken);
 | |
|       ooFreeH245Message(call, ph245msg);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    response->u.openLogicalChannelReject->forwardLogicalChannelNumber = 
 | |
|                                                                  channelNum;
 | |
|    response->u.openLogicalChannelReject->cause.t = cause;
 | |
| 
 | |
|    OOTRACEDBGA3 ("Built OpenLogicalChannelReject (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);
 | |
| 
 | |
|    ret = ooSendH245Msg (call, ph245msg);
 | |
| 
 | |
|    if (ret != OO_OK) {
 | |
|       OOTRACEERR3 
 | |
|          ("Error:Failed to enqueue OpenLogicalChannelReject "
 | |
|          "message to outbound queue.(%s, %s)\n", call->callType, 
 | |
|          call->callToken);
 | |
|    }
 | |
|    
 | |
|    ooFreeH245Message (call, ph245msg);
 | |
| 
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| int ooOnReceivedOpenLogicalChannelAck(OOH323CallData *call,
 | |
|                                       H245OpenLogicalChannelAck *olcAck)
 | |
| {
 | |
|    char remoteip[2+8*4+7];
 | |
|    regmatch_t pmatch[1];
 | |
|    ooLogicalChannel *pLogicalChannel;
 | |
|    H245H2250LogicalChannelAckParameters *h2250lcap;
 | |
|    H245UnicastAddress *unicastAddr;
 | |
|    H245UnicastAddress_iPAddress *iPAddress = NULL;
 | |
|    H245UnicastAddress_iP6Address *iP6Address = NULL;
 | |
|    H245UnicastAddress *unicastAddr1;
 | |
|    H245UnicastAddress_iPAddress *iPAddress1 = NULL;
 | |
|    H245UnicastAddress_iP6Address *iP6Address1 = NULL;
 | |
| 
 | |
|    if(!((olcAck->m.forwardMultiplexAckParametersPresent == 1) &&
 | |
|         (olcAck->forwardMultiplexAckParameters.t == 
 | |
|          T_H245OpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters)))
 | |
|    {
 | |
|       OOTRACEERR3("Error: Processing open logical channel ack - LogicalChannel"
 | |
|                   "Ack parameters absent (%s, %s)\n", call->callType, 
 | |
|                   call->callToken);
 | |
|       return OO_OK;  /* should send CloseLogicalChannel request */
 | |
|    }
 | |
| 
 | |
|    h2250lcap = 
 | |
|       olcAck->forwardMultiplexAckParameters.u.h2250LogicalChannelAckParameters;
 | |
|    /* Extract media channel address */
 | |
|    if(h2250lcap->m.mediaChannelPresent != 1)
 | |
|    { 
 | |
|       OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media channel "
 | |
|                   "absent (%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    if(h2250lcap->mediaChannel.t != T_H245TransportAddress_unicastAddress)
 | |
|    {
 | |
|       OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media channel "
 | |
|                   "address type is not unicast (%s, %s)\n", call->callType, 
 | |
|                   call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    
 | |
|    unicastAddr = h2250lcap->mediaChannel.u.unicastAddress;
 | |
|    if (call->versionIP == 6) {
 | |
|    	if(unicastAddr->t != T_H245UnicastAddress_iP6Address)
 | |
|    	{
 | |
|       	OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media channel "
 | |
|                   "address type is not IP6 (%s, %s)\n", call->callType, 
 | |
|                    call->callToken);
 | |
|       	return OO_FAILED;
 | |
|    	}
 | |
|    	iP6Address = unicastAddr->u.iP6Address;
 | |
| 	inet_ntop(AF_INET6, iP6Address->network.data, remoteip, sizeof(remoteip));
 | |
|    
 | |
|    } else {
 | |
|    	if(unicastAddr->t != T_H245UnicastAddress_iPAddress)
 | |
|    	{
 | |
|       	OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media channel "
 | |
|                   "address type is not IP (%s, %s)\n", call->callType, 
 | |
|                    call->callToken);
 | |
|       	return OO_FAILED;
 | |
|    	}
 | |
|    	iPAddress = unicastAddr->u.iPAddress;
 | |
| 	inet_ntop(AF_INET, iPAddress->network.data, remoteip, sizeof(remoteip));
 | |
|    }
 | |
|    
 | |
|    /* Extract media control channel address */
 | |
|    if(h2250lcap->m.mediaControlChannelPresent == 1) {
 | |
|    	if(h2250lcap->mediaControlChannel.t != 
 | |
|                                      T_H245TransportAddress_unicastAddress)
 | |
|    	{
 | |
|       	 OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media control "
 | |
|                   "channel address type is not unicast (%s, %s)\n", 
 | |
|                    call->callType, call->callToken);
 | |
|       	 return OO_FAILED;
 | |
|    	}
 | |
|    
 | |
|    	unicastAddr1 = h2250lcap->mediaControlChannel.u.unicastAddress;
 | |
| 	if (call->versionIP == 6) {
 | |
|    		if(unicastAddr1->t != T_H245UnicastAddress_iP6Address) {
 | |
|       			OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media control "
 | |
|                   	"channel address type is not IP6 (%s, %s)\n", call->callType, 
 | |
|                    	call->callToken);
 | |
|       		return OO_FAILED;
 | |
|    		}
 | |
|    		iP6Address1 = unicastAddr1->u.iP6Address;
 | |
| 	} else {
 | |
|    		if(unicastAddr1->t != T_H245UnicastAddress_iPAddress) {
 | |
|       			OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media control "
 | |
|                   	"channel address type is not IP (%s, %s)\n", call->callType, 
 | |
|                    	call->callToken);
 | |
|       		return OO_FAILED;
 | |
|    		}
 | |
|    		iPAddress1 = unicastAddr1->u.iPAddress;
 | |
| 	}
 | |
|    } else {
 | |
|       OOTRACEDBGA3("Warning: Processing OpenLogicalChannelAck - Missing media "
 | |
|                 "control channel (%s, %s)\n", call->callType, call->callToken);
 | |
|    }
 | |
| 
 | |
|    /* Set remote destination address for rtp session */
 | |
|    //   strcpy(call->remoteIP, remoteip);
 | |
|    
 | |
|    /* Start channel here */
 | |
|    pLogicalChannel = ooFindLogicalChannelByLogicalChannelNo(call,olcAck->forwardLogicalChannelNumber);
 | |
|    if(!pLogicalChannel)
 | |
|    {
 | |
|       OOTRACEERR4("ERROR:Logical channel %d not found in the channel list for "
 | |
|                   "call (%s, %s)\n", olcAck->forwardLogicalChannelNumber, 
 | |
|                   call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
| 
 | |
|    /* Update session id if we were waiting for remote to assign one and remote 
 | |
|       did assign one. */
 | |
|    if(pLogicalChannel->sessionID == 0 && h2250lcap->m.sessionIDPresent)
 | |
|       pLogicalChannel->sessionID = h2250lcap->sessionID;   
 | |
| 
 | |
|    /* Populate ports &ip  for channel */
 | |
| 
 | |
|    if (call->rtpMaskStr[0]) {
 | |
|      if (regexec(&call->rtpMask->regex, remoteip, 1, pmatch, 0)) {
 | |
| 		OOTRACEERR5("ERROR:H245 Address is not matched with filter %s/%s"
 | |
| 			"(%s, %s)\n", remoteip, call->rtpMaskStr, call->callType, call->callToken);
 | |
| 	 return OO_FAILED;
 | |
| 	}
 | |
|    }
 | |
| 
 | |
|    strcpy(pLogicalChannel->remoteIP, remoteip);   
 | |
|    if (call->versionIP == 6) {
 | |
|    	pLogicalChannel->remoteMediaPort = iP6Address->tsapIdentifier;
 | |
|    	if (iP6Address1)
 | |
|    		pLogicalChannel->remoteMediaControlPort = iP6Address1->tsapIdentifier;
 | |
|    } else {
 | |
|    	pLogicalChannel->remoteMediaPort = iPAddress->tsapIdentifier;
 | |
|    	if (iPAddress1)
 | |
|    		pLogicalChannel->remoteMediaControlPort = iPAddress1->tsapIdentifier;
 | |
|    }
 | |
|    if(pLogicalChannel->chanCap->startTransmitChannel)
 | |
|    {
 | |
|       pLogicalChannel->chanCap->startTransmitChannel(call, pLogicalChannel);
 | |
|       OOTRACEINFO4("TransmitLogical Channel of type %s started (%s, %s)\n", 
 | |
|                    ooGetCapTypeText(pLogicalChannel->chanCap->cap),
 | |
|                    call->callType, call->callToken);
 | |
|    }
 | |
|    else{
 | |
|       OOTRACEERR3("ERROR:No callback registered for starting transmit channel "
 | |
|                   "(%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    pLogicalChannel->state = OO_LOGICALCHAN_ESTABLISHED;
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| int ooOnReceivedOpenLogicalChannelRejected(OOH323CallData *call, 
 | |
|                                      H245OpenLogicalChannelReject *olcReject)
 | |
| {
 | |
|    switch(olcReject->cause.t)
 | |
|    {
 | |
|    case T_H245OpenLogicalChannelReject_cause_unspecified:
 | |
|       OOTRACEINFO4("Open logical channel %d rejected - unspecified (%s, %s)\n",
 | |
|                    olcReject->forwardLogicalChannelNumber, call->callType, 
 | |
|                    call->callToken);
 | |
|       break;
 | |
|    case T_H245OpenLogicalChannelReject_cause_unsuitableReverseParameters:
 | |
|       OOTRACEINFO4("Open logical channel %d rejected - "
 | |
|                    "unsuitableReverseParameters (%s, %s)\n", 
 | |
|                    olcReject->forwardLogicalChannelNumber, call->callType, 
 | |
|                    call->callToken);
 | |
|       break;
 | |
|    case T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported:
 | |
|       OOTRACEINFO4("Open logical channel %d rejected - dataTypeNotSupported"
 | |
|                    "(%s, %s)\n", olcReject->forwardLogicalChannelNumber, 
 | |
|                    call->callType, call->callToken);
 | |
|       break;
 | |
|    case T_H245OpenLogicalChannelReject_cause_dataTypeNotAvailable:
 | |
|       OOTRACEINFO4("Open logical channel %d rejected - dataTypeNotAvailable"
 | |
|                    "(%s, %s)\n", olcReject->forwardLogicalChannelNumber, 
 | |
|                    call->callType, call->callToken);
 | |
|       break;
 | |
|    case T_H245OpenLogicalChannelReject_cause_unknownDataType:
 | |
|       OOTRACEINFO4("Open logical channel %d rejected - unknownDataType"
 | |
|                    "(%s, %s)\n", olcReject->forwardLogicalChannelNumber, 
 | |
|                    call->callType, call->callToken);
 | |
|       break;
 | |
|    case T_H245OpenLogicalChannelReject_cause_dataTypeALCombinationNotSupported:
 | |
|       OOTRACEINFO4("Open logical channel %d rejected - "
 | |
|                    "dataTypeALCombinationNotSupported(%s, %s)\n", 
 | |
|                    olcReject->forwardLogicalChannelNumber, 
 | |
|                    call->callType, call->callToken);
 | |
|       break;
 | |
|    case T_H245OpenLogicalChannelReject_cause_multicastChannelNotAllowed:
 | |
|        OOTRACEINFO4("Open logical channel %d rejected - "
 | |
|                     "multicastChannelNotAllowed (%s, %s)\n", 
 | |
|                     olcReject->forwardLogicalChannelNumber, 
 | |
|                     call->callType, call->callToken);
 | |
|       break;
 | |
|    case T_H245OpenLogicalChannelReject_cause_insufficientBandwidth:
 | |
|       OOTRACEINFO4("Open logical channel %d rejected - insufficientBandwidth"
 | |
|                    "(%s, %s)\n", olcReject->forwardLogicalChannelNumber, 
 | |
|                    call->callType, call->callToken);
 | |
|       break;
 | |
|    case T_H245OpenLogicalChannelReject_cause_separateStackEstablishmentFailed:
 | |
|       OOTRACEINFO4("Open logical channel %d rejected - "
 | |
|                     "separateStackEstablishmentFailed (%s, %s)\n", 
 | |
|                     olcReject->forwardLogicalChannelNumber, 
 | |
|                     call->callType, call->callToken);
 | |
|       break;
 | |
|    case T_H245OpenLogicalChannelReject_cause_invalidSessionID:
 | |
|       OOTRACEINFO4("Open logical channel %d rejected - "
 | |
|                     "invalidSessionID (%s, %s)\n", 
 | |
|                     olcReject->forwardLogicalChannelNumber, 
 | |
|                     call->callType, call->callToken);
 | |
|       break;
 | |
|    case T_H245OpenLogicalChannelReject_cause_masterSlaveConflict:
 | |
|       OOTRACEINFO4("Open logical channel %d rejected - "
 | |
|                     "invalidSessionID (%s, %s)\n", 
 | |
|                     olcReject->forwardLogicalChannelNumber, 
 | |
|                     call->callType, call->callToken);
 | |
|       break;
 | |
|    case T_H245OpenLogicalChannelReject_cause_waitForCommunicationMode:
 | |
|       OOTRACEINFO4("Open logical channel %d rejected - "
 | |
|                     "waitForCommunicationMode (%s, %s)\n", 
 | |
|                     olcReject->forwardLogicalChannelNumber, 
 | |
|                     call->callType, call->callToken);
 | |
|       break;
 | |
|    case T_H245OpenLogicalChannelReject_cause_invalidDependentChannel:
 | |
|       OOTRACEINFO4("Open logical channel %d rejected - "
 | |
|                     "invalidDependentChannel (%s, %s)\n", 
 | |
|                     olcReject->forwardLogicalChannelNumber, 
 | |
|                     call->callType, call->callToken);
 | |
|       break;
 | |
|    case T_H245OpenLogicalChannelReject_cause_replacementForRejected:
 | |
|       OOTRACEINFO4("Open logical channel %d rejected - "
 | |
|                     "replacementForRejected (%s, %s)\n", 
 | |
|                     olcReject->forwardLogicalChannelNumber, 
 | |
|                     call->callType, call->callToken);
 | |
|       break;
 | |
|    default:
 | |
|       OOTRACEERR4("Error: OpenLogicalChannel %d rejected - "
 | |
|                   "invalid cause(%s, %s)\n",
 | |
|                    olcReject->forwardLogicalChannelNumber, 
 | |
|                     call->callType, call->callToken);
 | |
|    }
 | |
|    if(call->callState < OO_CALL_CLEAR)
 | |
|    {
 | |
|       call->callState = OO_CALL_CLEAR;
 | |
|       call->callEndReason = OO_REASON_LOCAL_CLEARED;
 | |
|    }
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Currently only disconnect end session command is supported.
 | |
|  **/
 | |
| int ooSendEndSessionCommand(OOH323CallData *call)
 | |
| {
 | |
|    int ret;
 | |
|    H245CommandMessage * command;
 | |
|    OOCTXT *pctxt;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    ret = ooCreateH245Message(call, &ph245msg, 
 | |
|                       T_H245MultimediaSystemControlMessage_command);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error: H245 message creation failed for - End Session "
 | |
|                   "Command (%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OOEndSessionCommand;
 | |
| 
 | |
|    command = ph245msg->h245Msg.u.command;
 | |
|    /* pctxt = &gH323ep.msgctxt; */
 | |
|    pctxt = call->msgctxt;
 | |
|    memset(command, 0, sizeof(H245CommandMessage));
 | |
|    command->t = T_H245CommandMessage_endSessionCommand;
 | |
|    command->u.endSessionCommand = (H245EndSessionCommand*) ASN1MALLOC(pctxt,
 | |
|                                   sizeof(H245EndSessionCommand));
 | |
|    memset(command->u.endSessionCommand, 0, sizeof(H245EndSessionCommand));
 | |
|    command->u.endSessionCommand->t = T_H245EndSessionCommand_disconnect;
 | |
|    OOTRACEDBGA3("Built EndSession Command (%s, %s)\n", call->callType,
 | |
|                 call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to enqueue EndSession message to outbound "
 | |
|                   "queue.(%s, %s)\n", call->callType, call->callToken);
 | |
|    }
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| int ooHandleH245Command(OOH323CallData *call, 
 | |
|                         H245CommandMessage *command)
 | |
| {
 | |
|    ASN1UINT i;
 | |
|    DListNode *pNode = NULL;
 | |
|    OOTimer *pTimer = NULL;
 | |
|    OOTRACEDBGC3("Handling H.245 command message. (%s, %s)\n", call->callType,
 | |
|                  call->callToken);
 | |
|    switch(command->t)
 | |
|    {
 | |
|       case T_H245CommandMessage_endSessionCommand:
 | |
|          OOTRACEINFO3("Received EndSession command (%s, %s)\n", 
 | |
|                        call->callType, call->callToken);
 | |
|          if(call->h245SessionState == OO_H245SESSION_ENDSENT)
 | |
|          {
 | |
|             /* Disable Session timer */
 | |
|             for(i = 0; i<call->timerList.count; i++)
 | |
|             {
 | |
|                pNode = dListFindByIndex(&call->timerList, i);
 | |
|                pTimer = (OOTimer*)pNode->data;
 | |
|                if(((ooTimerCallback*)pTimer->cbData)->timerType & 
 | |
|                                                             OO_SESSION_TIMER)
 | |
|                {
 | |
|                   ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
 | |
|                   ooTimerDelete(call->pctxt, &call->timerList, pTimer);
 | |
|                   OOTRACEDBGC3("Deleted Session Timer. (%s, %s)\n", 
 | |
|                                 call->callType, call->callToken);
 | |
|                   break;
 | |
|                }
 | |
|             }
 | |
|             ooCloseH245Connection(call);
 | |
| 	    if (call->callState < OO_CALL_CLEAR)
 | |
| 	        call->callState = OO_CALL_CLEAR;
 | |
|          }
 | |
|          else{
 | |
| 
 | |
|             call->h245SessionState = OO_H245SESSION_ENDRECVD;
 | |
|             if(call->logicalChans)
 | |
|             {
 | |
|                OOTRACEINFO3("In response to received EndSessionCommand - "
 | |
|                             "Clearing all logical channels. (%s, %s)\n", 
 | |
|                             call->callType, call->callToken);
 | |
|                ooClearAllLogicalChannels(call);
 | |
|             }
 | |
|             ooSendEndSessionCommand(call);
 | |
| 	    if (call->callState < OO_CALL_CLEAR)
 | |
| 	        call->callState = OO_CALL_CLEAR;
 | |
|          }
 | |
|             
 | |
|             
 | |
|          break;
 | |
|       case T_H245CommandMessage_sendTerminalCapabilitySet:
 | |
|          OOTRACEWARN3("Warning: Received command Send terminal capability set "
 | |
|                       "- Not handled (%s, %s)\n", call->callType, 
 | |
|                       call->callToken);
 | |
|          break;
 | |
|       case T_H245CommandMessage_flowControlCommand:
 | |
|          OOTRACEWARN3("Warning: Flow control command received - Not handled "
 | |
|                       "(%s, %s)\n", call->callType, call->callToken);
 | |
|          break;
 | |
|       default:
 | |
|          OOTRACEWARN3("Warning: Unhandled H245 command message received "
 | |
|                       "(%s, %s)\n", call->callType, call->callToken);
 | |
|    }
 | |
|    OOTRACEDBGC3("Handling H.245 command message done. (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);   
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| 
 | |
| int ooOnReceivedTerminalCapabilitySetAck(OOH323CallData* call)
 | |
| {
 | |
|    int ret = OO_OK;
 | |
|    call->localTermCapState = OO_LocalTermCapSetAckRecvd;
 | |
|    if(call->remoteTermCapState != OO_RemoteTermCapSetAckSent)
 | |
|       return OO_OK;
 | |
|    
 | |
|    if(call->masterSlaveState == OO_MasterSlave_Idle) {
 | |
|       ret = ooSendMasterSlaveDetermination(call);
 | |
|       if(ret != OO_OK) {
 | |
|                 OOTRACEERR3("ERROR:Sending Master-slave determination message "
 | |
|                             "(%s, %s)\n", call->callType, call->callToken);
 | |
|                 return ret;
 | |
|       }
 | |
|    } 
 | |
| 
 | |
|    if((call->masterSlaveState == OO_MasterSlave_Master ||
 | |
|        call->masterSlaveState == OO_MasterSlave_Slave) &&
 | |
|        (call->msAckStatus == OO_msAck_remoteReceived))
 | |
|    {
 | |
|       if(gH323ep.h323Callbacks.openLogicalChannels)
 | |
|          gH323ep.h323Callbacks.openLogicalChannels(call);
 | |
| 
 | |
|       /* ooSendStatusInquiry(call); */
 | |
|       
 | |
|       if(!ooGetTransmitLogicalChannel(call))
 | |
|          ooOpenLogicalChannels(call);
 | |
| #if 0
 | |
|       if(!call->logicalChans){
 | |
|          if(!gH323ep.h323Callbacks.openLogicalChannels)
 | |
|             ooOpenLogicalChannels(call);
 | |
|          else
 | |
|             gH323ep.h323Callbacks.openLogicalChannels(call);
 | |
|       }
 | |
| #endif
 | |
|    }
 | |
|       
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| int ooCloseAllLogicalChannels(OOH323CallData *call, char* dir)
 | |
| {
 | |
|    ooLogicalChannel *temp;
 | |
| 
 | |
|    temp = call->logicalChans;
 | |
|    while(temp)
 | |
|    {
 | |
|       if(temp->state == OO_LOGICALCHAN_ESTABLISHED && 
 | |
| 	(dir == NULL || !strcmp(temp->dir,dir)))
 | |
|       {
 | |
|          /* Sending closelogicalchannel only for outgoing channels*/
 | |
|          if(!strcmp(temp->dir, "transmit"))
 | |
|          {
 | |
|             ooSendCloseLogicalChannel(call, temp);
 | |
|          }
 | |
|          else{
 | |
|             ooSendRequestCloseLogicalChannel(call, temp);
 | |
|          }
 | |
|       }
 | |
|       temp = temp->next;
 | |
|    }
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| int ooUpdateAllLogicalChannels(OOH323CallData *call, char* localIP, int port)
 | |
| {
 | |
|    ooLogicalChannel *temp;
 | |
|    OOMediaInfo *pMediaInfo = NULL;
 | |
|    char *lIP = localIP;
 | |
|    OOBOOL eTCS = FALSE;
 | |
| 
 | |
|    if (!lIP || !lIP[0]) {
 | |
|       lIP = call->localIP;
 | |
|    }
 | |
| 
 | |
| /* close all log chans */
 | |
| 
 | |
|    temp = call->logicalChans;
 | |
|    while (temp) {
 | |
|       if (temp->state == OO_LOGICALCHAN_ESTABLISHED) {
 | |
|           /* Sending closelogicalchannel only for outgoing channels */
 | |
|          if (!strcmp(temp->dir, "transmit")) {
 | |
| 	    if (call->h245SessionState != OO_H245SESSION_IDLE) {
 | |
|               ooSendCloseLogicalChannel(call, temp);
 | |
|             } else {
 | |
|               ooClearLogicalChannel(call, temp->channelNo);
 | |
|             }
 | |
|          } else if (!eTCS && call->h245SessionState != OO_H245SESSION_IDLE) {
 | |
|             ooSendEmptyTermCapMsg(call);
 | |
|             eTCS = TRUE;
 | |
|          }
 | |
|       }
 | |
|       temp = temp->next;
 | |
|    }
 | |
| 
 | |
| /* change media address for all caps */
 | |
| 
 | |
|    if (call->mediaInfo) {
 | |
|       pMediaInfo = call->mediaInfo;
 | |
|       while (pMediaInfo) {
 | |
|          strcpy(pMediaInfo->lMediaIP, lIP);
 | |
|          pMediaInfo->lMediaRedirPort = port;
 | |
|          pMediaInfo->lMediaRedirCPort = port + 1;
 | |
|          pMediaInfo = pMediaInfo->next;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if (call->h245SessionState == OO_H245SESSION_IDLE) {
 | |
|       if (call->fsSent) {
 | |
|          ooSendFSUpdate(call);
 | |
|       }
 | |
|    } else {
 | |
|       call->TCSPending = TRUE;
 | |
|    }
 | |
| 
 | |
| /* Restart TCS exchange proc - Paul Cadah do it in chan_h323_exts native bridge code */
 | |
| /* We must do it after all log channels are closed */
 | |
| 
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| int ooSendCloseLogicalChannel(OOH323CallData *call, ooLogicalChannel *logicalChan)
 | |
| {
 | |
|    int ret = OO_OK, error=0;
 | |
|    H245Message *ph245msg = NULL;
 | |
|    OOCTXT *pctxt;
 | |
|    H245RequestMessage *request;
 | |
|    H245CloseLogicalChannel* clc;
 | |
|    
 | |
|    ret = ooCreateH245Message(call, &ph245msg, 
 | |
|                              T_H245MultimediaSystemControlMessage_request);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Failed to create H245 message for closeLogicalChannel"
 | |
|                   " message (%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OOCloseLogicalChannel;
 | |
|    ph245msg->logicalChannelNo = logicalChan->channelNo;
 | |
|    /* pctxt = &gH323ep.msgctxt; */
 | |
|    pctxt = call->msgctxt;
 | |
|    request = ph245msg->h245Msg.u.request;
 | |
| 
 | |
|    request->t = T_H245RequestMessage_closeLogicalChannel;
 | |
|    request->u.closeLogicalChannel = (H245CloseLogicalChannel*)ASN1MALLOC(pctxt,
 | |
|                                      sizeof(H245CloseLogicalChannel));
 | |
|    if(!request->u.closeLogicalChannel)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Memory allocation for CloseLogicalChannel failed "
 | |
|                   "(%s, %s)\n", call->callType, call->callToken);
 | |
|       ooFreeH245Message(call, ph245msg);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    clc = request->u.closeLogicalChannel;
 | |
|    memset(clc, 0, sizeof(H245CloseLogicalChannel));
 | |
| 
 | |
|    clc->forwardLogicalChannelNumber = logicalChan->channelNo;
 | |
|    clc->source.t = T_H245CloseLogicalChannel_source_lcse;
 | |
|    clc->m.reasonPresent = 1;
 | |
|    clc->reason.t = T_H245CloseLogicalChannel_reason_unknown;
 | |
| 
 | |
|    OOTRACEDBGA4("Built close logical channel for %d (%s, %s)\n", 
 | |
|                  logicalChan->channelNo, call->callType, call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|      OOTRACEERR3("Error:Failed to enqueue CloseLogicalChannel to outbound queue.(%s, %s)\n", call->callType,
 | |
|                  call->callToken);
 | |
|      error++;
 | |
|    }
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
|    
 | |
|    /* Stop the media transmission */
 | |
|    /* Moved to OnReceivedClosedChannelAck */
 | |
|    logicalChan->state = OO_LOGICALCHAN_CLOSEPENDING;
 | |
|    if (error) {
 | |
| 	return OO_FAILED;
 | |
|    }
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| /*TODO: Need to pass reason as a parameter */
 | |
| int ooSendRequestCloseLogicalChannel(OOH323CallData *call, 
 | |
|                                      ooLogicalChannel *logicalChan)
 | |
| {
 | |
|    int ret = OO_OK;
 | |
|    H245Message *ph245msg = NULL;
 | |
|    OOCTXT *pctxt;
 | |
|    H245RequestMessage *request;
 | |
|    H245RequestChannelClose *rclc;
 | |
| 
 | |
|    ret = ooCreateH245Message(call, &ph245msg, 
 | |
|                              T_H245MultimediaSystemControlMessage_request);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Failed to create H245 message for "
 | |
|                   "requestCloseLogicalChannel message (%s, %s)\n", 
 | |
|                    call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OORequestChannelClose;
 | |
|    ph245msg->logicalChannelNo = logicalChan->channelNo;
 | |
|    /* pctxt = &gH323ep.msgctxt; */
 | |
|    pctxt = call->msgctxt;
 | |
|    request = ph245msg->h245Msg.u.request;
 | |
| 
 | |
|    request->t = T_H245RequestMessage_requestChannelClose;
 | |
|    request->u.requestChannelClose = (H245RequestChannelClose*)ASN1MALLOC(pctxt,
 | |
|                                      sizeof(H245RequestChannelClose));
 | |
|    if(!request->u.requestChannelClose)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Memory allocation for RequestCloseLogicalChannel "
 | |
|                   " failed (%s, %s)\n", call->callType, call->callToken);
 | |
|       ooFreeH245Message(call, ph245msg);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
| 
 | |
|    rclc = request->u.requestChannelClose;
 | |
|    memset(rclc, 0, sizeof(H245RequestChannelClose));
 | |
|    rclc->forwardLogicalChannelNumber = logicalChan->channelNo;
 | |
|    
 | |
|    rclc->m.reasonPresent = 1;
 | |
|    rclc->reason.t = T_H245RequestChannelClose_reason_unknown;
 | |
| 
 | |
|    OOTRACEDBGA4("Built RequestCloseChannel for %d (%s, %s)\n", 
 | |
|                  logicalChan->channelNo, call->callType, call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|      OOTRACEERR3("Error:Failed to enqueue the RequestCloseChannel to outbound"
 | |
|                  " queue (%s, %s)\n", call->callType,
 | |
|                  call->callToken);
 | |
|    }
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
| 
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| int ooSendRequestChannelCloseRelease(OOH323CallData *call, int channelNum)
 | |
| {
 | |
|    int ret = OO_OK;
 | |
|    H245Message *ph245msg = NULL;
 | |
|    OOCTXT *pctxt;
 | |
|    H245IndicationMessage *indication;
 | |
| 
 | |
|    ret = ooCreateH245Message(call, &ph245msg, 
 | |
|                              T_H245MultimediaSystemControlMessage_indication);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Failed to create H245 message for "
 | |
|                   "RequestChannelCloseRelease message (%s, %s)\n", 
 | |
|                    call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OORequestChannelCloseRelease;
 | |
|    ph245msg->logicalChannelNo = channelNum;
 | |
|    /* pctxt = &gH323ep.msgctxt; */
 | |
|    pctxt = call->msgctxt;
 | |
|    indication = ph245msg->h245Msg.u.indication;
 | |
|    indication->t = T_H245IndicationMessage_requestChannelCloseRelease;
 | |
|    indication->u.requestChannelCloseRelease = (H245RequestChannelCloseRelease*)
 | |
|                      ASN1MALLOC(pctxt, sizeof(H245RequestChannelCloseRelease));
 | |
|    if(!indication->u.requestChannelCloseRelease)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to allocate memory for "
 | |
|                   "RequestChannelCloseRelease message. (%s, %s)\n", 
 | |
|                    call->callType, call->callToken);
 | |
|       ooFreeH245Message(call, ph245msg);
 | |
|    }
 | |
| 
 | |
|    indication->u.requestChannelCloseRelease->forwardLogicalChannelNumber = 
 | |
|                                                                 channelNum;
 | |
| 
 | |
|    OOTRACEDBGA4("Built RequestChannelCloseRelease for %d (%s, %s)\n", 
 | |
|                 channelNum, call->callType, call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|      OOTRACEERR3("Error:Failed to enqueue the RequestChannelCloseRelease to "
 | |
|                  "outbound queue (%s, %s)\n", call->callType, call->callToken);
 | |
|    }
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
| 
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
|    
 | |
| int ooOnReceivedRequestChannelClose(OOH323CallData *call, 
 | |
|                                     H245RequestChannelClose *rclc)
 | |
| {
 | |
|    int ret=0, error=0;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    H245ResponseMessage *response = NULL;
 | |
|    OOCTXT *pctxt=NULL;
 | |
|    H245RequestChannelCloseAck *rclcAck;
 | |
|    ooLogicalChannel * lChannel=NULL;
 | |
|    /* Send Ack: TODO: Need to send reject, if doesn't exist
 | |
|    */
 | |
|    lChannel = ooFindLogicalChannelByLogicalChannelNo(call, 
 | |
|                                         rclc->forwardLogicalChannelNumber);
 | |
|    if(!lChannel)
 | |
|    {
 | |
|       OOTRACEERR4("ERROR:Channel %d requested to be closed not found "
 | |
|                   "(%s, %s)\n", rclc->forwardLogicalChannelNumber,
 | |
|                   call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    else{
 | |
|       if(strcmp(lChannel->dir, "transmit"))
 | |
|       {
 | |
|          OOTRACEERR4("ERROR:Channel %d requested to be closed, Not a forward "
 | |
|                      "channel (%s, %s)\n", rclc->forwardLogicalChannelNumber,
 | |
|                      call->callType, call->callToken);
 | |
|          return OO_FAILED;
 | |
|       }
 | |
|    }
 | |
|    ret = ooCreateH245Message(call, &ph245msg, 
 | |
|                              T_H245MultimediaSystemControlMessage_response);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Memory allocation for RequestChannelCloseAck message "
 | |
|                   "failed (%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    /* pctxt = &gH323ep.msgctxt; */
 | |
|    pctxt = call->msgctxt;
 | |
|    ph245msg->msgType = OORequestChannelCloseAck;
 | |
|    ph245msg->logicalChannelNo = rclc->forwardLogicalChannelNumber;
 | |
|    response = ph245msg->h245Msg.u.response;
 | |
|    response->t = T_H245ResponseMessage_requestChannelCloseAck;
 | |
|    response->u.requestChannelCloseAck = (H245RequestChannelCloseAck*)ASN1MALLOC
 | |
|                                    (pctxt, sizeof(H245RequestChannelCloseAck));
 | |
|    if(!response->u.requestChannelCloseAck)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Failed to allocate memory for RequestChannelCloseAck "
 | |
|                   "message (%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    rclcAck = response->u.requestChannelCloseAck;
 | |
|    memset(rclcAck, 0, sizeof(H245RequestChannelCloseAck));
 | |
|    rclcAck->forwardLogicalChannelNumber = rclc->forwardLogicalChannelNumber;
 | |
| 
 | |
|    OOTRACEDBGA3("Built RequestCloseChannelAck message (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to enqueue RequestCloseChannelAck to outbound queue. (%s, %s)\n", call->callType,
 | |
|                   call->callToken);
 | |
|       error++;
 | |
|    }
 | |
| 
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
|    
 | |
|    /* Send Close Logical Channel if LogChan is established */
 | |
|    if (lChannel->state == OO_LOGICALCHAN_ESTABLISHED) {
 | |
|      ret = ooSendCloseLogicalChannel(call, lChannel);
 | |
|      if (ret != OO_OK) {
 | |
|       OOTRACEERR3("ERROR:Failed to build CloseLgicalChannel message(%s, %s)\n",
 | |
|                    call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|      }
 | |
|    }
 | |
|    if (error) {
 | |
| 	return OO_FAILED;
 | |
|    }
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| int ooSendRoundTripDelayRequest(OOH323CallData *call)
 | |
| {
 | |
|    int ret=0;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    H245RequestMessage *request = NULL;
 | |
|    OOCTXT *pctxt=NULL;
 | |
|    H245RoundTripDelayRequest *rtdr;
 | |
|    ooTimerCallback *cbData=NULL;
 | |
| 
 | |
|    if (call->rtdrSend > call->rtdrRecv + call->rtdrCount) {
 | |
| 	if(call->callState < OO_CALL_CLEAR) {
 | |
| 		call->callState = OO_CALL_CLEAR;
 | |
| 		call->callEndReason = OO_REASON_UNKNOWN;
 | |
| 		call->q931cause = Q931RecoveryOnTimerExpiry;
 | |
| 	}
 | |
| 	return OO_FAILED;
 | |
|    }
 | |
|    
 | |
|    ret = ooCreateH245Message(call, &ph245msg, 
 | |
|                              T_H245MultimediaSystemControlMessage_request);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Memory allocation for RoundTripDelayResponse message "
 | |
|                   "failed (%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
| 
 | |
|    pctxt = call->msgctxt;
 | |
|    ph245msg->msgType = OORequestDelayRequest;
 | |
|    request = ph245msg->h245Msg.u.request;
 | |
|    request->t = T_H245RequestMessage_roundTripDelayRequest;
 | |
|    request->u.roundTripDelayRequest = (H245RoundTripDelayRequest *)ASN1MALLOC
 | |
|                                    (pctxt, sizeof(H245RoundTripDelayRequest));
 | |
|    if(!request->u.roundTripDelayRequest)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Failed to allocate memory for H245RoundTripDelayRequest "
 | |
|                   "message (%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    rtdr = request->u.roundTripDelayRequest;
 | |
|    memset(rtdr, 0, sizeof(H245RoundTripDelayRequest));
 | |
|    rtdr->sequenceNumber = ++call->rtdrSend;
 | |
| 
 | |
|    OOTRACEDBGA3("Built RoundTripDelayRequest message (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to enqueue RoundTripDelayRequest to outbound queue. (%s, %s)\n",
 | |
| 	call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    } else {
 | |
|       cbData = (ooTimerCallback*) memAlloc(call->pctxt,
 | |
|                                      sizeof(ooTimerCallback));
 | |
|       if(!cbData)
 | |
|       {
 | |
|          OOTRACEERR3("Error:Unable to allocate memory for timer callback data."
 | |
|                      "(%s, %s)\n", call->callType, call->callToken);
 | |
|          return OO_FAILED;
 | |
|       }
 | |
|       cbData->call = call;
 | |
|       cbData->timerType = OO_RTD_TIMER;
 | |
|       if(!ooTimerCreate(call->pctxt, &call->timerList, &ooRTDTimerExpired,
 | |
|                         call->rtdrInterval, cbData, FALSE))
 | |
|       {
 | |
|          OOTRACEERR3("Error:Unable to create RTDR timer. "
 | |
|                      "(%s, %s)\n", call->callType, call->callToken);
 | |
|          memFreePtr(call->pctxt, cbData);
 | |
|          return OO_FAILED;
 | |
|       }
 | |
| 
 | |
|    }
 | |
| 
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
| 
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| int ooOnReceivedRoundTripDelayRequest(OOH323CallData *call, 
 | |
|                                      H245SequenceNumber sequenceNumber)
 | |
| {
 | |
|    int ret=0;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    H245ResponseMessage *response = NULL;
 | |
|    OOCTXT *pctxt=NULL;
 | |
|    H245RoundTripDelayResponse *rtdr;
 | |
| 
 | |
|    ret = ooCreateH245Message(call, &ph245msg, 
 | |
|                              T_H245MultimediaSystemControlMessage_response);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Memory allocation for RoundTripDelayResponse message "
 | |
|                   "failed (%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
| 
 | |
|    pctxt = call->msgctxt;
 | |
|    ph245msg->msgType = OORequestDelayResponse;
 | |
|    response = ph245msg->h245Msg.u.response;
 | |
|    response->t = T_H245ResponseMessage_roundTripDelayResponse;
 | |
|    response->u.roundTripDelayResponse = (H245RoundTripDelayResponse *)ASN1MALLOC
 | |
|                                    (pctxt, sizeof(H245RoundTripDelayResponse));
 | |
|    if(!response->u.roundTripDelayResponse)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Failed to allocate memory for H245RoundTripDelayResponse "
 | |
|                   "message (%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    rtdr = response->u.roundTripDelayResponse;
 | |
|    memset(rtdr, 0, sizeof(H245RoundTripDelayResponse));
 | |
|    rtdr->sequenceNumber = sequenceNumber;
 | |
| 
 | |
|    OOTRACEDBGA3("Built RoundTripDelayResponse message (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to enqueue RoundTripDelayResponse to outbound queue. (%s, %s)\n",
 | |
| 	call->callType, call->callToken);
 | |
|    }
 | |
| 
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
|    
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| /*
 | |
|   We clear channel here. Ideally the remote endpoint should send 
 | |
|   CloseLogicalChannel and then the channel should be cleared. But there's no
 | |
|   timer for this and if remote endpoint misbehaves, the call will keep waiting
 | |
|   for CloseLogicalChannel and hence, wouldn't be cleared. In case when remote
 | |
|   endpoint sends CloseLogicalChannel, we call ooClearLogicalChannel again,
 | |
|   which simply returns OO_OK as channel was already cleared. Other option is
 | |
|   to start a timer for call cleanup and if call is not cleaned up within 
 | |
|   timeout, we clean call forcefully. Note, no such timer is defined in 
 | |
|   standards.
 | |
| */
 | |
| int ooOnReceivedRequestChannelCloseAck
 | |
|                        (OOH323CallData *call, H245RequestChannelCloseAck *rccAck)
 | |
| {
 | |
|    int ret=OO_OK;
 | |
|    /* Remote endpoint is ok to close channel. So let's do it */
 | |
|    ret = ooClearLogicalChannel(call, rccAck->forwardLogicalChannelNumber);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR4("Error:Failed to clear logical channel %d. (%s, %s)\n", 
 | |
|                    rccAck->forwardLogicalChannelNumber, call->callType, 
 | |
|                    call->callToken);
 | |
|    }
 | |
| 
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| int ooOnReceivedRequestChannelCloseReject
 | |
|    (OOH323CallData *call, H245RequestChannelCloseReject *rccReject)
 | |
| {
 | |
|    int ret =0;
 | |
|    switch(rccReject->cause.t)
 | |
|    {
 | |
|    case T_H245RequestChannelCloseReject_cause_unspecified:
 | |
|       OOTRACEDBGA4("Remote endpoint has rejected request to close logical "
 | |
|                    "channel %d - cause unspecified. (%s, %s)\n", 
 | |
|                    rccReject->forwardLogicalChannelNumber, call->callType, 
 | |
|                    call->callToken);
 | |
|      break;
 | |
|    case T_H245RequestChannelCloseReject_cause_extElem1:
 | |
|       OOTRACEDBGA4("Remote endpoint has rejected request to close logical "
 | |
|                    "channel %d - cause propriatory. (%s, %s)\n", 
 | |
|                    rccReject->forwardLogicalChannelNumber, call->callType, 
 | |
|                    call->callToken);   
 | |
|       break;
 | |
|    default:
 | |
|       OOTRACEDBGA4("Remote endpoint has rejected request to close logical "
 | |
|                    "channel %d - cause INVALID. (%s, %s)\n", 
 | |
|                    rccReject->forwardLogicalChannelNumber, call->callType, 
 | |
|                    call->callToken);
 | |
|    }
 | |
|    OOTRACEDBGA4("Clearing logical channel %d. (%s, %s)\n", 
 | |
|                  rccReject->forwardLogicalChannelNumber, call->callType, 
 | |
|                  call->callToken);
 | |
|    ret = ooClearLogicalChannel(call, rccReject->forwardLogicalChannelNumber);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR4("Error: failed to clear logical channel %d.(%s, %s)\n", 
 | |
|                    rccReject->forwardLogicalChannelNumber, call->callType, 
 | |
|                    call->callToken);
 | |
|    }
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| /****/
 | |
| int ooOnReceivedCloseLogicalChannel(OOH323CallData *call, 
 | |
|                                     H245CloseLogicalChannel* clc)
 | |
| {
 | |
|    int ret=0;
 | |
|    H245Message *ph245msg = NULL;
 | |
|    OOCTXT *pctxt = NULL;
 | |
|    H245CloseLogicalChannelAck * clcAck;
 | |
|    H245ResponseMessage *response;
 | |
|    
 | |
|    OOTRACEINFO4("Closing logical channel number %d (%s, %s)\n",
 | |
|       clc->forwardLogicalChannelNumber, call->callType, call->callToken);
 | |
|    
 | |
|    ret = ooClearLogicalChannel(call, clc->forwardLogicalChannelNumber);
 | |
|    if (ret != OO_OK) {
 | |
|       OOTRACEERR4("ERROR:Failed to close logical channel %d (%s, %s)\n",
 | |
|          clc->forwardLogicalChannelNumber, call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
| 
 | |
|    ret = ooCreateH245Message(call, &ph245msg, 
 | |
|                               T_H245MultimediaSystemControlMessage_response);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Failed to create H245 message for "
 | |
|                   "closeLogicalChannelAck (%s, %s)\n", call->callType, 
 | |
|                   call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    /* pctxt = &gH323ep.msgctxt; */
 | |
|    pctxt = call->msgctxt;
 | |
|    ph245msg->msgType = OOCloseLogicalChannelAck;
 | |
|    ph245msg->logicalChannelNo = clc->forwardLogicalChannelNumber;
 | |
|    response = ph245msg->h245Msg.u.response;
 | |
|    response->t = T_H245ResponseMessage_closeLogicalChannelAck;
 | |
|    response->u.closeLogicalChannelAck = (H245CloseLogicalChannelAck*)
 | |
|                          ASN1MALLOC(pctxt, sizeof(H245CloseLogicalChannelAck));
 | |
|    clcAck = response->u.closeLogicalChannelAck;
 | |
|    if(!clcAck)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Failed to allocate memory for closeLogicalChannelAck "
 | |
|                   "(%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_OK;
 | |
|    }
 | |
|    memset(clcAck, 0, sizeof(H245CloseLogicalChannelAck));
 | |
|    clcAck->forwardLogicalChannelNumber = clc->forwardLogicalChannelNumber;
 | |
| 
 | |
|    OOTRACEDBGA3("Built CloseLogicalChannelAck message (%s, %s)\n",
 | |
|                  call->callType, call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|      OOTRACEERR3("Error:Failed to enqueue CloseLogicalChannelAck message to "
 | |
|                  "outbound queue.(%s, %s)\n", call->callType, call->callToken);
 | |
|    }
 | |
| 
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| int ooOnReceivedCloseChannelAck(OOH323CallData* call, 
 | |
|                                 H245CloseLogicalChannelAck* clcAck)
 | |
| {
 | |
|    int ret = OO_OK;
 | |
|    /* Stop the media transmission */
 | |
|    OOTRACEINFO4("Closing logical channel %d (%s, %s)\n",
 | |
|                 clcAck->forwardLogicalChannelNumber, call->callType,
 | |
|                 call->callToken);
 | |
|    ret = ooClearLogicalChannel(call, clcAck->forwardLogicalChannelNumber);
 | |
|    if (ret != OO_OK) {
 | |
|       OOTRACEERR4("ERROR:Failed to close logical channel %d (%s, %s)\n",
 | |
|          clcAck->forwardLogicalChannelNumber, call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| int ooHandleH245Message(OOH323CallData *call, H245Message * pmsg)
 | |
| {
 | |
|    ASN1UINT i;
 | |
|    DListNode *pNode = NULL;
 | |
|    OOTimer *pTimer = NULL;
 | |
|    H245Message *pH245 = (H245Message*)pmsg;
 | |
|    /* There are four major types of H.245 messages that can be received.
 | |
|       Request/Response/Command/Indication. Each one of them need to be 
 | |
|       handled separately.
 | |
|    */   
 | |
|    H245RequestMessage *request = NULL;
 | |
|    H245ResponseMessage *response = NULL;
 | |
|    H245CommandMessage *command = NULL;
 | |
|    H245IndicationMessage *indication = NULL;
 | |
|    
 | |
|    OOTRACEDBGC3("Handling H245 message. (%s, %s)\n", call->callType, 
 | |
|                  call->callToken);
 | |
|    
 | |
|    switch(pH245->h245Msg.t)
 | |
|    {
 | |
|       /* H.245 Request message is received */
 | |
|       case (T_H245MultimediaSystemControlMessage_request):
 | |
|          request = pH245->h245Msg.u.request;
 | |
|          switch(request->t)
 | |
|          {
 | |
|             case T_H245RequestMessage_terminalCapabilitySet:
 | |
|                /* If session isn't marked active yet, do it. possible in case of 
 | |
|                   tunneling */
 | |
|                if(call->h245SessionState == OO_H245SESSION_IDLE)
 | |
|                   call->h245SessionState = OO_H245SESSION_ACTIVE; 
 | |
| 
 | |
|                ooOnReceivedTerminalCapabilitySet(call, pH245);
 | |
|                if(call->localTermCapState == OO_LocalTermCapExchange_Idle)
 | |
|                   ooSendTermCapMsg(call);
 | |
|                break;
 | |
|             case T_H245RequestMessage_masterSlaveDetermination:
 | |
|                ooHandleMasterSlave(call, 
 | |
|                                      request->u.masterSlaveDetermination, 
 | |
|                                      OOMasterSlaveDetermination);
 | |
|                break;
 | |
|             case T_H245RequestMessage_openLogicalChannel:
 | |
|                ooHandleOpenLogicalChannel(call, 
 | |
|                                           request->u.openLogicalChannel);
 | |
| 		if(!ooGetTransmitLogicalChannel(call))
 | |
| 			ooOpenLogicalChannels(call);
 | |
|                break;
 | |
| 	    case T_H245RequestMessage_requestMode:
 | |
| 		OOTRACEINFO4("Received request mode - %d (%s, %s)\n",
 | |
| 		request->u.requestMode->sequenceNumber, call->callType, call->callToken);
 | |
| 	       ooHandleRequestMode(call, 
 | |
| 					request->u.requestMode);
 | |
| 		break;
 | |
|             case T_H245RequestMessage_closeLogicalChannel:
 | |
|                OOTRACEINFO4("Received close logical Channel - %d (%s, %s)\n",
 | |
|                   request->u.closeLogicalChannel->forwardLogicalChannelNumber, 
 | |
|                   call->callType, call->callToken);
 | |
|                if (ooOnReceivedCloseLogicalChannel(call, 
 | |
|                                                request->u.closeLogicalChannel) == OO_OK) {
 | |
| 		if (call->TCSPending && !ooGetTransmitLogicalChannel(call)) {
 | |
| 			call->TCSPending = FALSE;
 | |
| 			call->localTermCapState = OO_LocalTermCapExchange_Idle;
 | |
| 			ooSendTermCapMsg(call);
 | |
| 		} else if (!call->TCSPending) {
 | |
| 			ooCloseAllLogicalChannels(call, NULL);
 | |
| 		}
 | |
| 	       }
 | |
|                break;
 | |
|             case T_H245RequestMessage_requestChannelClose:
 | |
|                OOTRACEINFO4("Received RequestChannelClose - %d (%s, %s)\n",
 | |
|                   request->u.requestChannelClose->forwardLogicalChannelNumber, 
 | |
|                   call->callType, call->callToken);
 | |
|                ooOnReceivedRequestChannelClose(call, 
 | |
|                                                request->u.requestChannelClose);
 | |
|                break;
 | |
| 	     case T_H245RequestMessage_roundTripDelayRequest:
 | |
| 	       OOTRACEINFO4("Received roundTripDelayRequest - %d (%s, %s)\n",
 | |
| 		  request->u.roundTripDelayRequest->sequenceNumber,  call->callType, call->callToken);
 | |
| 	       ooOnReceivedRoundTripDelayRequest(call, request->u.roundTripDelayRequest->sequenceNumber);
 | |
| 	       break;
 | |
|             default:
 | |
|                ;
 | |
|          } /* End of Request Message */
 | |
|          break;
 | |
|       /* H.245 Response message is received */ 
 | |
|       case (T_H245MultimediaSystemControlMessage_response):
 | |
|          response = pH245->h245Msg.u.response;
 | |
|          switch(response->t)
 | |
|          {
 | |
|             case T_H245ResponseMessage_masterSlaveDeterminationAck:
 | |
|                /* Disable MSD timer */
 | |
|                for(i = 0; i<call->timerList.count; i++)
 | |
|                {
 | |
|                   pNode = dListFindByIndex(&call->timerList, i);
 | |
|                   pTimer = (OOTimer*)pNode->data;
 | |
|                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_MSD_TIMER)
 | |
|                   {
 | |
|                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
 | |
|                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
 | |
|                      OOTRACEDBGC3("Deleted MSD Timer. (%s, %s)\n", call->callType,
 | |
|                    call->callToken);
 | |
|                      break;
 | |
|                   }
 | |
|                }
 | |
| 
 | |
|                ooHandleMasterSlave(call, 
 | |
|                                    response->u.masterSlaveDeterminationAck, 
 | |
|                                    OOMasterSlaveAck);
 | |
|                break;
 | |
|             case T_H245ResponseMessage_masterSlaveDeterminationReject:
 | |
|                /* Disable MSD timer */
 | |
|                for(i = 0; i<call->timerList.count; i++)
 | |
|                {
 | |
|                   pNode = dListFindByIndex(&call->timerList, i);
 | |
|                   pTimer = (OOTimer*)pNode->data;
 | |
|                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_MSD_TIMER)
 | |
|                   {
 | |
|                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
 | |
|                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
 | |
|                      OOTRACEDBGC3("Deleted MSD Timer. (%s, %s)\n", call->callType,
 | |
|                    call->callToken);
 | |
|                      break;
 | |
|                   }
 | |
|                }
 | |
|                ooHandleMasterSlaveReject(call, 
 | |
|                                   response->u.masterSlaveDeterminationReject);
 | |
|                break;
 | |
|             case T_H245ResponseMessage_terminalCapabilitySetAck:
 | |
|                /* Disable TCS timer */
 | |
|                for(i = 0; i<call->timerList.count; i++)
 | |
|                {
 | |
|                   pNode = dListFindByIndex(&call->timerList, i);
 | |
|                   pTimer = (OOTimer*)pNode->data;
 | |
|                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_TCS_TIMER)
 | |
|                   {
 | |
|                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
 | |
|                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
 | |
|                      OOTRACEDBGC3("Deleted TCS Timer. (%s, %s)\n", call->callType,
 | |
|                         call->callToken);
 | |
|                      break;
 | |
|                   }
 | |
|                }
 | |
|                ooOnReceivedTerminalCapabilitySetAck(call);
 | |
|                break;
 | |
|             case T_H245ResponseMessage_terminalCapabilitySetReject:
 | |
|                OOTRACEINFO3("TerminalCapabilitySetReject message received."
 | |
|                             " (%s, %s)\n", call->callType, call->callToken);
 | |
|                if(response->u.terminalCapabilitySetReject->sequenceNumber != 
 | |
|                   call->localTermCapSeqNo)
 | |
|                {
 | |
|                   OOTRACEINFO5("Ignoring TCSReject with mismatched seqno %d "
 | |
|                               "(local - %d). (%s, %s)\n", 
 | |
|                           response->u.terminalCapabilitySetReject->sequenceNumber,
 | |
|                         call->localTermCapSeqNo, call->callType, call->callToken);
 | |
|                   break;
 | |
|                }
 | |
|                /* Disable TCS timer */
 | |
|                for(i = 0; i<call->timerList.count; i++)
 | |
|                {
 | |
|                   pNode = dListFindByIndex(&call->timerList, i);
 | |
|                   pTimer = (OOTimer*)pNode->data;
 | |
|                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_TCS_TIMER)
 | |
|                   {
 | |
|                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
 | |
|                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
 | |
|                      OOTRACEDBGC3("Deleted TCS Timer. (%s, %s)\n", call->callType,
 | |
|                         call->callToken);
 | |
|                      break;
 | |
|                   }
 | |
|                }
 | |
|                if(call->callState < OO_CALL_CLEAR)
 | |
|                {
 | |
|                   call->callState = OO_CALL_CLEAR;
 | |
|                   call->callEndReason = OO_REASON_NOCOMMON_CAPABILITIES;
 | |
|                }
 | |
|                break;
 | |
|             case T_H245ResponseMessage_requestModeAck:
 | |
| 	       if (call->requestSequence == response->u.requestModeAck->sequenceNumber) {
 | |
| 			/* response to our last request, process it */
 | |
|                		ooOnReceivedRequestModeAck(call, response->u.requestModeAck);
 | |
| 	       }
 | |
|                break;
 | |
|             case T_H245ResponseMessage_requestModeReject:
 | |
| 		OOTRACEDBGC3("Received requestModeReject, clearing call (%s, %s)\n",
 | |
| 				 call->callType, call->callToken);
 | |
|                if(call->callState < OO_CALL_CLEAR)
 | |
|                {
 | |
|                   call->callState = OO_CALL_CLEAR;
 | |
|                   call->callEndReason = OO_REASON_REMOTE_REJECTED;
 | |
|                }
 | |
|                break;
 | |
|             case T_H245ResponseMessage_openLogicalChannelAck:
 | |
|                for(i = 0; i<call->timerList.count; i++)
 | |
|                {
 | |
|                   pNode = dListFindByIndex(&call->timerList, i);
 | |
|                   pTimer = (OOTimer*)pNode->data;
 | |
|                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_OLC_TIMER)                                            && 
 | |
|                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
 | |
|                    response->u.openLogicalChannelAck->forwardLogicalChannelNumber)
 | |
|                   {
 | |
| 
 | |
|                      memFreePtr(call->pctxt, pTimer->cbData);
 | |
|                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
 | |
|                      OOTRACEDBGC3("Deleted OpenLogicalChannel Timer. (%s, %s)\n", 
 | |
|                                    call->callType, call->callToken);
 | |
|                      break;
 | |
|                   }
 | |
|                }
 | |
|                ooOnReceivedOpenLogicalChannelAck(call, 
 | |
|                                               response->u.openLogicalChannelAck);
 | |
|                break;
 | |
|             case T_H245ResponseMessage_openLogicalChannelReject:
 | |
|                OOTRACEINFO3("Open Logical Channel Reject received (%s, %s)\n",
 | |
|                              call->callType, call->callToken);
 | |
|                for(i = 0; i<call->timerList.count; i++)
 | |
|                {
 | |
|                   pNode = dListFindByIndex(&call->timerList, i);
 | |
|                   pTimer = (OOTimer*)pNode->data;
 | |
|                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_OLC_TIMER)                                            && 
 | |
|                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
 | |
|                    response->u.openLogicalChannelAck->forwardLogicalChannelNumber)
 | |
|                   {
 | |
| 
 | |
|                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
 | |
|                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
 | |
|                      OOTRACEDBGC3("Deleted OpenLogicalChannel Timer. (%s, %s)\n", 
 | |
|                                    call->callType, call->callToken);
 | |
|                      break;
 | |
|                   }
 | |
|                }
 | |
|                ooOnReceivedOpenLogicalChannelRejected(call, 
 | |
|                                         response->u.openLogicalChannelReject);
 | |
|                break;
 | |
|             case T_H245ResponseMessage_closeLogicalChannelAck:
 | |
|                OOTRACEINFO4("CloseLogicalChannelAck received for %d (%s, %s)\n",
 | |
|                   response->u.closeLogicalChannelAck->forwardLogicalChannelNumber,
 | |
|                   call->callType, call->callToken);
 | |
|                for(i = 0; i<call->timerList.count; i++)
 | |
|                {
 | |
|                   pNode = dListFindByIndex(&call->timerList, i);
 | |
|                   pTimer = (OOTimer*)pNode->data;
 | |
|                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_CLC_TIMER)                                            && 
 | |
|                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
 | |
|                   response->u.closeLogicalChannelAck->forwardLogicalChannelNumber)
 | |
|                   {
 | |
| 
 | |
|                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
 | |
|                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
 | |
|                      OOTRACEDBGC3("Deleted CloseLogicalChannel Timer. (%s, %s)\n",
 | |
|                                    call->callType, call->callToken);
 | |
|                      break;
 | |
|                   }
 | |
|                }
 | |
|                ooOnReceivedCloseChannelAck(call, 
 | |
|                                            response->u.closeLogicalChannelAck);
 | |
| 	       if (call->TCSPending && !ooGetReceiveLogicalChannel(call)) {
 | |
| 			call->TCSPending = FALSE;
 | |
| 			call->localTermCapState = OO_LocalTermCapExchange_Idle;
 | |
| 			ooSendTermCapMsg(call);
 | |
| 	       } else if (!ooGetTransmitLogicalChannel(call)) {
 | |
| 			ooOpenLogicalChannels(call);
 | |
| 	       }
 | |
|                break;
 | |
|             case T_H245ResponseMessage_requestChannelCloseAck:
 | |
|                 OOTRACEINFO4("RequestChannelCloseAck received - %d (%s, %s)\n",
 | |
|                   response->u.requestChannelCloseAck->forwardLogicalChannelNumber,
 | |
|                   call->callType, call->callToken);
 | |
|                 for(i = 0; i<call->timerList.count; i++)
 | |
|                 {
 | |
|                   pNode = dListFindByIndex(&call->timerList, i);
 | |
|                   pTimer = (OOTimer*)pNode->data;
 | |
|                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_RCC_TIMER)                                            && 
 | |
|                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
 | |
|                   response->u.requestChannelCloseAck->forwardLogicalChannelNumber)
 | |
|                   {
 | |
| 
 | |
|                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
 | |
|                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
 | |
|                      OOTRACEDBGC3("Deleted RequestChannelClose Timer. (%s, %s)\n",
 | |
|                                    call->callType, call->callToken);
 | |
|                      break;
 | |
|                   }
 | |
|                 }
 | |
| 		/* Do nothing by receive reqChanCloseAck */
 | |
|                 break;
 | |
|             case T_H245ResponseMessage_requestChannelCloseReject:
 | |
|                OOTRACEINFO4("RequestChannelCloseReject received - %d (%s, %s)\n",
 | |
|                response->u.requestChannelCloseReject->forwardLogicalChannelNumber,
 | |
|                  call->callType, call->callToken);
 | |
|                 for(i = 0; i<call->timerList.count; i++)
 | |
|                 {
 | |
|                   pNode = dListFindByIndex(&call->timerList, i);
 | |
|                   pTimer = (OOTimer*)pNode->data;
 | |
|                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_RCC_TIMER) && 
 | |
|                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
 | |
|                       response->u.requestChannelCloseReject->forwardLogicalChannelNumber)
 | |
|                   {
 | |
| 
 | |
|                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
 | |
|                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
 | |
|                      OOTRACEDBGC3("Deleted RequestChannelClose Timer. (%s, %s)\n",
 | |
|                                    call->callType, call->callToken);
 | |
|                      break;
 | |
|                   }
 | |
|                }
 | |
|                ooOnReceivedRequestChannelCloseReject(call, 
 | |
|                                            response->u.requestChannelCloseReject);
 | |
|                break;
 | |
| 	     case T_H245ResponseMessage_roundTripDelayResponse:
 | |
| 	       OOTRACEINFO4("Received roundTripDelayResponse - %d (%s, %s)\n",
 | |
| 		  response->u.roundTripDelayResponse->sequenceNumber,  call->callType, call->callToken);
 | |
| 	       call->rtdrRecv = response->u.roundTripDelayResponse->sequenceNumber;
 | |
| 	       break;
 | |
|             default:
 | |
|                ;
 | |
|          }
 | |
|          break;
 | |
|       /* H.245 command message is received */
 | |
|       case (T_H245MultimediaSystemControlMessage_command):
 | |
|          command = pH245->h245Msg.u.command;
 | |
|          ooHandleH245Command(call, command);
 | |
|          break;
 | |
|       /* H.245 Indication message received */
 | |
|       case (T_H245MultimediaSystemControlMessage_indication):
 | |
|          indication = pH245->h245Msg.u.indication;
 | |
|          switch(indication->t)
 | |
|          {
 | |
|             case T_H245IndicationMessage_userInput:
 | |
|                ooOnReceivedUserInputIndication(call, indication->u.userInput);
 | |
|                break;
 | |
|             default:
 | |
|                OOTRACEWARN3("Unhandled indication message received.(%s, %s)\n",
 | |
|                              call->callType, call->callToken);
 | |
|          }
 | |
|          break;
 | |
|       default:
 | |
|         ;
 | |
|    }
 | |
|    OOTRACEDBGC3("Finished handling H245 message. (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| 
 | |
| int ooOnReceivedUserInputIndication
 | |
|    (OOH323CallData *call, H245UserInputIndication *indication)
 | |
| {
 | |
|    if((indication->t == T_H245UserInputIndication_alphanumeric) && 
 | |
|       (call->dtmfmode & OO_CAP_DTMF_H245_alphanumeric))
 | |
|    {
 | |
|       if(gH323ep.h323Callbacks.onReceivedDTMF)
 | |
|          gH323ep.h323Callbacks.onReceivedDTMF(call,indication->u.alphanumeric);
 | |
|    }
 | |
|    else if((indication->t == T_H245UserInputIndication_signal) && 
 | |
|            (call->dtmfmode & OO_CAP_DTMF_H245_signal)) {
 | |
|       if(call->lastDTMF && indication->u.signal->signalType[0] == call->lastDTMF &&
 | |
|          call->nextDTMFstamp && indication->u.signal->m.rtpPresent && 
 | |
|          indication->u.signal->rtp.m.timestampPresent) {
 | |
| 	  if(call->nextDTMFstamp > indication->u.signal->rtp.timestamp) {
 | |
|             OOTRACEERR4("ERROR:Duplicate dtmf %c on ((%s, %s)\n", call->lastDTMF, call->callType, 
 | |
| 			call->callToken);
 | |
| 	    return OO_OK;
 | |
|           }
 | |
|       }
 | |
|       if (indication->u.signal->m.rtpPresent && indication->u.signal->rtp.m.timestampPresent &&
 | |
|           indication->u.signal->m.durationPresent) {
 | |
|           call->nextDTMFstamp = indication->u.signal->rtp.timestamp +
 | |
| 				indication->u.signal->duration;
 | |
| 	  call->lastDTMF = indication->u.signal->signalType[0];
 | |
|       } else {
 | |
| 	  call->nextDTMFstamp = 0;
 | |
| 	  call->lastDTMF = 0;
 | |
|       }
 | |
|       if(gH323ep.h323Callbacks.onReceivedDTMF)
 | |
|          gH323ep.h323Callbacks.onReceivedDTMF(call, 
 | |
|                                              indication->u.signal->signalType);
 | |
|    }
 | |
|    else {
 | |
|       OOTRACEINFO3("Unsupported userInput message type received - ignoring."
 | |
|                    "(%s, %s)\n", call->callType, call->callToken);
 | |
|    }
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| int ooOnReceivedTerminalCapabilitySet(OOH323CallData *call, H245Message *pmsg)
 | |
| {
 | |
|    int ret = 0,k;
 | |
|    H245TerminalCapabilitySet *tcs=NULL;
 | |
|    DListNode *pNode=NULL;
 | |
|    H245CapabilityTableEntry *capEntry = NULL;
 | |
|    ooLogicalChannel *temp = NULL;
 | |
| 
 | |
|    tcs =  pmsg->h245Msg.u.request->u.terminalCapabilitySet;
 | |
|    if(call->remoteTermCapSeqNo > tcs->sequenceNumber)
 | |
|    {
 | |
|       OOTRACEINFO4("Rejecting TermCapSet message with SeqNo %d, as already "
 | |
|                    "acknowledged message with this SeqNo (%s, %s)\n", 
 | |
|                    call->remoteTermCapSeqNo, call->callType, call->callToken);
 | |
|       ooSendTerminalCapabilitySetReject(call, tcs->sequenceNumber, 
 | |
|                          T_H245TerminalCapabilitySetReject_cause_unspecified);
 | |
|       return OO_OK;
 | |
| 
 | |
|     } else {
 | |
| /* 20090924 */
 | |
| /* bogus soft-switch can send more than one request with  cap set
 | |
|    if it goto to next choice. Right swith don't send but not all are right ;(
 | |
|    we can accept new capability set only. We must remember also that new join caps
 | |
|    will be previously joined caps with new cap set.
 | |
|  */
 | |
| 
 | |
| /* 20111103 */
 | |
| /* for addition for previous we must check repeated tcs if it's not first 
 | |
|    tcs i.e. SeqNo is not null */
 | |
| 
 | |
|    if(call->remoteTermCapSeqNo && call->remoteTermCapSeqNo == tcs->sequenceNumber)
 | |
|     call->localTermCapState = OO_LocalTermCapExchange_Idle;
 | |
|    }
 | |
| /* empty tcs - renegotiate logical channels */
 | |
|    if(!tcs->m.capabilityTablePresent)
 | |
|    {
 | |
|       OOTRACEDBGC3("Empty TCS found.  (%s, %s)\n",
 | |
|                     call->callType, call->callToken);
 | |
| 
 | |
|       call->remoteTermCapSeqNo = tcs->sequenceNumber;
 | |
|       ooH245AcknowledgeTerminalCapabilitySet(call);
 | |
| 
 | |
| /* close all transmit chans */
 | |
| 
 | |
|       temp = call->logicalChans;
 | |
|       while (temp) {
 | |
|        if (temp->state == OO_LOGICALCHAN_ESTABLISHED) {
 | |
|           /* Sending closelogicalchannel only for outgoing channels */
 | |
|          if (!strcmp(temp->dir, "transmit")) {
 | |
|             ooSendCloseLogicalChannel(call, temp);
 | |
|          }
 | |
|        }
 | |
|        temp = temp->next;
 | |
|       }
 | |
| 
 | |
|       call->TCSPending = TRUE;
 | |
|       return OO_OK;
 | |
|    }
 | |
|    call->remoteTermCapSeqNo = tcs->sequenceNumber;
 | |
| 
 | |
|    if(tcs->m.capabilityTablePresent) {
 | |
|       for(k=0; k<(int)tcs->capabilityTable.count; k++)
 | |
|       {
 | |
|          pNode = dListFindByIndex(&tcs->capabilityTable, k);
 | |
|          if(pNode)
 | |
|          {
 | |
|             OOTRACEDBGC4("Processing CapabilityTable Entry %d (%s, %s)\n", 
 | |
|                           k, call->callType, call->callToken);
 | |
|             capEntry = (H245CapabilityTableEntry*) pNode->data;
 | |
|             if(capEntry->m.capabilityPresent){
 | |
|                ret =  ooAddRemoteCapability(call, &capEntry->capability);
 | |
|                if(ret != OO_OK)
 | |
|                {
 | |
|                   OOTRACEERR4("Error:Failed to process remote capability in "
 | |
|                               "capability table at index %d. (%s, %s)\n", 
 | |
|                                k, call->callType, call->callToken);
 | |
|                }
 | |
|                ooCapabilityUpdateJointCapabilities(call, &capEntry->capability);
 | |
|             }
 | |
|          }
 | |
|          pNode = NULL;
 | |
|          capEntry=NULL;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if (call->t38sides == 3) /* both side support t.38 */
 | |
| 	OO_SETFLAG(call->flags, OO_M_T38SUPPORTED);
 | |
|    else
 | |
| 	OO_CLRFLAG(call->flags, OO_M_T38SUPPORTED);
 | |
|    
 | |
|    /* Update remoteTermCapSetState */
 | |
|    call->remoteTermCapState = OO_RemoteTermCapSetRecvd;
 | |
| 
 | |
|    ooH245AcknowledgeTerminalCapabilitySet(call);   
 | |
| 
 | |
|    /* If we haven't yet send TCS then send it now */
 | |
|    if(call->localTermCapState == OO_LocalTermCapExchange_Idle)
 | |
|    {
 | |
|       ret = ooSendTermCapMsg(call);
 | |
|       if(ret != OO_OK)
 | |
|       {
 | |
|          OOTRACEERR3("ERROR:Sending Terminal capability message (%s, %s)\n",
 | |
|                       call->callType, call->callToken);
 | |
|          return ret;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if(call->remoteTermCapState != OO_RemoteTermCapSetAckSent ||
 | |
|       call->localTermCapState  != OO_LocalTermCapSetAckRecvd)
 | |
|       return OO_OK;
 | |
| 
 | |
|    if(call->masterSlaveState == OO_MasterSlave_Idle) {
 | |
|       ret = ooSendMasterSlaveDetermination(call);
 | |
|       if(ret != OO_OK) {
 | |
|                 OOTRACEERR3("ERROR:Sending Master-slave determination message "
 | |
|                             "(%s, %s)\n", call->callType, call->callToken);
 | |
|                 return ret;
 | |
|       }
 | |
|    } 
 | |
| 
 | |
| 
 | |
|    /* Check MasterSlave procedure has finished */
 | |
|    if(call->masterSlaveState != OO_MasterSlave_Master &&
 | |
|       call->masterSlaveState != OO_MasterSlave_Slave)
 | |
|       return OO_OK;
 | |
| 
 | |
|    /* As both MasterSlave and TerminalCapabilitySet procedures have finished,
 | |
|       OpenLogicalChannels */
 | |
|  
 | |
|    if(gH323ep.h323Callbacks.openLogicalChannels)
 | |
|       gH323ep.h323Callbacks.openLogicalChannels(call);
 | |
| 
 | |
|    /* ooSendStatusInquiry(call); */
 | |
| 
 | |
|    if(!ooGetTransmitLogicalChannel(call))
 | |
|       ooOpenLogicalChannels(call);
 | |
| #if 0
 | |
|    if(!call->logicalChans){
 | |
|       if(!gH323ep.h323Callbacks.openLogicalChannels)
 | |
|          ret = ooOpenLogicalChannels(call);
 | |
|       else
 | |
|          gH323ep.h323Callbacks.openLogicalChannels(call);
 | |
|    }
 | |
| #endif
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| int ooSendTerminalCapabilitySetReject
 | |
|                         (OOH323CallData *call, int seqNo, ASN1UINT cause)
 | |
| {
 | |
|    H245Message *ph245msg=NULL;
 | |
|    H245ResponseMessage * response=NULL;
 | |
|    OOCTXT *pctxt=NULL;
 | |
|    int ret = ooCreateH245Message(call, &ph245msg, 
 | |
|                       T_H245MultimediaSystemControlMessage_response);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR1("ERROR:H245 message creation failed for - "
 | |
|                            "TerminalCapabilitySetReject\n");
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OOTerminalCapabilitySetReject;
 | |
|    response = ph245msg->h245Msg.u.response;
 | |
|    memset(response, 0, sizeof(H245ResponseMessage));
 | |
|    /* pctxt = &gH323ep.msgctxt; */
 | |
|    pctxt = call->msgctxt;
 | |
|    response->t = T_H245ResponseMessage_terminalCapabilitySetReject;
 | |
|    
 | |
|    response->u.terminalCapabilitySetReject = (H245TerminalCapabilitySetReject*)
 | |
|                    ASN1MALLOC(pctxt, sizeof(H245TerminalCapabilitySetReject));
 | |
| 
 | |
|    memset(response->u.terminalCapabilitySetReject, 0, 
 | |
|                                  sizeof(H245TerminalCapabilitySetReject));
 | |
|    response->u.terminalCapabilitySetReject->sequenceNumber = seqNo;
 | |
|    response->u.terminalCapabilitySetReject->cause.t = cause;
 | |
| 
 | |
|    OOTRACEDBGA3("Built TerminalCapabilitySetReject (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);
 | |
|  
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|      OOTRACEERR3("Error:Failed to enqueue TCSReject to outbound queue. "
 | |
|                  "(%s, %s)\n", call->callType, call->callToken);
 | |
|    }
 | |
|    else
 | |
|       call->remoteTermCapState = OO_RemoteTermCapExchange_Idle;
 | |
| 
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| int ooH245AcknowledgeTerminalCapabilitySet(OOH323CallData *call)
 | |
| {
 | |
|    H245Message *ph245msg=NULL;
 | |
|    H245ResponseMessage * response=NULL;
 | |
|    OOCTXT *pctxt=NULL;
 | |
|    int ret = ooCreateH245Message(call, &ph245msg, 
 | |
|                       T_H245MultimediaSystemControlMessage_response);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR1("ERROR:H245 message creation failed for - "
 | |
|                            "TerminalCapability Set Ack\n");
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OOTerminalCapabilitySetAck;
 | |
|    response = ph245msg->h245Msg.u.response;
 | |
|    memset(response, 0, sizeof(H245ResponseMessage));
 | |
|    /* pctxt = &gH323ep.msgctxt; */
 | |
|    pctxt = call->msgctxt;
 | |
|    response->t = T_H245ResponseMessage_terminalCapabilitySetAck;
 | |
|    
 | |
|    response->u.terminalCapabilitySetAck = (H245TerminalCapabilitySetAck*)
 | |
|                    ASN1MALLOC(pctxt, sizeof(H245TerminalCapabilitySetAck));
 | |
| 
 | |
|    memset(response->u.terminalCapabilitySetAck, 0, 
 | |
|                                  sizeof(H245TerminalCapabilitySetAck));
 | |
|    response->u.terminalCapabilitySetAck->sequenceNumber = call->remoteTermCapSeqNo;
 | |
| 
 | |
|    OOTRACEDBGA3("Built TerminalCapabilitySet Ack (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
| 
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|      OOTRACEERR3("Error:Failed to enqueue TCSAck to outbound queue. (%s, %s)\n", call->callType, call->callToken);
 | |
|    }
 | |
|    else
 | |
|       call->remoteTermCapState = OO_RemoteTermCapSetAckSent;
 | |
| 
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| int ooSendTerminalCapabilitySetRelease(OOH323CallData * call)
 | |
| {
 | |
|    int ret=0;
 | |
|    H245IndicationMessage* indication=NULL;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
 | |
|    OOCTXT *pctxt=call->msgctxt;
 | |
| 
 | |
|    ret = ooCreateH245Message
 | |
|       (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication);
 | |
| 
 | |
|    if (ret != OO_OK) {
 | |
|       OOTRACEERR3("Error:H245 message creation failed for - Terminal"
 | |
|                   "CapabilitySetRelease (%s, %s)\n",call->callType, 
 | |
|                   call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OOTerminalCapabilitySetRelease;
 | |
|    indication = ph245msg->h245Msg.u.indication;
 | |
| 
 | |
|    indication->t = T_H245IndicationMessage_terminalCapabilitySetRelease;
 | |
| 
 | |
|    indication->u.terminalCapabilitySetRelease = 
 | |
|       (H245TerminalCapabilitySetRelease*)
 | |
|       memAlloc (pctxt, sizeof(H245TerminalCapabilitySetRelease));
 | |
| 
 | |
|    if(!indication->u.terminalCapabilitySetRelease)
 | |
|    {
 | |
|       OOTRACEERR3("Error: Failed to allocate memory for TCSRelease message."
 | |
|                   " (%s, %s)\n", call->callType, call->callToken);
 | |
|       ooFreeH245Message(call, ph245msg);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    OOTRACEDBGA3 ("Built TerminalCapabilitySetRelease (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);
 | |
| 
 | |
|    ret = ooSendH245Msg (call, ph245msg);
 | |
| 
 | |
|    if (ret != OO_OK) {
 | |
|       OOTRACEERR3 
 | |
|          ("Error:Failed to enqueue TerminalCapabilitySetRelease "
 | |
|          "message to outbound queue.(%s, %s)\n", call->callType, 
 | |
|          call->callToken);
 | |
|    }
 | |
|    
 | |
|    ooFreeH245Message (call, ph245msg);
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| int ooSendH245UserInputIndication_alphanumeric
 | |
|    (OOH323CallData *call, const char *data)
 | |
| {
 | |
|    int ret=0;
 | |
|    H245IndicationMessage* indication=NULL;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
 | |
|    OOCTXT *pctxt=call->msgctxt;
 | |
| 
 | |
|    ret = ooCreateH245Message
 | |
|       (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication);
 | |
| 
 | |
|    if (ret != OO_OK) {
 | |
|       OOTRACEERR3("Error:H245 message creation failed for - H245UserInput"
 | |
|                   "Indication_alphanumeric (%s, %s)\n",call->callType, 
 | |
|                   call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OOUserInputIndication;
 | |
|    indication = ph245msg->h245Msg.u.indication;
 | |
| 
 | |
|    indication->t = T_H245IndicationMessage_userInput;
 | |
|    indication->u.userInput = 
 | |
|       (H245UserInputIndication*)
 | |
|       memAllocZ (pctxt, sizeof(H245UserInputIndication));
 | |
| 
 | |
|    if(!indication->u.userInput)
 | |
|    {
 | |
|       OOTRACEERR3("Error: Memory - ooH245UserInputIndication_alphanumeric - "
 | |
|                   " userInput (%s, %s)\n", call->callType, call->callToken);
 | |
|       ooFreeH245Message(call, ph245msg);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    indication->u.userInput->t = T_H245UserInputIndication_alphanumeric;
 | |
|    indication->u.userInput->u.alphanumeric = (ASN1GeneralString)
 | |
|                                               memAlloc(pctxt, strlen(data)+1);
 | |
|    if(!indication->u.userInput->u.alphanumeric)
 | |
|    {
 | |
|       OOTRACEERR3("Error: Memory - ooH245UserInputIndication-alphanumeric - "
 | |
|                   "alphanumeric (%s, %s).\n", call->callType, call->callToken);
 | |
|       ooFreeH245Message(call, ph245msg);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    strcpy(*(char**)&indication->u.userInput->u.alphanumeric, data);
 | |
|    OOTRACEDBGA3 ("Built UserInputIndication_alphanumeric (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);
 | |
| 
 | |
|    ret = ooSendH245Msg (call, ph245msg);
 | |
| 
 | |
|    if (ret != OO_OK) {
 | |
|       OOTRACEERR3 
 | |
|          ("Error:Failed to enqueue UserInputIndication_alphanumeric "
 | |
|           "message to outbound queue.(%s, %s)\n", call->callType, 
 | |
|           call->callToken);
 | |
|    }
 | |
|    
 | |
|    ooFreeH245Message (call, ph245msg);
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| int ooSendH245UserInputIndication_signal
 | |
|    (OOH323CallData *call, const char *data)
 | |
| {
 | |
|    int ret=0;
 | |
|    H245IndicationMessage* indication=NULL;
 | |
|    H245Message *ph245msg=NULL;
 | |
|    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
 | |
|    OOCTXT *pctxt=call->msgctxt;
 | |
| 
 | |
|    ret = ooCreateH245Message
 | |
|       (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication);
 | |
| 
 | |
|    if (ret != OO_OK) {
 | |
|       OOTRACEERR3("Error:H245 message creation failed for - H245UserInput"
 | |
|                   "Indication_signal (%s, %s)\n",call->callType, 
 | |
|                   call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ph245msg->msgType = OOUserInputIndication;
 | |
|    indication = ph245msg->h245Msg.u.indication;
 | |
| 
 | |
|    indication->t = T_H245IndicationMessage_userInput;
 | |
|    indication->u.userInput = 
 | |
|       (H245UserInputIndication*)
 | |
|       memAllocZ (pctxt, sizeof(H245UserInputIndication));
 | |
| 
 | |
|    if(!indication->u.userInput)
 | |
|    {
 | |
|       OOTRACEERR3("Error: Memory - ooH245UserInputIndication_signal - "
 | |
|                   " userInput (%s, %s)\n", call->callType, call->callToken);
 | |
|       ooFreeH245Message(call, ph245msg);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    indication->u.userInput->t = T_H245UserInputIndication_signal;
 | |
|    indication->u.userInput->u.signal = (H245UserInputIndication_signal*)
 | |
|                       memAllocZ(pctxt, sizeof(H245UserInputIndication_signal));
 | |
|    indication->u.userInput->u.signal->signalType = (ASN1IA5String)
 | |
|                                               memAlloc(pctxt, strlen(data)+1);
 | |
|    if(!indication->u.userInput->u.signal ||
 | |
|       !indication->u.userInput->u.signal->signalType)
 | |
|    {
 | |
|       OOTRACEERR3("Error: Memory - ooH245UserInputIndication_signal - "
 | |
|                   "signal (%s, %s).\n", call->callType, call->callToken);
 | |
|       ooFreeH245Message(call, ph245msg);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    strcpy(*(char**)&indication->u.userInput->u.signal->signalType, data);
 | |
|    OOTRACEDBGA3 ("Built UserInputIndication_signal (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);
 | |
| 
 | |
|    ret = ooSendH245Msg (call, ph245msg);
 | |
| 
 | |
|    if (ret != OO_OK) {
 | |
|       OOTRACEERR3 
 | |
|          ("Error:Failed to enqueue UserInputIndication_signal "
 | |
|           "message to outbound queue.(%s, %s)\n", call->callType, 
 | |
|           call->callToken);
 | |
|    }
 | |
|    
 | |
|    ooFreeH245Message (call, ph245msg);
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| int ooOpenLogicalChannels(OOH323CallData *call)
 | |
| {
 | |
|    int ret=0;
 | |
|    OOTRACEINFO3("Opening logical channels (%s, %s)\n", call->callType, 
 | |
|                  call->callToken); 
 | |
| 
 | |
|    /* Audio channels */
 | |
|    if(gH323ep.callMode == OO_CALLMODE_AUDIOCALL ||
 | |
|       gH323ep.callMode == OO_CALLMODE_AUDIOTX)
 | |
|    {
 | |
|       if (OO_TESTFLAG (call->flags, OO_M_AUDIOSESSION)) {
 | |
|          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_AUDIO);
 | |
|       } else if (OO_TESTFLAG (call->flags, OO_M_DATASESSION)) {
 | |
|          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_DATA);
 | |
|       }
 | |
|       if(ret != OO_OK) {
 | |
|        OOTRACEERR3("ERROR:Failed to open audio/data channels. Clearing call."
 | |
|                    "(%s, %s)\n", call->callType, call->callToken);
 | |
|        if (call->callState < OO_CALL_CLEAR) {
 | |
|         call->callEndReason = OO_REASON_LOCAL_CLEARED;
 | |
|         call->callState = OO_CALL_CLEAR;
 | |
|        }
 | |
|        return ret;
 | |
|       }
 | |
|    }
 | |
|    
 | |
|    if(gH323ep.callMode == OO_CALLMODE_VIDEOCALL)
 | |
|    {
 | |
|      /*      if (!OO_TESTFLAG (call->flags, OO_M_AUDIOSESSION))
 | |
|         {*/
 | |
|          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_AUDIO);
 | |
|          if(ret != OO_OK)
 | |
|          {
 | |
|             OOTRACEERR3("ERROR:Failed to open audio channel. Clearing call."
 | |
|                         "(%s, %s)\n", call->callType, call->callToken);
 | |
|             if(call->callState < OO_CALL_CLEAR)
 | |
|             {
 | |
|                call->callEndReason = OO_REASON_LOCAL_CLEARED;
 | |
|                call->callState = OO_CALL_CLEAR;
 | |
|             }
 | |
|             return ret;
 | |
|          }
 | |
|       //}
 | |
|       /*      if(!OO_TESTFLAG(call->flags, OO_M_VIDEOSESSION))
 | |
|       {*/
 | |
|          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_VIDEO);
 | |
|          if(ret != OO_OK)
 | |
|          {
 | |
|             OOTRACEERR3("ERROR:Failed to open video channel. Clearing call."
 | |
|                         "(%s, %s)\n", call->callType, call->callToken);
 | |
|             if(call->callState < OO_CALL_CLEAR)
 | |
|             {
 | |
|                call->callEndReason = OO_REASON_LOCAL_CLEARED;
 | |
|                call->callState = OO_CALL_CLEAR;
 | |
|             }
 | |
|             return ret;
 | |
|          }
 | |
|      //}
 | |
|    }
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| /* CapType indicates whether to Open Audio or Video channel */
 | |
| int ooOpenLogicalChannel(OOH323CallData *call, enum OOCapType capType )
 | |
| {
 | |
|    ooH323EpCapability *epCap=NULL;
 | |
|    int k=0;
 | |
| 
 | |
|    /* Check whether local endpoint has audio capability */
 | |
|    if(gH323ep.myCaps == 0 && call->ourCaps == 0)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Local endpoint does not have any audio capabilities"
 | |
|                   " (%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    
 | |
|    /* Go through local endpoints capabilities sequentially, and find out the
 | |
|       first one which has a match in the remote endpoints receive capabilities.
 | |
|    */
 | |
|    OOTRACEINFO3("Looking for matching capabilities. (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);
 | |
| /* May */
 | |
|    if(call->masterSlaveState == OO_MasterSlave_Master)
 | |
|    {
 | |
|       for(k=0; k<call->capPrefs.index; k++)
 | |
|       {
 | |
|          /*Search for audio caps only */
 | |
|          if(capType == OO_CAP_TYPE_AUDIO && 
 | |
|             call->capPrefs.order[k] > OO_CAP_VIDEO_BASE)
 | |
|             continue;
 | |
|          /* Search for video caps only */
 | |
|          if(capType == OO_CAP_TYPE_VIDEO && 
 | |
|             call->capPrefs.order[k] <= OO_CAP_VIDEO_BASE)
 | |
|             continue;
 | |
| 
 | |
|          epCap = call->jointCaps;
 | |
| 
 | |
|          while(epCap){
 | |
|             if(epCap->cap == call->capPrefs.order[k] && (epCap->dir & OOTX))
 | |
|                break;
 | |
|             epCap = epCap->next;
 | |
|          }
 | |
|          if(!epCap)
 | |
|          {
 | |
|             OOTRACEDBGA4("Prefereed capability %d is not a local transmit "
 | |
|                          "capability(%s, %s)\n", call->capPrefs.order[k],
 | |
|                          call->callType, call->callToken);
 | |
|             continue;
 | |
|          }
 | |
|          break;
 | |
|       }
 | |
|       if(!epCap)
 | |
|       {
 | |
|          OOTRACEERR4("ERROR:Incompatible capabilities - Can not open "
 | |
|                   "%s channel (%s, %s)\n", 
 | |
|                   (capType==OO_CAP_TYPE_AUDIO)?"audio":"video", call->callType,
 | |
|                   call->callToken);
 | |
|          return OO_FAILED;
 | |
|       }
 | |
| 
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       epCap = call->jointCaps;
 | |
| 
 | |
|       while(epCap){
 | |
|          if(epCap->capType == capType && epCap->dir & OOTX) { break; }
 | |
|          epCap = epCap->next;
 | |
|       }
 | |
|       if(!epCap)
 | |
|       {
 | |
|          OOTRACEERR4("ERROR:Incompatible audio capabilities - Can not open "
 | |
|                   "%s channel (%s, %s)\n", 
 | |
|                   (capType==OO_CAP_TYPE_AUDIO)?"audio":"video", call->callType,
 | |
|                   call->callToken);
 | |
|          return OO_FAILED;
 | |
|       }
 | |
|        
 | |
|    }
 | |
| 
 | |
|    switch(epCap->cap)
 | |
|    {
 | |
|    case OO_G711ALAW64K:
 | |
|    case OO_G711ALAW56K:
 | |
|    case OO_G711ULAW64K:
 | |
|    case OO_G711ULAW56K:
 | |
|    case OO_G726:
 | |
|    case OO_G726AAL2:
 | |
|    case OO_AMRNB:
 | |
|    case OO_SPEEX:
 | |
|    case OO_G728:
 | |
|    case OO_G729:
 | |
|    case OO_G729A:
 | |
|    case OO_G729B:
 | |
|    case OO_G7231:
 | |
|    case OO_GSMFULLRATE:
 | |
|    case OO_GSMHALFRATE:
 | |
|    case OO_GSMENHANCEDFULLRATE:
 | |
|    case OO_H263VIDEO:
 | |
|    case OO_T38:
 | |
|       ooOpenChannel(call, epCap);
 | |
|       break;
 | |
| 
 | |
|       
 | |
|    default:
 | |
|       OOTRACEERR3("ERROR:Unknown Audio Capability type (%s, %s)\n", 
 | |
|                    call->callType, call->callToken);
 | |
|    }
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| int ooOpenChannel(OOH323CallData* call, ooH323EpCapability *epCap)
 | |
| {
 | |
|    int ret;
 | |
|    H245Message *ph245msg = NULL;
 | |
|    H245RequestMessage * request;
 | |
|    OOCTXT *pctxt = NULL;
 | |
|    H245OpenLogicalChannel_forwardLogicalChannelParameters *flcp = NULL;
 | |
|    H245AudioCapability *audioCap = NULL;
 | |
|    H245VideoCapability *videoCap = NULL;
 | |
|    H245DataApplicationCapability *t38Cap = NULL;
 | |
|    H245H2250LogicalChannelParameters *h2250lcp = NULL;
 | |
|    H245UnicastAddress *unicastAddrs = NULL;
 | |
|    H245UnicastAddress_iPAddress *iPAddress = NULL;
 | |
|    H245UnicastAddress_iP6Address *iP6Address = NULL;
 | |
|    unsigned session_id=0;
 | |
|    ooLogicalChannel *pLogicalChannel = NULL;
 | |
|    
 | |
|    OOTRACEDBGC4("Doing Open Channel for %s. (%s, %s)\n", 
 | |
|                  ooGetCapTypeText(epCap->cap), call->callType, 
 | |
|                  call->callToken);
 | |
| 
 | |
|    ret = ooCreateH245Message(call, &ph245msg, 
 | |
|                       T_H245MultimediaSystemControlMessage_request);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR4("Error: H245 message creation failed for - Open %s"
 | |
|                   "channel (%s, %s)\n", ooGetCapTypeText(epCap->cap), 
 | |
|                   call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
| 
 | |
|    ph245msg->msgType = OOOpenLogicalChannel;
 | |
| 
 | |
|    ph245msg->logicalChannelNo =  call->logicalChanNoCur++;
 | |
|    if(call->logicalChanNoCur > call->logicalChanNoMax)
 | |
|       call->logicalChanNoCur = call->logicalChanNoBase; 
 | |
| 
 | |
|    request = ph245msg->h245Msg.u.request;
 | |
|    /* pctxt = &gH323ep.msgctxt; */
 | |
|    pctxt = call->msgctxt;
 | |
|    memset(request, 0, sizeof(H245RequestMessage));
 | |
| 
 | |
|    request->t = T_H245RequestMessage_openLogicalChannel;
 | |
|    request->u.openLogicalChannel = (H245OpenLogicalChannel*)
 | |
|                      memAlloc(pctxt, sizeof(H245OpenLogicalChannel));
 | |
|    if(!request->u.openLogicalChannel)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Memory - ooOpenChannel - openLogicalChannel."
 | |
|                   "(%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
| 
 | |
|    }
 | |
|    memset(request->u.openLogicalChannel, 0, 
 | |
|                                      sizeof(H245OpenLogicalChannel));
 | |
|    request->u.openLogicalChannel->forwardLogicalChannelNumber = 
 | |
|                                                  ph245msg->logicalChannelNo;
 | |
| 
 | |
|    
 | |
|    session_id = ooCallGenerateSessionID(call, epCap->capType, "transmit");
 | |
| 
 | |
| 
 | |
|    pLogicalChannel = ooAddNewLogicalChannel(call, 
 | |
|                    request->u.openLogicalChannel->forwardLogicalChannelNumber,
 | |
|                    session_id, "transmit", epCap);
 | |
|    
 | |
|    if(!pLogicalChannel)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Failed to add new logical channel entry (%s, %s)\n",
 | |
|                   call->callType, call->callToken);
 | |
|       ooFreeH245Message(call, ph245msg);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    /* Populate H245OpenLogicalChannel_ForwardLogicalChannel Parameters*/
 | |
|    flcp = &(request->u.openLogicalChannel->forwardLogicalChannelParameters);
 | |
|    flcp->m.portNumberPresent = 0;
 | |
|    flcp->m.forwardLogicalChannelDependencyPresent = 0;
 | |
|    flcp->m.replacementForPresent = 0;
 | |
| 
 | |
|    /* data type of channel */
 | |
|    if(epCap->capType == OO_CAP_TYPE_AUDIO)
 | |
|    {
 | |
|       flcp->dataType.t = T_H245DataType_audioData;
 | |
|       /* set audio capability for channel */
 | |
|       audioCap = ooCapabilityCreateAudioCapability(epCap,pctxt, OOTX);
 | |
|       if(!audioCap)
 | |
|       {
 | |
|          OOTRACEERR4("Error:Failed to create duplicate audio capability in "
 | |
|                      "ooOpenChannel- %s (%s, %s)\n", 
 | |
|                      ooGetCapTypeText(epCap->cap), call->callType, 
 | |
|                      call->callToken);
 | |
|          ooFreeH245Message(call, ph245msg);
 | |
|          return OO_FAILED;
 | |
|       }
 | |
|    
 | |
|       flcp->dataType.u.audioData = audioCap;
 | |
|    }
 | |
|    else if(epCap->capType == OO_CAP_TYPE_VIDEO)
 | |
|    {
 | |
|       flcp->dataType.t = T_H245DataType_videoData;      
 | |
|       videoCap = ooCapabilityCreateVideoCapability(epCap, pctxt, OOTX);
 | |
|       if(!videoCap)
 | |
|       {
 | |
|          OOTRACEERR4("Error:Failed to create duplicate video capability in "
 | |
|                      "ooOpenChannel- %s (%s, %s)\n", 
 | |
|                      ooGetCapTypeText(epCap->cap), call->callType, 
 | |
|                      call->callToken);
 | |
|          ooFreeH245Message(call, ph245msg);
 | |
|          return OO_FAILED;
 | |
|       }
 | |
|    
 | |
|       flcp->dataType.u.videoData = videoCap;
 | |
|    }
 | |
|    else if(epCap->capType == OO_CAP_TYPE_DATA)
 | |
|    {
 | |
|       flcp->dataType.t = T_H245DataType_data;
 | |
|       /* set audio capability for channel */
 | |
|       t38Cap = ooCapabilityCreateT38Capability(epCap,pctxt, OOTX);
 | |
|       if(!t38Cap)
 | |
|       {
 | |
|          OOTRACEERR4("Error:Failed to create duplicate T38 capability in "
 | |
|                      "ooOpenChannel- %s (%s, %s)\n", 
 | |
|                      ooGetCapTypeText(epCap->cap), call->callType, 
 | |
|                      call->callToken);
 | |
|          ooFreeH245Message(call, ph245msg);
 | |
|          return OO_FAILED;
 | |
|       }
 | |
|    
 | |
|       flcp->dataType.u.data = t38Cap;
 | |
|    }
 | |
|    else{
 | |
|       OOTRACEERR1("Error: Unhandled media type in ooOpenChannel\n");
 | |
|       return OO_FAILED;
 | |
|    }
 | |
| 
 | |
|   
 | |
|    flcp->multiplexParameters.t = 
 | |
|       T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters;
 | |
|    flcp->multiplexParameters.u.h2250LogicalChannelParameters = 
 | |
|                          (H245H2250LogicalChannelParameters*)ASN1MALLOC(pctxt, 
 | |
|                           sizeof(H245H2250LogicalChannelParameters));
 | |
| 
 | |
|    h2250lcp = flcp->multiplexParameters.u.h2250LogicalChannelParameters;
 | |
|    memset(h2250lcp, 0, sizeof(H245H2250LogicalChannelParameters));
 | |
| 
 | |
|    h2250lcp->sessionID = session_id;
 | |
| 
 | |
|    h2250lcp->mediaGuaranteedDelivery = 0;
 | |
|    h2250lcp->silenceSuppression = 0;
 | |
|    h2250lcp->m.mediaControlChannelPresent = 1;
 | |
|    
 | |
|    h2250lcp->mediaControlChannel.t = 
 | |
|                                  T_H245TransportAddress_unicastAddress;
 | |
|    h2250lcp->mediaControlChannel.u.unicastAddress =  (H245UnicastAddress*)
 | |
|                          ASN1MALLOC(pctxt, sizeof(H245UnicastAddress));
 | |
| 
 | |
|    unicastAddrs = h2250lcp->mediaControlChannel.u.unicastAddress;
 | |
|    memset(unicastAddrs, 0, sizeof(H245UnicastAddress));
 | |
|    if (call->versionIP == 6) {
 | |
|    	unicastAddrs->t = T_H245UnicastAddress_iP6Address;
 | |
|    	unicastAddrs->u.iP6Address = (H245UnicastAddress_iP6Address*)
 | |
|                ASN1MALLOC(pctxt, sizeof(H245UnicastAddress_iP6Address));
 | |
|    	iP6Address = unicastAddrs->u.iP6Address;
 | |
|    	memset(iP6Address, 0, sizeof(H245UnicastAddress_iP6Address));
 | |
| 
 | |
| 	inet_pton(AF_INET6, pLogicalChannel->localIP, iP6Address->network.data);
 | |
|    	iP6Address->network.numocts = 16;
 | |
|    	iP6Address->tsapIdentifier = pLogicalChannel->localRtcpPort;
 | |
|    } else {
 | |
|    	unicastAddrs->t = T_H245UnicastAddress_iPAddress;
 | |
|    	unicastAddrs->u.iPAddress = (H245UnicastAddress_iPAddress*)
 | |
|                ASN1MALLOC(pctxt, sizeof(H245UnicastAddress_iPAddress));
 | |
|    	iPAddress = unicastAddrs->u.iPAddress;
 | |
|    	memset(iPAddress, 0, sizeof(H245UnicastAddress_iPAddress));
 | |
| 
 | |
| 	inet_pton(AF_INET, pLogicalChannel->localIP, iPAddress->network.data);
 | |
|    	iPAddress->network.numocts = 4;
 | |
|    	iPAddress->tsapIdentifier = pLogicalChannel->localRtcpPort;
 | |
|    }
 | |
|    pLogicalChannel->state = OO_LOGICALCHAN_PROPOSED; 
 | |
|    OOTRACEDBGA4("Built OpenLogicalChannel-%s (%s, %s)\n", 
 | |
|                  ooGetCapTypeText(epCap->cap), call->callType, 
 | |
|                  call->callToken);
 | |
|    ret = ooSendH245Msg(call, ph245msg);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR3("Error:Failed to enqueue OpenLogicalChannel to outbound "
 | |
|                  "queue. (%s, %s)\n", call->callType,
 | |
|                  call->callToken);
 | |
|    }
 | |
|    ooFreeH245Message(call, ph245msg);
 | |
|   
 | |
|    return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Used to build  OLCs for fast connect. Keep in mind that forward and 
 | |
|    reverse 
 | |
|    are always with respect to the endpoint which proposes channels 
 | |
|    TODO: Need to clean logical channel in case of failure.    */
 | |
| int ooBuildFastStartOLC
 | |
|    (OOH323CallData *call, H245OpenLogicalChannel *olc, 
 | |
|     ooH323EpCapability *epCap, OOCTXT*pctxt, int dir)
 | |
| {
 | |
|    OOBOOL reverse=FALSE, forward=FALSE;
 | |
|    unsigned sessionID=0;
 | |
|    H245OpenLogicalChannel_forwardLogicalChannelParameters *flcp=NULL;
 | |
|    H245OpenLogicalChannel_reverseLogicalChannelParameters *rlcp=NULL;
 | |
|    H245H2250LogicalChannelParameters *pH2250lcp1=NULL, *pH2250lcp2=NULL;
 | |
|    H245UnicastAddress *pUnicastAddrs=NULL, *pUniAddrs=NULL;
 | |
|    H245UnicastAddress_iPAddress *pIpAddrs=NULL, *pUniIpAddrs=NULL;
 | |
|    H245UnicastAddress_iP6Address *pIp6Addrs=NULL, *pUniIp6Addrs=NULL;
 | |
|    unsigned session_id = 0;
 | |
|    ooLogicalChannel *pLogicalChannel = NULL;
 | |
|    int outgoing=FALSE;
 | |
| 
 | |
|    if(!strcmp(call->callType, "outgoing"))   
 | |
|       outgoing = TRUE;
 | |
|    
 | |
|    if(dir & OORX)
 | |
|    {
 | |
|       OOTRACEDBGA3("Building OpenLogicalChannel for Receive  Capability "
 | |
|                    "(%s, %s)\n", call->callType, call->callToken);
 | |
|       session_id = ooCallGenerateSessionID(call, epCap->capType, "receive");
 | |
|       pLogicalChannel = ooAddNewLogicalChannel(call, 
 | |
|                                  olc->forwardLogicalChannelNumber, session_id, 
 | |
|                                  "receive", epCap);
 | |
|       if(outgoing)
 | |
|          reverse = TRUE;
 | |
|       else
 | |
|          forward = TRUE;
 | |
|    }
 | |
|    else if(dir & OOTX)
 | |
|    {
 | |
|       OOTRACEDBGA3("Building OpenLogicalChannel for transmit Capability "
 | |
|                    "(%s, %s)\n", call->callType, call->callToken);
 | |
|       session_id = ooCallGenerateSessionID(call, epCap->capType, "transmit");
 | |
|       pLogicalChannel = ooAddNewLogicalChannel(call, 
 | |
|                                   olc->forwardLogicalChannelNumber, session_id,
 | |
|                                   "transmit", epCap);
 | |
|       if(outgoing)
 | |
|          forward = TRUE;
 | |
|       else
 | |
|          reverse = TRUE;
 | |
|    }
 | |
|    else if(dir & OORXTX)
 | |
|    {
 | |
|       OOTRACEDBGA3("Building OpenLogicalChannel for ReceiveAndTransmit  "
 | |
|                    "Capability (%s, %s)\n", call->callType, call->callToken);
 | |
|       reverse = 1;
 | |
|       forward = 1;
 | |
|       OOTRACEERR3("Symmetric capability is not supported as of now (%s, %s)\n",
 | |
|                    call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
| 
 | |
|    if(forward)
 | |
|    {
 | |
|       OOTRACEDBGC3("Building forward olc. (%s, %s)\n", call->callType, 
 | |
|                     call->callToken);
 | |
|       flcp = &(olc->forwardLogicalChannelParameters);
 | |
|       memset(flcp, 0, 
 | |
|              sizeof(H245OpenLogicalChannel_forwardLogicalChannelParameters));
 | |
| 
 | |
|       if(epCap->capType == OO_CAP_TYPE_AUDIO) {
 | |
|          sessionID =1;
 | |
|          flcp->dataType.t = T_H245DataType_audioData;
 | |
|          flcp->dataType.u.audioData = ooCapabilityCreateAudioCapability(epCap, 
 | |
|                                                                    pctxt, dir);
 | |
|       }
 | |
|       else if(epCap->capType == OO_CAP_TYPE_VIDEO) {
 | |
|          sessionID = 2;
 | |
|          flcp->dataType.t = T_H245DataType_videoData;
 | |
|          flcp->dataType.u.videoData = ooCapabilityCreateVideoCapability(epCap,
 | |
|                                                                    pctxt, dir);
 | |
|       }
 | |
|       flcp->multiplexParameters.t = T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters;
 | |
|       pH2250lcp1 = (H245H2250LogicalChannelParameters*)ASN1MALLOC(pctxt, 
 | |
|                                     sizeof(H245H2250LogicalChannelParameters));
 | |
|       memset(pH2250lcp1, 0, sizeof(H245H2250LogicalChannelParameters));
 | |
|       flcp->multiplexParameters.t = T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters;
 | |
|       
 | |
|       flcp->multiplexParameters.u.h2250LogicalChannelParameters = pH2250lcp1;
 | |
|           
 | |
|       pH2250lcp1->sessionID = sessionID;
 | |
|       if(!outgoing)
 | |
|       {
 | |
|          pH2250lcp1->m.mediaChannelPresent = 1;
 | |
|          pH2250lcp1->mediaChannel.t = 
 | |
|                                     T_H245TransportAddress_unicastAddress;
 | |
|          pUniAddrs = (H245UnicastAddress*) ASN1MALLOC(pctxt, 
 | |
|                                                    sizeof(H245UnicastAddress));
 | |
|          memset(pUniAddrs, 0, sizeof(H245UnicastAddress));
 | |
|          pH2250lcp1->mediaChannel.u.unicastAddress =  pUniAddrs;
 | |
| 	 if (call->versionIP == 6) {
 | |
|          	pUniAddrs->t = T_H245UnicastAddress_iP6Address;
 | |
|          	pUniIp6Addrs = (H245UnicastAddress_iP6Address*) ASN1MALLOC(pctxt, 
 | |
|                                          sizeof(H245UnicastAddress_iP6Address));
 | |
|          	memset(pUniIp6Addrs, 0, sizeof(H245UnicastAddress_iP6Address));
 | |
|          	pUniAddrs->u.iP6Address = pUniIp6Addrs;
 | |
|      
 | |
| 		inet_pton(AF_INET6, pLogicalChannel->localIP, pUniIp6Addrs->network.data);
 | |
| 
 | |
|          	pUniIp6Addrs->network.numocts = 16;
 | |
|          	pUniIp6Addrs->tsapIdentifier = pLogicalChannel->localRtpPort;
 | |
| 	 } else {
 | |
|          	pUniAddrs->t = T_H245UnicastAddress_iPAddress;
 | |
|          	pUniIpAddrs = (H245UnicastAddress_iPAddress*) ASN1MALLOC(pctxt, 
 | |
|                                          sizeof(H245UnicastAddress_iPAddress));
 | |
|          	memset(pUniIpAddrs, 0, sizeof(H245UnicastAddress_iPAddress));
 | |
|          	pUniAddrs->u.iPAddress = pUniIpAddrs;
 | |
|      
 | |
| 		inet_pton(AF_INET, pLogicalChannel->localIP, pUniIpAddrs->network.data);
 | |
| 
 | |
|          	pUniIpAddrs->network.numocts = 4;
 | |
|          	pUniIpAddrs->tsapIdentifier = pLogicalChannel->localRtpPort;
 | |
| 	 }
 | |
|       }
 | |
|       pH2250lcp1->m.mediaControlChannelPresent = 1;
 | |
|       pH2250lcp1->mediaControlChannel.t = 
 | |
|                                  T_H245TransportAddress_unicastAddress;
 | |
|       pUnicastAddrs = (H245UnicastAddress*) ASN1MALLOC(pctxt, 
 | |
|                                                    sizeof(H245UnicastAddress));
 | |
|       memset(pUnicastAddrs, 0, sizeof(H245UnicastAddress));
 | |
|       pH2250lcp1->mediaControlChannel.u.unicastAddress =  pUnicastAddrs;
 | |
|       if (call->versionIP == 6) {
 | |
|          	pUnicastAddrs->t = T_H245UnicastAddress_iP6Address;
 | |
|          	pIp6Addrs = (H245UnicastAddress_iP6Address*) ASN1MALLOC(pctxt, 
 | |
|                                          sizeof(H245UnicastAddress_iP6Address));
 | |
|          	memset(pIp6Addrs, 0, sizeof(H245UnicastAddress_iP6Address));
 | |
|          	pUnicastAddrs->u.iP6Address = pIp6Addrs;
 | |
|      
 | |
| 		inet_pton(AF_INET6, pLogicalChannel->localIP, pIp6Addrs->network.data);
 | |
| 
 | |
|          	pIp6Addrs->network.numocts = 16;
 | |
|          	pIp6Addrs->tsapIdentifier = pLogicalChannel->localRtcpPort;
 | |
| 	 } else {
 | |
|          	pUnicastAddrs->t = T_H245UnicastAddress_iPAddress;
 | |
|          	pIpAddrs = (H245UnicastAddress_iPAddress*) ASN1MALLOC(pctxt, 
 | |
|                                          sizeof(H245UnicastAddress_iPAddress));
 | |
|          	memset(pIpAddrs, 0, sizeof(H245UnicastAddress_iPAddress));
 | |
|          	pUnicastAddrs->u.iPAddress = pIpAddrs;
 | |
|      
 | |
| 		inet_pton(AF_INET, pLogicalChannel->localIP, pIpAddrs->network.data);
 | |
| 
 | |
|          	pIpAddrs->network.numocts = 4;
 | |
|          	pIpAddrs->tsapIdentifier = pLogicalChannel->localRtcpPort;
 | |
| 	}
 | |
| 
 | |
|       if(!outgoing)
 | |
|       {
 | |
|          if(epCap->startReceiveChannel)
 | |
|          {   
 | |
|             epCap->startReceiveChannel(call, pLogicalChannel);      
 | |
|             OOTRACEINFO4("Receive channel of type %s started (%s, %s)\n", 
 | |
|                         (epCap->capType == OO_CAP_TYPE_AUDIO)?"audio":"video",
 | |
|                         call->callType, call->callToken);
 | |
|          }
 | |
|          else{
 | |
|             OOTRACEERR4("ERROR:No callback registered to start receive %s"
 | |
|                        " channel (%s, %s)\n", 
 | |
|                         (epCap->capType == OO_CAP_TYPE_AUDIO)?"audio":"video", 
 | |
|                         call->callType, call->callToken);
 | |
|             return OO_FAILED;
 | |
|          }
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if(reverse)
 | |
|    {
 | |
|       OOTRACEDBGC3("Building reverse olc. (%s, %s)\n", call->callType, 
 | |
|                     call->callToken);
 | |
|       olc->forwardLogicalChannelParameters.dataType.t = 
 | |
|                                                       T_H245DataType_nullData;
 | |
|       olc->forwardLogicalChannelParameters.multiplexParameters.t = 
 | |
|          T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_none;
 | |
|       olc->m.reverseLogicalChannelParametersPresent = 1;
 | |
|       rlcp = &(olc->reverseLogicalChannelParameters);
 | |
|       memset(rlcp, 0, sizeof(H245OpenLogicalChannel_reverseLogicalChannelParameters));
 | |
|       if(epCap->capType == OO_CAP_TYPE_AUDIO) {
 | |
|          sessionID = 1;
 | |
|          rlcp->dataType.t = T_H245DataType_audioData;
 | |
|   
 | |
|          rlcp->dataType.u.audioData = ooCapabilityCreateAudioCapability(epCap, 
 | |
|                                                                    pctxt, dir);
 | |
|       }
 | |
|       else if(epCap->capType == OO_CAP_TYPE_VIDEO)  {
 | |
|          sessionID = 2;
 | |
|          rlcp->dataType.t = T_H245DataType_videoData;
 | |
|   
 | |
|          rlcp->dataType.u.videoData = ooCapabilityCreateVideoCapability(epCap, 
 | |
|                                                                    pctxt, dir);
 | |
|       }
 | |
| 
 | |
|       rlcp->m.multiplexParametersPresent = 1;
 | |
|       rlcp->multiplexParameters.t = T_H245OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters;
 | |
|       pH2250lcp2 = (H245H2250LogicalChannelParameters*) ASN1MALLOC(pctxt, sizeof(H245H2250LogicalChannelParameters));
 | |
|       rlcp->multiplexParameters.u.h2250LogicalChannelParameters = pH2250lcp2;
 | |
|       memset(pH2250lcp2, 0, sizeof(H245H2250LogicalChannelParameters));
 | |
|       pH2250lcp2->sessionID = sessionID;
 | |
| 
 | |
|       if(outgoing)
 | |
|       {
 | |
|          pH2250lcp2->m.mediaChannelPresent = 1;
 | |
| 
 | |
|          pH2250lcp2->mediaChannel.t = 
 | |
|                                     T_H245TransportAddress_unicastAddress;
 | |
|          pUnicastAddrs = (H245UnicastAddress*) memAlloc(pctxt, 
 | |
|                                                   sizeof(H245UnicastAddress));
 | |
|          memset(pUnicastAddrs, 0, sizeof(H245UnicastAddress));
 | |
|          pH2250lcp2->mediaChannel.u.unicastAddress =  pUnicastAddrs;
 | |
| 
 | |
| 	 /* May 20101022 */
 | |
|       
 | |
|       	 if (call->versionIP == 6) {
 | |
|          	pUnicastAddrs->t = T_H245UnicastAddress_iP6Address;
 | |
|          	pIp6Addrs = (H245UnicastAddress_iP6Address*) ASN1MALLOC(pctxt, 
 | |
|                                          sizeof(H245UnicastAddress_iP6Address));
 | |
|          	memset(pIp6Addrs, 0, sizeof(H245UnicastAddress_iP6Address));
 | |
|          	pUnicastAddrs->u.iP6Address = pIp6Addrs;
 | |
|      
 | |
| 		inet_pton(AF_INET6, pLogicalChannel->localIP, pIp6Addrs->network.data);
 | |
| 
 | |
|          	pIp6Addrs->network.numocts = 16;
 | |
|          	pIp6Addrs->tsapIdentifier = pLogicalChannel->localRtpPort;
 | |
| 	 } else {
 | |
|          	pUnicastAddrs->t = T_H245UnicastAddress_iPAddress;
 | |
|          	pIpAddrs = (H245UnicastAddress_iPAddress*) ASN1MALLOC(pctxt, 
 | |
|                                          sizeof(H245UnicastAddress_iPAddress));
 | |
|          	memset(pIpAddrs, 0, sizeof(H245UnicastAddress_iPAddress));
 | |
|          	pUnicastAddrs->u.iPAddress = pIpAddrs;
 | |
|      
 | |
| 		inet_pton(AF_INET, pLogicalChannel->localIP, pIpAddrs->network.data);
 | |
| 
 | |
|          	pIpAddrs->network.numocts = 4;
 | |
|          	pIpAddrs->tsapIdentifier = pLogicalChannel->localRtpPort;
 | |
| 	}
 | |
| 
 | |
|       }
 | |
|       pH2250lcp2->m.mediaControlChannelPresent = 1;
 | |
|       pH2250lcp2->mediaControlChannel.t = 
 | |
|                                  T_H245TransportAddress_unicastAddress;
 | |
|       pUniAddrs = (H245UnicastAddress*) ASN1MALLOC(pctxt, sizeof(H245UnicastAddress));
 | |
|       
 | |
|       memset(pUniAddrs, 0, sizeof(H245UnicastAddress));
 | |
|       pH2250lcp2->mediaControlChannel.u.unicastAddress =  pUniAddrs;
 | |
| 
 | |
|       /* May 20101023 */
 | |
|       
 | |
| 	 if (call->versionIP == 6) {
 | |
|          	pUniAddrs->t = T_H245UnicastAddress_iP6Address;
 | |
|          	pUniIp6Addrs = (H245UnicastAddress_iP6Address*) ASN1MALLOC(pctxt, 
 | |
|                                          sizeof(H245UnicastAddress_iP6Address));
 | |
|          	memset(pUniIp6Addrs, 0, sizeof(H245UnicastAddress_iP6Address));
 | |
|          	pUniAddrs->u.iP6Address = pUniIp6Addrs;
 | |
|      
 | |
| 		inet_pton(AF_INET6, pLogicalChannel->localIP, pUniIp6Addrs->network.data);
 | |
| 
 | |
|          	pUniIp6Addrs->network.numocts = 16;
 | |
|          	pUniIp6Addrs->tsapIdentifier = pLogicalChannel->localRtcpPort;
 | |
| 	 } else {
 | |
|          	pUniAddrs->t = T_H245UnicastAddress_iPAddress;
 | |
|          	pUniIpAddrs = (H245UnicastAddress_iPAddress*) ASN1MALLOC(pctxt, 
 | |
|                                          sizeof(H245UnicastAddress_iPAddress));
 | |
|          	memset(pUniIpAddrs, 0, sizeof(H245UnicastAddress_iPAddress));
 | |
|          	pUniAddrs->u.iPAddress = pUniIpAddrs;
 | |
|      
 | |
| 		inet_pton(AF_INET, pLogicalChannel->localIP, pUniIpAddrs->network.data);
 | |
| 
 | |
|          	pUniIpAddrs->network.numocts = 4;
 | |
|          	pUniIpAddrs->tsapIdentifier = pLogicalChannel->localRtcpPort;
 | |
| 	 }
 | |
| 
 | |
|       /*
 | |
|          In case of fast start, the local endpoint need to be ready to
 | |
|          receive all the media types proposed in the fast connect, before
 | |
|          the actual call is established.
 | |
|       */
 | |
|       if(outgoing)
 | |
|       {
 | |
|          if(epCap->startReceiveChannel)
 | |
|          {
 | |
|             epCap->startReceiveChannel(call, pLogicalChannel);      
 | |
|             OOTRACEINFO4("Receive channel of type %s started (%s, %s)\n",
 | |
|                          (epCap->capType == OO_CAP_TYPE_AUDIO)?"audio":"video",
 | |
|                           call->callType, call->callToken);
 | |
|          }
 | |
|          else{
 | |
|             OOTRACEERR4("ERROR:No callback registered to start receive %s "
 | |
|                         "channel (%s, %s)\n", 
 | |
|                         (epCap->capType == OO_CAP_TYPE_AUDIO)?"audio":"video", 
 | |
|                         call->callType, call->callToken);
 | |
|             return OO_FAILED;
 | |
|          }
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    /* State of logical channel. for out going calls, as we are sending setup, 
 | |
|       state of all channels are proposed, for incoming calls, state is 
 | |
|       established. */
 | |
|    if(!outgoing) {
 | |
|       pLogicalChannel->state = OO_LOGICALCHAN_ESTABLISHED;
 | |
|    }
 | |
|    else {
 | |
|       /* Calling other ep, with SETUP message */
 | |
|       /* Call is "outgoing */
 | |
|       pLogicalChannel->state = OO_LOGICALCHAN_PROPOSEDFS;
 | |
|    }
 | |
|    
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| int ooMSDTimerExpired(void *data)
 | |
| {
 | |
|    ooTimerCallback *cbData = (ooTimerCallback*)data;
 | |
|    OOH323CallData *call = cbData->call;
 | |
|    OOTRACEINFO3("MasterSlaveDetermination timeout. (%s, %s)\n", call->callType,
 | |
|                  call->callToken);
 | |
|    ASN1MEMFREEPTR(call->pctxt, cbData);
 | |
|    ooSendMasterSlaveDeterminationRelease(call);
 | |
|    if(call->callState < OO_CALL_CLEAR)
 | |
|    {
 | |
|       call->callState = OO_CALL_CLEAR;
 | |
|       call->callEndReason = OO_REASON_LOCAL_CLEARED;
 | |
|    }
 | |
| 
 | |
|    return OO_OK;
 | |
| }
 | |
|    
 | |
| int ooTCSTimerExpired(void *data)
 | |
| {
 | |
|    ooTimerCallback *cbData = (ooTimerCallback*)data;
 | |
|    OOH323CallData *call = cbData->call;
 | |
|    OOTRACEINFO3("TerminalCapabilityExchange timeout. (%s, %s)\n", 
 | |
|                  call->callType, call->callToken);
 | |
|    ASN1MEMFREEPTR(call->pctxt, cbData);
 | |
|    ooSendTerminalCapabilitySetRelease(call);
 | |
|    if(call->callState < OO_CALL_CLEAR)
 | |
|    {
 | |
|       call->callState = OO_CALL_CLEAR;
 | |
|       call->callEndReason = OO_REASON_LOCAL_CLEARED;
 | |
|    }
 | |
| 
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| int ooRTDTimerExpired(void *data)
 | |
| {
 | |
|    ooTimerCallback *cbData = (ooTimerCallback*)data;
 | |
|    OOH323CallData *call = cbData->call;
 | |
|    OOTRACEINFO3("Time to send new RTD request. (%s, %s)\n",
 | |
|                  call->callType, call->callToken);
 | |
|    ASN1MEMFREEPTR(call->pctxt, cbData);
 | |
|    ooSendRoundTripDelayRequest(call);
 | |
|    return OO_OK;
 | |
| 
 | |
| }
 | |
| 
 | |
| int ooOpenLogicalChannelTimerExpired(void *pdata)
 | |
| {
 | |
|    ooTimerCallback *cbData = (ooTimerCallback*)pdata;
 | |
|    OOH323CallData *call = cbData->call;
 | |
|    ooLogicalChannel *pChannel = NULL;
 | |
|    OOTRACEINFO3("OpenLogicalChannelTimer expired. (%s, %s)\n", call->callType,
 | |
|                  call->callToken);
 | |
|    pChannel = ooFindLogicalChannelByLogicalChannelNo(call, 
 | |
|                                                cbData->channelNumber);
 | |
|    if(pChannel)
 | |
|       ooSendCloseLogicalChannel(call, pChannel);
 | |
|    
 | |
|    if(call->callState < OO_CALL_CLEAR)
 | |
|    {
 | |
|       call->callState = OO_CALL_CLEAR;
 | |
|       call->callEndReason = OO_REASON_LOCAL_CLEARED;
 | |
|    }
 | |
|    ASN1MEMFREEPTR(call->pctxt, cbData);
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| int ooCloseLogicalChannelTimerExpired(void *pdata)
 | |
| {
 | |
|    ooTimerCallback *cbData = (ooTimerCallback*)pdata;
 | |
|    OOH323CallData *call = cbData->call;
 | |
| 
 | |
|    OOTRACEINFO3("CloseLogicalChannelTimer expired. (%s, %s)\n", call->callType,
 | |
|                  call->callToken);
 | |
| 
 | |
|    ooClearLogicalChannel(call, cbData->channelNumber);
 | |
|    
 | |
|    if(call->callState < OO_CALL_CLEAR)
 | |
|    {
 | |
|       call->callState = OO_CALL_CLEAR;
 | |
|       call->callEndReason = OO_REASON_LOCAL_CLEARED;
 | |
|    }
 | |
|    ASN1MEMFREEPTR(call->pctxt, cbData);
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| int ooRequestChannelCloseTimerExpired(void *pdata)
 | |
| {
 | |
|    int ret = 0;
 | |
|    ooLogicalChannel *pChannel = NULL;
 | |
|    ooTimerCallback *cbData = (ooTimerCallback*)pdata;
 | |
|    OOH323CallData *call = cbData->call;
 | |
| 
 | |
|    OOTRACEINFO3("CloseLogicalChannelTimer expired. (%s, %s)\n", call->callType,
 | |
|                  call->callToken);
 | |
|   
 | |
|    pChannel = ooFindLogicalChannelByLogicalChannelNo(call, 
 | |
|                                                cbData->channelNumber);
 | |
|    if(pChannel)
 | |
|       ooSendRequestChannelCloseRelease(call, cbData->channelNumber);
 | |
|    else
 | |
|       return OO_OK;
 | |
|    
 | |
| 
 | |
|    ret = ooClearLogicalChannel(call, cbData->channelNumber);
 | |
|    if(ret != OO_OK)
 | |
|    {
 | |
|       OOTRACEERR4("Error:Failed to clear logical channel %d. (%s, %s)\n",
 | |
|                    cbData->channelNumber, call->callType, call->callToken);
 | |
|    } 
 | |
| 
 | |
|    if(call->callState < OO_CALL_CLEAR)
 | |
|    {
 | |
|       call->callState = OO_CALL_CLEAR;
 | |
|       call->callEndReason = OO_REASON_LOCAL_CLEARED;
 | |
|    }
 | |
|    ASN1MEMFREEPTR(call->pctxt, cbData);
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| int ooSessionTimerExpired(void *pdata)
 | |
| {
 | |
|    int ret = 0;
 | |
|    ooTimerCallback *cbData = (ooTimerCallback*)pdata;
 | |
|    OOH323CallData *call = cbData->call;
 | |
| 
 | |
|    OOTRACEINFO3("SessionTimer expired. (%s, %s)\n", call->callType,
 | |
|                  call->callToken);
 | |
| 
 | |
|    if(call->h245SessionState != OO_H245SESSION_IDLE && 
 | |
|       call->h245SessionState != OO_H245SESSION_CLOSED &&
 | |
|       call->h245SessionState != OO_H245SESSION_PAUSED) {
 | |
| 
 | |
|       ret = ooCloseH245Connection(call);
 | |
|    
 | |
|       if(ret != OO_OK) {
 | |
|          OOTRACEERR3("Error:Failed to close H.245 connection (%s, %s)\n",
 | |
|                      call->callType, call->callToken);
 | |
|       } 
 | |
|    }
 | |
| 
 | |
|    memFreePtr(call->pctxt, cbData);
 | |
| 
 | |
|    if(call->callState == OO_CALL_CLEAR_RELEASESENT)
 | |
|       call->callState = OO_CALL_CLEARED;
 | |
|    
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| 
 | |
| int ooGetIpPortFromH245TransportAddress
 | |
|    (OOH323CallData *call, H245TransportAddress *h245Address, char *ip, 
 | |
|     int *port)
 | |
| {
 | |
|    H245UnicastAddress *unicastAddress = NULL;
 | |
|    H245UnicastAddress_iPAddress *ipAddress = NULL;
 | |
|    H245UnicastAddress_iP6Address *ip6Address = NULL;
 | |
|    regmatch_t pmatch[1];
 | |
| 
 | |
|    if(h245Address->t != T_H245TransportAddress_unicastAddress)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:Unsupported H245 address type "
 | |
|                            "(%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    } 
 | |
|       
 | |
|    unicastAddress = h245Address->u.unicastAddress;
 | |
|    if (call->versionIP == 6) {
 | |
| 	if (unicastAddress->t != T_H245UnicastAddress_iP6Address) {
 | |
|       		OOTRACEERR3("ERROR:H245 Address type is not IP6"
 | |
|                    "(%s, %s)\n", call->callType, call->callToken);
 | |
|       		return OO_FAILED;
 | |
| 	}
 | |
| 	ip6Address = unicastAddress->u.iP6Address;
 | |
| 	*port = ip6Address->tsapIdentifier;
 | |
| 	inet_ntop(AF_INET6, ip6Address->network.data, ip, INET6_ADDRSTRLEN);
 | |
| 
 | |
|    } else { if(unicastAddress->t != T_H245UnicastAddress_iPAddress)
 | |
|    {
 | |
|       OOTRACEERR3("ERROR:H245 Address type is not IP"
 | |
|                    "(%s, %s)\n", call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
|    ipAddress = unicastAddress->u.iPAddress;
 | |
| 
 | |
|    *port = ipAddress->tsapIdentifier;
 | |
|    inet_ntop(AF_INET,  ipAddress->network.data, ip, INET_ADDRSTRLEN);
 | |
|    }
 | |
|    if (call->rtpMaskStr[0]) {
 | |
|      if (regexec(&call->rtpMask->regex, ip, 1, pmatch, 0)) {
 | |
| 		OOTRACEERR5("ERROR:H245 Address is not matched with filter %s/%s"
 | |
| 			"(%s, %s)\n", ip, call->rtpMaskStr, call->callType, call->callToken);
 | |
| 	 return OO_FAILED;
 | |
| 	}
 | |
|    }
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| 
 | |
| int ooPrepareFastStartResponseOLC
 | |
|    (OOH323CallData *call, H245OpenLogicalChannel *olc, 
 | |
|     ooH323EpCapability *epCap, OOCTXT*pctxt, int dir)
 | |
| {
 | |
|    OOBOOL reverse=FALSE, forward=FALSE;
 | |
|    H245OpenLogicalChannel_forwardLogicalChannelParameters *flcp=NULL;
 | |
|    H245OpenLogicalChannel_reverseLogicalChannelParameters *rlcp=NULL;
 | |
|    H245H2250LogicalChannelParameters *pH2250lcp1=NULL, *pH2250lcp2=NULL;
 | |
|    H245UnicastAddress *pUnicastAddrs=NULL, *pUniAddrs=NULL;
 | |
|    H245UnicastAddress_iPAddress *pIpAddrs=NULL, *pUniIpAddrs=NULL;
 | |
|    H245UnicastAddress_iP6Address *pIp6Addrs=NULL, *pUniIp6Addrs=NULL;
 | |
|    unsigned session_id = 0;
 | |
|    ooLogicalChannel *pLogicalChannel = NULL;
 | |
|    
 | |
|    if(dir & OORX)
 | |
|    {
 | |
|       OOTRACEDBGA3("ooPrepareFastStartResponseOLC for Receive  Capability "
 | |
|                    "(%s, %s)\n", call->callType, call->callToken);
 | |
|       session_id = ooCallGenerateSessionID(call, epCap->capType, "receive");
 | |
|       pLogicalChannel = ooAddNewLogicalChannel(call, 
 | |
|                                  olc->forwardLogicalChannelNumber, session_id, 
 | |
|                                  "receive", epCap);
 | |
|       forward = TRUE;
 | |
|    }
 | |
|    else if(dir & OOTX)
 | |
|    {
 | |
|       OOTRACEDBGA3("ooPrepareFastStartResponseOLC for transmit Capability "
 | |
|                    "(%s, %s)\n", call->callType, call->callToken);
 | |
|       session_id = ooCallGenerateSessionID(call, epCap->capType, "transmit");
 | |
|       pLogicalChannel = ooAddNewLogicalChannel(call, 
 | |
|                                   olc->forwardLogicalChannelNumber, session_id,
 | |
|                                   "transmit", epCap);
 | |
|       reverse = TRUE;
 | |
|    }
 | |
|    else if(dir & OORXTX)
 | |
|    {
 | |
|       OOTRACEDBGA3("ooPrepareFastStartResponseOLC for ReceiveAndTransmit  "
 | |
|                    "Capability (%s, %s)\n", call->callType, call->callToken);
 | |
|       reverse = 1;
 | |
|       forward = 1;
 | |
|       OOTRACEERR3("Symmetric capability is not supported as of now (%s, %s)\n",
 | |
|                    call->callType, call->callToken);
 | |
|       return OO_FAILED;
 | |
|    }
 | |
| 
 | |
|    if(forward)
 | |
|    {
 | |
|       OOTRACEDBGC3("Preparing olc for receive channel. (%s, %s)\n", 
 | |
|                    call->callType, call->callToken);
 | |
|       flcp = &(olc->forwardLogicalChannelParameters);
 | |
| 
 | |
|       pH2250lcp1 = flcp->multiplexParameters.u.h2250LogicalChannelParameters;
 | |
|           
 | |
| 
 | |
|       pH2250lcp1->m.mediaChannelPresent = 1;
 | |
|       pH2250lcp1->mediaChannel.t = T_H245TransportAddress_unicastAddress;
 | |
|       pUniAddrs = (H245UnicastAddress*) memAllocZ(pctxt, 
 | |
|                                                    sizeof(H245UnicastAddress));
 | |
|       pH2250lcp1->mediaChannel.u.unicastAddress =  pUniAddrs;
 | |
|       if (call->versionIP == 6) {
 | |
|       	pUniIp6Addrs = (H245UnicastAddress_iP6Address*) memAllocZ(pctxt, 
 | |
|                                          sizeof(H245UnicastAddress_iP6Address));
 | |
|       	if(!pUniAddrs || !pUniIpAddrs) {
 | |
|          	OOTRACEERR3("Error:Memory - ooPrepareFastStartResponseOLC - pUniAddrs"
 | |
|                      "/pUniIpAddrs (%s, %s)\n", call->callType, 
 | |
|                      call->callToken);
 | |
|          return OO_FAILED;
 | |
|       	}
 | |
| 
 | |
|       	pUniAddrs->t = T_H245UnicastAddress_iP6Address;
 | |
|       	pUniAddrs->u.iP6Address = pUniIp6Addrs;
 | |
|      	inet_pton(AF_INET6, pLogicalChannel->localIP, pUniIp6Addrs->network.data);
 | |
| 
 | |
|       	pUniIp6Addrs->network.numocts = 16;
 | |
|       	pUniIp6Addrs->tsapIdentifier = pLogicalChannel->localRtpPort;
 | |
| 
 | |
|       } else {
 | |
|       	pUniIpAddrs = (H245UnicastAddress_iPAddress*) memAllocZ(pctxt, 
 | |
|                                          sizeof(H245UnicastAddress_iPAddress));
 | |
|       	if(!pUniAddrs || !pUniIpAddrs) {
 | |
|          OOTRACEERR3("Error:Memory - ooPrepareFastStartResponseOLC - pUniAddrs"
 | |
|                      "/pUniIpAddrs (%s, %s)\n", call->callType, 
 | |
|                      call->callToken);
 | |
|          return OO_FAILED;
 | |
|       	}
 | |
| 
 | |
|       	pUniAddrs->t = T_H245UnicastAddress_iPAddress;
 | |
|       	pUniAddrs->u.iPAddress = pUniIpAddrs;
 | |
| 	inet_pton(AF_INET, pLogicalChannel->localIP, pUniIpAddrs->network.data);
 | |
|      
 | |
|       	pUniIpAddrs->network.numocts = 4;
 | |
|       	pUniIpAddrs->tsapIdentifier = pLogicalChannel->localRtpPort;
 | |
|       }
 | |
| 
 | |
| 
 | |
|       pH2250lcp1->m.mediaControlChannelPresent = 1;
 | |
|       pH2250lcp1->mediaControlChannel.t = 
 | |
|                                  T_H245TransportAddress_unicastAddress;
 | |
|       pUnicastAddrs = (H245UnicastAddress*) memAllocZ(pctxt, 
 | |
|                                                    sizeof(H245UnicastAddress));
 | |
|       pH2250lcp1->mediaControlChannel.u.unicastAddress =  pUnicastAddrs;
 | |
| 
 | |
|       if (call->versionIP == 6) {
 | |
|       	pIp6Addrs = (H245UnicastAddress_iP6Address*) memAllocZ(pctxt, 
 | |
|                                          sizeof(H245UnicastAddress_iP6Address));
 | |
|       	if(!pUnicastAddrs || !pIp6Addrs) {
 | |
|          OOTRACEERR3("Error:Memory - ooPrepareFastStartResponseOLC - "
 | |
|                      "pUnicastAddrs/pIpAddrs (%s, %s)\n", call->callType, 
 | |
|                      call->callToken);
 | |
|          return OO_FAILED;
 | |
|       	}
 | |
|       	pUnicastAddrs->t = T_H245UnicastAddress_iP6Address;
 | |
|       	pUnicastAddrs->u.iP6Address = pIp6Addrs;
 | |
|       	inet_pton(AF_INET6, pLogicalChannel->localIP, pIp6Addrs->network.data);
 | |
|       	pIp6Addrs->network.numocts = 16;
 | |
|       	pIp6Addrs->tsapIdentifier = pLogicalChannel->localRtcpPort;
 | |
|       } else {
 | |
| 
 | |
|       	pIpAddrs = (H245UnicastAddress_iPAddress*) memAllocZ(pctxt, 
 | |
|                                          sizeof(H245UnicastAddress_iPAddress));
 | |
|       	if(!pUnicastAddrs || !pIpAddrs) {
 | |
|          	OOTRACEERR3("Error:Memory - ooPrepareFastStartResponseOLC - "
 | |
|                      "pUnicastAddrs/pIpAddrs (%s, %s)\n", call->callType, 
 | |
|                      call->callToken);
 | |
|          	return OO_FAILED;
 | |
|       	}
 | |
|       	pUnicastAddrs->t = T_H245UnicastAddress_iPAddress;
 | |
|       	pUnicastAddrs->u.iPAddress = pIpAddrs;
 | |
|       	inet_pton(AF_INET, pLogicalChannel->localIP, pIpAddrs->network.data);
 | |
|       	pIpAddrs->network.numocts = 4;
 | |
|       	pIpAddrs->tsapIdentifier = pLogicalChannel->localRtcpPort;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if(reverse)
 | |
|    {
 | |
|       OOTRACEDBGC3("Building reverse olc. (%s, %s)\n", call->callType, 
 | |
|                     call->callToken);
 | |
| 
 | |
|       rlcp = &(olc->reverseLogicalChannelParameters);
 | |
| 
 | |
|       pH2250lcp2 = rlcp->multiplexParameters.u.h2250LogicalChannelParameters;
 | |
|       pH2250lcp2->m.mediaChannelPresent = 0;
 | |
|       memset(&pH2250lcp2->mediaChannel, 0, sizeof(H245TransportAddress));
 | |
| 
 | |
|       pH2250lcp2->m.mediaControlChannelPresent = 1;
 | |
|       pH2250lcp2->mediaControlChannel.t = 
 | |
|                                  T_H245TransportAddress_unicastAddress;
 | |
|       pUniAddrs = (H245UnicastAddress*) memAlloc(pctxt, 
 | |
|                                                    sizeof(H245UnicastAddress));
 | |
|       pH2250lcp2->mediaControlChannel.u.unicastAddress =  pUniAddrs;
 | |
| 
 | |
|       if (call->versionIP == 6) {
 | |
|       	pUniIp6Addrs = (H245UnicastAddress_iP6Address*) memAlloc(pctxt, 
 | |
|                                          sizeof(H245UnicastAddress_iP6Address));
 | |
|       	if(!pUniAddrs || !pUniIp6Addrs) {
 | |
|          	OOTRACEERR3("Error:Memory - ooPrepareFastStartResponseOLC - "
 | |
|                     "pUniAddrs/pUniIpAddrs (%s, %s)\n", call->callType, 
 | |
|                      call->callToken);
 | |
|          return OO_FAILED;
 | |
|       	}
 | |
| 
 | |
|       
 | |
|       	pUniAddrs->t = T_H245UnicastAddress_iP6Address;
 | |
|       	pUniAddrs->u.iP6Address = pUniIp6Addrs; 
 | |
| 	inet_pton(AF_INET6, pLogicalChannel->localIP, pUniIp6Addrs->network.data);
 | |
| 	pUniIp6Addrs->network.numocts = 16;
 | |
|       	pUniIp6Addrs->tsapIdentifier = pLogicalChannel->localRtcpPort;
 | |
|       } else {
 | |
|       	pUniIpAddrs = (H245UnicastAddress_iPAddress*) memAlloc(pctxt, 
 | |
|                                          sizeof(H245UnicastAddress_iPAddress));
 | |
|       	if(!pUniAddrs || !pUniIpAddrs) {
 | |
|          	OOTRACEERR3("Error:Memory - ooPrepareFastStartResponseOLC - "
 | |
|                     "pUniAddrs/pUniIpAddrs (%s, %s)\n", call->callType, 
 | |
|                      call->callToken);
 | |
|          return OO_FAILED;
 | |
|       	}
 | |
| 
 | |
|       	pH2250lcp2->mediaControlChannel.u.unicastAddress =  pUniAddrs;
 | |
|       
 | |
|       	pUniAddrs->t = T_H245UnicastAddress_iPAddress;
 | |
|       	pUniAddrs->u.iPAddress = pUniIpAddrs; 
 | |
| 	inet_pton(AF_INET, pLogicalChannel->localIP, pUniIpAddrs->network.data);
 | |
| 	pUniIpAddrs->network.numocts = 4;
 | |
|       	pUniIpAddrs->tsapIdentifier = pLogicalChannel->localRtcpPort;
 | |
|       }
 | |
|           
 | |
|    }
 | |
| 
 | |
|    pLogicalChannel->state = OO_LOGICALCHAN_ESTABLISHED;
 | |
| 
 | |
|    return OO_OK;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 |