Files
asterisk/addons/ooh323c/src/ooStackCmds.c
Alexandr Anikin aa41d4f640 Corrections for properly work with H.323v2 (older) endpoints and other
small fixes.

Interpret remote side H.225 version.

Corrections for H.323v2 endpoints: 
don't start TCS and MSD before connect,
don't start TCS and MSD by accepting H.245 connection,
start TCS and MSD by StartH245 facility message.

Other fixes:
fix non zeroended remoteDisplayName issue, small fixes in call clearing
by closing H.245 connection, tcp keepalive introduced on TCP
connections (now is hardcoded, will be configurable in the future), 
don't force H.245tunneling if FastStart is active, don't send Alerting 
singal more than once per call.

(issue 0018542)
Reported by: vmikhelson
Patches: 
      issue18542-final-3.patch uploaded by may213 (license 454)
Tested by: vmikhelson


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@307509 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2011-02-10 18:50:50 +00:00

621 lines
13 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 "ooStackCmds.h"
#include "ooh323ep.h"
#include "ooCalls.h"
#include "ooCmdChannel.h"
extern OOSOCKET gCmdChan;
extern ast_mutex_t newCallLock;
static int counter = 1;
int ooGenerateOutgoingCallToken (char *callToken, size_t size)
{
char aCallToken[200];
int ret = 0;
ast_mutex_lock(&newCallLock);
sprintf (aCallToken, "ooh323c_o_%d", counter++);
if (counter > OO_MAX_CALL_TOKEN)
counter = 1;
ast_mutex_unlock(&newCallLock);
if ((strlen(aCallToken)+1) < size)
strcpy (callToken, aCallToken);
else {
ret = OO_FAILED;
}
return ret;
}
int isRunning(char *callToken) {
OOH323CallData *call;
if((call = ooFindCallByToken(callToken)))
if (call->Monitor)
return 1;
return 0;
}
OOStkCmdStat ooMakeCall
(const char* dest, char* callToken, size_t bufsiz, ooCallOptions *opts)
{
OOStackCommand cmd;
if(!callToken)
return OO_STKCMD_INVALIDPARAM;
/* Generate call token*/
if (ooGenerateOutgoingCallToken (callToken, bufsiz) != OO_OK){
return OO_STKCMD_INVALIDPARAM;
}
if(gCmdChan == 0)
{
if(ooCreateCmdConnection() != OO_OK)
return OO_STKCMD_CONNECTIONERR;
}
memset(&cmd, 0, sizeof(OOStackCommand));
cmd.type = OO_CMD_MAKECALL;
cmd.param1 = (void*) malloc(strlen(dest)+1);
if(!cmd.param1)
{
return OO_STKCMD_MEMERR;
}
strcpy((char*)cmd.param1, dest);
cmd.param2 = (void*) malloc(strlen(callToken)+1);
if(!cmd.param2)
{
free(cmd.param1);
return OO_STKCMD_MEMERR;
}
strcpy((char*)cmd.param2, callToken);
if(!opts)
{
cmd.param3 = 0;
}
else {
cmd.param3 = (void*) malloc(sizeof(ooCallOptions));
if(!cmd.param3)
{
free(cmd.param1);
free(cmd.param2);
return OO_STKCMD_MEMERR;
}
memcpy((void*)cmd.param3, opts, sizeof(ooCallOptions));
}
if(ooWriteStackCommand(&cmd) != OO_OK)
{
free(cmd.param1);
free(cmd.param2);
if(cmd.param3) free(cmd.param3);
return OO_STKCMD_WRITEERR;
}
return OO_STKCMD_SUCCESS;
}
OOStkCmdStat ooRunCall
(const char* dest, char* callToken, size_t bufsiz, ooCallOptions *opts)
{
OOStackCommand cmd;
OOH323CallData *call;
if(!callToken)
{
return OO_STKCMD_INVALIDPARAM;
}
if(!(call = ooFindCallByToken(callToken))) {
return OO_STKCMD_INVALIDPARAM;
}
if(call->CmdChan == 0)
{
if(ooCreateCallCmdConnection(call) != OO_OK)
return OO_STKCMD_CONNECTIONERR;
}
if(!callToken)
return OO_STKCMD_INVALIDPARAM;
memset(&cmd, 0, sizeof(OOStackCommand));
cmd.type = OO_CMD_MAKECALL;
cmd.param1 = (void*) malloc(strlen(dest)+1);
if(!cmd.param1)
{
return OO_STKCMD_MEMERR;
}
strcpy((char*)cmd.param1, dest);
cmd.plen1 = strlen(dest);
cmd.param2 = (void*) malloc(strlen(callToken)+1);
if(!cmd.param2)
{
free(cmd.param1);
return OO_STKCMD_MEMERR;
}
strcpy((char*)cmd.param2, callToken);
cmd.plen2 = strlen(callToken);
if(!opts)
{
cmd.param3 = 0;
}
else {
cmd.param3 = (void*) malloc(sizeof(ooCallOptions));
if(!cmd.param3)
{
free(cmd.param1);
free(cmd.param2);
return OO_STKCMD_MEMERR;
}
memcpy((void*)cmd.param3, opts, sizeof(ooCallOptions));
cmd.plen3 = sizeof(ooCallOptions);
}
if(ooWriteCallStackCommand(call, &cmd) != OO_OK)
{
free(cmd.param1);
free(cmd.param2);
if(cmd.param3) free(cmd.param3);
return OO_STKCMD_WRITEERR;
}
free(cmd.param1);
free(cmd.param2);
if(cmd.param3) free(cmd.param3);
return OO_STKCMD_SUCCESS;
}
OOStkCmdStat ooManualRingback(const char *callToken)
{
OOStackCommand cmd;
OOH323CallData *call;
if(!callToken)
{
return OO_STKCMD_INVALIDPARAM;
}
if(!(call = ooFindCallByToken(callToken))) {
return OO_STKCMD_INVALIDPARAM;
}
if(call->CmdChan == 0)
{
if(ooCreateCallCmdConnection(call) != OO_OK)
return OO_STKCMD_CONNECTIONERR;
}
memset(&cmd, 0, sizeof(OOStackCommand));
cmd.type = OO_CMD_MANUALRINGBACK;
cmd.param1 = (void*) malloc(strlen(callToken)+1);
if(!cmd.param1)
{
return OO_STKCMD_MEMERR;
}
strcpy((char*)cmd.param1, callToken);
cmd.plen1 = strlen(callToken);
if(ooWriteCallStackCommand(call,&cmd) != OO_OK)
{
free(cmd.param1);
return OO_STKCMD_WRITEERR;
}
free(cmd.param1);
return OO_STKCMD_SUCCESS;
}
OOStkCmdStat ooManualProgress(const char *callToken)
{
OOStackCommand cmd;
OOH323CallData *call;
if(!callToken)
{
return OO_STKCMD_INVALIDPARAM;
}
if(!(call = ooFindCallByToken(callToken))) {
return OO_STKCMD_INVALIDPARAM;
}
if(call->CmdChan == 0)
{
if(ooCreateCallCmdConnection(call) != OO_OK)
return OO_STKCMD_CONNECTIONERR;
}
if (call->h225version < 4)
return OO_STKCMD_SUCCESS;
memset(&cmd, 0, sizeof(OOStackCommand));
cmd.type = OO_CMD_MANUALPROGRESS;
cmd.param1 = (void*) malloc(strlen(callToken)+1);
if(!cmd.param1)
{
return OO_STKCMD_MEMERR;
}
strcpy((char*)cmd.param1, callToken);
cmd.plen1 = strlen(callToken);
if(ooWriteCallStackCommand(call, &cmd) != OO_OK)
{
free(cmd.param1);
return OO_STKCMD_WRITEERR;
}
free(cmd.param1);
return OO_STKCMD_SUCCESS;
}
OOStkCmdStat ooAnswerCall(const char *callToken)
{
OOStackCommand cmd;
OOH323CallData *call;
if(!callToken)
{
return OO_STKCMD_INVALIDPARAM;
}
if(!(call = ooFindCallByToken(callToken))) {
return OO_STKCMD_INVALIDPARAM;
}
if(call->CmdChan == 0)
{
if(ooCreateCallCmdConnection(call) != OO_OK)
return OO_STKCMD_CONNECTIONERR;
}
memset(&cmd, 0, sizeof(OOStackCommand));
cmd.type = OO_CMD_ANSCALL;
cmd.param1 = (void*) malloc(strlen(callToken)+1);
if(!cmd.param1)
{
return OO_STKCMD_MEMERR;
}
strcpy((char*)cmd.param1, callToken);
cmd.plen1 = strlen(callToken);
if(ooWriteCallStackCommand(call, &cmd) != OO_OK)
{
free(cmd.param1);
return OO_STKCMD_WRITEERR;
}
free(cmd.param1);
return OO_STKCMD_SUCCESS;
}
OOStkCmdStat ooForwardCall(const char* callToken, char *dest)
{
OOStackCommand cmd;
OOH323CallData *call;
if(!callToken || !dest)
{
return OO_STKCMD_INVALIDPARAM;
}
if(!(call = ooFindCallByToken(callToken))) {
return OO_STKCMD_INVALIDPARAM;
}
if(call->CmdChan == 0)
{
if(ooCreateCallCmdConnection(call) != OO_OK)
return OO_STKCMD_CONNECTIONERR;
}
memset(&cmd, 0, sizeof(OOStackCommand));
cmd.type = OO_CMD_FWDCALL;
cmd.param1 = (void*) malloc(strlen(callToken)+1);
cmd.param2 = (void*) malloc(strlen(dest)+1);
if(!cmd.param1 || !cmd.param2)
{
if(cmd.param1) free(cmd.param1); /* Release memory */
if(cmd.param2) free(cmd.param2);
return OO_STKCMD_MEMERR;
}
strcpy((char*)cmd.param1, callToken);
cmd.plen1 = strlen(callToken);
strcpy((char*)cmd.param2, dest);
cmd.plen2 = strlen(dest);
if(ooWriteCallStackCommand(call, &cmd) != OO_OK)
{
free(cmd.param1);
free(cmd.param2);
return OO_STKCMD_WRITEERR;
}
free(cmd.param1);
free(cmd.param2);
return OO_STKCMD_SUCCESS;
}
OOStkCmdStat ooHangCall(const char* callToken, OOCallClearReason reason, int q931cause)
{
OOStackCommand cmd;
OOH323CallData *call;
if(!callToken)
{
return OO_STKCMD_INVALIDPARAM;
}
if(!(call = ooFindCallByToken(callToken))) {
return OO_STKCMD_INVALIDPARAM;
}
if(call->CmdChan == 0)
{
if(ooCreateCallCmdConnection(call) != OO_OK)
return OO_STKCMD_CONNECTIONERR;
}
memset(&cmd, 0, sizeof(OOStackCommand));
cmd.type = OO_CMD_HANGCALL;
cmd.param1 = (void*) malloc(strlen(callToken)+1);
cmd.param2 = (void*) malloc(sizeof(OOCallClearReason));
cmd.param3 = (void*) malloc(sizeof(int));
if(!cmd.param1 || !cmd.param2 || !cmd.param3)
{
if(cmd.param1) free(cmd.param1); /* Release memory */
if(cmd.param2) free(cmd.param2);
if(cmd.param3) free(cmd.param3);
return OO_STKCMD_MEMERR;
}
strcpy((char*)cmd.param1, callToken);
cmd.plen1 = strlen(callToken);
*((OOCallClearReason*)cmd.param2) = reason;
cmd.plen2 = sizeof(OOCallClearReason);
*(int *)cmd.param3 = q931cause;
cmd.plen3 = sizeof(int);
if(ooWriteCallStackCommand(call, &cmd) != OO_OK)
{
free(cmd.param1);
free(cmd.param2);
free(cmd.param3);
return OO_STKCMD_WRITEERR;
}
free(cmd.param1);
free(cmd.param2);
free(cmd.param3);
return OO_STKCMD_SUCCESS;
}
OOStkCmdStat ooStopMonitor()
{
OOStackCommand cmd;
if(gCmdChan == 0)
{
if(ooCreateCmdConnection() != OO_OK)
return OO_STKCMD_CONNECTIONERR;
}
memset(&cmd, 0, sizeof(OOStackCommand));
cmd.type = OO_CMD_STOPMONITOR;
if(ooWriteStackCommand(&cmd) != OO_OK)
return OO_STKCMD_WRITEERR;
return OO_STKCMD_SUCCESS;
}
OOStkCmdStat ooSendDTMFDigit(const char *callToken, const char* dtmf)
{
OOStackCommand cmd;
OOH323CallData *call;
if(!callToken)
{
return OO_STKCMD_INVALIDPARAM;
}
if(!(call = ooFindCallByToken(callToken))) {
return OO_STKCMD_INVALIDPARAM;
}
if(call->CmdChan == 0)
{
if(ooCreateCallCmdConnection(call) != OO_OK)
return OO_STKCMD_CONNECTIONERR;
}
memset(&cmd, 0, sizeof(OOStackCommand));
cmd.type = OO_CMD_SENDDIGIT;
cmd.param1 = (void*) malloc(strlen(callToken)+1);
cmd.param2 = (void*) malloc(strlen(dtmf)+1);
if(!cmd.param1 || !cmd.param2)
{
if(cmd.param1) free(cmd.param1); /* Release memory */
if(cmd.param2) free(cmd.param2);
return OO_STKCMD_MEMERR;
}
strcpy((char*)cmd.param1, callToken);
cmd.plen1 = strlen(callToken);
strcpy((char*)cmd.param2, dtmf);
cmd.plen2 = strlen(dtmf);
if(ooWriteCallStackCommand(call,&cmd) != OO_OK)
{
free(cmd.param1);
free(cmd.param2);
return OO_STKCMD_WRITEERR;
}
free(cmd.param1);
free(cmd.param2);
return OO_STKCMD_SUCCESS;
}
OOStkCmdStat ooSetANI(const char *callToken, const char* ani)
{
OOStackCommand cmd;
OOH323CallData *call;
if(!callToken)
{
return OO_STKCMD_INVALIDPARAM;
}
if(!(call = ooFindCallByToken(callToken))) {
return OO_STKCMD_INVALIDPARAM;
}
if(call->CmdChan == 0)
{
if(ooCreateCallCmdConnection(call) != OO_OK)
return OO_STKCMD_CONNECTIONERR;
}
memset(&cmd, 0, sizeof(OOStackCommand));
cmd.type = OO_CMD_SETANI;
cmd.param1 = (void*) malloc(strlen(callToken)+1);
cmd.param2 = (void*) malloc(strlen(ani)+1);
if(!cmd.param1 || !cmd.param2)
{
if(cmd.param1) free(cmd.param1); /* Release memory */
if(cmd.param2) free(cmd.param2);
return OO_STKCMD_MEMERR;
}
strcpy((char*)cmd.param1, callToken);
cmd.plen1 = strlen(callToken);
strcpy((char*)cmd.param2, ani);
cmd.plen2 = strlen(ani);
if(ooWriteCallStackCommand(call,&cmd) != OO_OK)
{
free(cmd.param1);
free(cmd.param2);
return OO_STKCMD_WRITEERR;
}
free(cmd.param1);
free(cmd.param2);
return OO_STKCMD_SUCCESS;
}
OOStkCmdStat ooRequestChangeMode(const char *callToken, int isT38Mode)
{
OOStackCommand cmd;
OOH323CallData *call;
if(!callToken)
{
return OO_STKCMD_INVALIDPARAM;
}
if(!(call = ooFindCallByToken(callToken))) {
return OO_STKCMD_INVALIDPARAM;
}
if(call->CmdChan == 0)
{
if(ooCreateCallCmdConnection(call) != OO_OK)
return OO_STKCMD_CONNECTIONERR;
}
memset(&cmd, 0, sizeof(OOStackCommand));
cmd.type = OO_CMD_REQMODE;
cmd.param1 = (void*) malloc(strlen(callToken)+1);
cmd.param2 = (void*) malloc(sizeof(int));
if(!cmd.param1 || !cmd.param2)
{
if(cmd.param1) free(cmd.param1); /* Release memory */
if(cmd.param2) free(cmd.param2);
return OO_STKCMD_MEMERR;
}
strcpy((char*)cmd.param1, callToken);
cmd.plen1 = strlen(callToken);
*((int *) cmd.param2) = isT38Mode;
cmd.plen2 = sizeof(int);
if(ooWriteCallStackCommand(call,&cmd) != OO_OK)
{
free(cmd.param1);
free(cmd.param2);
return OO_STKCMD_WRITEERR;
}
free(cmd.param1);
free(cmd.param2);
return OO_STKCMD_SUCCESS;
}
const char* ooGetStkCmdStatusCodeTxt(OOStkCmdStat stat)
{
switch(stat)
{
case OO_STKCMD_SUCCESS:
return "Stack command - successfully issued";
case OO_STKCMD_MEMERR:
return "Stack command - Memory allocation error";
case OO_STKCMD_INVALIDPARAM:
return "Stack command - Invalid parameter";
case OO_STKCMD_WRITEERR:
return "Stack command - write error";
case OO_STKCMD_CONNECTIONERR:
return "Stack command - Failed to create command channel";
default:
return "Invalid status code";
}
}