2020 lines
65 KiB
C
2020 lines
65 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 "asterisk/poll-compat.h"
|
|
#include "asterisk/config.h"
|
|
#include "asterisk/netsock2.h"
|
|
|
|
#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 "ooSocket.h"
|
|
#include "ootypes.h"
|
|
|
|
|
|
/** Global endpoint structure */
|
|
extern OOH323EndPoint gH323ep;
|
|
extern ast_mutex_t callListLock;
|
|
extern ast_mutex_t monitorLock;
|
|
|
|
extern DList g_TimerList;
|
|
|
|
static OOBOOL gMonitor = FALSE;
|
|
|
|
int ooSetCmdFDSETs(struct pollfd *pfds, int *nfds);
|
|
int ooProcessCmdFDSETsAndTimers
|
|
(struct pollfd *pfds, int nfds, struct timeval *pToMin);
|
|
int ooSetFDSETs(struct pollfd *pfds, int *nfds);
|
|
int ooProcessFDSETsAndTimers
|
|
(struct pollfd* pfds, int nfds, struct timeval *pToMin);
|
|
int ooProcessCallFDSETsAndTimers
|
|
(OOH323CallData *call, struct pollfd* pfds, int nfds, struct timeval *pToMin);
|
|
int ooSetCallFDSETs(OOH323CallData* call, struct pollfd* pfds, int *nfds);
|
|
|
|
|
|
|
|
int ooCreateH245Listener(OOH323CallData *call)
|
|
{
|
|
int ret=0;
|
|
OOSOCKET channelSocket=0;
|
|
OOTRACEINFO1("Creating H245 listener\n");
|
|
if((ret=ooSocketCreate (&channelSocket, call->versionIP))!=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), 4096);
|
|
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, call->versionIP))!=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 successful (%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;
|
|
}
|
|
}
|
|
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, (char *)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, i;
|
|
OOSOCKET channelSocket=0;
|
|
for (i=0;i<3;i++) {
|
|
if((ret=ooSocketCreate (&channelSocket, call->versionIP))!=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;
|
|
|
|
OOTRACEINFO6("Trying to connect to remote endpoint(%s:%d) (IPv%d) to setup "
|
|
"H2250 channel (%s, %s)\n", call->remoteIP,
|
|
call->remotePort, call->versionIP, call->callType, call->callToken);
|
|
|
|
if((ret=ooSocketConnect(channelSocket, call->remoteIP,
|
|
call->remotePort))==ASN_OK)
|
|
{
|
|
call->pH225Channel->sock = channelSocket;
|
|
|
|
OOTRACEINFO3("H2250 transmitter channel creation - successful "
|
|
"(%s, %s)\n", call->callType, call->callToken);
|
|
|
|
/* If multihomed, get ip from socket */
|
|
if(!strcmp(call->localIP, "0.0.0.0") || !strcmp(call->localIP, "::"))
|
|
{
|
|
OOTRACEDBGA3("Determining IP address for outgoing call in "
|
|
"multihomed mode. (%s, %s)\n", call->callType,
|
|
call->callToken);
|
|
ret = ooSocketGetIpAndPort(channelSocket, call->localIP, 2+8*4+7,
|
|
&call->pH225Channel->port, NULL);
|
|
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
|
|
{
|
|
OOTRACEERR5("ERROR:Failed to connect to remote destination for "
|
|
"transmit H2250 channel(%s, %s, %d, %s)\n",call->callType,
|
|
call->callToken, channelSocket, call->localIP);
|
|
close(channelSocket);
|
|
|
|
if(call->callState < OO_CALL_CLEAR)
|
|
{ /* No one is listening at remote end */
|
|
call->callState = OO_CALL_CLEAR;
|
|
call->callEndReason = OO_REASON_NOUSER;
|
|
}
|
|
if (i>=2) return OO_FAILED; else continue;
|
|
}
|
|
|
|
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 */
|
|
ret = ast_parse_arg(gH323ep.signallingIP, PARSE_ADDR, &ipaddrs);
|
|
if((ret=ooSocketCreate (&channelSocket, ast_sockaddr_is_ipv6(&ipaddrs) ? 6 : 4))
|
|
!=ASN_OK)
|
|
{
|
|
OOTRACEERR1("Failed to create socket for H323 Listener\n");
|
|
return OO_FAILED;
|
|
}
|
|
if((ret=ooSocketBind (channelSocket, ipaddrs,
|
|
gH323ep.listenPort))==ASN_OK)
|
|
{
|
|
gH323ep.listener = (OOSOCKET*)memAlloc(&gH323ep.ctxt,sizeof(OOSOCKET));
|
|
*(gH323ep.listener) = channelSocket;
|
|
|
|
ooSocketListen(channelSocket,2048); /*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];
|
|
char remoteIP[2+8*4+7];
|
|
OOSOCKET h225Channel=0;
|
|
|
|
memset(remoteIP, 0, sizeof(remoteIP));
|
|
ret = ooSocketAccept (*(gH323ep.listener), &h225Channel,
|
|
remoteIP, 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;
|
|
}
|
|
|
|
ast_mutex_lock(&call->Lock);
|
|
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") || !strcmp(call->localIP,"::"))
|
|
{
|
|
OOTRACEDBGA3("Determining IP address for incoming call in multihomed "
|
|
"mode (%s, %s)\n", call->callType, call->callToken);
|
|
|
|
}
|
|
ret = ooSocketGetIpAndPort(h225Channel, call->localIP, 2+8*4+7,
|
|
&call->pH225Channel->port, &call->versionIP);
|
|
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;
|
|
}
|
|
ast_mutex_unlock(&call->Lock);
|
|
return OO_FAILED;
|
|
}
|
|
OOTRACEDBGA5("Using Local IP address %s (IPv%d) for incoming call "
|
|
"(%s, %s)\n", call->localIP, call->versionIP, call->callType,
|
|
call->callToken);
|
|
|
|
if (remoteIP[0]) {
|
|
memcpy(call->remoteIP, remoteIP, strlen(remoteIP) + 1);
|
|
}
|
|
|
|
ast_mutex_unlock(&call->Lock);
|
|
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);
|
|
|
|
return OO_OK;
|
|
}
|
|
|
|
|
|
int ooSetCmdFDSETs(struct pollfd *pfds, int *nfds)
|
|
{
|
|
if(gH323ep.cmdSock)
|
|
{
|
|
pfds[*nfds].fd = gH323ep.cmdSock;
|
|
pfds[*nfds].events = POLLIN;
|
|
(*nfds)++;
|
|
}
|
|
|
|
return OO_OK;
|
|
|
|
}
|
|
|
|
int ooProcessCmdFDSETsAndTimers
|
|
(struct pollfd *pfds, int nfds, struct timeval *pToMin)
|
|
{
|
|
if(gH323ep.cmdSock) {
|
|
if(ooPDRead(pfds, nfds, gH323ep.cmdSock)) {
|
|
if(ooReadAndProcessStackCommand() != OO_OK) {
|
|
/* ooReadAndProcessStackCommand prints an error message */
|
|
return OO_FAILED;
|
|
}
|
|
}
|
|
}
|
|
|
|
return OO_OK;
|
|
|
|
}
|
|
|
|
|
|
int ooSetFDSETs(struct pollfd *pfds, int *nfds)
|
|
{
|
|
if(gH323ep.gkClient && gH323ep.gkClient->rasSocket != 0)
|
|
{
|
|
pfds[*nfds].fd = gH323ep.gkClient->rasSocket;
|
|
pfds[*nfds].events = POLLIN;
|
|
(*nfds)++;
|
|
}
|
|
if(gH323ep.listener)
|
|
{
|
|
pfds[*nfds].fd = *gH323ep.listener;
|
|
pfds[*nfds].events = POLLIN;
|
|
(*nfds)++;
|
|
}
|
|
|
|
return OO_OK;
|
|
|
|
}
|
|
|
|
int ooSetCallFDSETs(OOH323CallData* call, struct pollfd* pfds, int *nfds)
|
|
{
|
|
|
|
if(call) {
|
|
|
|
if(call->cmdSock && call->callState < OO_CALL_CLEAR) {
|
|
pfds[*nfds].fd = call->cmdSock;
|
|
pfds[*nfds].events = POLLIN;
|
|
(*nfds)++;
|
|
}
|
|
|
|
if (0 != call->pH225Channel && 0 != call->pH225Channel->sock) {
|
|
pfds[*nfds].fd = call->pH225Channel->sock;
|
|
pfds[*nfds].events = POLLIN;
|
|
|
|
if (call->pH225Channel->outQueue.count > 0 ||
|
|
(OO_TESTFLAG (call->flags, OO_M_TUNNELING) &&
|
|
0 != call->pH245Channel &&
|
|
call->pH245Channel->outQueue.count>0))
|
|
pfds[*nfds].events |= POLLOUT;
|
|
(*nfds)++;
|
|
|
|
}
|
|
|
|
if (0 != call->pH245Channel && call->pH245Channel->sock != 0) {
|
|
pfds[*nfds].fd = call->pH245Channel->sock;
|
|
pfds[*nfds].events = POLLIN;
|
|
if (call->pH245Channel->outQueue.count>0)
|
|
pfds[*nfds].events |= POLLOUT;
|
|
(*nfds)++;
|
|
}
|
|
else if(call->h245listener) {
|
|
OOTRACEINFO3("H.245 Listerner socket being monitored "
|
|
"(%s, %s)\n", call->callType, call->callToken);
|
|
pfds[*nfds].fd = *(call->h245listener);
|
|
pfds[*nfds].events = POLLIN;
|
|
(*nfds)++;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
return OO_OK;
|
|
}
|
|
|
|
int ooProcessFDSETsAndTimers
|
|
(struct pollfd* pfds, int nfds, struct timeval *pToMin)
|
|
{
|
|
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)
|
|
{
|
|
ooGkClientHandleClientOrGkFailure(gH323ep.gkClient);
|
|
}
|
|
}
|
|
|
|
/* Manage ready descriptors after select */
|
|
|
|
if(0 != gH323ep.gkClient && 0 != gH323ep.gkClient->rasSocket)
|
|
{
|
|
if(ooPDRead(pfds, nfds, gH323ep.gkClient->rasSocket) )
|
|
{
|
|
ooGkClientReceive(gH323ep.gkClient);
|
|
if(gH323ep.gkClient->state == GkClientFailed ||
|
|
gH323ep.gkClient->state == GkClientGkErr) {
|
|
ooGkClientHandleClientOrGkFailure(gH323ep.gkClient);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(gH323ep.listener)
|
|
{
|
|
if(ooPDRead(pfds, nfds, *(gH323ep.listener)))
|
|
{
|
|
OOTRACEDBGA1("New connection at H225 receiver\n");
|
|
ooAcceptH225Connection();
|
|
}
|
|
}
|
|
|
|
|
|
return OO_OK;
|
|
|
|
}
|
|
int ooProcessCallFDSETsAndTimers
|
|
(OOH323CallData *call, struct pollfd* pfds, int nfds, struct timeval *pToMin)
|
|
{
|
|
struct timeval toNext;
|
|
|
|
if(call)
|
|
{
|
|
|
|
if(call->cmdSock) {
|
|
if(ooPDRead(pfds, nfds, call->cmdSock)) {
|
|
ast_mutex_lock(&call->Lock);
|
|
if(ooReadAndProcessCallStackCommand(call) != OO_OK) {
|
|
/* ooReadAndProcessStackCommand prints an error message */
|
|
ast_mutex_unlock(&call->Lock);
|
|
return OO_FAILED;
|
|
}
|
|
ast_mutex_unlock(&call->Lock);
|
|
}
|
|
}
|
|
|
|
ooTimerFireExpired(call->pctxt, &call->timerList);
|
|
if (0 != call->pH225Channel && 0 != call->pH225Channel->sock)
|
|
{
|
|
if(ooPDRead(pfds, nfds, call->pH225Channel->sock))
|
|
{
|
|
if(ooH2250Receive(call) != OO_OK)
|
|
{
|
|
OOTRACEERR3("ERROR:Failed ooH2250Receive - Clearing call "
|
|
"(%s, %s)\n", call->callType, call->callToken);
|
|
if(call->callState < OO_CALL_CLEAR)
|
|
{
|
|
if (!call->callEndReason) call->callEndReason = OO_REASON_INVALIDMESSAGE;
|
|
call->callState = OO_CALL_CLEAR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0 != call->pH245Channel && 0 != call->pH245Channel->sock)
|
|
if(ooPDRead(pfds, nfds, call->pH245Channel->sock))
|
|
ooH245Receive(call);
|
|
|
|
if (0 != call->pH245Channel && 0 != call->pH245Channel->sock)
|
|
{
|
|
if(ooPDWrite(pfds, nfds, call->pH245Channel->sock)) {
|
|
if (call->pH245Channel->outQueue.count>0) {
|
|
if (ooSendMsg(call, OOH245MSG) != OO_OK)
|
|
OOTRACEERR1("Error in sending h245 message\n");
|
|
}
|
|
}
|
|
}
|
|
else if(call->h245listener)
|
|
{
|
|
if(ooPDRead(pfds, nfds, *(call->h245listener)))
|
|
{
|
|
OOTRACEDBGC3("Incoming H.245 connection (%s, %s)\n",
|
|
call->callType, call->callToken);
|
|
ooAcceptH245Connection(call);
|
|
}
|
|
}
|
|
|
|
if (0 != call->pH225Channel && 0 != call->pH225Channel->sock)
|
|
{
|
|
if(ooPDWrite(pfds, nfds, call->pH225Channel->sock))
|
|
{
|
|
if (call->pH225Channel->outQueue.count>0)
|
|
{
|
|
OOTRACEDBGC3("Sending H225 message (%s, %s)\n",
|
|
call->callType, call->callToken);
|
|
if (ooSendMsg(call, OOQ931MSG) != OO_OK)
|
|
OOTRACEERR1("Error in sending h225 message\n");
|
|
}
|
|
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);
|
|
if (ooSendMsg(call, OOH245MSG) != OO_OK)
|
|
OOTRACEERR1("Error in sending h245 message\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
if(ooTimerNextTimeout(&call->timerList, &toNext))
|
|
{
|
|
if(ooCompareTimeouts(pToMin, &toNext) > 0)
|
|
{
|
|
pToMin->tv_sec = toNext.tv_sec;
|
|
pToMin->tv_usec = toNext.tv_usec;
|
|
}
|
|
}
|
|
|
|
if(call->callState >= OO_CALL_CLEAR && call->callState < OO_CALL_CLEARED) {
|
|
ast_mutex_lock(&call->Lock);
|
|
ooEndCall(call);
|
|
ast_mutex_unlock(&call->Lock);
|
|
} else if(call->callState == OO_CALL_CLEARED) {
|
|
ast_mutex_lock(&call->Lock);
|
|
ooEndCall(call);
|
|
ast_mutex_unlock(&call->Lock);
|
|
}
|
|
if(call->callState >= OO_CALL_CLEARED)
|
|
ooStopMonitorCallChannels(call);
|
|
}
|
|
|
|
return OO_OK;
|
|
|
|
}
|
|
|
|
int ooMonitorCmdChannels()
|
|
{
|
|
int ret=0, nfds=0;
|
|
struct timeval toMin;
|
|
struct pollfd pfds[1];
|
|
|
|
gMonitor = TRUE;
|
|
|
|
toMin.tv_sec = 3;
|
|
toMin.tv_usec = 0;
|
|
|
|
while(1)
|
|
{
|
|
nfds = 0;
|
|
ooSetCmdFDSETs(pfds, &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;
|
|
ooSocketPoll(pfds, nfds, toMin.tv_usec / 1000);
|
|
}
|
|
#endif
|
|
else
|
|
ret = ooSocketPoll(pfds, nfds, toMin.tv_sec * 1000 + toMin.tv_usec / 1000);
|
|
|
|
if(ret == -1)
|
|
{
|
|
|
|
OOTRACEERR1("Error in poll ...exiting\n");
|
|
exit(-1);
|
|
continue;
|
|
}
|
|
|
|
toMin.tv_sec = 2; /* 2 sec */
|
|
toMin.tv_usec = 100000; /* 100ms*/
|
|
|
|
ast_mutex_lock(&monitorLock);
|
|
if(ooProcessCmdFDSETsAndTimers(pfds, nfds, &toMin) != OO_OK)
|
|
{
|
|
/* ooStopMonitorCalls(); */
|
|
ast_mutex_unlock(&monitorLock);
|
|
continue;
|
|
}
|
|
ast_mutex_unlock(&monitorLock);
|
|
|
|
}/* while(1)*/
|
|
return OO_OK;
|
|
}
|
|
|
|
int ooMonitorChannels()
|
|
{
|
|
int ret=0, nfds=0;
|
|
struct timeval toMin, toNext;
|
|
struct pollfd pfds[2];
|
|
|
|
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");
|
|
// not need more, now it can be restarted correctly
|
|
// ooGkClientDestroy();
|
|
}
|
|
}
|
|
|
|
while(1)
|
|
{
|
|
nfds = 0;
|
|
ooSetFDSETs(pfds, &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;
|
|
ooSocketPoll(pfds, nfds, toMin.tv_usec / 1000);
|
|
}
|
|
#endif
|
|
else
|
|
ret = ooSocketPoll(pfds, nfds, toMin.tv_sec * 1000 + toMin.tv_usec / 1000);
|
|
|
|
if(ret == -1)
|
|
{
|
|
|
|
OOTRACEERR1("Error in poll ...exiting\n");
|
|
exit(-1);
|
|
}
|
|
|
|
toMin.tv_sec = 2; /* 2 sec */
|
|
toMin.tv_usec = 100000; /* 100ms*/
|
|
/*This is for test application. Not part of actual stack */
|
|
|
|
ast_mutex_lock(&monitorLock);
|
|
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(pfds, nfds, &toMin) != OO_OK)
|
|
{
|
|
ast_mutex_unlock(&monitorLock);
|
|
ooStopMonitorCalls();
|
|
continue;
|
|
}
|
|
|
|
ast_mutex_unlock(&monitorLock);
|
|
}/* while(1)*/
|
|
return OO_OK;
|
|
}
|
|
int ooMonitorCallChannels(OOH323CallData *call)
|
|
{
|
|
int ret=0, nfds=0, zeroloops = 0;
|
|
#define MAX_ZERO_LOOP 1020
|
|
struct timeval toMin;
|
|
struct pollfd pfds[5];
|
|
|
|
OOCTXT* pctxt;
|
|
|
|
call->Monitor = TRUE;
|
|
|
|
toMin.tv_sec = 3;
|
|
toMin.tv_usec = 0;
|
|
|
|
while(1)
|
|
{
|
|
if(!call->Monitor) {
|
|
OOTRACEINFO1("Ending Call Monitor thread\n");
|
|
break;
|
|
}
|
|
|
|
nfds = 0;
|
|
ooSetCallFDSETs(call, pfds, &nfds);
|
|
|
|
|
|
if(nfds == 0)
|
|
#ifdef _WIN32
|
|
Sleep(10);
|
|
#else
|
|
{
|
|
if (zeroloops++ > MAX_ZERO_LOOP) {
|
|
ooCleanCall(call);
|
|
ooStopMonitorCallChannels(call);
|
|
break;
|
|
}
|
|
toMin.tv_sec = 0;
|
|
toMin.tv_usec = 10000;
|
|
ooSocketPoll(pfds, nfds, toMin.tv_usec / 1000);
|
|
}
|
|
#endif
|
|
else
|
|
ret = ooSocketPoll(pfds, nfds, toMin.tv_sec * 1000 + toMin.tv_usec / 1000);
|
|
|
|
if(ret == -1)
|
|
{
|
|
|
|
OOTRACEERR2("Error in poll %d ...exiting\n", errno);
|
|
call->callEndReason = OO_REASON_INVALIDMESSAGE;
|
|
call->callState = OO_CALL_CLEARED;
|
|
ooCleanCall(call);
|
|
ooStopMonitorCallChannels(call);
|
|
break;
|
|
|
|
}
|
|
|
|
toMin.tv_sec = 2; /* 2 sec */
|
|
toMin.tv_usec = 100000; /* 100ms*/
|
|
/*This is for test application. Not part of actual stack */
|
|
|
|
if(ooProcessCallFDSETsAndTimers(call, pfds, nfds, &toMin) != OO_OK)
|
|
{
|
|
ooStopMonitorCallChannels(call);
|
|
continue;
|
|
}
|
|
|
|
}/* while(1)*/
|
|
|
|
if (call->cmdSock)
|
|
ooCloseCallCmdConnection(call);
|
|
|
|
ast_mutex_lock(&call->Lock);
|
|
ast_mutex_unlock(&call->Lock);
|
|
ast_mutex_destroy(&call->Lock);
|
|
ast_mutex_destroy(&call->GkLock);
|
|
ast_cond_destroy(&call->gkWait);
|
|
pctxt = call->pctxt;
|
|
freeContext(pctxt);
|
|
ast_free(pctxt);
|
|
|
|
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 = call->msgctxt;
|
|
|
|
struct timeval timeout;
|
|
|
|
|
|
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); */
|
|
memReset(call->pctxt);
|
|
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(pctxt, 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(pctxt, 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;
|
|
|
|
if(len > MAXMSGLEN - 4)
|
|
{
|
|
OOTRACEERR4("Error: Invalid TPKT header for H225 message "
|
|
"Len = %d (%s, %s)\n", len, call->callType,
|
|
call->callToken);
|
|
ooCloseH225Connection(call);
|
|
ooFreeQ931Message(pctxt, pmsg);
|
|
if(call->callState < OO_CALL_CLEAR)
|
|
{
|
|
call->callEndReason = OO_REASON_INVALIDMESSAGE;
|
|
call->callState = OO_CALL_CLEAR;
|
|
}
|
|
return OO_FAILED;
|
|
}
|
|
|
|
/* 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)
|
|
{
|
|
struct pollfd pfds;
|
|
|
|
pfds.fd = call->pH225Channel->sock;
|
|
pfds.events = POLLIN;
|
|
timeout.tv_sec = 3;
|
|
timeout.tv_usec = 0;
|
|
ret = ooSocketPoll(&pfds, 1, timeout.tv_sec * 1000);
|
|
if(ret == -1)
|
|
{
|
|
OOTRACEERR3("Error in select while receiving H.2250 message - "
|
|
"clearing call (%s, %s)\n", call->callType,
|
|
call->callToken);
|
|
ooFreeQ931Message(pctxt, pmsg);
|
|
if(call->callState < OO_CALL_CLEAR)
|
|
{
|
|
call->callEndReason = OO_REASON_TRANSPORTFAILURE;
|
|
call->callState = OO_CALL_CLEAR;
|
|
}
|
|
return OO_FAILED;
|
|
}
|
|
|
|
/* exit If remaining part of the message is not received in 3 seconds */
|
|
|
|
if(!ooPDRead(&pfds, 1, call->pH225Channel->sock))
|
|
{
|
|
OOTRACEERR3("Error: Incomplete H.2250 message received - clearing "
|
|
"call (%s, %s)\n", call->callType, call->callToken);
|
|
ooFreeQ931Message(pctxt, pmsg);
|
|
if(call->callState < OO_CALL_CLEAR)
|
|
{
|
|
call->callEndReason = OO_REASON_INVALIDMESSAGE;
|
|
call->callState = OO_CALL_CLEAR;
|
|
}
|
|
return OO_FAILED;
|
|
}
|
|
|
|
recvLen = ooSocketRecv (call->pH225Channel->sock, message1, len-total);
|
|
if (recvLen == 0) {
|
|
OOTRACEERR3("Error in read while receiving H.2250 message - "
|
|
"clearing call (%s, %s)\n", call->callType,
|
|
call->callToken);
|
|
ooFreeQ931Message(pctxt, pmsg);
|
|
if(call->callState < OO_CALL_CLEAR)
|
|
{
|
|
call->callEndReason = OO_REASON_TRANSPORTFAILURE;
|
|
call->callState = OO_CALL_CLEAR;
|
|
}
|
|
return OO_FAILED;
|
|
}
|
|
memcpy(message+total, message1, recvLen);
|
|
total = total + recvLen;
|
|
|
|
}
|
|
|
|
OOTRACEDBGC3("Received Q.931 message: (%s, %s)\n",
|
|
call->callType, call->callToken);
|
|
|
|
initializePrintHandler(&printHandler, "Received H.2250 Message");
|
|
setEventHandler (pctxt, &printHandler);
|
|
setPERBuffer (pctxt, message, len, TRUE);
|
|
ret = ooQ931Decode (call, pmsg, len, message, 1);
|
|
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) {
|
|
ret = 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; */
|
|
OOCTXT *pctxt = call->pctxt;
|
|
struct timeval timeout;
|
|
|
|
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.
|
|
*/
|
|
|
|
if(len > MAXMSGLEN - 4)
|
|
{
|
|
OOTRACEERR4("Error: Invalid TPKT header length %d for H245 message (%s, %s)\n",
|
|
len, 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;
|
|
}
|
|
|
|
while(total < len)
|
|
{
|
|
struct pollfd pfds;
|
|
recvLen = ooSocketRecv (call->pH245Channel->sock, message1, len-total);
|
|
memcpy(message+total, message1, recvLen);
|
|
total = total + recvLen;
|
|
if(total == len) break; /* Complete message is received */
|
|
|
|
pfds.fd = call->pH245Channel->sock;
|
|
pfds.events = POLLIN;
|
|
timeout.tv_sec = 3;
|
|
timeout.tv_usec = 0;
|
|
ret = ooSocketPoll(&pfds, 1, timeout.tv_sec * 1000);
|
|
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(!ooPDRead(&pfds, 1, call->pH245Channel->sock))
|
|
{
|
|
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_FAILED;
|
|
}
|
|
|
|
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;
|
|
} else if (call->callState == OO_CALL_CLEAR)
|
|
call->callState = OO_CALL_CLEAR_RELEASESENT;
|
|
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 OOStatus:
|
|
OOTRACEINFO3("Sent Message - Status (%s, %s) \n", call->callType,
|
|
call->callToken);
|
|
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);
|
|
|
|
call->endTime = (H235TimeStamp) time(NULL);
|
|
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);
|
|
if(call->callState < OO_CALL_CLEAR)
|
|
call->callState = OO_CALL_CLEAR;
|
|
}
|
|
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;
|
|
}
|
|
|
|
void ooStopMonitorCallChannels(OOH323CallData * call) {
|
|
if (call->Monitor)
|
|
call->Monitor = FALSE;
|
|
/* if (call->cmdSock)
|
|
ooCloseCallCmdConnection(call); */
|
|
}
|
|
|
|
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 = { .tv_usec = 500 };
|
|
struct pollfd pfds = { .fd = sock, .events = POLLIN };
|
|
int ret = 0;
|
|
|
|
ret = ast_poll2(&pfds, 1, &to);
|
|
|
|
if(ret == -1)
|
|
{
|
|
OOTRACEERR3("Error in select ...broken pipe check(%s, %s)\n",
|
|
call->callType, call->callToken );
|
|
return FALSE;
|
|
}
|
|
|
|
if (pfds.events & POLLIN) {
|
|
char buf[2];
|
|
if(ooSocketRecvPeek(sock, (ASN1OCTET*) 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;
|
|
}
|