diff options
Diffstat (limited to 'addons/ooh323c/src/oochannels.c')
-rw-r--r-- | addons/ooh323c/src/oochannels.c | 1785 |
1 files changed, 1785 insertions, 0 deletions
diff --git a/addons/ooh323c/src/oochannels.c b/addons/ooh323c/src/oochannels.c new file mode 100644 index 000000000..8fe8c60cd --- /dev/null +++ b/addons/ooh323c/src/oochannels.c @@ -0,0 +1,1785 @@ +/* + * 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 "ooports.h" +#include "oochannels.h" +#include "ootrace.h" +#include "ooq931.h" +#include "ooh245.h" +#include "ooh323.h" +#include "ooCalls.h" +#include "printHandler.h" +#include "ooGkClient.h" +#include "stdio.h" +#include "ooTimer.h" +#include "ooh323ep.h" +#include "ooStackCmds.h" +#include "ooCmdChannel.h" +#include "ootypes.h" + +/** Global endpoint structure */ +extern OOH323EndPoint gH323ep; + +extern DList g_TimerList; + +static OOBOOL gMonitor = FALSE; + + +int ooCreateH245Listener(OOH323CallData *call) +{ + int ret=0; + OOSOCKET channelSocket=0; + OOTRACEINFO1("Creating H245 listener\n"); + if((ret=ooSocketCreate (&channelSocket))!=ASN_OK) + { + OOTRACEERR3("ERROR: Failed to create socket for H245 listener " + "(%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + ret = ooBindPort (OOTCP, channelSocket, call->localIP); + if(ret == OO_FAILED) + { + OOTRACEERR3("Error:Unable to bind to a TCP port - H245 listener creation" + " (%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + call->h245listenport = (int*) memAlloc(call->pctxt, sizeof(int)); + *(call->h245listenport) = ret; + call->h245listener = (OOSOCKET*)memAlloc(call->pctxt, sizeof(OOSOCKET)); + *(call->h245listener) = channelSocket; + ret = ooSocketListen(*(call->h245listener), 20); + if(ret != ASN_OK) + { + OOTRACEERR3("Error:Unable to listen on H.245 socket (%s, %s)\n", + call->callType, call->callToken); + return OO_FAILED; + } + + OOTRACEINFO4("H245 listener creation - successful(port %d) (%s, %s)\n", + *(call->h245listenport),call->callType, call->callToken); + return OO_OK; +} + +int ooCreateH245Connection(OOH323CallData *call) +{ + int ret=0; + OOSOCKET channelSocket=0; + ooTimerCallback *cbData=NULL; + + OOTRACEINFO1("Creating H245 Connection\n"); + if((ret=ooSocketCreate (&channelSocket))!=ASN_OK) + { + OOTRACEERR3("ERROR:Failed to create socket for H245 connection " + "(%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + else + { + if (0 == call->pH245Channel) { + call->pH245Channel = + (OOH323Channel*) memAllocZ (call->pctxt, sizeof(OOH323Channel)); + } + + /* + bind socket to a port before connecting. Thus avoiding + implicit bind done by a connect call. + */ + ret = ooBindPort(OOTCP, channelSocket, call->localIP); + if(ret == OO_FAILED) + { + OOTRACEERR3("Error:Unable to bind to a TCP port - h245 connection " + "(%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + call->pH245Channel->port = ret; + OOTRACEDBGC4("Local H.245 port is %d (%s, %s)\n", + call->pH245Channel->port, + call->callType, call->callToken); + OOTRACEINFO5("Trying to connect to remote endpoint to setup H245 " + "connection %s:%d(%s, %s)\n", call->remoteIP, + call->remoteH245Port, call->callType, call->callToken); + + if((ret=ooSocketConnect(channelSocket, call->remoteIP, + call->remoteH245Port))==ASN_OK) + { + call->pH245Channel->sock = channelSocket; + call->h245SessionState = OO_H245SESSION_ACTIVE; + + OOTRACEINFO3("H245 connection creation succesful (%s, %s)\n", + call->callType, call->callToken); + + /*Start terminal capability exchange and master slave determination */ + ret = ooSendTermCapMsg(call); + if(ret != OO_OK) + { + OOTRACEERR3("ERROR:Sending Terminal capability message (%s, %s)\n", + call->callType, call->callToken); + return ret; + } + ret = ooSendMasterSlaveDetermination(call); + if(ret != OO_OK) + { + OOTRACEERR3("ERROR:Sending Master-slave determination message " + "(%s, %s)\n", call->callType, call->callToken); + return ret; + } + } + else + { + if(call->h245ConnectionAttempts >= 3) + { + OOTRACEERR3("Error:Failed to setup an H245 connection with remote " + "destination. (%s, %s)\n", call->callType, + call->callToken); + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + else{ + OOTRACEWARN4("Warn:Failed to connect to remote destination for " + "H245 connection - will retry after %d seconds" + "(%s, %s)\n", DEFAULT_H245CONNECTION_RETRYTIMEOUT, + call->callType, call->callToken); + + cbData = (ooTimerCallback*) memAlloc(call->pctxt, + sizeof(ooTimerCallback)); + if(!cbData) + { + OOTRACEERR3("Error:Unable to allocate memory for timer " + "callback.(%s, %s)\n", call->callType, + call->callToken); + return OO_FAILED; + } + cbData->call = call; + cbData->timerType = OO_H245CONNECT_TIMER; + if(!ooTimerCreate(call->pctxt, &call->timerList, + &ooCallH245ConnectionRetryTimerExpired, + DEFAULT_H245CONNECTION_RETRYTIMEOUT, cbData, + FALSE)) + { + OOTRACEERR3("Error:Unable to create H245 connection retry timer" + "(%s, %s)\n", call->callType, call->callToken); + memFreePtr(call->pctxt, cbData); + return OO_FAILED; + } + return OO_OK; + } + } + } + return OO_OK; +} + +int ooSendH225Msg(OOH323CallData *call, Q931Message *msg) +{ + int iRet=0; + ASN1OCTET * encodebuf; + if(!call) + return OO_FAILED; + + encodebuf = (ASN1OCTET*) memAlloc (call->pctxt, MAXMSGLEN); + if(!encodebuf) + { + OOTRACEERR3("Error:Failed to allocate memory for encoding H225 " + "message(%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + iRet = ooEncodeH225Message(call, msg, encodebuf, MAXMSGLEN); + if(iRet != OO_OK) + { + OOTRACEERR3("Error:Failed to encode H225 message. (%s, %s)\n", + call->callType, call->callToken); + memFreePtr (call->pctxt, encodebuf); + return OO_FAILED; + } + + /* If high priority messages, send immediately.*/ + if(encodebuf[0] == OOReleaseComplete || + (encodebuf[0]==OOFacility && encodebuf[1]==OOEndSessionCommand)) + { + dListFreeAll(call->pctxt, &call->pH225Channel->outQueue); + dListAppend (call->pctxt, &call->pH225Channel->outQueue, encodebuf); + // ooSendMsg(call, OOQ931MSG); + } + else{ + dListAppend (call->pctxt, &call->pH225Channel->outQueue, encodebuf); + + OOTRACEDBGC4("Queued H225 messages %d. (%s, %s)\n", + call->pH225Channel->outQueue.count, + call->callType, call->callToken); + } + return OO_OK; +} + +int ooCreateH225Connection(OOH323CallData *call) +{ + int ret=0; + OOSOCKET channelSocket=0; + if((ret=ooSocketCreate (&channelSocket))!=ASN_OK) + { + OOTRACEERR3("Failed to create socket for transmit H2250 channel (%s, %s)" + "\n", call->callType, call->callToken); + if(call->callState < OO_CALL_CLEAR) + { + call->callState = OO_CALL_CLEAR; + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + } + return OO_FAILED; + } + else + { + /* + bind socket to a port before connecting. Thus avoiding + implicit bind done by a connect call. Avoided on windows as + windows sockets have problem in reusing the addresses even after + setting SO_REUSEADDR, hence in windows we just allow os to bind + to any random port. + */ +#ifndef _WIN32 + ret = ooBindPort(OOTCP,channelSocket, call->localIP); +#else + ret = ooBindOSAllocatedPort(channelSocket, call->localIP); +#endif + + if(ret == OO_FAILED) + { + OOTRACEERR3("Error:Unable to bind to a TCP port (%s, %s)\n", + call->callType, call->callToken); + if(call->callState < OO_CALL_CLEAR) + { + call->callState = OO_CALL_CLEAR; + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + } + return OO_FAILED; + } + + if (0 == call->pH225Channel) { + call->pH225Channel = + (OOH323Channel*) memAllocZ (call->pctxt, sizeof(OOH323Channel)); + } + call->pH225Channel->port = ret; + + OOTRACEINFO5("Trying to connect to remote endpoint(%s:%d) to setup " + "H2250 channel (%s, %s)\n", call->remoteIP, + call->remotePort, call->callType, call->callToken); + + if((ret=ooSocketConnect(channelSocket, call->remoteIP, + call->remotePort))==ASN_OK) + { + call->pH225Channel->sock = channelSocket; + + OOTRACEINFO3("H2250 transmiter channel creation - succesful " + "(%s, %s)\n", call->callType, call->callToken); + + /* If multihomed, get ip from socket */ + if(!strcmp(call->localIP, "0.0.0.0")) + { + OOTRACEDBGA3("Determining IP address for outgoing call in " + "multihomed mode. (%s, %s)\n", call->callType, + call->callToken); + ret = ooSocketGetIpAndPort(channelSocket, call->localIP, 20, + &call->pH225Channel->port); + if(ret != ASN_OK) + { + OOTRACEERR3("ERROR:Failed to retrieve local ip and port from " + "socket for multihomed mode.(%s, %s)\n", + call->callType, call->callToken); + if(call->callState < OO_CALL_CLEAR) + { /* transport failure */ + call->callState = OO_CALL_CLEAR; + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + } + return OO_FAILED; + } + OOTRACEDBGA4("Using local ip %s for outgoing call(multihomedMode)." + " (%s, %s)\n", call->localIP, call->callType, + call->callToken); + } + return OO_OK; + } + else + { + OOTRACEERR3("ERROR:Failed to connect to remote destination for " + "transmit H2250 channel(%s, %s)\n",call->callType, + call->callToken); + if(call->callState < OO_CALL_CLEAR) + { /* No one is listening at remote end */ + call->callState = OO_CALL_CLEAR; + call->callEndReason = OO_REASON_NOUSER; + } + return OO_FAILED; + } + + return OO_FAILED; + } +} + +int ooCloseH225Connection (OOH323CallData *call) +{ + if (0 != call->pH225Channel) + { + if(call->pH225Channel->sock != 0) + ooSocketClose (call->pH225Channel->sock); + if (call->pH225Channel->outQueue.count > 0) + { + dListFreeAll (call->pctxt, &(call->pH225Channel->outQueue)); + } + memFreePtr (call->pctxt, call->pH225Channel); + call->pH225Channel = NULL; + } + return OO_OK; +} + +int ooCreateH323Listener() +{ + int ret=0; + OOSOCKET channelSocket=0; + OOIPADDR ipaddrs; + + /* Create socket */ + if((ret=ooSocketCreate (&channelSocket))!=ASN_OK) + { + OOTRACEERR1("Failed to create socket for H323 Listener\n"); + return OO_FAILED; + } + ret= ooSocketStrToAddr (gH323ep.signallingIP, &ipaddrs); + if((ret=ooSocketBind (channelSocket, ipaddrs, + gH323ep.listenPort))==ASN_OK) + { + gH323ep.listener = (OOSOCKET*)memAlloc(&gH323ep.ctxt,sizeof(OOSOCKET)); + *(gH323ep.listener) = channelSocket; + + ooSocketListen(channelSocket,20); /*listen on socket*/ + OOTRACEINFO1("H323 listener creation - successful\n"); + return OO_OK; + } + else + { + OOTRACEERR1("ERROR:Failed to create H323 listener\n"); + return OO_FAILED; + } +} + + + +int ooAcceptH225Connection() +{ + OOH323CallData * call; + int ret; + char callToken[20]; + OOSOCKET h225Channel=0; + ret = ooSocketAccept (*(gH323ep.listener), &h225Channel, + NULL, NULL); + if(ret != ASN_OK) + { + OOTRACEERR1("Error:Accepting h225 connection\n"); + return OO_FAILED; + } + ooGenerateCallToken(callToken, sizeof(callToken)); + + call = ooCreateCall("incoming", callToken); + if(!call) + { + OOTRACEERR1("ERROR:Failed to create an incoming call\n"); + return OO_FAILED; + } + + call->pH225Channel = (OOH323Channel*) + memAllocZ (call->pctxt, sizeof(OOH323Channel)); + + call->pH225Channel->sock = h225Channel; + + /* If multihomed, get ip from socket */ + if(!strcmp(call->localIP, "0.0.0.0")) + { + OOTRACEDBGA3("Determining IP address for incoming call in multihomed " + "mode (%s, %s)\n", call->callType, call->callToken); + + ret = ooSocketGetIpAndPort(h225Channel, call->localIP, 20, + &call->pH225Channel->port); + if(ret != ASN_OK) + { + OOTRACEERR3("Error:Failed to retrieve local ip and port from " + "socket for multihomed mode.(%s, %s)\n", + call->callType, call->callToken); + if(call->callState < OO_CALL_CLEAR) + { /* transport failure */ + call->callState = OO_CALL_CLEAR; + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + } + return OO_FAILED; + } + OOTRACEDBGA4("Using Local IP address %s for incoming call in multihomed " + "mode. (%s, %s)\n", call->localIP, call->callType, + call->callToken); + } + + return OO_OK; +} + +int ooAcceptH245Connection(OOH323CallData *call) +{ + int ret; + OOSOCKET h245Channel=0; + ret = ooSocketAccept (*(call->h245listener), &h245Channel, + NULL, NULL); + if(ret != ASN_OK) + { + OOTRACEERR1("Error:Accepting h245 connection\n"); + return OO_FAILED; + } + + if (0 == call->pH245Channel) { + call->pH245Channel = + (OOH323Channel*) memAllocZ (call->pctxt, sizeof(OOH323Channel)); + } + call->pH245Channel->sock = h245Channel; + call->h245SessionState = OO_H245SESSION_ACTIVE; + + + OOTRACEINFO3("H.245 connection established (%s, %s)\n", + call->callType, call->callToken); + + + /* Start terminal capability exchange and master slave determination */ + ret = ooSendTermCapMsg(call); + if(ret != OO_OK) + { + OOTRACEERR3("ERROR:Sending Terminal capability message (%s, %s)\n", + call->callType, call->callToken); + return ret; + } + ret = ooSendMasterSlaveDetermination(call); + if(ret != OO_OK) + { + OOTRACEERR3("ERROR:Sending Master-slave determination message " + "(%s, %s)\n", call->callType, call->callToken); + return ret; + } + return OO_OK; +} + + +int ooSetFDSETs(fd_set *pReadfds, fd_set *pWritefds, int *nfds) +{ + OOH323CallData *call=NULL; + + if(gH323ep.gkClient && gH323ep.gkClient->rasSocket != 0) + { + FD_SET(gH323ep.gkClient->rasSocket, pReadfds ); + if ( *nfds < (int)gH323ep.gkClient->rasSocket) + *nfds = (int)gH323ep.gkClient->rasSocket; + } + if(gH323ep.listener) + { + FD_SET(*(gH323ep.listener), pReadfds); + if(*nfds < (int)*(gH323ep.listener)) + *nfds = *((int*)gH323ep.listener); + } + + if(gH323ep.cmdSock) + { + FD_SET(gH323ep.cmdSock, pReadfds); + if(*nfds < (int)gH323ep.cmdSock) + *nfds = (int)gH323ep.cmdSock; + } + + + + if(gH323ep.callList) + { + call = gH323ep.callList; + while(call) + { + if (0 != call->pH225Channel && 0 != call->pH225Channel->sock) + { + FD_SET (call->pH225Channel->sock, pReadfds); + if (call->pH225Channel->outQueue.count > 0 || + (OO_TESTFLAG (call->flags, OO_M_TUNNELING) && + 0 != call->pH245Channel && + call->pH245Channel->outQueue.count>0)) + FD_SET (call->pH225Channel->sock, pWritefds); + if(*nfds < (int)call->pH225Channel->sock) + *nfds = call->pH225Channel->sock; + } + + if (0 != call->pH245Channel && call->pH245Channel->sock != 0) + { + FD_SET(call->pH245Channel->sock, pReadfds); + if (call->pH245Channel->outQueue.count>0) + FD_SET(call->pH245Channel->sock, pWritefds); + if(*nfds < (int)call->pH245Channel->sock) + *nfds = call->pH245Channel->sock; + } + else if(call->h245listener) + { + OOTRACEINFO3("H.245 Listerner socket being monitored " + "(%s, %s)\n", call->callType, call->callToken); + FD_SET(*(call->h245listener), pReadfds); + if(*nfds < (int)*(call->h245listener)) + *nfds = *(call->h245listener); + } + call = call->next; + + }/* while(call) */ + }/*if(gH323ep.callList) */ + + + if(*nfds != 0) *nfds = *nfds+1; + + return OO_OK; + +} + +int ooProcessFDSETsAndTimers + (fd_set *pReadfds, fd_set *pWritefds, struct timeval *pToMin) +{ + OOH323CallData *call, *prev=NULL; + struct timeval toNext; + + /* Process gatekeeper client timers */ + if(gH323ep.gkClient) + { + ooTimerFireExpired(&gH323ep.gkClient->ctxt, + &gH323ep.gkClient->timerList); + if(ooTimerNextTimeout(&gH323ep.gkClient->timerList, &toNext)) + { + if(ooCompareTimeouts(pToMin, &toNext)>0) + { + pToMin->tv_sec = toNext.tv_sec; + pToMin->tv_usec = toNext.tv_usec; + } + } + if(gH323ep.gkClient->state == GkClientFailed || + gH323ep.gkClient->state == GkClientGkErr) + { + if(ooGkClientHandleClientOrGkFailure(gH323ep.gkClient)!=OO_OK) + { + //ooStopMonitorCalls(); //Function calling ooProcessFDSETsAndTimers is responsible for this. + return OO_FAILED; + } + } + } + + if(gH323ep.cmdSock) { + if(FD_ISSET(gH323ep.cmdSock, pReadfds)) { + if(ooReadAndProcessStackCommand() != OO_OK) { + /* ooReadAndProcessStackCommand prints an error message */ + return OO_FAILED; + } + } + } + + /* Manage ready descriptors after select */ + + if(0 != gH323ep.gkClient && 0 != gH323ep.gkClient->rasSocket) + { + if(FD_ISSET( gH323ep.gkClient->rasSocket, pReadfds) ) + { + ooGkClientReceive(gH323ep.gkClient); + if(gH323ep.gkClient->state == GkClientFailed || + gH323ep.gkClient->state == GkClientGkErr) { + ooGkClientHandleClientOrGkFailure(gH323ep.gkClient); + } + } + } + + if(gH323ep.listener) + { + if(FD_ISSET(*(gH323ep.listener), pReadfds)) + { + OOTRACEDBGA1("New connection at H225 receiver\n"); + ooAcceptH225Connection(); + } + } + + + if(gH323ep.callList) + { + call = gH323ep.callList; + while(call) + { + ooTimerFireExpired(call->pctxt, &call->timerList); + if (0 != call->pH225Channel && 0 != call->pH225Channel->sock) + { + if(FD_ISSET(call->pH225Channel->sock, pReadfds)) + { + if(ooH2250Receive(call) != OO_OK) + { + OOTRACEERR3("ERROR:Failed ooH2250Receive - Clearing call " + "(%s, %s)\n", call->callType, call->callToken); + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEAR; + } + } + } + } + + + if (0 != call->pH245Channel && 0 != call->pH245Channel->sock) + { + if(FD_ISSET(call->pH245Channel->sock, pReadfds)) + { + ooH245Receive(call); + } + } + + if (0 != call->pH245Channel && 0 != call->pH245Channel->sock) + { + if(FD_ISSET(call->pH245Channel->sock, pWritefds)) + { + if(call->pH245Channel->outQueue.count>0) + ooSendMsg(call, OOH245MSG); + } + } + else if(call->h245listener) + { + if(FD_ISSET(*(call->h245listener), pReadfds)) + { + OOTRACEDBGC3("Incoming H.245 connection (%s, %s)\n", + call->callType, call->callToken); + ooAcceptH245Connection(call); + } + } + + if (0 != call->pH225Channel && 0 != call->pH225Channel->sock) + { + if(FD_ISSET(call->pH225Channel->sock, pWritefds)) + { + if(call->pH225Channel->outQueue.count>0) + { + OOTRACEDBGC3("Sending H225 message (%s, %s)\n", + call->callType, call->callToken); + ooSendMsg(call, OOQ931MSG); + } + if(call->pH245Channel && + call->pH245Channel->outQueue.count>0 && + OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + { + OOTRACEDBGC3("H245 message needs to be tunneled. " + "(%s, %s)\n", call->callType, + call->callToken); + ooSendMsg(call, OOH245MSG); + } + } + } + + if(ooTimerNextTimeout(&call->timerList, &toNext)) + { + if(ooCompareTimeouts(pToMin, &toNext) > 0) + { + pToMin->tv_sec = toNext.tv_sec; + pToMin->tv_usec = toNext.tv_usec; + } + } + prev = call; + call = call->next; + if(prev->callState >= OO_CALL_CLEAR) + ooEndCall(prev); + }/* while(call) */ + }/* if(gH323ep.callList) */ + + return OO_OK; + +} + +int ooMonitorChannels() +{ + int ret=0, nfds=0; + struct timeval toMin, toNext; + fd_set readfds, writefds; + + gMonitor = TRUE; + + toMin.tv_sec = 3; + toMin.tv_usec = 0; + ooH323EpPrintConfig(); + + if(gH323ep.gkClient) { + ooGkClientPrintConfig(gH323ep.gkClient); + if(OO_OK != ooGkClientStart(gH323ep.gkClient)) + { + OOTRACEERR1("Error:Failed to start Gatekeeper client\n"); + ooGkClientDestroy(); + } + } + + while(1) + { + FD_ZERO(&readfds); + FD_ZERO(&writefds); + nfds = 0; + ooSetFDSETs(&readfds, &writefds, &nfds); + + if(!gMonitor) { + OOTRACEINFO1("Ending Monitor thread\n"); + break; + } + + + if(nfds == 0) +#ifdef _WIN32 + Sleep(10); +#else + { + toMin.tv_sec = 0; + toMin.tv_usec = 10000; + ooSocketSelect(1, 0, 0, 0, &toMin); + } +#endif + else + ret = ooSocketSelect(nfds, &readfds, &writefds, + NULL, &toMin); + + if(ret == -1) + { + + OOTRACEERR1("Error in select ...exiting\n"); + exit(-1); + } + + toMin.tv_sec = 0; + toMin.tv_usec = 100000; /* 100ms*/ + /*This is for test application. Not part of actual stack */ + + ooTimerFireExpired(&gH323ep.ctxt, &g_TimerList); + if(ooTimerNextTimeout(&g_TimerList, &toNext)) + { + if(ooCompareTimeouts(&toMin, &toNext)>0) + { + toMin.tv_sec = toNext.tv_sec; + toMin.tv_usec = toNext.tv_usec; + } + } + + if(ooProcessFDSETsAndTimers(&readfds, &writefds, &toMin) != OO_OK) + { + ooStopMonitorCalls(); + continue; + } + + }/* while(1)*/ + return OO_OK; +} + +int ooH2250Receive(OOH323CallData *call) +{ + int recvLen=0, total=0, ret=0; + ASN1OCTET message[MAXMSGLEN], message1[MAXMSGLEN]; + int len; + Q931Message *pmsg; + OOCTXT *pctxt = &gH323ep.msgctxt; + struct timeval timeout; + fd_set readfds; + + + pmsg = (Q931Message*)memAlloc(pctxt, sizeof(Q931Message)); + if(!pmsg) + { + OOTRACEERR3("ERROR:Failed to allocate memory for incoming H.2250 message" + " (%s, %s)\n", call->callType, call->callToken); + memReset(&gH323ep.msgctxt); + return OO_FAILED; + } + memset(pmsg, 0, sizeof(Q931Message)); + /* First read just TPKT header which is four bytes */ + recvLen = ooSocketRecv (call->pH225Channel->sock, message, 4); + if(recvLen <= 0) + { + if(recvLen == 0) + OOTRACEWARN3("Warn:RemoteEndpoint closed connection (%s, %s)\n", + call->callType, call->callToken); + else + OOTRACEERR3("Error:Transport failure while reading Q931 " + "message (%s, %s)\n", call->callType, call->callToken); + + ooCloseH225Connection(call); + if(call->callState < OO_CALL_CLEARED) + { + if(call->callState < OO_CALL_CLEAR) + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + call->callState = OO_CALL_CLEARED; + + } + ooFreeQ931Message(pmsg); + return OO_OK; + } + OOTRACEDBGC3("Receiving H.2250 message (%s, %s)\n", + call->callType, call->callToken); + /* Since we are working with TCP, need to determine the + message boundary. Has to be done at channel level, as channels + know the message formats and can determine boundaries + */ + if(recvLen != 4) + { + OOTRACEERR4("Error: Reading TPKT header for H225 message " + "recvLen= %d (%s, %s)\n", recvLen, call->callType, + call->callToken); + ooFreeQ931Message(pmsg); + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + + + len = message[2]; + len = len<<8; + len = len | message[3]; + /* Remaining message length is length - tpkt length */ + len = len - 4; + + /* Now read actual Q931 message body. We should make sure that we + receive complete message as indicated by len. If we don't then there + is something wrong. The loop below receives message, then checks whether + complete message is received. If not received, then uses select to peek + for remaining bytes of the message. If message is not received in 3 + seconds, then we have a problem. Report an error and exit. + */ + while(total < len) + { + recvLen = ooSocketRecv (call->pH225Channel->sock, message1, len-total); + memcpy(message+total, message1, recvLen); + total = total + recvLen; + + if(total == len) break; /* Complete message is received */ + + FD_ZERO(&readfds); + FD_SET(call->pH225Channel->sock, &readfds); + timeout.tv_sec = 3; + timeout.tv_usec = 0; + ret = ooSocketSelect(call->pH225Channel->sock+1, &readfds, NULL, + NULL, &timeout); + if(ret == -1) + { + OOTRACEERR3("Error in select while receiving H.2250 message - " + "clearing call (%s, %s)\n", call->callType, + call->callToken); + ooFreeQ931Message(pmsg); + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + /* If remaining part of the message is not received in 3 seconds + exit */ + if(!FD_ISSET(call->pH225Channel->sock, &readfds)) + { + OOTRACEERR3("Error: Incomplete H.2250 message received - clearing " + "call (%s, %s)\n", call->callType, call->callToken); + ooFreeQ931Message(pmsg); + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + } + + OOTRACEDBGC3("Received Q.931 message: (%s, %s)\n", + call->callType, call->callToken); + + initializePrintHandler(&printHandler, "Received H.2250 Message"); + setEventHandler (pctxt, &printHandler); + ret = ooQ931Decode (call, pmsg, len, message); + if(ret != OO_OK) { + OOTRACEERR3("Error:Failed to decode received H.2250 message. (%s, %s)\n", + call->callType, call->callToken); + } + OOTRACEDBGC3("Decoded Q931 message (%s, %s)\n", call->callType, + call->callToken); + finishPrint(); + removeEventHandler(pctxt); + if(ret == OO_OK) { + ooHandleH2250Message(call, pmsg); + } + return ret; +} + + + +int ooH245Receive(OOH323CallData *call) +{ + int recvLen, ret, len, total=0; + ASN1OCTET message[MAXMSGLEN], message1[MAXMSGLEN]; + ASN1BOOL aligned = TRUE; + H245Message *pmsg; + OOCTXT *pctxt = &gH323ep.msgctxt; + struct timeval timeout; + fd_set readfds; + + pmsg = (H245Message*)memAlloc(pctxt, sizeof(H245Message)); + + /* First read just TPKT header which is four bytes */ + recvLen = ooSocketRecv (call->pH245Channel->sock, message, 4); + /* Since we are working with TCP, need to determine the + message boundary. Has to be done at channel level, as channels + know the message formats and can determine boundaries + */ + if(recvLen<=0 && call->h245SessionState != OO_H245SESSION_PAUSED) + { + if(recvLen == 0) + OOTRACEINFO3("Closing H.245 channels as remote end point closed H.245" + " connection (%s, %s)\n", call->callType, call->callToken); + else + OOTRACEERR3("Error: Transport failure while trying to receive H245" + " message (%s, %s)\n", call->callType, call->callToken); + + ooCloseH245Connection(call); + ooFreeH245Message(call, pmsg); + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + if(call->h245SessionState == OO_H245SESSION_PAUSED) + { + ooLogicalChannel *temp; + + OOTRACEINFO3("Call Paused, closing logical channels" + " (%s, %s)\n", call->callType, call->callToken); + + 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->masterSlaveState = OO_MasterSlave_Idle; + call->callState = OO_CALL_PAUSED; + call->localTermCapState = OO_LocalTermCapExchange_Idle; + call->remoteTermCapState = OO_RemoteTermCapExchange_Idle; + call->h245SessionState = OO_H245SESSION_IDLE; + call->logicalChans = NULL; + } + OOTRACEDBGC1("Receiving H245 message\n"); + if(recvLen != 4) + { + OOTRACEERR3("Error: Reading TPKT header for H245 message (%s, %s)\n", + call->callType, call->callToken); + ooFreeH245Message(call, pmsg); + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_INVALIDMESSAGE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + + len = message[2]; + len = len<<8; + len = (len | message[3]); + /* Remaining message length is length - tpkt length */ + len = len - 4; + /* Now read actual H245 message body. We should make sure that we + receive complete message as indicated by len. If we don't then there + is something wrong. The loop below receives message, then checks whether + complete message is received. If not received, then uses select to peek + for remaining bytes of the message. If message is not received in 3 + seconds, then we have a problem. Report an error and exit. + */ + while(total < len) + { + recvLen = ooSocketRecv (call->pH245Channel->sock, message1, len-total); + memcpy(message+total, message1, recvLen); + total = total + recvLen; + if(total == len) break; /* Complete message is received */ + FD_ZERO(&readfds); + FD_SET(call->pH245Channel->sock, &readfds); + timeout.tv_sec = 3; + timeout.tv_usec = 0; + ret = ooSocketSelect(call->pH245Channel->sock+1, &readfds, NULL, + NULL, &timeout); + if(ret == -1) + { + OOTRACEERR3("Error in select...H245 Receive-Clearing call (%s, %s)\n", + call->callType, call->callToken); + ooFreeH245Message(call, pmsg); + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + /* If remaining part of the message is not received in 3 seconds + exit */ + if(!FD_ISSET(call->pH245Channel->sock, &readfds)) + { + OOTRACEERR3("Error: Incomplete h245 message received (%s, %s)\n", + call->callType, call->callToken); + ooFreeH245Message(call, pmsg); + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + } + + OOTRACEDBGC3("Complete H245 message received (%s, %s)\n", + call->callType, call->callToken); + setPERBuffer(pctxt, message, recvLen, aligned); + initializePrintHandler(&printHandler, "Received H.245 Message"); + + /* Set event handler */ + setEventHandler (pctxt, &printHandler); + + ret = asn1PD_H245MultimediaSystemControlMessage(pctxt, &(pmsg->h245Msg)); + if(ret != ASN_OK) + { + OOTRACEERR3("Error decoding H245 message (%s, %s)\n", + call->callType, call->callToken); + ooFreeH245Message(call, pmsg); + return OO_FAILED; + } + finishPrint(); + removeEventHandler(pctxt); + ooHandleH245Message(call, pmsg); + return OO_OK; +} + +/* Generic Send Message functionality. Based on type of message to be sent, + it calls the corresponding function to retrieve the message buffer and + then transmits on the associated channel + Interpreting msgptr: + Q931 messages except facility + 1st octet - msgType, next 4 octets - tpkt header, + followed by encoded msg + Q931 message facility + 1st octect - OOFacility, 2nd octet - tunneled msg + type(in case no tunneled msg - OOFacility), + 3rd and 4th octet - associated logical channel + of the tunneled msg(0 when no channel is + associated. ex. in case of MSD, TCS), next + 4 octets - tpkt header, followed by encoded + message. + + H.245 messages no tunneling + 1st octet - msg type, next two octets - logical + channel number(0, when no channel is associated), + next two octets - total length of the message + (including tpkt header) + + H.245 messages - tunneling. + 1st octet - msg type, next two octets - logical + channel number(0, when no channel is associated), + next two octets - total length of the message. + Note, no tpkt header is present in this case. + +*/ +int ooSendMsg(OOH323CallData *call, int type) +{ + + int len=0, ret=0, msgType=0, tunneledMsgType=0, logicalChannelNo = 0; + DListNode * p_msgNode=NULL; + ASN1OCTET *msgptr, *msgToSend=NULL; + + + + if(call->callState == OO_CALL_CLEARED) + { + OOTRACEDBGA3("Warning:Call marked for cleanup. Can not send message." + "(%s, %s)\n", call->callType, call->callToken); + return OO_OK; + } + + if(type == OOQ931MSG) + { + if(call->pH225Channel->outQueue.count == 0) + { + OOTRACEWARN3("WARN:No H.2250 message to send. (%s, %s)\n", + call->callType, call->callToken); + return OO_FAILED; + } + + OOTRACEDBGA3("Sending Q931 message (%s, %s)\n", call->callType, + call->callToken); + p_msgNode = call->pH225Channel->outQueue.head; + msgptr = (ASN1OCTET*) p_msgNode->data; + msgType = msgptr[0]; + + if(msgType == OOFacility) + { + tunneledMsgType = msgptr[1]; + logicalChannelNo = msgptr[2]; + logicalChannelNo = logicalChannelNo << 8; + logicalChannelNo = (logicalChannelNo | msgptr[3]); + len = msgptr[6]; + len = len<<8; + len = (len | msgptr[7]); + msgToSend = msgptr+4; + } + else { + len = msgptr[3]; + len = len<<8; + len = (len | msgptr[4]); + msgToSend = msgptr+1; + } + + /* Remove the message from rtdlist pH225Channel->outQueue */ + dListRemove(&(call->pH225Channel->outQueue), p_msgNode); + if(p_msgNode) + memFreePtr(call->pctxt, p_msgNode); + + /*TODO: This is not required ideally. We will see for some time and if + we don't face any problems we will delete this code */ +#if 0 + /* Check whether connection with remote is alright */ + if(!ooChannelsIsConnectionOK(call, call->pH225Channel->sock)) + { + OOTRACEERR3("Error:Transport failure for signalling channel. " + "Abandoning message send and marking call for cleanup.(%s" + "'%s)\n", call->callType, call->callToken); + if(call->callState < OO_CALL_CLEAR) + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + call->callState = OO_CALL_CLEARED; + return OO_OK; + } +#endif + /* Send message out via TCP */ + ret = ooSocketSend(call->pH225Channel->sock, msgToSend, len); + if(ret == ASN_OK) + { + memFreePtr (call->pctxt, msgptr); + OOTRACEDBGC3("H2250/Q931 Message sent successfully (%s, %s)\n", + call->callType, call->callToken); + ooOnSendMsg(call, msgType, tunneledMsgType, logicalChannelNo); + return OO_OK; + } + else{ + OOTRACEERR3("H2250Q931 Message send failed (%s, %s)\n", + call->callType, call->callToken); + memFreePtr (call->pctxt, msgptr); + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + }/* end of type==OOQ931MSG */ + if(type == OOH245MSG) + { + if(call->pH245Channel->outQueue.count == 0) + { + OOTRACEWARN3("WARN:No H.245 message to send. (%s, %s)\n", + call->callType, call->callToken); + return OO_FAILED; + } + OOTRACEDBGA3("Sending H245 message (%s, %s)\n", call->callType, + call->callToken); + p_msgNode = call->pH245Channel->outQueue.head; + msgptr = (ASN1OCTET*) p_msgNode->data; + msgType = msgptr[0]; + + logicalChannelNo = msgptr[1]; + logicalChannelNo = logicalChannelNo << 8; + logicalChannelNo = (logicalChannelNo | msgptr[2]); + + len = msgptr[3]; + len = len<<8; + len = (len | msgptr[4]); + /* Remove the message from queue */ + dListRemove(&(call->pH245Channel->outQueue), p_msgNode); + if(p_msgNode) + memFreePtr(call->pctxt, p_msgNode); + + /* Send message out */ + if (0 == call->pH245Channel && !OO_TESTFLAG(call->flags, OO_M_TUNNELING)) + { + OOTRACEWARN3("Neither H.245 channel nor tunneling active " + "(%s, %s)\n", call->callType, call->callToken); + memFreePtr (call->pctxt, msgptr); + /*ooCloseH245Session(call);*/ + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + call->callState = OO_CALL_CLEAR; + } + return OO_OK; + } + + if (0 != call->pH245Channel && 0 != call->pH245Channel->sock) + { + OOTRACEDBGC4("Sending %s H245 message over H.245 channel. " + "(%s, %s)\n", ooGetMsgTypeText(msgType), + call->callType, call->callToken); + + ret = ooSocketSend(call->pH245Channel->sock, msgptr+5, len); + if(ret == ASN_OK) + { + memFreePtr (call->pctxt, msgptr); + OOTRACEDBGA3("H245 Message sent successfully (%s, %s)\n", + call->callType, call->callToken); + ooOnSendMsg(call, msgType, tunneledMsgType, logicalChannelNo); + return OO_OK; + } + else{ + memFreePtr (call->pctxt, msgptr); + OOTRACEERR3("ERROR:H245 Message send failed (%s, %s)\n", + call->callType, call->callToken); + if(call->callState < OO_CALL_CLEAR) + { + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + call->callState = OO_CALL_CLEAR; + } + return OO_FAILED; + } + } + else if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) { + OOTRACEDBGC4("Sending %s H245 message as a tunneled message." + "(%s, %s)\n", ooGetMsgTypeText(msgType), + call->callType, call->callToken); + + ret = ooSendAsTunneledMessage + (call, msgptr+5,len,msgType, logicalChannelNo); + + if(ret != OO_OK) + { + memFreePtr (call->pctxt, msgptr); + 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, msgptr); + return OO_OK; + } + } + /* Need to add support for other messages such as T38 etc */ + OOTRACEWARN3("ERROR:Unknown message type - message not Sent (%s, %s)\n", + call->callType, call->callToken); + return OO_FAILED; +} + +int ooCloseH245Connection(OOH323CallData *call) +{ + OOTRACEINFO3("Closing H.245 connection (%s, %s)\n", call->callType, + call->callToken); + + if (0 != call->pH245Channel) + { + if(0 != call->pH245Channel->sock) + ooSocketClose (call->pH245Channel->sock); + if (call->pH245Channel->outQueue.count > 0) + dListFreeAll(call->pctxt, &(call->pH245Channel->outQueue)); + memFreePtr (call->pctxt, call->pH245Channel); + call->pH245Channel = NULL; + OOTRACEDBGC3("Closed H245 connection. (%s, %s)\n", call->callType, + call->callToken); + } + call->h245SessionState = OO_H245SESSION_CLOSED; + + return OO_OK; +} + +int ooCloseH245Listener(OOH323CallData *call) +{ + OOTRACEINFO3("Closing H.245 Listener (%s, %s)\n", call->callType, + call->callToken); + if(call->h245listener) + { + ooSocketClose(*(call->h245listener)); + memFreePtr(call->pctxt, call->h245listener); + call->h245listener = NULL; + } + return OO_OK; +} + +int ooOnSendMsg + (OOH323CallData *call, int msgType, int tunneledMsgType, int associatedChan) +{ + ooTimerCallback *cbData=NULL; + switch(msgType) + { + case OOSetup: + OOTRACEINFO3("Sent Message - Setup (%s, %s)\n", call->callType, + call->callToken); + /* Start call establishment timer */ + cbData = (ooTimerCallback*) memAlloc(call->pctxt, + sizeof(ooTimerCallback)); + if(!cbData) + { + OOTRACEERR3("Error:Unable to allocate memory for timer callback." + "(%s, %s)\n", call->callType, call->callToken); + return OO_FAILED; + } + cbData->call = call; + cbData->timerType = OO_CALLESTB_TIMER; + if(!ooTimerCreate(call->pctxt, &call->timerList, &ooCallEstbTimerExpired, + gH323ep.callEstablishmentTimeout, cbData, FALSE)) + { + OOTRACEERR3("Error:Unable to create call establishment timer. " + "(%s, %s)\n", call->callType, call->callToken); + memFreePtr(call->pctxt, cbData); + return OO_FAILED; + } + + if(gH323ep.h323Callbacks.onOutgoingCall) + gH323ep.h323Callbacks.onOutgoingCall(call); + break; + case OOCallProceeding: + OOTRACEINFO3("Sent Message - CallProceeding (%s, %s)\n", call->callType, + call->callToken); + break; + case OOAlert: + OOTRACEINFO3("Sent Message - Alerting (%s, %s) \n", call->callType, + call->callToken); + if(gH323ep.h323Callbacks.onAlerting && call->callState < OO_CALL_CLEAR) + gH323ep.h323Callbacks.onAlerting(call); + break; + case OOConnect: + OOTRACEINFO3("Sent Message - Connect (%s, %s)\n", call->callType, + call->callToken); + if(gH323ep.h323Callbacks.onCallEstablished) + gH323ep.h323Callbacks.onCallEstablished(call); + break; + case OOReleaseComplete: + OOTRACEINFO3("Sent Message - ReleaseComplete (%s, %s)\n", call->callType, + call->callToken); + + if(call->callState == OO_CALL_CLEAR_RELEASERECVD) + call->callState = OO_CALL_CLEARED; + else{ + call->callState = OO_CALL_CLEAR_RELEASESENT; + if(gH323ep.gkClient && !OO_TESTFLAG(call->flags, OO_M_DISABLEGK) && + gH323ep.gkClient->state == GkClientRegistered){ + OOTRACEDBGA3("Sending DRQ after sending ReleaseComplete." + "(%s, %s)\n", call->callType, call->callToken); + ooGkClientSendDisengageRequest(gH323ep.gkClient, call); + } + } + + if(call->callState == OO_CALL_CLEAR_RELEASESENT && + call->h245SessionState == OO_H245SESSION_IDLE) + { + 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_SESSION_TIMER; + cbData->channelNumber = 0; + if(!ooTimerCreate(call->pctxt, &call->timerList, + &ooSessionTimerExpired, gH323ep.sessionTimeout, cbData, FALSE)) + { + OOTRACEERR3("Error:Unable to create EndSession timer- " + "ReleaseComplete.(%s, %s)\n", call->callType, + call->callToken); + memFreePtr(call->pctxt, cbData); + return OO_FAILED; + } + } + + if(call->h245SessionState == OO_H245SESSION_CLOSED) + { + call->callState = OO_CALL_CLEARED; + } + break; + + case OOFacility: + if(tunneledMsgType == OOFacility) + { + OOTRACEINFO3("Sent Message - Facility. (%s, %s)\n", + call->callType, call->callToken); + } + else{ + OOTRACEINFO4("Sent Message - Facility(%s) (%s, %s)\n", + ooGetMsgTypeText(tunneledMsgType), + call->callType, call->callToken); + + ooOnSendMsg(call, tunneledMsgType, 0, associatedChan); + } + break; + + case OOMasterSlaveDetermination: + if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + OOTRACEINFO3("Tunneled Message - MasterSlaveDetermination (%s, %s)\n", + call->callType, call->callToken); + else + OOTRACEINFO3("Sent Message - MasterSlaveDetermination (%s, %s)\n", + call->callType, call->callToken); + /* Start MSD timer */ + 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_MSD_TIMER; + if(!ooTimerCreate(call->pctxt, &call->timerList, &ooMSDTimerExpired, + gH323ep.msdTimeout, cbData, FALSE)) + { + OOTRACEERR3("Error:Unable to create MSD timer. " + "(%s, %s)\n", call->callType, call->callToken); + memFreePtr(call->pctxt, cbData); + return OO_FAILED; + } + + break; + case OOMasterSlaveAck: + if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + OOTRACEINFO3("Tunneled Message - MasterSlaveDeterminationAck (%s, %s)" + "\n", call->callType, call->callToken); + else + OOTRACEINFO3("Sent Message - MasterSlaveDeterminationAck (%s, %s)\n", + call->callType, call->callToken); + break; + case OOMasterSlaveReject: + if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + OOTRACEINFO3("Tunneled Message - MasterSlaveDeterminationReject " + "(%s, %s)\n", call->callType, call->callToken); + else + OOTRACEINFO3("Sent Message - MasterSlaveDeterminationReject(%s, %s)\n", + call->callType, call->callToken); + break; + case OOMasterSlaveRelease: + if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + OOTRACEINFO3("Tunneled Message - MasterSlaveDeterminationRelease " + "(%s, %s)\n", call->callType, call->callToken); + else + OOTRACEINFO3("Sent Message - MasterSlaveDeterminationRelease " + "(%s, %s)\n", call->callType, call->callToken); + break; + case OOTerminalCapabilitySet: + if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) { + /* If session isn't marked active yet, do it. possible in case of + tunneling */ + if(call->h245SessionState == OO_H245SESSION_IDLE || + call->h245SessionState == OO_H245SESSION_PAUSED) { + call->h245SessionState = OO_H245SESSION_ACTIVE; + } + OOTRACEINFO3("Tunneled Message - TerminalCapabilitySet (%s, %s)\n", + call->callType, call->callToken); + } + else { + OOTRACEINFO3("Sent Message - TerminalCapabilitySet (%s, %s)\n", + call->callType, call->callToken); + } + /* Start TCS timer */ + 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_TCS_TIMER; + if(!ooTimerCreate(call->pctxt, &call->timerList, &ooTCSTimerExpired, + gH323ep.tcsTimeout, cbData, FALSE)) + { + OOTRACEERR3("Error:Unable to create TCS timer. " + "(%s, %s)\n", call->callType, call->callToken); + memFreePtr(call->pctxt, cbData); + return OO_FAILED; + } + break; + + + case OOTerminalCapabilitySetAck: + if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + OOTRACEINFO3("Tunneled Message - TerminalCapabilitySetAck (%s, %s)\n", + call->callType, call->callToken); + else + OOTRACEINFO3("Sent Message - TerminalCapabilitySetAck (%s, %s)\n", + call->callType, call->callToken); + break; + case OOTerminalCapabilitySetReject: + if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + OOTRACEINFO3("Tunneled Message - TerminalCapabilitySetReject " + "(%s, %s)\n", call->callType, call->callToken); + else + OOTRACEINFO3("Sent Message - TerminalCapabilitySetReject (%s, %s)\n", + call->callType, call->callToken); + break; + case OOOpenLogicalChannel: + if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + OOTRACEINFO4("Tunneled Message - OpenLogicalChannel(%d). (%s, %s)\n", + associatedChan, call->callType, call->callToken); + else + OOTRACEINFO4("Sent Message - OpenLogicalChannel(%d). (%s, %s)\n", + associatedChan, call->callType, call->callToken); + /* Start LogicalChannel timer */ + 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_OLC_TIMER; + cbData->channelNumber = associatedChan; + if(!ooTimerCreate(call->pctxt, &call->timerList, + &ooOpenLogicalChannelTimerExpired, gH323ep.logicalChannelTimeout, + cbData, FALSE)) + { + OOTRACEERR3("Error:Unable to create OpenLogicalChannel timer. " + "(%s, %s)\n", call->callType, call->callToken); + memFreePtr(call->pctxt, cbData); + return OO_FAILED; + } + + break; + case OOOpenLogicalChannelAck: + if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + OOTRACEINFO4("Tunneled Message - OpenLogicalChannelAck(%d) (%s,%s)\n", + associatedChan, call->callType, call->callToken); + else + OOTRACEINFO4("Sent Message - OpenLogicalChannelAck(%d) (%s, %s)\n", + associatedChan, call->callType, call->callToken); + break; + case OOOpenLogicalChannelReject: + if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + OOTRACEINFO4("Tunneled Message - OpenLogicalChannelReject(%d)" + "(%s, %s)\n", associatedChan, call->callType, + call->callToken); + else + OOTRACEINFO4("Sent Message - OpenLogicalChannelReject(%d) (%s, %s)\n", + associatedChan, call->callType, call->callToken); + break; + case OOEndSessionCommand: + if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + OOTRACEINFO3("Tunneled Message - EndSessionCommand(%s, %s)\n", + call->callType, call->callToken); + else + OOTRACEINFO3("Sent Message - EndSessionCommand (%s, %s)\n", + call->callType, call->callToken); + if((call->h245SessionState == OO_H245SESSION_ACTIVE)) + { + /* Start EndSession timer */ + call->h245SessionState = OO_H245SESSION_ENDSENT; + 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_SESSION_TIMER; + cbData->channelNumber = 0; + if(!ooTimerCreate(call->pctxt, &call->timerList, + &ooSessionTimerExpired, gH323ep.sessionTimeout, cbData, FALSE)) + { + OOTRACEERR3("Error:Unable to create EndSession timer. " + "(%s, %s)\n", call->callType, call->callToken); + memFreePtr(call->pctxt, cbData); + return OO_FAILED; + } + } + else{ + ooCloseH245Connection(call); + } + break; + case OOCloseLogicalChannel: + if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + OOTRACEINFO3("Tunneled Message - CloseLogicalChannel (%s, %s)\n", + call->callType, call->callToken); + else + OOTRACEINFO3("Sent Message - CloseLogicalChannel (%s, %s)\n", + call->callType, call->callToken); + /* Start LogicalChannel timer */ + 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_CLC_TIMER; + cbData->channelNumber = associatedChan; + if(!ooTimerCreate(call->pctxt, &call->timerList, + &ooCloseLogicalChannelTimerExpired, gH323ep.logicalChannelTimeout, + cbData, FALSE)) + { + OOTRACEERR3("Error:Unable to create CloseLogicalChannel timer. " + "(%s, %s)\n", call->callType, call->callToken); + memFreePtr(call->pctxt, cbData); + return OO_FAILED; + } + + break; + case OOCloseLogicalChannelAck: + if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + OOTRACEINFO3("Tunneled Message - CloseLogicalChannelAck (%s, %s)\n", + call->callType, call->callToken); + else + OOTRACEINFO3("Sent Message - CloseLogicalChannelAck (%s, %s)\n", + call->callType, call->callToken); + break; + case OORequestChannelClose: + if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + OOTRACEINFO3("Tunneled Message - RequestChannelClose (%s, %s)\n", + call->callType, call->callToken); + else + OOTRACEINFO3("Sent Message - RequestChannelClose (%s, %s)\n", + call->callType, call->callToken); + /* Start RequestChannelClose timer */ + 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_RCC_TIMER; + cbData->channelNumber = associatedChan; + if(!ooTimerCreate(call->pctxt, &call->timerList, + &ooRequestChannelCloseTimerExpired, gH323ep.logicalChannelTimeout, + cbData, FALSE)) + { + OOTRACEERR3("Error:Unable to create RequestChannelClose timer. " + "(%s, %s)\n", call->callType, call->callToken); + memFreePtr(call->pctxt, cbData); + return OO_FAILED; + } + break; + case OORequestChannelCloseAck: + if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) + OOTRACEINFO3("Tunneled Message - RequestChannelCloseAck (%s, %s)\n", + call->callType, call->callToken); + else + OOTRACEINFO3("Sent Message - RequestChannelCloseAck (%s, %s)\n", + call->callType, call->callToken); + break; + + default: + ; + } + return OO_OK; +} + + +int ooStopMonitorCalls() +{ + OOH323CallData * call; + if(gMonitor) + { + OOTRACEINFO1("Doing ooStopMonitorCalls\n"); + if(gH323ep.cmdSock) + { + ooCloseCmdConnection(); + } + + if(gH323ep.callList) + { + OOTRACEWARN1("Warn:Abruptly ending calls as stack going down\n"); + call = gH323ep.callList; + while(call) + { + OOTRACEWARN3("Clearing call (%s, %s)\n", call->callType, + call->callToken); + call->callEndReason = OO_REASON_LOCAL_CLEARED; + ooCleanCall(call); + call = NULL; + call = gH323ep.callList; + } + gH323ep.callList = NULL; + } + OOTRACEINFO1("Stopping listener for incoming calls\n"); + if(gH323ep.listener) + { + ooSocketClose(*(gH323ep.listener)); + memFreePtr(&gH323ep.ctxt, gH323ep.listener); + gH323ep.listener = NULL; + } + + gMonitor = FALSE; + OOTRACEINFO1("Done ooStopMonitorCalls\n"); + } + return OO_OK; +} + +OOBOOL ooChannelsIsConnectionOK(OOH323CallData *call, OOSOCKET sock) +{ + struct timeval to; + fd_set readfds; + int ret = 0, nfds=0; + + to.tv_sec = 0; + to.tv_usec = 500; + FD_ZERO(&readfds); + + FD_SET(sock, &readfds); + if(nfds < (int)sock) + nfds = (int)sock; + + nfds++; + + ret = ooSocketSelect(nfds, &readfds, NULL, NULL, &to); + + if(ret == -1) + { + OOTRACEERR3("Error in select ...broken pipe check(%s, %s)\n", + call->callType, call->callToken ); + return FALSE; + } + + if(FD_ISSET(sock, &readfds)) + { + char buf[2]; + if(ooSocketRecvPeek(sock, buf, 2) == 0) + { + OOTRACEWARN3("Broken pipe detected. (%s, %s)", call->callType, + call->callToken); + if(call->callState < OO_CALL_CLEAR) + call->callEndReason = OO_REASON_TRANSPORTFAILURE; + call->callState = OO_CALL_CLEARED; + return FALSE; + } + } + return TRUE; +} |