aboutsummaryrefslogtreecommitdiffstats
path: root/addons/ooh323c/src/ooq931.c
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2009-06-30 16:40:38 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2009-06-30 16:40:38 +0000
commite9d15cbea7a98184521c851500176da7aa424012 (patch)
treed3d6aa7ea86d11ecaa6e88efbc46a5dde1c63ea5 /addons/ooh323c/src/ooq931.c
parentb85bdd32a783a8f07004d41db8a696645685a331 (diff)
Move Asterisk-addons modules into the main Asterisk source tree.
Someone asked yesterday, "is there a good reason why we can't just put these modules in Asterisk?". After a brief discussion, as long as the modules are clearly set aside in their own directory and not enabled by default, it is perfectly fine. For more information about why a module goes in addons, see README-addons.txt. chan_ooh323 does not currently compile as it is behind some trunk API updates. However, it will not build by default, so it should be okay for now. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@204413 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'addons/ooh323c/src/ooq931.c')
-rw-r--r--addons/ooh323c/src/ooq931.c3448
1 files changed, 3448 insertions, 0 deletions
diff --git a/addons/ooh323c/src/ooq931.c b/addons/ooh323c/src/ooq931.c
new file mode 100644
index 000000000..e440b4c7b
--- /dev/null
+++ b/addons/ooh323c/src/ooq931.c
@@ -0,0 +1,3448 @@
+/*
+ * 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 "ooq931.h"
+#include "ootrace.h"
+#include "ooasn1.h"
+#include "oochannels.h"
+#include "printHandler.h"
+#include "ooCalls.h"
+#include "ooh323.h"
+#include "ooh245.h"
+#include "ooh323ep.h"
+#include "ooCapability.h"
+#include "ooGkClient.h"
+#include "ooUtils.h"
+#include "ootypes.h"
+#include <time.h>
+#include <ctype.h>
+
+/** Global endpoint structure */
+extern OOH323EndPoint gH323ep;
+
+
+static ASN1OBJID gProtocolID = {
+ 6, { 0, 0, 8, 2250, 0, 4 }
+};
+
+EXTERN int ooQ931Decode
+ (OOH323CallData *call, Q931Message* msg, int length, ASN1OCTET *data)
+{
+ int offset, x;
+ int rv = ASN_OK;
+ char number[128];
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+
+ dListInit (&msg->ies); /* clear information elements list */
+
+ if (length < 5) /* Packet too short */
+ return Q931_E_TOOSHORT;
+
+ msg->protocolDiscriminator = data[0];
+ OOTRACEDBGB2(" protocolDiscriminator = %d\n", msg->protocolDiscriminator);
+ if (data[1] != 2) /* Call reference must be 2 bytes long */
+ return Q931_E_INVCALLREF;
+
+ msg->callReference = ((data[2] & 0x7f) << 8) | data[3];
+
+ OOTRACEDBGB2(" callReference = %d\n", msg->callReference);
+
+ msg->fromDestination = (data[2] & 0x80) != 0;
+ if(msg->fromDestination)
+ OOTRACEDBGB1(" from = destination\n");
+ else
+ OOTRACEDBGB1(" from = originator\n");
+
+
+ msg->messageType = data[4];
+ OOTRACEDBGB2(" messageType = %x\n", msg->messageType);
+
+
+ /* Have preamble, start getting the informationElements into buffers */
+ offset = 5;
+ while (offset < length) {
+ Q931InformationElement *ie;
+ int ieOff = offset;
+ /* Get field discriminator */
+ int discriminator = data[offset++];
+
+ /* For discriminator with high bit set there is no data */
+ if ((discriminator & 0x80) == 0) {
+ int len = data[offset++], alen;
+
+ if (discriminator == Q931UserUserIE) {
+ /* Special case of User-user field, there is some confusion here as
+ the Q931 documentation claims the length is a single byte,
+ unfortunately all H.323 based apps have a 16 bit length here, so
+ we allow for said longer length. There is presumably an addendum
+ to Q931 which describes this, and provides a means to
+ discriminate between the old 1 byte and the new 2 byte systems.
+ However, at present we assume it is always 2 bytes until we find
+ something that breaks it.
+ */
+ len <<= 8;
+ len |= data[offset++];
+
+ /* we also have a protocol discriminator, which we ignore */
+ offset++;
+ len--;
+ }
+
+ /* watch out for negative lengths! (ED, 11/5/03) */
+ if (len < 0) {
+ return Q931_E_INVLENGTH;
+ }
+ else if (offset + len > length) {
+ alen = 0;
+ len = -len;
+ rv = Q931_E_INVLENGTH;
+ }
+ else alen = len;
+
+ ie = (Q931InformationElement*)
+ memAlloc (pctxt, sizeof(*ie) - sizeof(ie->data) + alen);
+ if(!ie)
+ {
+ OOTRACEERR3("Error:Memory - ooQ931Decode - ie(%s, %s)\n",
+ call->callType, call->callToken);
+ return OO_FAILED;
+ }
+ ie->discriminator = discriminator;
+ ie->offset = ieOff;
+ ie->length = len;
+ if (alen != 0)
+ memcpy(ie->data, data + offset, alen);
+ offset += len;
+ }
+ else {
+ ie = (Q931InformationElement*) memAlloc (pctxt,
+ sizeof(*ie) - sizeof(ie->data));
+ if(!ie)
+ {
+ OOTRACEERR3("Error:Memory - ooQ931Decode - ie(%s, %s)\n",
+ call->callType, call->callToken);
+ return OO_FAILED;
+ }
+ ie->discriminator = discriminator;
+ ie->offset = offset;
+ ie->length = 0;
+ }
+ if(ie->discriminator == Q931BearerCapabilityIE)
+ {
+ OOTRACEDBGB1(" Bearer-Capability IE = {\n");
+ for(x=0; x<ie->length; x++)
+ {
+ if(x==0)
+ OOTRACEDBGB2(" %x", ie->data[x]);
+ else
+ OOTRACEDBGB2(", %x", ie->data[x]);
+ }
+ OOTRACEDBGB1(" }\n");
+ }
+ if(ie->discriminator == Q931DisplayIE)
+ {
+ OOTRACEDBGB1(" Display IE = {\n");
+ OOTRACEDBGB2(" %s\n", ie->data);
+ OOTRACEDBGB1(" }\n");
+ }
+
+ if(ie->discriminator == Q931KeypadIE)
+ {
+ OOTRACEDBGB1(" Keypad IE = {\n");
+ OOTRACEDBGB2(" %s\n", ie->data);
+ OOTRACEDBGB1(" }\n");
+ if(gH323ep.h323Callbacks.onReceivedDTMF)
+ {
+ gH323ep.h323Callbacks.onReceivedDTMF(call, ie->data);
+ }
+ }
+ /* Extract calling party number TODO:Give respect to presentation and
+ screening indicators ;-) */
+ if(ie->discriminator == Q931CallingPartyNumberIE)
+ {
+ OOTRACEDBGB1(" CallingPartyNumber IE = {\n");
+ if(ie->length < OO_MAX_NUMBER_LENGTH)
+ {
+ int numoffset=1;
+ if(!(0x80 & ie->data[0])) numoffset = 2;
+ memcpy(number, ie->data+numoffset,ie->length-numoffset);
+ number[ie->length-numoffset]='\0';
+ OOTRACEDBGB2(" %s\n", number);
+ if(!call->callingPartyNumber)
+ ooCallSetCallingPartyNumber(call, number);
+ }
+ else{
+ OOTRACEERR3("Error:Calling party number too long. (%s, %s)\n",
+ call->callType, call->callToken);
+ }
+ OOTRACEDBGB1(" }\n");
+ }
+
+ /* Extract called party number */
+ if(ie->discriminator == Q931CalledPartyNumberIE)
+ {
+ OOTRACEDBGB1(" CalledPartyNumber IE = {\n");
+ if(ie->length < OO_MAX_NUMBER_LENGTH)
+ {
+ memcpy(number, ie->data+1,ie->length-1);
+ number[ie->length-1]='\0';
+ OOTRACEDBGB2(" %s\n", number);
+ if(!call->calledPartyNumber)
+ ooCallSetCalledPartyNumber(call, number);
+ }
+ else{
+ OOTRACEERR3("Error:Calling party number too long. (%s, %s)\n",
+ call->callType, call->callToken);
+ }
+ OOTRACEDBGB1(" }\n");
+ }
+
+ /* Handle Cause ie */
+ if(ie->discriminator == Q931CauseIE)
+ {
+ msg->causeIE = ie;
+ OOTRACEDBGB1(" Cause IE = {\n");
+ OOTRACEDBGB2(" %s\n", ooGetQ931CauseValueText(ie->data[1]&0x7f));
+ OOTRACEDBGB1(" }\n");
+ }
+
+ /* TODO: Get rid of ie list.*/
+ dListAppend (pctxt, &msg->ies, ie);
+ if (rv != ASN_OK)
+ return rv;
+ }
+
+ /*cisco router sends Q931Notify without UU ie,
+ we just ignore notify message as of now as handling is optional for
+ end point*/
+ if(msg->messageType != Q931NotifyMsg)
+ rv = ooDecodeUUIE(msg);
+ return rv;
+}
+
+EXTERN Q931InformationElement* ooQ931GetIE (const Q931Message* q931msg,
+ int ieCode)
+{
+ DListNode* curNode;
+ unsigned int i;
+
+ for(i = 0, curNode = q931msg->ies.head; i < q931msg->ies.count; i++) {
+ Q931InformationElement *ie = (Q931InformationElement*) curNode->data;
+ if (ie->discriminator == ieCode) {
+ return ie;
+ }
+ curNode = curNode->next;
+ }
+ return NULL;
+}
+
+char* ooQ931GetMessageTypeName(int messageType, char* buf) {
+ switch (messageType) {
+ case Q931AlertingMsg :
+ strcpy(buf, "Alerting");
+ break;
+ case Q931CallProceedingMsg :
+ strcpy(buf, "CallProceeding");
+ break;
+ case Q931ConnectMsg :
+ strcpy(buf, "Connect");
+ break;
+ case Q931ConnectAckMsg :
+ strcpy(buf, "ConnectAck");
+ break;
+ case Q931ProgressMsg :
+ strcpy(buf, "Progress");
+ break;
+ case Q931SetupMsg :
+ strcpy(buf, "Setup");
+ break;
+ case Q931SetupAckMsg :
+ strcpy(buf, "SetupAck");
+ break;
+ case Q931FacilityMsg :
+ strcpy(buf, "Facility");
+ break;
+ case Q931ReleaseCompleteMsg :
+ strcpy(buf, "ReleaseComplete");
+ break;
+ case Q931StatusEnquiryMsg :
+ strcpy(buf, "StatusEnquiry");
+ break;
+ case Q931StatusMsg :
+ strcpy(buf, "Status");
+ break;
+ case Q931InformationMsg :
+ strcpy(buf, "Information");
+ break;
+ case Q931NationalEscapeMsg :
+ strcpy(buf, "Escape");
+ break;
+ default:
+ sprintf(buf, "<%u>", messageType);
+ }
+ return buf;
+}
+
+char* ooQ931GetIEName(int number, char* buf) {
+ switch (number) {
+ case Q931BearerCapabilityIE :
+ strcpy(buf, "Bearer-Capability");
+ break;
+ case Q931CauseIE :
+ strcpy(buf, "Cause");
+ break;
+ case Q931FacilityIE :
+ strcpy(buf, "Facility");
+ break;
+ case Q931ProgressIndicatorIE :
+ strcpy(buf, "Progress-Indicator");
+ break;
+ case Q931CallStateIE :
+ strcpy(buf, "Call-State");
+ break;
+ case Q931DisplayIE :
+ strcpy(buf, "Display");
+ break;
+ case Q931SignalIE :
+ strcpy(buf, "Signal");
+ break;
+ case Q931CallingPartyNumberIE :
+ strcpy(buf, "Calling-Party-Number");
+ break;
+ case Q931CalledPartyNumberIE :
+ strcpy(buf, "Called-Party-Number");
+ break;
+ case Q931RedirectingNumberIE :
+ strcpy(buf, "Redirecting-Number");
+ break;
+ case Q931UserUserIE :
+ strcpy(buf, "User-User");
+ break;
+ default:
+ sprintf(buf, "0x%02x", number);
+ }
+ return buf;
+}
+
+EXTERN void ooQ931Print (const Q931Message* q931msg) {
+ char buf[1000];
+ DListNode* curNode;
+ unsigned int i;
+
+ printf("Q.931 Message:\n");
+ printf(" protocolDiscriminator: %i\n", q931msg->protocolDiscriminator);
+ printf(" callReference: %i\n", q931msg->callReference);
+ printf(" from: %s\n", (q931msg->fromDestination ?
+ "destination" : "originator"));
+ printf(" messageType: %s (0x%X)\n\n",
+ ooQ931GetMessageTypeName(q931msg->messageType, buf),
+ q931msg->messageType);
+
+ for(i = 0, curNode = q931msg->ies.head; i < q931msg->ies.count; i++) {
+ Q931InformationElement *ie = (Q931InformationElement*) curNode->data;
+ int length = (ie->length >= 0) ? ie->length : -ie->length;
+ printf(" IE[%i] (offset 0x%X):\n", i, ie->offset);
+ printf(" discriminator: %s (0x%X)\n",
+ ooQ931GetIEName(ie->discriminator, buf), ie->discriminator);
+ printf(" data length: %i\n", length);
+
+ curNode = curNode->next;
+ printf("\n");
+ }
+}
+
+int ooCreateQ931Message(Q931Message **q931msg, int msgType)
+{
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+
+ *q931msg = (Q931Message*)memAllocZ(pctxt, sizeof(Q931Message));
+
+ if(!*q931msg)
+ {
+ OOTRACEERR1("Error:Memory - ooCreateQ931Message - q931msg\n");
+ return OO_FAILED;
+ }
+ else
+ {
+ (*q931msg)->protocolDiscriminator = 8;
+ (*q931msg)->fromDestination = FALSE;
+ (*q931msg)->messageType = msgType;
+ (*q931msg)->tunneledMsgType = msgType;
+ (*q931msg)->logicalChannelNo = 0;
+ (*q931msg)->bearerCapabilityIE = NULL;
+ (*q931msg)->callingPartyNumberIE = NULL;
+ (*q931msg)->calledPartyNumberIE = NULL;
+ (*q931msg)->causeIE = NULL;
+ return OO_OK;
+ }
+}
+
+
+int ooGenerateCallToken (char *callToken, size_t size)
+{
+ static int counter = 1;
+ char aCallToken[200];
+ int ret = 0;
+
+ sprintf (aCallToken, "ooh323c_%d", counter++);
+
+ if (counter > OO_MAX_CALL_TOKEN)
+ counter = 1;
+
+ if ((strlen(aCallToken)+1) < size)
+ strcpy (callToken, aCallToken);
+ else {
+ OOTRACEERR1 ("Error: Insufficient buffer size to generate call token");
+ ret = OO_FAILED;
+ }
+
+
+ return ret;
+}
+
+/* CallReference is a two octet field, thus max value can be 0xffff
+ or 65535 decimal. We restrict max value to 32760, however, this should
+ not cause any problems as there won't be those many simultaneous calls
+ CallRef has to be locally unique and generated by caller.
+*/
+ASN1USINT ooGenerateCallReference()
+{
+ static ASN1USINT lastCallRef=0;
+ ASN1USINT newCallRef=0;
+
+
+ if(lastCallRef == 0)
+ {
+ /* Generate a new random callRef */
+ srand((unsigned)time(0));
+ lastCallRef = (ASN1USINT)(rand()%100);
+ }
+ else
+ lastCallRef++;
+
+ /* Note callReference can be at the most 15 bits that is from 0 to 32767.
+ if we generate number bigger than that, bring it in range.
+ */
+ if(lastCallRef>=32766)
+ lastCallRef=1;
+
+ newCallRef = lastCallRef;
+
+
+ OOTRACEDBGC2("Generated callRef %d\n", newCallRef);
+ return newCallRef;
+}
+
+
+int ooGenerateCallIdentifier(H225CallIdentifier *callid)
+{
+ ASN1INT64 timestamp;
+ int i=0;
+#ifdef _WIN32
+
+ SYSTEMTIME systemTime;
+ GetLocalTime(&systemTime);
+ SystemTimeToFileTime(&systemTime, (LPFILETIME)&timestamp);
+#else
+ struct timeval systemTime;
+ gettimeofday(&systemTime, NULL);
+ timestamp = systemTime.tv_sec * 10000000 + systemTime.tv_usec*10;
+#endif
+
+ callid->guid.numocts = 16;
+ callid->guid.data[0] = 'o';
+ callid->guid.data[1] = 'o';
+ callid->guid.data[2] = 'h';
+ callid->guid.data[3] = '3';
+ callid->guid.data[4] = '2';
+ callid->guid.data[5] = '3';
+ callid->guid.data[6] = 'c';
+ callid->guid.data[7] = '-';
+
+ for (i = 8; i < 16; i++)
+ callid->guid.data[i] = (ASN1OCTET)((timestamp>>((i-8+1)*8))&0xff);
+
+ return OO_OK;
+
+}
+
+int ooFreeQ931Message(Q931Message *q931Msg)
+{
+ if(!q931Msg)
+ {
+ memReset(&gH323ep.msgctxt);
+ }
+ return OO_OK;
+}
+
+int ooEncodeUUIE(Q931Message *q931msg)
+{
+ ASN1OCTET msgbuf[1024];
+ ASN1OCTET * msgptr=NULL;
+ int len;
+ ASN1BOOL aligned = TRUE;
+ Q931InformationElement* ie=NULL;
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+ /* memset(msgbuf, 0, sizeof(msgbuf));*/
+ if(!q931msg)
+ {
+ OOTRACEERR1("ERROR: Invalid Q931 message in add user-user IE\n");
+ return OO_FAILED;
+ }
+
+ if(!q931msg->userInfo)
+ {
+ OOTRACEERR1("ERROR: No User-User IE to encode\n");
+ return OO_FAILED;
+ }
+
+ setPERBuffer(pctxt, msgbuf, sizeof(msgbuf), aligned);
+
+ if(asn1PE_H225H323_UserInformation (pctxt,
+ q931msg->userInfo)==ASN_OK)
+ {
+ OOTRACEDBGC1("UserInfo encoding - successful\n");
+ }
+ else{
+ OOTRACEERR1("ERROR: UserInfo encoding failed\n");
+ return OO_FAILED;
+ }
+ msgptr = encodeGetMsgPtr(pctxt, &len);
+
+ /* Allocate memory to hold complete UserUser Information */
+ ie = (Q931InformationElement*)memAlloc (pctxt,
+ sizeof(*ie) - sizeof(ie->data) + len);
+ if(ie == NULL)
+ {
+ OOTRACEERR1("Error: Memory - ooEncodeUUIE - ie\n");
+ return OO_FAILED;
+ }
+ ie->discriminator = Q931UserUserIE;
+ ie->length = len;
+ memcpy(ie->data, msgptr, len);
+ /* Add the user to user IE NOTE: ALL IEs SHOULD BE IN ASCENDING ORDER OF
+ THEIR DISCRIMINATOR AS PER SPEC.
+ */
+ dListInit (&(q931msg->ies));
+ if((dListAppend (pctxt,
+ &(q931msg->ies), ie)) == NULL)
+ {
+ OOTRACEERR1("Error: Failed to add UUIE in outgoing message\n");
+ return OO_FAILED;
+ }
+
+ return OO_OK;
+}
+
+int ooDecodeUUIE(Q931Message *q931Msg)
+{
+ DListNode* curNode;
+ unsigned int i;
+ ASN1BOOL aligned=TRUE;
+ int stat;
+ Q931InformationElement *ie;
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+ if(q931Msg ==NULL)
+ {
+ OOTRACEERR1("Error: ooDecodeUUIE failed - NULL q931 message\n");
+ return OO_FAILED;
+ }
+
+ /* Search for UserUser IE */
+ for(i = 0, curNode = q931Msg->ies.head; i < q931Msg->ies.count;
+ i++, curNode = curNode->next)
+ {
+ ie = (Q931InformationElement*) curNode->data;
+ if(ie->discriminator == Q931UserUserIE)
+ break;
+ }
+ if(i == q931Msg->ies.count)
+ {
+ OOTRACEERR1("No UserUser IE found in ooDecodeUUIE\n");
+ return OO_FAILED;
+ }
+
+ /* Decode user-user ie */
+ q931Msg->userInfo = (H225H323_UserInformation *) memAlloc(pctxt,
+ sizeof(H225H323_UserInformation));
+ if(!q931Msg->userInfo)
+ {
+ OOTRACEERR1("ERROR:Memory - ooDecodeUUIE - userInfo\n");
+ return OO_FAILED;
+ }
+ memset(q931Msg->userInfo, 0, sizeof(H225H323_UserInformation));
+
+ setPERBuffer (pctxt, ie->data, ie->length, aligned);
+
+ stat = asn1PD_H225H323_UserInformation (pctxt, q931Msg->userInfo);
+ if(stat != ASN_OK)
+ {
+ OOTRACEERR1("Error: UserUser IE decode failed\n");
+ return OO_FAILED;
+ }
+ OOTRACEDBGC1("UUIE decode successful\n");
+ return OO_OK;
+}
+
+#ifndef _COMPACT
+static void ooQ931PrintMessage
+ (OOH323CallData* call, ASN1OCTET *msgbuf, ASN1UINT msglen)
+{
+
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+ Q931Message q931Msg;
+ int ret;
+
+ initializePrintHandler(&printHandler, "Q931 Message");
+
+ /* Set event handler */
+ setEventHandler (pctxt, &printHandler);
+
+ setPERBuffer (pctxt, msgbuf, msglen, TRUE);
+
+ ret = ooQ931Decode (call, &q931Msg, msglen, msgbuf);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3("Error:Failed decoding Q931 message. (%s, %s)\n",
+ call->callType, call->callToken);
+ }
+ finishPrint();
+ removeEventHandler(pctxt);
+
+}
+#endif
+
+
+
+int ooEncodeH225Message(OOH323CallData *call, Q931Message *pq931Msg,
+ char *msgbuf, int size)
+{
+ int len=0, i=0, j=0, ieLen=0;
+ int stat=0;
+ DListNode* curNode=NULL;
+
+ if(!msgbuf || size<200)
+ {
+ OOTRACEERR3("Error: Invalid message buffer/size for ooEncodeH245Message."
+ " (%s, %s)\n", call->callType, call->callToken);
+ return OO_FAILED;
+ }
+
+ if(pq931Msg->messageType == Q931SetupMsg){
+ msgbuf[i++] = OOSetup;
+ }
+ else if(pq931Msg->messageType == Q931ConnectMsg){
+ msgbuf[i++] = OOConnect;
+ }
+ else if(pq931Msg->messageType == Q931CallProceedingMsg){
+ msgbuf[i++] = OOCallProceeding;
+ }
+ else if(pq931Msg->messageType == Q931AlertingMsg){
+ msgbuf[i++] = OOAlert;
+ }
+ else if(pq931Msg->messageType == Q931ReleaseCompleteMsg){
+ msgbuf[i++] = OOReleaseComplete;
+ }
+ else if(pq931Msg->messageType == Q931InformationMsg){
+ msgbuf[i++] = OOInformationMessage;
+ }
+ else if(pq931Msg->messageType == Q931FacilityMsg){
+ msgbuf[i++] = OOFacility;
+ msgbuf[i++] = pq931Msg->tunneledMsgType;
+ msgbuf[i++] = pq931Msg->logicalChannelNo>>8;
+ msgbuf[i++] = pq931Msg->logicalChannelNo;
+ }
+ else{
+ OOTRACEERR3("Error:Unknow Q931 message type. (%s, %s)\n", call->callType,
+ call->callToken);
+ return OO_FAILED;
+ }
+
+ stat = ooEncodeUUIE(pq931Msg);
+ if(stat != OO_OK)
+ {
+ OOTRACEERR3("Error:Failed to encode uuie. (%s, %s)\n", call->callType,
+ call->callToken);
+ return OO_FAILED;
+ }
+
+ msgbuf[i++] = 3; /* TPKT version */
+ msgbuf[i++] = 0; /* TPKT resevred */
+ /* 1st octet of length, will be populated once len is determined */
+ msgbuf[i++] = 0;
+ /* 2nd octet of length, will be populated once len is determined */
+ msgbuf[i++] = 0;
+ /* Q931 protocol discriminator */
+ msgbuf[i++] = pq931Msg->protocolDiscriminator;
+ msgbuf[i++] = 2; /* length of call ref is two octets */
+ msgbuf[i] = (pq931Msg->callReference >> 8); /* populate 1st octet */
+ if(!strcmp(call->callType, "incoming"))
+ msgbuf[i++] |= 0x80; /* fromDestination*/
+ else
+ i++; /* fromOriginator*/
+
+
+ msgbuf[i++] = pq931Msg->callReference; /* populate 2nd octet */
+ msgbuf[i++] = pq931Msg->messageType; /* type of q931 message */
+
+ /* Note: the order in which ies are added is important. It is in the
+ ascending order of ie codes.
+ */
+ /* Add bearer IE */
+ if(pq931Msg->bearerCapabilityIE)
+ {
+ msgbuf[i++] = Q931BearerCapabilityIE; /* ie discriminator */
+ msgbuf[i++] = pq931Msg->bearerCapabilityIE->length;
+ memcpy(msgbuf+i, pq931Msg->bearerCapabilityIE->data,
+ pq931Msg->bearerCapabilityIE->length);
+ i += pq931Msg->bearerCapabilityIE->length;
+ }
+
+ /* Add cause IE */
+ if(pq931Msg->causeIE)
+ {
+ msgbuf[i++] = Q931CauseIE;
+ msgbuf[i++] = pq931Msg->causeIE->length;
+ memcpy(msgbuf+i, pq931Msg->causeIE->data, pq931Msg->causeIE->length);
+ i += pq931Msg->causeIE->length;
+ }
+
+ /*Add progress indicator IE
+ if(pq931Msg->messageType == Q931AlertingMsg || pq931Msg->messageType == Q931CallProceedingMsg)
+ {
+ msgbuf[i++] = Q931ProgressIndicatorIE;
+ msgbuf[i++] = 2; //Length is 2 octet
+ msgbuf[i++] = 0x80; //PI=8
+ msgbuf[i++] = 0x88;
+ }*/
+
+ /*Add display ie. */
+ if(!ooUtilsIsStrEmpty(call->ourCallerId))
+ {
+ msgbuf[i++] = Q931DisplayIE;
+ ieLen = strlen(call->ourCallerId)+1;
+ msgbuf[i++] = ieLen;
+ memcpy(msgbuf+i, call->ourCallerId, ieLen-1);
+ i += ieLen-1;
+ msgbuf[i++] = '\0';
+ }
+
+ /* Add calling Party ie */
+ if(pq931Msg->callingPartyNumberIE)
+ {
+ msgbuf[i++] = Q931CallingPartyNumberIE;
+ msgbuf[i++] = pq931Msg->callingPartyNumberIE->length;
+ memcpy(msgbuf+i, pq931Msg->callingPartyNumberIE->data,
+ pq931Msg->callingPartyNumberIE->length);
+ i += pq931Msg->callingPartyNumberIE->length;
+ }
+
+ /* Add called Party ie */
+ if(pq931Msg->calledPartyNumberIE)
+ {
+ msgbuf[i++] = Q931CalledPartyNumberIE;
+ msgbuf[i++] = pq931Msg->calledPartyNumberIE->length;
+ memcpy(msgbuf+i, pq931Msg->calledPartyNumberIE->data,
+ pq931Msg->calledPartyNumberIE->length);
+ i += pq931Msg->calledPartyNumberIE->length;
+ }
+
+ /* Add keypad ie */
+ if(pq931Msg->keypadIE)
+ {
+ msgbuf[i++] = Q931KeypadIE;
+ msgbuf[i++] = pq931Msg->keypadIE->length;
+ memcpy(msgbuf+i, pq931Msg->keypadIE->data, pq931Msg->keypadIE->length);
+ i += pq931Msg->keypadIE->length;
+ }
+
+ /* Note: Have to fix this, though it works. Need to get rid of ie list.
+ Right now we only put UUIE in ie list. Can be easily removed.
+ */
+
+ for(j = 0, curNode = pq931Msg->ies.head; j < (int)pq931Msg->ies.count; j++)
+ {
+ Q931InformationElement *ie = (Q931InformationElement*) curNode->data;
+
+ ieLen = ie->length;
+
+ /* Add the ie discriminator in message buffer */
+ msgbuf[i++] = ie->discriminator;
+
+ /* For user-user IE, we have to add protocol discriminator */
+ if (ie->discriminator == Q931UserUserIE)
+ {
+ ieLen++; /* length includes protocol discriminator octet. */
+ msgbuf[i++] = (ieLen>>8); /* 1st octet for length */
+ msgbuf[i++] = ieLen; /* 2nd octet for length */
+ ieLen--;
+ msgbuf[i++] = 5; /* protocol discriminator */
+ memcpy((msgbuf + i), ie->data, ieLen);
+
+ i += ieLen;
+
+ }
+ else
+ {
+ OOTRACEWARN1("Warning: Only UUIE is supported currently\n");
+ return OO_FAILED;
+ }
+ }
+ // len = i+1-4; /* complete message length */
+
+
+ /* Tpkt length octets populated with total length of the message */
+ if(msgbuf[0] != OOFacility)
+ {
+ len = i-1;
+ msgbuf[3] = (len >> 8);
+ msgbuf[4] = len; /* including tpkt header */
+ }
+ else{
+ len = i-4;
+ msgbuf[6] = (len >> 8);
+ msgbuf[7] = len;
+ }
+
+#ifndef _COMPACT
+ if(msgbuf[0] != OOFacility)
+ ooQ931PrintMessage (call, msgbuf+5, len-4);
+ else
+ ooQ931PrintMessage (call, msgbuf+8, len-4);
+#endif
+ return OO_OK;
+}
+
+int ooSetFastStartResponse(OOH323CallData *pCall, Q931Message *pQ931msg,
+ ASN1UINT *fsCount, ASN1DynOctStr **fsElem)
+{
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+ int ret = 0, i=0, j=0, remoteMediaPort=0, remoteMediaControlPort = 0, dir=0;
+ char remoteMediaIP[20], remoteMediaControlIP[20];
+ DListNode *pNode = NULL;
+ H245OpenLogicalChannel *olc = NULL, printOlc;
+ ooH323EpCapability *epCap = NULL;
+ ASN1DynOctStr *pFS=NULL;
+ H245H2250LogicalChannelParameters *h2250lcp = NULL;
+ ooLogicalChannel* pChannel;
+
+
+ if(pCall->pFastStartRes) {
+ ASN1UINT k = 0;
+ ASN1OCTET* pData;
+
+ /* copy the stored fast start response to structure */
+ *fsCount = pCall->pFastStartRes->n;
+ *fsElem = (ASN1DynOctStr*)
+ memAlloc(pctxt, pCall->pFastStartRes->n * sizeof(ASN1DynOctStr));
+
+ for(k = 0; k < pCall->pFastStartRes->n; k ++) {
+ (*fsElem)[k].numocts = pCall->pFastStartRes->elem[k].numocts;
+ pData = (ASN1OCTET*) memAlloc(
+ pctxt, (*fsElem)[k].numocts * sizeof(ASN1OCTET));
+ memcpy(pData,
+ pCall->pFastStartRes->elem[k].data,
+ pCall->pFastStartRes->elem[k].numocts);
+ (*fsElem)[k].data = pData;
+ }
+
+ /* free the stored fast start response */
+ if(pQ931msg->messageType == Q931ConnectMsg) {
+ for(k = 0; k < pCall->pFastStartRes->n; k ++) {
+ memFreePtr(pCall->pctxt, pCall->pFastStartRes->elem[k].data);
+ }
+ memFreePtr(pCall->pctxt, pCall->pFastStartRes->elem);
+ memFreePtr(pCall->pctxt, pCall->pFastStartRes);
+ pCall->pFastStartRes = NULL;
+ }
+
+ return ASN_OK;
+ }
+
+
+ /* If fast start supported and remote endpoint has sent faststart element */
+ if(OO_TESTFLAG(gH323ep.flags, OO_M_FASTSTART) &&
+ pCall->remoteFastStartOLCs.count>0)
+ {
+ pFS = (ASN1DynOctStr*)memAlloc(pctxt,
+ pCall->remoteFastStartOLCs.count*sizeof(ASN1DynOctStr));
+ if(!pFS)
+ {
+ OOTRACEERR3("Error:Memory - ooSetFastStartResponse - pFS (%s, %s)\n",
+ pCall->callType, pCall->callToken);
+ return OO_FAILED;
+ }
+ memset(pFS, 0, pCall->remoteFastStartOLCs.count*sizeof(ASN1DynOctStr));
+
+ /* Go though all the proposed channels */
+ for(i=0, j=0; i<(int)pCall->remoteFastStartOLCs.count; i++)
+ {
+
+ pNode = dListFindByIndex(&pCall->remoteFastStartOLCs, i);
+ olc = (H245OpenLogicalChannel*)pNode->data;
+
+ /* Don't support both direction channel */
+ if(olc->forwardLogicalChannelParameters.dataType.t !=
+ T_H245DataType_nullData &&
+ olc->m.reverseLogicalChannelParametersPresent)
+ {
+ OOTRACEINFO3("Ignoring bidirectional OLC as it is not supported."
+ "(%s, %s)\n", pCall->callType, pCall->callToken);
+ continue;
+ }
+
+ /* Check forward logic channel */
+ if(olc->forwardLogicalChannelParameters.dataType.t !=
+ T_H245DataType_nullData)
+ {
+ /* Forward Channel - remote transmits - local receives */
+ OOTRACEDBGC4("Processing received forward olc %d (%s, %s)\n",
+ olc->forwardLogicalChannelNumber, pCall->callType,
+ pCall->callToken);
+ dir = OORX;
+ epCap = ooIsDataTypeSupported(pCall,
+ &olc->forwardLogicalChannelParameters.dataType,
+ OORX);
+
+ if(!epCap) { continue; } /* Not Supported Channel */
+
+ OOTRACEINFO1("Receive Channel data type supported\n");
+ if(olc->forwardLogicalChannelParameters.multiplexParameters.t !=
+ T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
+ {
+ OOTRACEERR4("ERROR:Unknown multiplex parameter type for "
+ "channel %d (%s, %s)\n",
+ olc->forwardLogicalChannelNumber,
+ pCall->callType, pCall->callToken);
+ memFreePtr(pCall->pctxt, epCap);
+ epCap = NULL;
+ continue;
+ }
+ h2250lcp = olc->forwardLogicalChannelParameters.multiplexParameters.u.h2250LogicalChannelParameters;
+
+ /* Check session is Not already established */
+ if(ooIsSessionEstablished(pCall, olc->forwardLogicalChannelParameters.multiplexParameters.u.h2250LogicalChannelParameters->sessionID, "receive"))
+ {
+
+ OOTRACEINFO4("Receive channel with sessionID %d already "
+ "established.(%s, %s)\n", olc->forwardLogicalChannelParameters.multiplexParameters.u.h2250LogicalChannelParameters->sessionID,
+ pCall->callType, pCall->callToken);
+ memFreePtr(pCall->pctxt, epCap);
+ epCap = NULL;
+ continue;
+ }
+
+ /* Extract mediaControlChannel info, if supplied */
+ if(h2250lcp->m.mediaControlChannelPresent)
+ {
+ if(OO_OK != ooGetIpPortFromH245TransportAddress(pCall,
+ &h2250lcp->mediaControlChannel,
+ remoteMediaControlIP, &remoteMediaControlPort))
+ {
+ OOTRACEERR3("Error: Invalid media control channel address "
+ "(%s, %s)\n", pCall->callType, pCall->callToken);
+ memFreePtr(pCall->pctxt, epCap);
+ epCap = NULL;
+ continue;
+ }
+ }
+ }
+ /* Check reverse logical channel */
+ else if(olc->m.reverseLogicalChannelParametersPresent)
+ {
+ /* Reverse channel - remote receives - local transmits */
+ OOTRACEDBGC4("Processing received reverse olc %d (%s, %s)\n",
+ olc->forwardLogicalChannelNumber, pCall->callType,
+ pCall->callToken);
+ dir = OOTX;
+ epCap = ooIsDataTypeSupported(pCall,
+ &olc->reverseLogicalChannelParameters.dataType,
+ OOTX);
+
+ if(!epCap) { continue; } /* Capability not supported */
+
+ OOTRACEINFO1("Transmit Channel data type supported\n");
+
+ if(olc->reverseLogicalChannelParameters.multiplexParameters.t !=
+ T_H245OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
+ {
+ OOTRACEERR4("ERROR:Unknown multiplex parameter type for "
+ "channel %d (%s, %s)\n",
+ olc->forwardLogicalChannelNumber,
+ pCall->callType, pCall->callToken);
+ memFreePtr(pCall->pctxt, epCap);
+ epCap = NULL;
+ continue;
+ }
+
+ /* Check session is not established */
+ if(ooIsSessionEstablished(pCall, olc->reverseLogicalChannelParameters.multiplexParameters.u.h2250LogicalChannelParameters->sessionID, "transmit"))
+ {
+
+ OOTRACEINFO4("Transmit session with sessionID %d already "
+ "established.(%s, %s)\n", olc->reverseLogicalChannelParameters.multiplexParameters.u.h2250LogicalChannelParameters->sessionID, pCall->callType, pCall->callToken);
+
+ memFreePtr(pCall->pctxt, epCap);
+ epCap = NULL;
+ continue;
+ }
+
+ /* Extract the remote media endpoint address */
+ h2250lcp = olc->reverseLogicalChannelParameters.multiplexParameters.u.h2250LogicalChannelParameters;
+ if(!h2250lcp)
+ {
+ OOTRACEERR3("ERROR:Invalid OLC received in fast start. No "
+ "reverse Logical Channel Parameters found. "
+ "(%s, %s)\n", pCall->callType, pCall->callToken);
+ memFreePtr(pCall->pctxt, epCap);
+ epCap = NULL;
+ return OO_FAILED;
+ }
+
+ /* Reverse Channel info will be always present, crash proof */
+ if(!h2250lcp->m.mediaChannelPresent)
+ {
+ OOTRACEERR3("ERROR:Invalid OLC received in fast start. No "
+ "reverse media channel information found. "
+ "(%s, %s)\n", pCall->callType, pCall->callToken);
+ memFreePtr(pCall->pctxt, epCap);
+ epCap = NULL;
+ return OO_FAILED;
+ }
+
+ /* Get IP, PORT of reverse channel */
+ if(OO_OK != ooGetIpPortFromH245TransportAddress(pCall,
+ &h2250lcp->mediaChannel,
+ remoteMediaIP, &remoteMediaPort))
+ {
+ OOTRACEERR3("Error: Invalid media channel address "
+ "(%s, %s)\n", pCall->callType, pCall->callToken);
+ memFreePtr(pCall->pctxt, epCap);
+ epCap = NULL;
+ continue;
+ }
+
+ /* Extract mediaControlChannel info, if supplied */
+ if(h2250lcp->m.mediaControlChannelPresent)
+ {
+ if(OO_OK != ooGetIpPortFromH245TransportAddress(pCall,
+ &h2250lcp->mediaControlChannel,
+ remoteMediaControlIP, &remoteMediaControlPort))
+ {
+ OOTRACEERR3("Error: Invalid media control channel address "
+ "(%s, %s)\n", pCall->callType, pCall->callToken);
+ memFreePtr(pCall->pctxt, epCap);
+ epCap = NULL;
+ continue;
+ }
+ }
+ }
+
+ if(dir & OOTX)
+ {
+ /* According to the spec if we are accepting olc for transmission
+ from called endpoint to calling endpoint, called endpoint should
+ insert a unqiue forwardLogicalChannelNumber into olc
+ */
+ olc->forwardLogicalChannelNumber = pCall->logicalChanNoCur++;
+ if(pCall->logicalChanNoCur > pCall->logicalChanNoMax)
+ pCall->logicalChanNoCur = pCall->logicalChanNoBase;
+ }
+
+
+ ooPrepareFastStartResponseOLC(pCall, olc, epCap, pctxt, dir);
+
+ pChannel = ooFindLogicalChannelByLogicalChannelNo
+ (pCall, olc->forwardLogicalChannelNumber);
+
+ /* start receive and tramsmit channel listening */
+ if(dir & OORX)
+ {
+ strcpy(pChannel->remoteIP, remoteMediaControlIP);
+ pChannel->remoteMediaControlPort = remoteMediaControlPort;
+ if(epCap->startReceiveChannel)
+ {
+ epCap->startReceiveChannel(pCall, pChannel);
+ OOTRACEINFO4("Receive channel of type %s started (%s, %s)\n",
+ (epCap->capType == OO_CAP_TYPE_AUDIO)?"audio":"video",
+ pCall->callType, pCall->callToken);
+ }
+ else{
+ OOTRACEERR4("ERROR:No callback registered to start receive %s"
+ " channel (%s, %s)\n",
+ (epCap->capType == OO_CAP_TYPE_AUDIO)?"audio":"video",
+ pCall->callType, pCall->callToken);
+ return OO_FAILED;
+ }
+ }
+ if(dir & OOTX)
+ {
+ pChannel->remoteMediaPort = remoteMediaPort;
+ strcpy(pChannel->remoteIP, remoteMediaIP);
+ pChannel->remoteMediaControlPort = remoteMediaControlPort;
+
+ if(epCap->startTransmitChannel)
+ {
+ epCap->startTransmitChannel(pCall, pChannel);
+ OOTRACEINFO3("Transmit channel of type audio started "
+ "(%s, %s)\n", pCall->callType, pCall->callToken);
+ /*OO_SETFLAG (pCall->flags, OO_M_AUDIO);*/
+ }
+ else{
+ OOTRACEERR3("ERROR:No callback registered to start transmit"
+ " audio channel (%s, %s)\n", pCall->callType,
+ pCall->callToken);
+ return OO_FAILED;
+ }
+ }
+
+ /* Encode fast start element */
+ setPERBuffer(pctxt, NULL, 0, 1);
+ if(asn1PE_H245OpenLogicalChannel(pctxt, olc) != ASN_OK)
+ {
+ OOTRACEERR3("ERROR:Encoding of olc failed for faststart "
+ "(%s, %s)\n", pCall->callType, pCall->callToken);
+ ooFreeQ931Message(pQ931msg);
+ if(pCall->callState < OO_CALL_CLEAR)
+ {
+ pCall->callEndReason = OO_REASON_LOCAL_CLEARED;
+ pCall->callState = OO_CALL_CLEAR;
+ }
+ return OO_FAILED;
+ }
+ pFS[j].data = encodeGetMsgPtr(pctxt, &(pFS[j].numocts));
+
+
+ /* start print call */
+ setPERBuffer(pctxt, (char*)pFS[j].data, pFS[j].numocts, 1);
+ initializePrintHandler(&printHandler, "FastStart Element");
+ setEventHandler (pctxt, &printHandler);
+ memset(&printOlc, 0, sizeof(printOlc));
+ ret = asn1PD_H245OpenLogicalChannel(pctxt, &(printOlc));
+ if(ret != ASN_OK)
+ {
+ OOTRACEERR3("Error: Failed decoding FastStart Element (%s, %s)\n",
+ pCall->callType, pCall->callToken);
+ ooFreeQ931Message(pQ931msg);
+ if(pCall->callState < OO_CALL_CLEAR)
+ {
+ pCall->callEndReason = OO_REASON_LOCAL_CLEARED;
+ pCall->callState = OO_CALL_CLEAR;
+ }
+ return OO_FAILED;
+ }
+ finishPrint();
+ removeEventHandler(pctxt);
+ /* end print call */
+
+ olc = NULL;
+ j++;
+ epCap = NULL;
+ }
+ OOTRACEDBGA4("Added %d fast start elements to message "
+ "(%s, %s)\n", j, pCall->callType, pCall->callToken);
+ if(j != 0)
+ {
+ ASN1UINT k = 0;
+ ASN1OCTET* pData;
+ //*fsPresent = TRUE;
+ *fsCount = j;
+ *fsElem = pFS;
+
+ /* save the fast start response for later use in ALERTING, CONNECT */
+ pCall->pFastStartRes = (FastStartResponse*)
+ memAlloc(pCall->pctxt, sizeof(FastStartResponse));
+ pCall->pFastStartRes->n = j;
+ pCall->pFastStartRes->elem = (ASN1DynOctStr*) memAlloc(pCall->pctxt,
+ pCall->pFastStartRes->n * sizeof(ASN1DynOctStr));
+
+ for(k = 0; k < pCall->pFastStartRes->n; k ++) {
+ pCall->pFastStartRes->elem[k].numocts = (*fsElem)[k].numocts;
+ pData = (ASN1OCTET*) memAlloc(pCall->pctxt,
+ pCall->pFastStartRes->elem[k].numocts * sizeof(ASN1OCTET));
+ memcpy(pData, (*fsElem)[k].data, (*fsElem)[k].numocts);
+ pCall->pFastStartRes->elem[k].data = pData;
+ }
+ }
+ else{
+ OOTRACEINFO3("None of the faststart elements received in setup can be"
+ " supported, rejecting faststart.(%s, %s)\n",
+ pCall->callType, pCall->callToken);
+ //*fsPresent = FALSE;
+ OO_CLRFLAG(pCall->flags, OO_M_FASTSTART);
+ OOTRACEDBGC3("Faststart for pCall is disabled by local endpoint."
+ "(%s, %s)\n", pCall->callType, pCall->callToken);
+ }
+ }
+ return ASN_OK;
+}
+
+
+/*
+
+*/
+
+int ooSendCallProceeding(OOH323CallData *call)
+{
+ int ret;
+ H225VendorIdentifier *vendor;
+ H225CallProceeding_UUIE *callProceeding;
+ Q931Message *q931msg=NULL;
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+
+ OOTRACEDBGC3("Building CallProceeding (%s, %s)\n", call->callType,
+ call->callToken);
+ ret = ooCreateQ931Message(&q931msg, Q931CallProceedingMsg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR1("Error: In allocating memory for - H225 Call "
+ "Proceeding message\n");
+ return OO_FAILED;
+ }
+
+ q931msg->callReference = call->callReference;
+
+ q931msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
+ sizeof(H225H323_UserInformation));
+ if(!q931msg->userInfo)
+ {
+ OOTRACEERR1("ERROR:Memory - ooSendCallProceeding - userInfo\n");
+ return OO_FAILED;
+ }
+ memset (q931msg->userInfo, 0, sizeof(H225H323_UserInformation));
+ q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1;
+ q931msg->userInfo->h323_uu_pdu.h245Tunneling =
+ OO_TESTFLAG(gH323ep.flags, OO_M_TUNNELING);
+ q931msg->userInfo->h323_uu_pdu.h323_message_body.t =
+ T_H225H323_UU_PDU_h323_message_body_callProceeding;
+
+ callProceeding = (H225CallProceeding_UUIE*)memAlloc(pctxt,
+ sizeof(H225CallProceeding_UUIE));
+ if(!callProceeding)
+ {
+ OOTRACEERR1("ERROR:Memory - ooSendCallProceeding - callProceeding\n");
+ return OO_FAILED;
+ }
+ memset(callProceeding, 0, sizeof(H225CallProceeding_UUIE));
+ q931msg->userInfo->h323_uu_pdu.h323_message_body.u.callProceeding = callProceeding;
+ callProceeding->m.multipleCallsPresent = 1;
+ callProceeding->m.maintainConnectionPresent = 1;
+ callProceeding->multipleCalls = FALSE;
+ callProceeding->maintainConnection = FALSE;
+
+ callProceeding->m.callIdentifierPresent = 1;
+ callProceeding->callIdentifier.guid.numocts =
+ call->callIdentifier.guid.numocts;
+ memcpy(callProceeding->callIdentifier.guid.data,
+ call->callIdentifier.guid.data,
+ call->callIdentifier.guid.numocts);
+ callProceeding->protocolIdentifier = gProtocolID;
+
+ /* Pose as Terminal or Gateway */
+ if(gH323ep.isGateway)
+ callProceeding->destinationInfo.m.gatewayPresent = TRUE;
+ else
+ callProceeding->destinationInfo.m.terminalPresent = TRUE;
+
+ callProceeding->destinationInfo.m.vendorPresent = 1;
+ vendor = &callProceeding->destinationInfo.vendor;
+ if(gH323ep.productID)
+ {
+ vendor->m.productIdPresent = 1;
+ vendor->productId.numocts = ASN1MIN(strlen(gH323ep.productID),
+ sizeof(vendor->productId.data));
+ strncpy(vendor->productId.data, gH323ep.productID,
+ vendor->productId.numocts);
+ }
+ if(gH323ep.versionID)
+ {
+ vendor->m.versionIdPresent = 1;
+ vendor->versionId.numocts = ASN1MIN(strlen(gH323ep.versionID),
+ sizeof(vendor->versionId.data));
+ strncpy(vendor->versionId.data, gH323ep.versionID,
+ vendor->versionId.numocts);
+ }
+
+ vendor->vendor.t35CountryCode = gH323ep.t35CountryCode;
+ vendor->vendor.t35Extension = gH323ep.t35Extension;
+ vendor->vendor.manufacturerCode = gH323ep.manufacturerCode;
+
+ OOTRACEDBGA3("Built Call Proceeding(%s, %s)\n", call->callType,
+ call->callToken);
+ ret = ooSendH225Msg(call, q931msg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3("Error:Failed to enqueue CallProceeding message to outbound queue.(%s, %s)\n", call->callType, call->callToken);
+ }
+
+ memReset(&gH323ep.msgctxt);
+
+ return ret;
+}
+
+int ooSendAlerting(OOH323CallData *call)
+{
+ int ret;
+ H225Alerting_UUIE *alerting;
+ H225VendorIdentifier *vendor;
+ Q931Message *q931msg=NULL;
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+
+ ret = ooCreateQ931Message(&q931msg, Q931AlertingMsg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR1("Error: In allocating memory for - H225 "
+ "Alerting message\n");
+ return OO_FAILED;
+ }
+
+ q931msg->callReference = call->callReference;
+
+ q931msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
+ sizeof(H225H323_UserInformation));
+ if(!q931msg->userInfo)
+ {
+ OOTRACEERR1("ERROR:Memory - ooSendAlerting - userInfo\n");
+ return OO_FAILED;
+ }
+ memset (q931msg->userInfo, 0, sizeof(H225H323_UserInformation));
+ q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1;
+ q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(gH323ep.flags,
+ OO_M_TUNNELING);
+ q931msg->userInfo->h323_uu_pdu.h323_message_body.t =
+ T_H225H323_UU_PDU_h323_message_body_alerting;
+
+ alerting = (H225Alerting_UUIE*)memAlloc(pctxt,
+ sizeof(H225Alerting_UUIE));
+ if(!alerting)
+ {
+ OOTRACEERR1("ERROR:Memory - ooSendAlerting - alerting\n");
+ return OO_FAILED;
+ }
+ memset(alerting, 0, sizeof(H225Alerting_UUIE));
+ q931msg->userInfo->h323_uu_pdu.h323_message_body.u.alerting = alerting;
+ alerting->m.multipleCallsPresent = 1;
+ alerting->m.maintainConnectionPresent = 1;
+ alerting->multipleCalls = FALSE;
+ alerting->maintainConnection = FALSE;
+
+ /*Populate aliases */
+ alerting->m.alertingAddressPresent = TRUE;
+ if(call->ourAliases)
+ ret = ooPopulateAliasList(pctxt, call->ourAliases,
+ &alerting->alertingAddress);
+ else
+ ret = ooPopulateAliasList(pctxt, gH323ep.aliases,
+ &alerting->alertingAddress);
+ if(OO_OK != ret)
+ {
+ OOTRACEERR1("Error:Failed to populate alias list in Alert message\n");
+ memReset(pctxt);
+ return OO_FAILED;
+ }
+ alerting->m.presentationIndicatorPresent = TRUE;
+ alerting->presentationIndicator.t =
+ T_H225PresentationIndicator_presentationAllowed;
+ alerting->m.screeningIndicatorPresent = TRUE;
+ alerting->screeningIndicator = userProvidedNotScreened;
+
+
+
+ alerting->m.callIdentifierPresent = 1;
+ alerting->callIdentifier.guid.numocts =
+ call->callIdentifier.guid.numocts;
+ memcpy(alerting->callIdentifier.guid.data,
+ call->callIdentifier.guid.data,
+ call->callIdentifier.guid.numocts);
+ alerting->protocolIdentifier = gProtocolID;
+
+ /* Pose as Terminal or Gateway */
+ if(gH323ep.isGateway)
+ alerting->destinationInfo.m.gatewayPresent = TRUE;
+ else
+ alerting->destinationInfo.m.terminalPresent = TRUE;
+
+ alerting->destinationInfo.m.vendorPresent = 1;
+ vendor = &alerting->destinationInfo.vendor;
+ if(gH323ep.productID)
+ {
+ vendor->m.productIdPresent = 1;
+ vendor->productId.numocts = ASN1MIN(strlen(gH323ep.productID),
+ sizeof(vendor->productId.data));
+ strncpy(vendor->productId.data, gH323ep.productID,
+ vendor->productId.numocts);
+ }
+ if(gH323ep.versionID)
+ {
+ vendor->m.versionIdPresent = 1;
+ vendor->versionId.numocts = ASN1MIN(strlen(gH323ep.versionID),
+ sizeof(vendor->versionId.data));
+ strncpy(vendor->versionId.data, gH323ep.versionID,
+ vendor->versionId.numocts);
+ }
+
+ vendor->vendor.t35CountryCode = gH323ep.t35CountryCode;
+ vendor->vendor.t35Extension = gH323ep.t35Extension;
+ vendor->vendor.manufacturerCode = gH323ep.manufacturerCode;
+
+ ret = ooSetFastStartResponse(call, q931msg,
+ &alerting->fastStart.n, &alerting->fastStart.elem);
+ if(ret != ASN_OK) { return ret; }
+ if(alerting->fastStart.n > 0) {
+ alerting->m.fastStartPresent = TRUE;
+ }
+ else {
+ alerting->m.fastStartPresent = FALSE;
+ }
+
+ OOTRACEDBGA3("Built Alerting (%s, %s)\n", call->callType, call->callToken);
+
+ ret = ooSendH225Msg(call, q931msg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3("Error: Failed to enqueue Alerting message to outbound queue. (%s, %s)\n", call->callType, call->callToken);
+ }
+
+ memReset(&gH323ep.msgctxt);
+
+ return ret;
+}
+
+
+int ooSendFacility(OOH323CallData *call)
+{
+ int ret=0;
+ Q931Message *pQ931Msg = NULL;
+ H225Facility_UUIE *facility=NULL;
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+
+ OOTRACEDBGA3("Building Facility message (%s, %s)\n", call->callType,
+ call->callToken);
+ ret = ooCreateQ931Message(&pQ931Msg, Q931FacilityMsg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3
+ ("ERROR: In allocating memory for facility message (%s, %s)\n",
+ call->callType, call->callToken);
+ return OO_FAILED;
+ }
+
+ pQ931Msg->callReference = call->callReference;
+
+ pQ931Msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
+ sizeof(H225H323_UserInformation));
+ if(!pQ931Msg->userInfo)
+ {
+ OOTRACEERR3("ERROR:Memory - ooSendFacility - userInfo(%s, %s)\n",
+ call->callType, call->callToken);
+ return OO_FAILED;
+ }
+ memset (pQ931Msg->userInfo, 0, sizeof(H225H323_UserInformation));
+ pQ931Msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1;
+
+ pQ931Msg->userInfo->h323_uu_pdu.h245Tunneling =
+ OO_TESTFLAG (call->flags, OO_M_TUNNELING);
+
+ pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.t =
+ T_H225H323_UU_PDU_h323_message_body_facility;
+
+ facility = (H225Facility_UUIE*)
+ memAllocZ (pctxt, sizeof(H225Facility_UUIE));
+
+ if(!facility)
+ {
+ OOTRACEERR3("ERROR:Memory - ooSendFacility - facility (%s, %s)"
+ "\n", call->callType, call->callToken);
+ return OO_FAILED;
+ }
+
+ pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.u.facility = facility;
+
+ /* Populate Facility UUIE */
+ facility->protocolIdentifier = gProtocolID;
+ facility->m.callIdentifierPresent = 1;
+ facility->callIdentifier.guid.numocts =
+ call->callIdentifier.guid.numocts;
+ memcpy(facility->callIdentifier.guid.data,
+ call->callIdentifier.guid.data,
+ call->callIdentifier.guid.numocts);
+ facility->reason.t = T_H225FacilityReason_transportedInformation;
+ OOTRACEDBGA3("Built Facility message to send (%s, %s)\n", call->callType,
+ call->callToken);
+
+ ret = ooSendH225Msg(call, pQ931Msg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3
+ ("Error:Failed to enqueue Facility message to outbound "
+ "queue.(%s, %s)\n", call->callType, call->callToken);
+ }
+ memReset (&gH323ep.msgctxt);
+ return ret;
+}
+
+int ooSendReleaseComplete(OOH323CallData *call)
+{
+ int ret;
+ Q931Message *q931msg=NULL;
+ H225ReleaseComplete_UUIE *releaseComplete;
+ enum Q931CauseValues cause = Q931ErrorInCauseIE;
+ unsigned h225ReasonCode = T_H225ReleaseCompleteReason_undefinedReason;
+
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+ OOTRACEDBGA3("Building Release Complete message to send(%s, %s)\n",
+ call->callType, call->callToken);
+ ret = ooCreateQ931Message(&q931msg, Q931ReleaseCompleteMsg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3("Error: In ooCreateQ931Message - H225 Release Complete "
+ "message(%s, %s)\n", call->callType, call->callToken);
+ if(call->callState < OO_CALL_CLEAR)
+ {
+ call->callEndReason = OO_REASON_LOCAL_CLEARED;
+ call->callState = OO_CALL_CLEAR;
+ }
+ return OO_FAILED;
+ }
+
+ q931msg->callReference = call->callReference;
+
+ q931msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
+ sizeof(H225H323_UserInformation));
+ if(!q931msg->userInfo)
+ {
+ OOTRACEERR1("ERROR:Memory - ooSendReleaseComplete - userInfo\n");
+ return OO_FAILED;
+ }
+ memset (q931msg->userInfo, 0, sizeof(H225H323_UserInformation));
+
+ releaseComplete = (H225ReleaseComplete_UUIE*)memAlloc(pctxt,
+ sizeof(H225ReleaseComplete_UUIE));
+ if(!releaseComplete)
+ {
+ OOTRACEERR3("Error:Memory - ooSendReleaseComplete - releaseComplete"
+ "(%s, %s)\n", call->callType, call->callToken);
+ return OO_FAILED;
+ }
+ memset(releaseComplete, 0, sizeof(H225ReleaseComplete_UUIE));
+ q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1;
+ q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(gH323ep.flags,
+ OO_M_TUNNELING);
+ q931msg->userInfo->h323_uu_pdu.h323_message_body.t =
+ T_H225H323_UU_PDU_h323_message_body_releaseComplete;
+
+ /* Get cause value and h225 reason code corresponding to OOCallClearReason*/
+ ooQ931GetCauseAndReasonCodeFromCallClearReason(call->callEndReason,
+ &cause, &h225ReasonCode);
+ /* Set Cause IE */
+ ooQ931SetCauseIE(q931msg, cause, 0, 0);
+
+ /* Set H225 releaseComplete reasonCode */
+ releaseComplete->m.reasonPresent = TRUE;
+ releaseComplete->reason.t = h225ReasonCode;
+
+ /* Add user-user ie */
+ q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=TRUE;
+ q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG (call->flags, OO_M_TUNNELING);
+ q931msg->userInfo->h323_uu_pdu.h323_message_body.t =
+ T_H225H323_UU_PDU_h323_message_body_releaseComplete;
+
+ q931msg->userInfo->h323_uu_pdu.h323_message_body.u.releaseComplete =
+ releaseComplete;
+ releaseComplete->m.callIdentifierPresent = 1;
+ releaseComplete->protocolIdentifier = gProtocolID;
+ releaseComplete->callIdentifier.guid.numocts =
+ call->callIdentifier.guid.numocts;
+ memcpy(releaseComplete->callIdentifier.guid.data,
+ call->callIdentifier.guid.data,
+ call->callIdentifier.guid.numocts);
+
+ OOTRACEDBGA3("Built Release Complete message (%s, %s)\n",
+ call->callType, call->callToken);
+ /* Send H225 message */
+ ret = ooSendH225Msg(call, q931msg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3("Error:Failed to enqueue ReleaseComplete message to outbound"
+ " queue.(%s, %s)\n", call->callType, call->callToken);
+ }
+ memReset(&gH323ep.msgctxt);
+
+ return ret;
+}
+
+int ooSendConnect(OOH323CallData *call)
+{
+ ooAcceptCall(call);
+ return OO_OK;
+}
+
+/*TODO: Need to clean logical channel in case of failure after creating one */
+int ooAcceptCall(OOH323CallData *call)
+{
+ int ret = 0, i=0;
+ H225Connect_UUIE *connect;
+ H225TransportAddress_ipAddress *h245IpAddr;
+ H225VendorIdentifier *vendor;
+ Q931Message *q931msg=NULL;
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+
+ ret = ooCreateQ931Message(&q931msg, Q931ConnectMsg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR1("Error: In allocating memory for - H225 "
+ "Connect message\n");
+ return OO_FAILED;
+ }
+ q931msg->callReference = call->callReference;
+
+ /* Set bearer capability */
+ if(OO_OK != ooSetBearerCapabilityIE(q931msg, Q931CCITTStd,
+ Q931TransferUnrestrictedDigital, Q931TransferPacketMode,
+ Q931TransferRatePacketMode, Q931UserInfoLayer1G722G725))
+ // Q931TransferSpeech, Q931TransferCircuitMode,
+ // Q931TransferRate64Kbps, Q931UserInfoLayer1G711ULaw))
+ {
+ OOTRACEERR3("Error: Failed to set bearer capability ie. (%s, %s)\n",
+ call->callType, call->callToken);
+ return OO_FAILED;
+ }
+
+ q931msg->userInfo = (H225H323_UserInformation*)
+ memAllocZ (pctxt,sizeof(H225H323_UserInformation));
+
+ if(!q931msg->userInfo)
+ {
+ OOTRACEERR1("ERROR:Memory - ooAcceptCall - userInfo\n");
+ return OO_FAILED;
+ }
+
+ q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=TRUE;
+
+ q931msg->userInfo->h323_uu_pdu.h245Tunneling =
+ OO_TESTFLAG (call->flags, OO_M_TUNNELING);
+
+ q931msg->userInfo->h323_uu_pdu.h323_message_body.t =
+ T_H225H323_UU_PDU_h323_message_body_connect;
+
+ connect = (H225Connect_UUIE*)
+ memAllocZ (pctxt, sizeof(H225Connect_UUIE));
+
+ if(!connect)
+ {
+ OOTRACEERR1("ERROR:Memory - ooAcceptCall - connect\n");
+ return OO_FAILED;
+ }
+
+ q931msg->userInfo->h323_uu_pdu.h323_message_body.u.connect = connect;
+ connect->m.fastStartPresent = 0;
+ connect->m.multipleCallsPresent = 1;
+ connect->m.maintainConnectionPresent = 1;
+ connect->multipleCalls = FALSE;
+ connect->maintainConnection = FALSE;
+
+
+ connect->conferenceID.numocts = 16;
+ for (i = 0; i < 16; i++)
+ connect->conferenceID.data[i] = i + 1;
+
+ connect->m.callIdentifierPresent = 1;
+ connect->callIdentifier.guid.numocts =
+ call->callIdentifier.guid.numocts;
+ memcpy(connect->callIdentifier.guid.data, call->callIdentifier.guid.data,
+ call->callIdentifier.guid.numocts);
+
+ connect->conferenceID.numocts = call->confIdentifier.numocts;
+ memcpy(connect->conferenceID.data, call->confIdentifier.data,
+ call->confIdentifier.numocts);
+ /* Populate alias addresses */
+ connect->m.connectedAddressPresent = TRUE;
+ if(call->ourAliases)
+ ret = ooPopulateAliasList(pctxt, call->ourAliases,
+ &connect->connectedAddress);
+ else
+ ret = ooPopulateAliasList(pctxt, gH323ep.aliases,
+ &connect->connectedAddress);
+ if(OO_OK != ret)
+ {
+ OOTRACEERR1("Error:Failed to populate alias list in Connect message\n");
+ memReset(pctxt);
+ return OO_FAILED;
+ }
+ connect->m.presentationIndicatorPresent = TRUE;
+ connect->presentationIndicator.t =
+ T_H225PresentationIndicator_presentationAllowed;
+ connect->m.screeningIndicatorPresent = TRUE;
+ connect->screeningIndicator = userProvidedNotScreened;
+
+ connect->protocolIdentifier = gProtocolID;
+
+ /* Pose as Terminal or Gateway */
+ if(gH323ep.isGateway)
+ connect->destinationInfo.m.gatewayPresent = TRUE;
+ else
+ connect->destinationInfo.m.terminalPresent = TRUE;
+
+
+ connect->destinationInfo.m.vendorPresent = 1;
+ vendor = &connect->destinationInfo.vendor;
+
+ vendor->vendor.t35CountryCode = gH323ep.t35CountryCode;
+ vendor->vendor.t35Extension = gH323ep.t35Extension;
+ vendor->vendor.manufacturerCode = gH323ep.manufacturerCode;
+ if(gH323ep.productID)
+ {
+ vendor->m.productIdPresent = 1;
+ vendor->productId.numocts = ASN1MIN(strlen(gH323ep.productID),
+ sizeof(vendor->productId.data));
+ strncpy(vendor->productId.data, gH323ep.productID,
+ vendor->productId.numocts);
+ }
+ if(gH323ep.versionID)
+ {
+ vendor->m.versionIdPresent = 1;
+ vendor->versionId.numocts = ASN1MIN(strlen(gH323ep.versionID),
+ sizeof(vendor->versionId.data));
+ strncpy(vendor->versionId.data, gH323ep.versionID,
+ vendor->versionId.numocts);
+ }
+
+ ret = ooSetFastStartResponse(call, q931msg,
+ &connect->fastStart.n, &connect->fastStart.elem);
+ if(ret != ASN_OK) { return ret; }
+ if(connect->fastStart.n > 0) {
+ connect->m.fastStartPresent = TRUE;
+ }
+ else {
+ connect->m.fastStartPresent = FALSE;
+ }
+
+ /* Add h245 listener address. Do not add H245 listener address in case
+ of fast-start. */
+ if ((!OO_TESTFLAG(call->flags, OO_M_FASTSTART) ||
+ call->remoteFastStartOLCs.count == 0) &&
+ !OO_TESTFLAG (call->flags, OO_M_TUNNELING))
+ {
+ ooCreateH245Listener(call); /* First create an H.245 listener */
+ connect->m.h245AddressPresent = TRUE;
+ connect->h245Address.t = T_H225TransportAddress_ipAddress;
+
+ h245IpAddr = (H225TransportAddress_ipAddress*)
+ memAllocZ (pctxt, sizeof(H225TransportAddress_ipAddress));
+ if(!h245IpAddr)
+ {
+ OOTRACEERR3("Error:Memory - ooAcceptCall - h245IpAddr"
+ "(%s, %s)\n", call->callType, call->callToken);
+ return OO_FAILED;
+ }
+ ooSocketConvertIpToNwAddr(call->localIP, h245IpAddr->ip.data);
+ h245IpAddr->ip.numocts=4;
+ h245IpAddr->port = *(call->h245listenport);
+ connect->h245Address.u.ipAddress = h245IpAddr;
+ }
+
+ OOTRACEDBGA3("Built H.225 Connect message (%s, %s)\n", call->callType,
+ call->callToken);
+
+ /* H225 message callback */
+ if(gH323ep.h225Callbacks.onBuiltConnect)
+ gH323ep.h225Callbacks.onBuiltConnect(call, q931msg);
+
+ ret=ooSendH225Msg(call, q931msg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3("Error:Failed to enqueue Connect message to outbound queue.(%s, %s)\n", call->callType, call->callToken);
+ memReset(&gH323ep.msgctxt);
+ return OO_FAILED;
+ }
+ memReset(&gH323ep.msgctxt);
+
+#if 0
+ if (OO_TESTFLAG (call->flags, OO_M_TUNNELING))
+ {
+ /* 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;
+ }
+ }
+#endif
+ return OO_OK;
+}
+
+int ooH323HandleCallFwdRequest(OOH323CallData *call)
+{
+ OOH323CallData *fwdedCall=NULL;
+ OOCTXT *pctxt;
+ ooAliases *pNewAlias=NULL, *alias=NULL;
+ int i=0, irand=0, ret = OO_OK;
+ /* Note: We keep same callToken, for new call which is going
+ to replace an existing call, thus treating it as a single call.*/
+
+ fwdedCall = ooCreateCall("outgoing", call->callToken);
+
+ pctxt = fwdedCall->pctxt;
+
+ /* Retrieve new destination info from original call */
+ if(!ooUtilsIsStrEmpty(call->pCallFwdData->ip))
+ {
+ strcpy(fwdedCall->remoteIP, call->pCallFwdData->ip);
+ }
+ fwdedCall->remotePort = call->pCallFwdData->port;
+
+ if(call->pCallFwdData->aliases)
+ {
+ alias = call->pCallFwdData->aliases;
+ while(alias)
+ {
+ pNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases));
+ pNewAlias->value = (char*) memAlloc(pctxt, strlen(alias->value)+1);
+ if(!pNewAlias || !pNewAlias->value)
+ {
+ OOTRACEERR3("Error:Memory - ooH323HandleCallFwdRequest - "
+ "pNewAlias/pNewAlias->value"
+ "(%s, %s)\n", call->callType, call->callToken);
+ ooCleanCall(fwdedCall);
+ return OO_FAILED;
+ }
+ pNewAlias->type = alias->type;
+ strcpy(pNewAlias->value, alias->value);
+ pNewAlias->next = fwdedCall->remoteAliases;
+ fwdedCall->remoteAliases = pNewAlias;
+ alias = alias->next;
+ pNewAlias = NULL;
+ }
+ }
+
+ fwdedCall->callReference = ooGenerateCallReference();
+ ooGenerateCallIdentifier(&fwdedCall->callIdentifier);
+ fwdedCall->confIdentifier.numocts = 16;
+ irand = rand();
+ for (i = 0; i < 16; i++) {
+ fwdedCall->confIdentifier.data[i] = irand++;
+ }
+
+
+ if(gH323ep.gkClient && !OO_TESTFLAG(fwdedCall->flags, OO_M_DISABLEGK))
+ {
+ /* No need to check registration status here as it is already checked for
+ MakeCall command */
+ ret = ooGkClientSendAdmissionRequest(gH323ep.gkClient, fwdedCall, FALSE);
+ fwdedCall->callState = OO_CALL_WAITING_ADMISSION;
+ }
+ else {
+ ret = ooH323CallAdmitted (fwdedCall);
+ }
+
+ return OO_OK;
+
+}
+
+int ooH323MakeCall(char *dest, char *callToken, ooCallOptions *opts)
+{
+ OOCTXT *pctxt;
+ OOH323CallData *call;
+ int ret=0, i=0, irand=0;
+ char tmp[30]="\0";
+ char *ip=NULL, *port = NULL;
+
+ if(!dest)
+ {
+ OOTRACEERR1("ERROR:Invalid destination for new call\n");
+ return OO_FAILED;
+ }
+ if(!callToken)
+ {
+ OOTRACEERR1("ERROR: Invalid callToken parameter to make call\n");
+ return OO_FAILED;
+ }
+
+ call = ooCreateCall("outgoing", callToken);
+ pctxt = call->pctxt;
+ if(opts)
+ {
+ if(opts->fastStart)
+ OO_SETFLAG(call->flags, OO_M_FASTSTART);
+ else
+ OO_CLRFLAG(call->flags, OO_M_FASTSTART);
+
+ if(opts->tunneling)
+ OO_SETFLAG(call->flags, OO_M_TUNNELING);
+ else
+ OO_CLRFLAG(call->flags, OO_M_TUNNELING);
+
+ if(opts->disableGk)
+ OO_SETFLAG(call->flags, OO_M_DISABLEGK);
+ else
+ OO_CLRFLAG(call->flags, OO_M_DISABLEGK);
+
+ call->callMode = opts->callMode;
+ }
+
+
+ ret = ooParseDestination(call, dest, tmp, 30, &call->remoteAliases);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR2("Error: Failed to parse the destination string %s for "
+ "new call\n", dest);
+ ooCleanCall(call);
+ return OO_FAILED;
+ }
+
+ /* Check whether we have ip address */
+ if(!ooUtilsIsStrEmpty(tmp)) {
+ ip = tmp;
+ port = strchr(tmp, ':');
+ *port = '\0';
+ port++;
+ strcpy(call->remoteIP, ip);
+ call->remotePort = atoi(port);
+ }
+
+ strcpy(callToken, call->callToken);
+ call->callReference = ooGenerateCallReference();
+ ooGenerateCallIdentifier(&call->callIdentifier);
+ call->confIdentifier.numocts = 16;
+ irand = rand();
+ for (i = 0; i < 16; i++) {
+ call->confIdentifier.data[i] = irand++;
+ }
+
+
+ if(gH323ep.gkClient && !OO_TESTFLAG(call->flags, OO_M_DISABLEGK))
+ {
+ /* No need to check registration status here as it is already checked for
+ MakeCall command */
+ ret = ooGkClientSendAdmissionRequest(gH323ep.gkClient, call, FALSE);
+ call->callState = OO_CALL_WAITING_ADMISSION;
+ }
+ else {
+ /* Send as H225 message to calling endpoint */
+ ret = ooH323CallAdmitted (call);
+ }
+
+ return OO_OK;
+}
+
+
+int ooH323CallAdmitted(OOH323CallData *call)
+{
+ int ret=0;
+
+ if(!call)
+ {
+ /* Call not supplied. Must locate it in list */
+ OOTRACEERR1("ERROR: Invalid call parameter to ooH323CallAdmitted");
+ return OO_FAILED;
+ }
+
+ if(!strcmp(call->callType, "outgoing")) {
+ ret = ooCreateH225Connection(call);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3("ERROR:Failed to create H225 connection to %s:%d\n",
+ call->remoteIP, call->remotePort);
+ if(call->callState< OO_CALL_CLEAR)
+ {
+ call->callState = OO_CALL_CLEAR;
+ call->callEndReason = OO_REASON_UNKNOWN;
+ }
+ return OO_FAILED;
+ }
+
+ ret = ooH323MakeCall_helper(call);
+ }
+ else {
+ /* incoming call */
+ if(gH323ep.h323Callbacks.onIncomingCall) {
+ /* Incoming call callback function */
+ gH323ep.h323Callbacks.onIncomingCall(call);
+ }
+
+ /* Check for manual ringback generation */
+ if(!OO_TESTFLAG(gH323ep.flags, OO_M_MANUALRINGBACK))
+ {
+ ooSendAlerting(call); /* Send alerting message */
+
+ if(OO_TESTFLAG(gH323ep.flags, OO_M_AUTOANSWER)) {
+ ooSendConnect(call); /* Send connect message - call accepted */
+ }
+ }
+ }
+
+ return OO_OK;
+}
+
+int ooH323MakeCall_helper(OOH323CallData *call)
+{
+ int ret=0,i=0, k;
+ Q931Message *q931msg = NULL;
+ H225Setup_UUIE *setup;
+
+ ASN1DynOctStr *pFS=NULL;
+ H225TransportAddress_ipAddress *destCallSignalIpAddress;
+
+ H225TransportAddress_ipAddress *srcCallSignalIpAddress;
+ ooH323EpCapability *epCap=NULL;
+ OOCTXT *pctxt = NULL;
+ H245OpenLogicalChannel *olc, printOlc;
+ ASN1BOOL aligned = 1;
+ ooAliases *pAlias = NULL;
+
+ pctxt = &gH323ep.msgctxt;
+
+ ret = ooCreateQ931Message(&q931msg, Q931SetupMsg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR1("ERROR:Failed to Create Q931 SETUP Message\n ");
+ return OO_FAILED;
+ }
+
+ q931msg->callReference = call->callReference;
+
+ /* Set bearer capability */
+ if(OO_OK != ooSetBearerCapabilityIE(q931msg, Q931CCITTStd,
+ Q931TransferUnrestrictedDigital, Q931TransferPacketMode,
+ Q931TransferRatePacketMode, Q931UserInfoLayer1G722G725))
+// Q931TransferRate64Kbps, Q931UserInfoLayer1G711ULaw))
+ {
+ OOTRACEERR3("Error: Failed to set bearer capability ie.(%s, %s)\n",
+ call->callType, call->callToken);
+ return OO_FAILED;
+ }
+
+ /* Set calling party number Q931 IE */
+ if(call->callingPartyNumber)
+ ooQ931SetCallingPartyNumberIE(q931msg,
+ (const char*)call->callingPartyNumber, 1, 0, 0, 0);
+
+
+ /* Set called party number Q931 IE */
+ if(call->calledPartyNumber)
+ ooQ931SetCalledPartyNumberIE(q931msg,
+ (const char*)call->calledPartyNumber, 1, 0);
+ else if(call->remoteAliases) {
+ pAlias = call->remoteAliases;
+ while(pAlias) {
+ if(pAlias->type == T_H225AliasAddress_dialedDigits)
+ break;
+ pAlias = pAlias->next;
+ }
+ if(pAlias)
+ {
+ call->calledPartyNumber = (char*)memAlloc(call->pctxt,
+ strlen(pAlias->value)+1);
+ if(!call->calledPartyNumber)
+ {
+ OOTRACEERR3("Error:Memory - ooH323MakeCall_helper - "
+ "calledPartyNumber(%s, %s)\n", call->callType,
+ call->callToken);
+ return OO_FAILED;
+ }
+ strcpy(call->calledPartyNumber, pAlias->value);
+ ooQ931SetCalledPartyNumberIE(q931msg,
+ (const char*)call->calledPartyNumber, 1, 0);
+ }
+
+ }
+
+ q931msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
+ sizeof(H225H323_UserInformation));
+ if(!q931msg->userInfo)
+ {
+ OOTRACEERR1("ERROR:Memory - ooH323MakeCall_helper - userInfo\n");
+ return OO_FAILED;
+ }
+ memset(q931msg->userInfo, 0, sizeof(H225H323_UserInformation));
+
+ setup = (H225Setup_UUIE*) memAlloc(pctxt, sizeof(H225Setup_UUIE));
+ if(!setup)
+ {
+ OOTRACEERR3("Error:Memory - ooH323MakeCall_helper - setup (%s, %s)\n",
+ call->callType, call->callToken);
+ return OO_FAILED;
+ }
+ memset (setup, 0, sizeof(H225Setup_UUIE));
+ setup->protocolIdentifier = gProtocolID;
+
+ /* Populate Alias Address.*/
+
+ if(call->ourAliases || gH323ep.aliases)
+ {
+ setup->m.sourceAddressPresent = TRUE;
+ if(call->ourAliases)
+ ret = ooPopulateAliasList(pctxt, call->ourAliases,
+ &setup->sourceAddress);
+ else if(gH323ep.aliases)
+ ret = ooPopulateAliasList(pctxt, gH323ep.aliases,
+ &setup->sourceAddress);
+ if(OO_OK != ret)
+ {
+ OOTRACEERR1("Error:Failed to populate alias list in SETUP message\n");
+ memReset(pctxt);
+ return OO_FAILED;
+ }
+ }
+
+ setup->m.presentationIndicatorPresent = TRUE;
+ setup->presentationIndicator.t =
+ T_H225PresentationIndicator_presentationAllowed;
+ setup->m.screeningIndicatorPresent = TRUE;
+ setup->screeningIndicator = userProvidedNotScreened;
+
+ setup->m.multipleCallsPresent = TRUE;
+ setup->multipleCalls = FALSE;
+ setup->m.maintainConnectionPresent = TRUE;
+ setup->maintainConnection = FALSE;
+
+ /* Populate Destination aliases */
+ if(call->remoteAliases)
+ {
+ setup->m.destinationAddressPresent = TRUE;
+ ret = ooPopulateAliasList(pctxt, call->remoteAliases,
+ &setup->destinationAddress);
+ if(OO_OK != ret)
+ {
+ OOTRACEERR1("Error:Failed to populate destination alias list in SETUP"
+ "message\n");
+ memReset(pctxt);
+ return OO_FAILED;
+ }
+ }
+
+ /* Populate the vendor information */
+ if(gH323ep.isGateway)
+ setup->sourceInfo.m.gatewayPresent = TRUE;
+ else
+ setup->sourceInfo.m.terminalPresent = TRUE;
+
+ setup->sourceInfo.m.vendorPresent=TRUE;
+ setup->sourceInfo.vendor.vendor.t35CountryCode = gH323ep.t35CountryCode;
+ setup->sourceInfo.vendor.vendor.t35Extension = gH323ep.t35Extension;
+ setup->sourceInfo.vendor.vendor.manufacturerCode= gH323ep.manufacturerCode;
+
+ if(gH323ep.productID)
+ {
+ setup->sourceInfo.vendor.m.productIdPresent=TRUE;
+ setup->sourceInfo.vendor.productId.numocts = ASN1MIN(
+ strlen(gH323ep.productID),
+ sizeof(setup->sourceInfo.vendor.productId.data));
+ strncpy((char*)setup->sourceInfo.vendor.productId.data,
+ gH323ep.productID, setup->sourceInfo.vendor.productId.numocts);
+ }
+ else
+ setup->sourceInfo.vendor.m.productIdPresent=FALSE;
+
+ if(gH323ep.versionID)
+ {
+ setup->sourceInfo.vendor.m.versionIdPresent=TRUE;
+ setup->sourceInfo.vendor.versionId.numocts = ASN1MIN(
+ strlen(gH323ep.versionID),
+ sizeof(setup->sourceInfo.vendor.versionId.data));
+ strncpy((char*)setup->sourceInfo.vendor.versionId.data,
+ gH323ep.versionID, setup->sourceInfo.vendor.versionId.numocts);
+ }
+ else
+ setup->sourceInfo.vendor.m.versionIdPresent=FALSE;
+
+ setup->sourceInfo.mc = FALSE;
+ setup->sourceInfo.undefinedNode = FALSE;
+
+ /* Populate the destination Call Signal Address */
+ setup->destCallSignalAddress.t=T_H225TransportAddress_ipAddress;
+ destCallSignalIpAddress = (H225TransportAddress_ipAddress*)memAlloc(pctxt,
+ sizeof(H225TransportAddress_ipAddress));
+ if(!destCallSignalIpAddress)
+ {
+ OOTRACEERR3("Error:Memory - ooH323MakeCall_helper - "
+ "destCallSignalAddress. (%s, %s)\n", call->callType,
+ call->callToken);
+ return OO_FAILED;
+ }
+ ooSocketConvertIpToNwAddr(call->remoteIP, destCallSignalIpAddress->ip.data);
+
+ destCallSignalIpAddress->ip.numocts=4;
+ destCallSignalIpAddress->port = call->remotePort;
+
+ setup->destCallSignalAddress.u.ipAddress = destCallSignalIpAddress;
+ setup->m.destCallSignalAddressPresent=TRUE;
+ setup->activeMC=FALSE;
+
+ /* Populate the source Call Signal Address */
+ setup->sourceCallSignalAddress.t=T_H225TransportAddress_ipAddress;
+ srcCallSignalIpAddress = (H225TransportAddress_ipAddress*)memAlloc(pctxt,
+ sizeof(H225TransportAddress_ipAddress));
+ if(!srcCallSignalIpAddress)
+ {
+ OOTRACEERR3("Error:Memory - ooH323MakeCall_helper - srcCallSignalAddress"
+ "(%s, %s)\n", call->callType, call->callToken);
+ return OO_FAILED;
+ }
+ ooSocketConvertIpToNwAddr(call->localIP, srcCallSignalIpAddress->ip.data);
+
+ srcCallSignalIpAddress->ip.numocts=4;
+ srcCallSignalIpAddress->port= call->pH225Channel->port;
+ setup->sourceCallSignalAddress.u.ipAddress = srcCallSignalIpAddress;
+ setup->m.sourceCallSignalAddressPresent=TRUE;
+ /* No fast start */
+ if(!OO_TESTFLAG(gH323ep.flags, OO_M_FASTSTART))
+ {
+ setup->m.fastStartPresent = FALSE;
+ }
+ else{
+ setup->m.fastStartPresent = TRUE;
+ pFS = (ASN1DynOctStr*)memAlloc(pctxt, gH323ep.noOfCaps*
+ sizeof(ASN1DynOctStr));
+ if(!pFS)
+ {
+ OOTRACEERR3("Error:Memory - ooH323MakeCall_helper - pFS(%s, %s)\n",
+ call->callType, call->callToken);
+ return OO_FAILED;
+ }
+
+ /* Use preference order of codecs */
+ i=0;
+ for(k=0; k< call->capPrefs.index; k++)
+ {
+ OOTRACEDBGC5("Preffered capability at index %d is %s. (%s, %s)\n",
+ k, ooGetCapTypeText(call->capPrefs.order[k]),
+ call->callType, call->callToken);
+
+ if(call->ourCaps) {
+ epCap = call->ourCaps;
+ OOTRACEDBGC3("Using call specific capabilities in faststart of "
+ "setup message. (%s, %s)\n", call->callType,
+ call->callToken);
+ }
+ else{
+ epCap = gH323ep.myCaps;
+ OOTRACEDBGC3("Using end-point capabilities for faststart of setup"
+ "message. (%s, %s)\n", call->callType,
+ call->callToken);
+ }
+
+ while(epCap){
+ if(epCap->cap == call->capPrefs.order[k]) break;
+ else epCap = epCap->next;
+ }
+ if(!epCap)
+ {
+ OOTRACEWARN4("Warn:Preferred capability %s is abscent in "
+ "capability list. (%s, %s)\n",
+ ooGetCapTypeText(call->capPrefs.order[k]),
+ call->callType, call->callToken);
+ continue;
+ }
+
+
+
+ OOTRACEDBGC4("Building olcs with capability %s. (%s, %s)\n",
+ ooGetCapTypeText(epCap->cap), call->callType,
+ call->callToken);
+ if(epCap->dir & OORX)
+ {
+ olc = (H245OpenLogicalChannel*)memAlloc(pctxt,
+ sizeof(H245OpenLogicalChannel));
+ if(!olc)
+ {
+ OOTRACEERR3("ERROR:Memory - ooH323MakeCall_helper - olc(%s, %s)"
+ "\n", call->callType, call->callToken);
+ ooFreeQ931Message(q931msg);
+ if(call->callState < OO_CALL_CLEAR)
+ {
+ call->callEndReason = OO_REASON_LOCAL_CLEARED;
+ call->callState = OO_CALL_CLEAR;
+ }
+ return OO_FAILED;
+ }
+ memset(olc, 0, sizeof(H245OpenLogicalChannel));
+ olc->forwardLogicalChannelNumber = call->logicalChanNoCur++;
+ if(call->logicalChanNoCur > call->logicalChanNoMax)
+ call->logicalChanNoCur = call->logicalChanNoBase;
+
+ ooBuildFastStartOLC(call, olc, epCap, pctxt, OORX);
+ /* Do not specify msg buffer let automatic allocation work */
+ setPERBuffer(pctxt, NULL, 0, aligned);
+ if(asn1PE_H245OpenLogicalChannel(pctxt, olc) != ASN_OK)
+ {
+ OOTRACEERR3("ERROR:Encoding of olc failed for faststart(%s, %s)"
+ "\n", call->callType, call->callToken);
+ ooFreeQ931Message(q931msg);
+ if(call->callState < OO_CALL_CLEAR)
+ {
+ call->callEndReason = OO_REASON_LOCAL_CLEARED;
+ call->callState = OO_CALL_CLEAR;
+ }
+ return OO_FAILED;
+ }
+ pFS[i].data = encodeGetMsgPtr(pctxt, &(pFS[i].numocts));
+
+
+ /* Dump faststart element in logfile for debugging purpose */
+ setPERBuffer(pctxt, (char*)pFS[i].data, pFS[i].numocts, 1);
+ initializePrintHandler(&printHandler, "FastStart Element");
+ setEventHandler (pctxt, &printHandler);
+ memset(&printOlc, 0, sizeof(printOlc));
+ ret = asn1PD_H245OpenLogicalChannel(pctxt, &(printOlc));
+ if(ret != ASN_OK)
+ {
+ OOTRACEERR3("Error: Failed decoding FastStart Element."
+ "(%s, %s)\n", call->callType, call->callToken);
+ ooFreeQ931Message(q931msg);
+ if(call->callState < OO_CALL_CLEAR)
+ {
+ call->callEndReason = OO_REASON_LOCAL_CLEARED;
+ call->callState = OO_CALL_CLEAR;
+ }
+ return OO_FAILED;
+ }
+ finishPrint();
+ removeEventHandler(pctxt);
+
+
+ olc = NULL;
+ i++;
+ OOTRACEDBGC5("Added RX fs element %d with capability %s(%s, %s)\n",
+ i, ooGetCapTypeText(epCap->cap), call->callType,
+ call->callToken);
+ }
+
+ if(epCap->dir & OOTX)
+ {
+ olc = (H245OpenLogicalChannel*)memAlloc(pctxt,
+ sizeof(H245OpenLogicalChannel));
+ if(!olc)
+ {
+ OOTRACEERR3("ERROR:Memory - ooH323MakeCall_helper - olc(%s, %s)"
+ "\n", call->callType, call->callToken);
+ ooFreeQ931Message(q931msg);
+ if(call->callState < OO_CALL_CLEAR)
+ {
+ call->callEndReason = OO_REASON_LOCAL_CLEARED;
+ call->callState = OO_CALL_CLEAR;
+ }
+ return OO_FAILED;
+ }
+ memset(olc, 0, sizeof(H245OpenLogicalChannel));
+ olc->forwardLogicalChannelNumber = call->logicalChanNoCur++;
+ if(call->logicalChanNoCur > call->logicalChanNoMax)
+ call->logicalChanNoCur = call->logicalChanNoBase;
+
+ ooBuildFastStartOLC(call, olc, epCap, pctxt, OOTX);
+ /* Do not specify msg buffer let automatic allocation work */
+ setPERBuffer(pctxt, NULL, 0, aligned);
+ if(asn1PE_H245OpenLogicalChannel(pctxt, olc) != ASN_OK)
+ {
+ OOTRACEERR3("ERROR:Encoding of olc failed for faststart(%s, %s)"
+ "\n", call->callType, call->callToken);
+ ooFreeQ931Message(q931msg);
+ if(call->callState < OO_CALL_CLEAR)
+ {
+ call->callEndReason = OO_REASON_LOCAL_CLEARED;
+ call->callState = OO_CALL_CLEAR;
+ }
+ return OO_FAILED;
+ }
+ pFS[i].data = encodeGetMsgPtr(pctxt, &(pFS[i].numocts));
+
+ /* Dump faststart element in logfile for debugging purpose */
+ setPERBuffer(pctxt, (char*)pFS[i].data, pFS[i].numocts, 1);
+ initializePrintHandler(&printHandler, "FastStart Element");
+ setEventHandler (pctxt, &printHandler);
+ memset(&printOlc, 0, sizeof(printOlc));
+ ret = asn1PD_H245OpenLogicalChannel(pctxt, &(printOlc));
+ if(ret != ASN_OK)
+ {
+ OOTRACEERR3("Error: Failed decoding FastStart Element."
+ "(%s, %s)\n", call->callType, call->callToken);
+ ooFreeQ931Message(q931msg);
+ if(call->callState < OO_CALL_CLEAR)
+ {
+ call->callEndReason = OO_REASON_LOCAL_CLEARED;
+ call->callState = OO_CALL_CLEAR;
+ }
+ return OO_FAILED;
+ }
+ finishPrint();
+ removeEventHandler(pctxt);
+
+
+ olc = NULL;
+ i++;
+ OOTRACEDBGC5("Added TX fs element %d with capability %s(%s, %s)\n",
+ i, ooGetCapTypeText(epCap->cap), call->callType,
+ call->callToken);
+ }
+
+ }
+ OOTRACEDBGA4("Added %d fast start elements to SETUP message (%s, %s)\n",
+ i, call->callType, call->callToken);
+ setup->fastStart.n = i;
+ setup->fastStart.elem = pFS;
+ }
+
+ setup->conferenceID.numocts= call->confIdentifier.numocts;
+ memcpy(setup->conferenceID.data, call->confIdentifier.data,
+ call->confIdentifier.numocts);
+
+ setup->conferenceGoal.t = T_H225Setup_UUIE_conferenceGoal_create;
+ /* H.225 point to point call */
+ setup->callType.t = T_H225CallType_pointToPoint;
+
+ /* Populate optional fields */
+ setup->m.callIdentifierPresent = TRUE;
+ /*ooGenerateCallIdentifier(&setup->callIdentifier);*/
+ setup->callIdentifier.guid.numocts = call->callIdentifier.guid.numocts;
+ memcpy(setup->callIdentifier.guid.data, call->callIdentifier.guid.data,
+ call->callIdentifier.guid.numocts);
+
+ setup->m.mediaWaitForConnectPresent = TRUE;
+ if(OO_TESTFLAG(call->flags, OO_M_MEDIAWAITFORCONN)) {
+ setup->mediaWaitForConnect = TRUE;
+ }
+ else {
+ setup->mediaWaitForConnect = FALSE;
+ }
+ setup->m.canOverlapSendPresent = TRUE;
+ setup->canOverlapSend = FALSE;
+
+ /* Populate the userInfo structure with the setup UUIE */
+
+ q931msg->userInfo->h323_uu_pdu.h323_message_body.t =
+ T_H225H323_UU_PDU_h323_message_body_setup;
+ q931msg->userInfo->h323_uu_pdu.h323_message_body.u.setup = setup;
+ q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1;
+
+ q931msg->userInfo->h323_uu_pdu.h245Tunneling =
+ OO_TESTFLAG (call->flags, OO_M_TUNNELING);
+
+ /* For H.323 version 4 and higher, if fast connect, tunneling should be
+ supported.
+ */
+ if(OO_TESTFLAG(call->flags, OO_M_FASTSTART))
+ q931msg->userInfo->h323_uu_pdu.h245Tunneling = TRUE;
+
+ OOTRACEDBGA3("Built SETUP message (%s, %s)\n", call->callType,
+ call->callToken);
+
+ /* H225 message callback */
+ if(gH323ep.h225Callbacks.onBuiltSetup)
+ gH323ep.h225Callbacks.onBuiltSetup(call, q931msg);
+
+ ret=ooSendH225Msg(call, q931msg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3("Error:Failed to enqueue SETUP message to outbound queue. (%s, %s)\n", call->callType, call->callToken);
+ }
+ memReset(&gH323ep.msgctxt);
+
+ return ret;
+}
+
+
+
+int ooQ931SendDTMFAsKeyPadIE(OOH323CallData *call, const char* data)
+{
+ int ret;
+ H225Information_UUIE *information=NULL;
+ Q931Message *q931msg=NULL;
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+
+ ret = ooCreateQ931Message(&q931msg, Q931InformationMsg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3("Error: In allocating memory for - H225 Information message."
+ "(%s, %s)\n", call->callType, call->callToken);
+ return OO_FAILED;
+ }
+
+ q931msg->callReference = call->callReference;
+
+ q931msg->userInfo = (H225H323_UserInformation*)memAllocZ(pctxt,
+ sizeof(H225H323_UserInformation));
+ if(!q931msg->userInfo)
+ {
+ OOTRACEERR3("ERROR:Memory - ooQ931SendDTMFAsKeypadIE - userInfo"
+ "(%s, %s)\n", call->callType, call->callToken);
+ memReset(&gH323ep.msgctxt);
+ return OO_FAILED;
+ }
+ q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1;
+ q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(gH323ep.flags,
+ OO_M_TUNNELING);
+ q931msg->userInfo->h323_uu_pdu.h323_message_body.t =
+ T_H225H323_UU_PDU_h323_message_body_information;
+
+ information = (H225Information_UUIE*)memAllocZ(pctxt,
+ sizeof(H225Information_UUIE));
+ if(!information)
+ {
+ OOTRACEERR3("ERROR:Memory - ooQ931SendDTMFAsKeypadIE - information"
+ "(%s, %s)\n", call->callType, call->callToken);
+ memReset(&gH323ep.msgctxt);
+ return OO_FAILED;
+ }
+ q931msg->userInfo->h323_uu_pdu.h323_message_body.u.information =
+ information;
+ information->m.callIdentifierPresent = 1;
+ information->callIdentifier.guid.numocts =
+ call->callIdentifier.guid.numocts;
+ memcpy(information->callIdentifier.guid.data,
+ call->callIdentifier.guid.data,
+ call->callIdentifier.guid.numocts);
+ information->protocolIdentifier = gProtocolID;
+
+ /*Add keypad IE*/
+ ret = ooQ931SetKeypadIE(q931msg, data);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3("Error:Creating keypad IE for (%s, %s)\n", call->callType,
+ call->callToken);
+ memReset(&gH323ep.msgctxt);
+ return OO_FAILED;
+ }
+
+ ret=ooSendH225Msg(call, q931msg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3("Error:Failed to enqueue Information message to outbound "
+ "queue. (%s, %s)\n", call->callType, call->callToken);
+ }
+ memReset(&gH323ep.msgctxt);
+
+ return ret;
+
+}
+
+int ooH323ForwardCall(char* callToken, char *dest)
+{
+ int ret=0;
+ Q931Message *pQ931Msg = NULL;
+ H225Facility_UUIE *facility=NULL;
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+ OOH323CallData *call;
+ char ip[30]="\0", *pcPort=NULL;
+ H225TransportAddress_ipAddress *fwdCallSignalIpAddress;
+
+ call= ooFindCallByToken(callToken);
+ if(!call)
+ {
+ OOTRACEERR2("ERROR: Invalid call token for forward - %s\n", callToken);
+ return OO_FAILED;
+ }
+ OOTRACEDBGA3("Building Facility message for call forward (%s, %s)\n",
+ call->callType, call->callToken);
+ call->pCallFwdData = (OOCallFwdData*)memAllocZ(call->pctxt,
+ sizeof(OOCallFwdData));
+ if(!call->pCallFwdData)
+ {
+ OOTRACEERR3("Error:Memory - ooH323ForwardCall - pCallFwdData (%s, %s)\n",
+ call->callType, call->callToken);
+ return OO_FAILED;
+ }
+
+ ret = ooParseDestination(call, dest, ip, 20,
+ &call->pCallFwdData->aliases);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR4("Error:Failed to parse the destination %s for call fwd."
+ "(%s, %s)\n", dest, call->callType, call->callToken);
+ memFreePtr(call->pctxt, call->pCallFwdData);
+ return OO_FAILED;
+ }
+
+ if(!ooUtilsIsStrEmpty(ip))
+ {
+ pcPort = strchr(ip, ':');
+ if(pcPort)
+ {
+ *pcPort = '\0';
+ pcPort++;
+ call->pCallFwdData->port = atoi(pcPort);
+ }
+ strcpy(call->pCallFwdData->ip, ip);
+ }
+
+ ret = ooCreateQ931Message(&pQ931Msg, Q931FacilityMsg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3
+ ("ERROR: In allocating memory for call transfer facility message "
+ "(%s, %s)\n", call->callType, call->callToken);
+ return OO_FAILED;
+ }
+
+ pQ931Msg->callReference = call->callReference;
+
+ pQ931Msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
+ sizeof(H225H323_UserInformation));
+ if(!pQ931Msg->userInfo)
+ {
+ OOTRACEERR3("ERROR:Memory - ooH323ForwardCall - userInfo(%s, %s)\n",
+ call->callType, call->callToken);
+ return OO_FAILED;
+ }
+ memset (pQ931Msg->userInfo, 0, sizeof(H225H323_UserInformation));
+ pQ931Msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1;
+
+ pQ931Msg->userInfo->h323_uu_pdu.h245Tunneling =
+ OO_TESTFLAG (call->flags, OO_M_TUNNELING);
+
+ pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.t =
+ T_H225H323_UU_PDU_h323_message_body_facility;
+
+ facility = (H225Facility_UUIE*)
+ memAllocZ (pctxt, sizeof(H225Facility_UUIE));
+
+ if(!facility)
+ {
+ OOTRACEERR3("ERROR:Memory - ooH323ForwardCall - facility (%s, %s)"
+ "\n", call->callType, call->callToken);
+ return OO_FAILED;
+ }
+
+ pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.u.facility = facility;
+
+ facility->protocolIdentifier = gProtocolID;
+ facility->m.callIdentifierPresent = 1;
+ facility->callIdentifier.guid.numocts =
+ call->callIdentifier.guid.numocts;
+
+ memcpy(facility->callIdentifier.guid.data,
+ call->callIdentifier.guid.data,
+ call->callIdentifier.guid.numocts);
+
+ facility->reason.t = T_H225FacilityReason_callForwarded;
+
+ if(!ooUtilsIsStrEmpty(call->pCallFwdData->ip))
+ {
+ facility->m.alternativeAddressPresent = TRUE;
+ facility->alternativeAddress.t=T_H225TransportAddress_ipAddress;
+ fwdCallSignalIpAddress = (H225TransportAddress_ipAddress*)memAlloc(pctxt,
+ sizeof(H225TransportAddress_ipAddress));
+ if(!fwdCallSignalIpAddress)
+ {
+ OOTRACEERR3("Error:Memory - ooH323ForwardCall - fwdCallSignalAddress"
+ "(%s, %s)\n", call->callType, call->callToken);
+ return OO_FAILED;
+ }
+ ooSocketConvertIpToNwAddr(call->pCallFwdData->ip,
+ fwdCallSignalIpAddress->ip.data);
+
+ fwdCallSignalIpAddress->ip.numocts=4;
+ fwdCallSignalIpAddress->port = call->pCallFwdData->port;
+ facility->alternativeAddress.u.ipAddress = fwdCallSignalIpAddress;
+ }
+
+ if(call->pCallFwdData->aliases)
+ {
+ facility->m.alternativeAliasAddressPresent = TRUE;
+ ret = ooPopulateAliasList(pctxt, call->pCallFwdData->aliases,
+ &facility->alternativeAliasAddress);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3("Error:Failed to populate alternate aliases in "
+ "ooH323ForwardCall. (%s, %s)\n", call->callType,
+ call->callToken);
+ return OO_FAILED;
+ }
+ }
+
+ ret = ooSendH225Msg(call, pQ931Msg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3
+ ("Error:Failed to enqueue Forward Facility message to outbound "
+ "queue.(%s, %s)\n", call->callType, call->callToken);
+ }
+ call->callEndReason = OO_REASON_LOCAL_FWDED;
+ memReset (&gH323ep.msgctxt);
+ return ret;
+}
+
+int ooH323HangCall(char * callToken, OOCallClearReason reason)
+{
+ OOH323CallData *call;
+
+ call= ooFindCallByToken(callToken);
+ if(!call)
+ {
+ OOTRACEWARN2("WARN: Call hangup failed - Call %s not present\n",
+ callToken);
+ return OO_FAILED;
+ }
+ OOTRACEINFO3("Hanging up call (%s, %s)\n", call->callType, call->callToken);
+ if(call->callState < OO_CALL_CLEAR)
+ {
+ call->callEndReason = reason;
+ call->callState = OO_CALL_CLEAR;
+ }
+ return OO_OK;
+}
+
+int ooSetBearerCapabilityIE
+ (Q931Message *pmsg, enum Q931CodingStandard codingStandard,
+ enum Q931InformationTransferCapability capability,
+ enum Q931TransferMode transferMode, enum Q931TransferRate transferRate,
+ enum Q931UserInfoLayer1Protocol userInfoLayer1)
+{
+ unsigned size = 3;
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+
+ if(pmsg->bearerCapabilityIE)
+ {
+ memFreePtr(pctxt, pmsg->bearerCapabilityIE);
+ pmsg->bearerCapabilityIE = NULL;
+ }
+
+ pmsg->bearerCapabilityIE = (Q931InformationElement*)
+ memAlloc(pctxt, sizeof(Q931InformationElement)+size-1);
+ if(!pmsg->bearerCapabilityIE)
+ {
+ OOTRACEERR1("Error:Memory - ooSetBearerCapabilityIE - bearerCapabilityIE"
+ "\n");
+ return OO_FAILED;
+ }
+
+ pmsg->bearerCapabilityIE->discriminator = Q931BearerCapabilityIE;
+ pmsg->bearerCapabilityIE->length = size;
+ pmsg->bearerCapabilityIE->data[0] = (ASN1OCTET)(0x80 | ((codingStandard&3) << 5) | (capability&31));
+
+ pmsg->bearerCapabilityIE->data[1] = (0x80 | ((transferMode & 3) << 5) | (transferRate & 31));
+
+ pmsg->bearerCapabilityIE->data[2] = (0x80 | (1<<5) | userInfoLayer1);
+
+ return OO_OK;
+}
+
+int ooQ931SetKeypadIE(Q931Message *pmsg, const char* data)
+{
+ unsigned len = 0;
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+
+ len = strlen(data);
+ pmsg->keypadIE = (Q931InformationElement*)
+ memAlloc(pctxt, sizeof(Q931InformationElement)+len-1);
+ if(!pmsg->keypadIE)
+ {
+ OOTRACEERR1("Error:Memory - ooQ931SetKeypadIE - keypadIE\n");
+ return OO_FAILED;
+ }
+
+ pmsg->keypadIE->discriminator = Q931KeypadIE;
+ pmsg->keypadIE->length = len;
+ memcpy(pmsg->keypadIE->data, data, len);
+ return OO_OK;
+}
+
+
+
+
+int ooQ931SetCallingPartyNumberIE
+ (Q931Message *pmsg, const char *number, unsigned plan, unsigned type,
+ unsigned presentation, unsigned screening)
+{
+ unsigned len = 0;
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+
+ if(pmsg->callingPartyNumberIE)
+ {
+ memFreePtr(pctxt, pmsg->callingPartyNumberIE);
+ pmsg->callingPartyNumberIE = NULL;
+ }
+
+ len = strlen(number);
+ pmsg->callingPartyNumberIE = (Q931InformationElement*)
+ memAlloc(pctxt, sizeof(Q931InformationElement)+len+2-1);
+ if(!pmsg->callingPartyNumberIE)
+ {
+ OOTRACEERR1("Error:Memory - ooQ931SetCallingPartyNumberIE - "
+ "callingPartyNumberIE\n");
+ return OO_FAILED;
+ }
+ pmsg->callingPartyNumberIE->discriminator = Q931CallingPartyNumberIE;
+ pmsg->callingPartyNumberIE->length = len+2;
+ pmsg->callingPartyNumberIE->data[0] = (((type&7)<<4)|(plan&15));
+ pmsg->callingPartyNumberIE->data[1] = (0x80|((presentation&3)<<5)|(screening&3));
+ memcpy(pmsg->callingPartyNumberIE->data+2, number, len);
+
+ return OO_OK;
+}
+
+int ooQ931SetCalledPartyNumberIE
+ (Q931Message *pmsg, const char *number, unsigned plan, unsigned type)
+{
+ unsigned len = 0;
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+
+ if(pmsg->calledPartyNumberIE)
+ {
+ memFreePtr(pctxt, pmsg->calledPartyNumberIE);
+ pmsg->calledPartyNumberIE = NULL;
+ }
+
+ len = strlen(number);
+ pmsg->calledPartyNumberIE = (Q931InformationElement*)
+ memAlloc(pctxt, sizeof(Q931InformationElement)+len+1-1);
+ if(!pmsg->calledPartyNumberIE)
+ {
+ OOTRACEERR1("Error:Memory - ooQ931SetCalledPartyNumberIE - "
+ "calledPartyNumberIE\n");
+ return OO_FAILED;
+ }
+ pmsg->calledPartyNumberIE->discriminator = Q931CalledPartyNumberIE;
+ pmsg->calledPartyNumberIE->length = len+1;
+ pmsg->calledPartyNumberIE->data[0] = (0x80|((type&7)<<4)|(plan&15));
+ memcpy(pmsg->calledPartyNumberIE->data+1, number, len);
+
+ return OO_OK;
+}
+
+int ooQ931SetCauseIE
+ (Q931Message *pmsg, enum Q931CauseValues cause, unsigned coding,
+ unsigned location)
+{
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+
+ if(pmsg->causeIE){
+ memFreePtr(pctxt, pmsg->causeIE);
+ pmsg->causeIE = NULL;
+ }
+
+ pmsg->causeIE = (Q931InformationElement*)
+ memAlloc(pctxt, sizeof(Q931InformationElement)+1);
+ if(!pmsg->causeIE)
+ {
+ OOTRACEERR1("Error:Memory - ooQ931SetCauseIE - causeIE\n");
+ return OO_FAILED;
+ }
+ pmsg->causeIE->discriminator = Q931CauseIE;
+ pmsg->causeIE->length = 2;
+ pmsg->causeIE->data[0] = (0x80 | ((coding & 0x03) <<5) | (location & 0x0F));
+
+ pmsg->causeIE->data[1] = (0x80 | cause);
+
+ return OO_OK;
+}
+
+
+/* Build a Facility message and tunnel H.245 message through it */
+int ooSendAsTunneledMessage(OOH323CallData *call, ASN1OCTET* msgbuf,
+ int h245Len, int h245MsgType, int associatedChan)
+{
+ Q931Message *pQ931Msg = NULL;
+ H225H323_UU_PDU *pH323UUPDU = NULL;
+ H225H323_UU_PDU_h245Control *pH245Control = NULL;
+ ASN1DynOctStr * elem;
+ int ret =0;
+ H225Facility_UUIE *facility=NULL;
+ OOCTXT *pctxt = &gH323ep.msgctxt;
+
+ OOTRACEDBGA4("Building Facility message for tunneling %s (%s, %s)\n",
+ ooGetMsgTypeText(h245MsgType), call->callType, call->callToken);
+
+ ret = ooCreateQ931Message(&pQ931Msg, Q931FacilityMsg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3("ERROR: In allocating memory for facility message "
+ "(%s, %s)\n", call->callType, call->callToken);
+ return OO_FAILED;
+ }
+
+ pQ931Msg->callReference = call->callReference;
+
+ pQ931Msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
+ sizeof(H225H323_UserInformation));
+ if(!pQ931Msg->userInfo)
+ {
+ OOTRACEERR3("ERROR:Memory - ooSendAsTunneledMessage - userInfo"
+ " (%s, %s)\n", call->callType, call->callToken);
+ memReset(&gH323ep.msgctxt);
+ return OO_FAILED;
+ }
+ memset (pQ931Msg->userInfo, 0, sizeof(H225H323_UserInformation));
+ pQ931Msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1;
+
+ pQ931Msg->userInfo->h323_uu_pdu.h245Tunneling =
+ OO_TESTFLAG (call->flags, OO_M_TUNNELING);
+
+ pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.t =
+ T_H225H323_UU_PDU_h323_message_body_facility;
+
+ facility = (H225Facility_UUIE*)
+ memAllocZ (pctxt, sizeof(H225Facility_UUIE));
+
+ if(!facility)
+ {
+ OOTRACEERR3("ERROR:Memory - ooSendAsTunneledMessage - facility (%s, %s)"
+ "\n", call->callType, call->callToken);
+ memReset(&gH323ep.msgctxt);
+ return OO_FAILED;
+ }
+
+ pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.u.facility = facility;
+ /* Populate Facility UUIE */
+ facility->protocolIdentifier = gProtocolID;
+ facility->m.callIdentifierPresent = 1;
+ facility->callIdentifier.guid.numocts =
+ call->callIdentifier.guid.numocts;
+
+ memcpy(facility->callIdentifier.guid.data,
+ call->callIdentifier.guid.data,
+ call->callIdentifier.guid.numocts);
+
+ facility->reason.t = T_H225FacilityReason_transportedInformation;
+
+ pH323UUPDU = (H225H323_UU_PDU*) &pQ931Msg->userInfo->h323_uu_pdu;
+ pH323UUPDU->m.h245TunnelingPresent = TRUE;
+ pH323UUPDU->m.h245ControlPresent = TRUE;
+ pH323UUPDU->h245Tunneling = TRUE;
+ pH245Control = (H225H323_UU_PDU_h245Control*)
+ &pH323UUPDU->h245Control;
+
+ elem = (ASN1DynOctStr*) memAlloc(pctxt,
+ sizeof(ASN1DynOctStr));
+ if(!elem)
+ {
+ OOTRACEERR3("ERROR:Memory - ooSendAsTunneledMessage - elem "
+ "(%s, %s)\n", call->callType, call->callToken);
+ return OO_FAILED;
+ }
+ elem->data = msgbuf;
+ elem->numocts = h245Len;
+ pH245Control->elem = elem;
+ pH245Control->n = 1;
+ pQ931Msg->tunneledMsgType = h245MsgType;
+ pQ931Msg->logicalChannelNo = associatedChan;
+
+
+ ret = ooSendH225Msg(call, pQ931Msg);
+ if(ret != OO_OK)
+ {
+ OOTRACEERR3("Error:Failed to enqueue Facility(tunneling) message to "
+ "outbound queue.(%s, %s)\n", call->callType, call->callToken);
+ }
+
+ /* Can't do memReset here because if we are sending H.245 message as a
+ response to received tunneled h.245 message, we can't reset unless the \
+ main received H225 message processing is finished. Rule. No reset when
+ tunneling
+ */
+ memFreePtr(&gH323ep.msgctxt, pQ931Msg);
+ return ret;
+}
+
+int ooCallEstbTimerExpired(void *data)
+{
+
+ ooTimerCallback *cbData = (ooTimerCallback*) data;
+ OOH323CallData *call = cbData->call;
+ OOTRACEINFO3("Call Establishment timer expired. (%s, %s)\n",
+ call->callType, call->callToken);
+ memFreePtr(call->pctxt, cbData);
+ if(call->callState < OO_CALL_CLEAR){
+ call->callState = OO_CALL_CLEAR;
+ call->callEndReason = OO_REASON_LOCAL_CLEARED;
+ }
+
+ return OO_OK;
+}
+
+
+int ooQ931GetCauseAndReasonCodeFromCallClearReason
+ (OOCallClearReason clearReason, enum Q931CauseValues *cause,
+ unsigned *reasonCode)
+{
+ switch(clearReason)
+ {
+ case OO_REASON_INVALIDMESSAGE:
+ case OO_REASON_TRANSPORTFAILURE:
+ *reasonCode = T_H225ReleaseCompleteReason_undefinedReason;
+ *cause = Q931ProtocolErrorUnspecified;
+ break;
+ case OO_REASON_NOBW:
+ *reasonCode = T_H225ReleaseCompleteReason_noBandwidth;
+ *cause = Q931ErrorInCauseIE;
+ break;
+ case OO_REASON_GK_NOCALLEDUSER:
+ *reasonCode = T_H225ReleaseCompleteReason_calledPartyNotRegistered;
+ *cause = Q931SubscriberAbsent;
+ break;
+ case OO_REASON_GK_NOCALLERUSER:
+ *reasonCode = T_H225ReleaseCompleteReason_callerNotRegistered;
+ *cause = Q931SubscriberAbsent;
+ break;
+ case OO_REASON_GK_UNREACHABLE:
+ *reasonCode = T_H225ReleaseCompleteReason_unreachableGatekeeper;
+ *cause = Q931TemporaryFailure;
+ break;
+ case OO_REASON_GK_NORESOURCES:
+ case OO_REASON_GK_CLEARED:
+ *reasonCode = T_H225ReleaseCompleteReason_gatekeeperResources;
+ *cause = Q931Congestion;
+ break;
+ case OO_REASON_NOCOMMON_CAPABILITIES:
+ *reasonCode = T_H225ReleaseCompleteReason_undefinedReason;
+ *cause = Q931IncompatibleDestination;
+ break;
+ case OO_REASON_LOCAL_FWDED:
+ case OO_REASON_REMOTE_FWDED:
+ *reasonCode = T_H225ReleaseCompleteReason_facilityCallDeflection;
+ *cause = Q931Redirection;
+ break;
+ case OO_REASON_REMOTE_CLEARED:
+ case OO_REASON_LOCAL_CLEARED:
+ *reasonCode = T_H225ReleaseCompleteReason_undefinedReason;
+ *cause = Q931NormalCallClearing;
+ break;
+ case OO_REASON_REMOTE_BUSY:
+ case OO_REASON_LOCAL_BUSY:
+ *reasonCode = T_H225ReleaseCompleteReason_inConf;
+ *cause = Q931UserBusy;
+ break;
+ case OO_REASON_REMOTE_NOANSWER:
+ case OO_REASON_LOCAL_NOTANSWERED:
+ *reasonCode = T_H225ReleaseCompleteReason_undefinedReason;
+ *cause = Q931NoAnswer;
+ break;
+ case OO_REASON_REMOTE_REJECTED:
+ case OO_REASON_LOCAL_REJECTED:
+ *reasonCode = T_H225ReleaseCompleteReason_destinationRejection;
+ *cause = Q931CallRejected;
+ break;
+ case OO_REASON_REMOTE_CONGESTED:
+ case OO_REASON_LOCAL_CONGESTED:
+ *reasonCode = T_H225ReleaseCompleteReason_noBandwidth;
+ *cause = Q931Congestion;
+ break;
+ case OO_REASON_NOROUTE:
+ *reasonCode = T_H225ReleaseCompleteReason_unreachableDestination;
+ *cause = Q931NoRouteToDestination;
+ break;
+ case OO_REASON_NOUSER:
+ *reasonCode = T_H225ReleaseCompleteReason_undefinedReason;
+ *cause = Q931SubscriberAbsent;
+ break;
+ case OO_REASON_UNKNOWN:
+ default:
+ *reasonCode = T_H225ReleaseCompleteReason_undefinedReason;
+ *cause = Q931NormalUnspecified;
+ }
+
+ return OO_OK;
+}
+
+enum OOCallClearReason ooGetCallClearReasonFromCauseAndReasonCode
+ (enum Q931CauseValues cause, unsigned reasonCode)
+{
+ switch(cause)
+ {
+ case Q931NormalCallClearing:
+ return OO_REASON_REMOTE_CLEARED;
+
+ case Q931UserBusy:
+ return OO_REASON_REMOTE_BUSY;
+
+ case Q931NoResponse:
+ case Q931NoAnswer:
+ return OO_REASON_REMOTE_NOANSWER;
+
+ case Q931CallRejected:
+ return OO_REASON_REMOTE_REJECTED;
+
+ case Q931Redirection:
+ return OO_REASON_REMOTE_FWDED;
+
+ case Q931NetworkOutOfOrder:
+ case Q931TemporaryFailure:
+ return OO_REASON_TRANSPORTFAILURE;
+
+ case Q931NoCircuitChannelAvailable:
+ case Q931Congestion:
+ case Q931RequestedCircuitUnAvailable:
+ case Q931ResourcesUnavailable:
+ return OO_REASON_REMOTE_CONGESTED;
+
+ case Q931NoRouteToDestination:
+ case Q931NoRouteToNetwork:
+ return OO_REASON_NOROUTE;
+ case Q931NumberChanged:
+ case Q931UnallocatedNumber:
+ case Q931SubscriberAbsent:
+ return OO_REASON_NOUSER;
+ case Q931ChannelUnacceptable:
+ case Q931DestinationOutOfOrder:
+ case Q931InvalidNumberFormat:
+ case Q931NormalUnspecified:
+ case Q931StatusEnquiryResponse:
+ case Q931IncompatibleDestination:
+ case Q931ProtocolErrorUnspecified:
+ case Q931RecoveryOnTimerExpiry:
+ case Q931InvalidCallReference:
+ default:
+ switch(reasonCode)
+ {
+ case T_H225ReleaseCompleteReason_noBandwidth:
+ return OO_REASON_NOBW;
+ case T_H225ReleaseCompleteReason_gatekeeperResources:
+ return OO_REASON_GK_NORESOURCES;
+ case T_H225ReleaseCompleteReason_unreachableDestination:
+ return OO_REASON_NOROUTE;
+ case T_H225ReleaseCompleteReason_destinationRejection:
+ return OO_REASON_REMOTE_REJECTED;
+ case T_H225ReleaseCompleteReason_inConf:
+ return OO_REASON_REMOTE_BUSY;
+ case T_H225ReleaseCompleteReason_facilityCallDeflection:
+ return OO_REASON_REMOTE_FWDED;
+ case T_H225ReleaseCompleteReason_calledPartyNotRegistered:
+ return OO_REASON_GK_NOCALLEDUSER;
+ case T_H225ReleaseCompleteReason_callerNotRegistered:
+ return OO_REASON_GK_NOCALLERUSER;
+ case T_H225ReleaseCompleteReason_gatewayResources:
+ return OO_REASON_GK_NORESOURCES;
+ case T_H225ReleaseCompleteReason_unreachableGatekeeper:
+ return OO_REASON_GK_UNREACHABLE;
+ case T_H225ReleaseCompleteReason_invalidRevision:
+ case T_H225ReleaseCompleteReason_noPermission:
+ case T_H225ReleaseCompleteReason_badFormatAddress:
+ case T_H225ReleaseCompleteReason_adaptiveBusy:
+ case T_H225ReleaseCompleteReason_undefinedReason:
+ case T_H225ReleaseCompleteReason_securityDenied:
+ case T_H225ReleaseCompleteReason_newConnectionNeeded:
+ case T_H225ReleaseCompleteReason_nonStandardReason:
+ case T_H225ReleaseCompleteReason_replaceWithConferenceInvite:
+ case T_H225ReleaseCompleteReason_genericDataReason:
+ case T_H225ReleaseCompleteReason_neededFeatureNotSupported:
+ case T_H225ReleaseCompleteReason_tunnelledSignallingRejected:
+ case T_H225ReleaseCompleteReason_invalidCID:
+ case T_H225ReleaseCompleteReason_securityError:
+ case T_H225ReleaseCompleteReason_hopCountExceeded:
+ case T_H225ReleaseCompleteReason_extElem1:
+ default:
+ return OO_REASON_UNKNOWN;
+ }
+ }
+ return OO_REASON_UNKNOWN;
+}
+
+/**
+ This function is used to parse destination string passed to ooH323MakeCall and
+ ooH323ForwardCall. If the string contains ip address and port, it is returned
+ in the parsedIP buffer and if it contains alias, it is added to aliasList
+*/
+int ooParseDestination
+ (struct OOH323CallData *call, char *dest, char* parsedIP, unsigned len,
+ ooAliases** aliasList)
+{
+ int iEk=-1, iDon=-1, iTeen=-1, iChaar=-1, iPort = -1, i;
+ ooAliases * psNewAlias = NULL;
+ char *cAt = NULL, *host=NULL;
+ char tmp[256], buf[30];
+ char *alias=NULL;
+ OOCTXT *pctxt = call->pctxt;
+ parsedIP[0] = '\0';
+
+ OOTRACEINFO2("Parsing destination %s\n", dest);
+
+ /* Test for an IP address:Note that only supports dotted IPv4.
+ IPv6 won't pass the test and so will numeric IP representation*/
+
+ sscanf(dest, "%d.%d.%d.%d:%d", &iEk, &iDon, &iTeen, &iChaar, &iPort);
+ if((iEk > 0 && iEk <= 255) &&
+ (iDon >= 0 && iDon <= 255) &&
+ (iTeen >=0 && iTeen <= 255) &&
+ (iChaar >= 0 && iChaar <= 255) &&
+ (!strchr(dest, ':') || iPort != -1))
+ {
+ if(!strchr(dest, ':'))
+ iPort = 1720; /*Default h.323 port */
+
+ sprintf(buf, "%d.%d.%d.%d:%d", iEk, iDon, iTeen, iChaar, iPort);
+ if(strlen(buf)+1>len)
+ {
+ OOTRACEERR1("Error:Insufficient buffer space for parsed ip - "
+ "ooParseDestination\n");
+ return OO_FAILED;
+ }
+
+ strcpy(parsedIP, buf);
+ return OO_OK;
+ }
+
+ /* alias@host */
+ strncpy(tmp, dest, sizeof(tmp)-1);
+ tmp[sizeof(tmp)-1]='\0';
+ if((host=strchr(tmp, '@')) != NULL)
+ {
+ *host = '\0';
+ host++;
+ sscanf(host, "%d.%d.%d.%d:%d", &iEk, &iDon, &iTeen, &iChaar, &iPort);
+ if((iEk > 0 && iEk <= 255) &&
+ (iDon >= 0 && iDon <= 255) &&
+ (iTeen >=0 && iTeen <= 255) &&
+ (iChaar >= 0 && iChaar <= 255) &&
+ (!strchr(host, ':') || iPort != -1))
+ {
+ if(!strchr(dest, ':'))
+ iPort = 1720; /*Default h.323 port */
+
+ sprintf(buf, "%d.%d.%d.%d:%d", iEk, iDon, iTeen, iChaar, iPort);
+ if(strlen(buf)+1>len)
+ {
+ OOTRACEERR1("Error:Insufficient buffer space for parsed ip - "
+ "ooParseDestination\n");
+ return OO_FAILED;
+ }
+
+ strncpy(parsedIP, buf, len-1);
+ parsedIP[len-1]='\0';
+ alias = tmp;
+ }
+ }
+
+ if(!alias)
+ {
+ alias = dest;
+ }
+ /* url test */
+ if(alias == strstr(alias, "http://"))
+ {
+ psNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases));
+ if(!psNewAlias)
+ {
+ OOTRACEERR1("Error:Memory - ooParseDestination - psNewAlias\n");
+ return OO_FAILED;
+ }
+ psNewAlias->type = T_H225AliasAddress_url_ID;
+ psNewAlias->value = (char*) memAlloc(pctxt, strlen(alias)+1);
+ if(!psNewAlias->value)
+ {
+ OOTRACEERR1("Error:Memory - ooParseDestination - "
+ "psNewAlias->value\n");
+ memFreePtr(pctxt, psNewAlias);
+ return OO_FAILED;
+ }
+ strcpy(psNewAlias->value, alias);
+ psNewAlias->next = *aliasList;
+ *aliasList = psNewAlias;
+ OOTRACEINFO2("Destination parsed as url %s\n", psNewAlias->value);
+ return OO_OK;
+ }
+
+ /* E-mail ID test */
+ if((cAt = strchr(alias, '@')) && alias != strchr(alias, '@'))
+ {
+ if(strchr(cAt, '.'))
+ {
+ psNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases));
+ if(!psNewAlias)
+ {
+ OOTRACEERR1("Error:Memory - ooParseDestination - psNewAlias\n");
+ return OO_FAILED;
+ }
+ psNewAlias->type = T_H225AliasAddress_email_ID;
+ psNewAlias->value = (char*) memAlloc(pctxt, strlen(alias)+1);
+ if(!psNewAlias->value)
+ {
+ OOTRACEERR1("Error:Memory - ooParseDestination - "
+ "psNewAlias->value\n");
+ memFreePtr(pctxt, psNewAlias);
+ return OO_FAILED;
+ }
+ strcpy(psNewAlias->value, alias);
+ psNewAlias->next = *aliasList;
+ *aliasList = psNewAlias;
+ OOTRACEINFO2("Destination is parsed as email %s\n",psNewAlias->value);
+ return OO_OK;
+ }
+ }
+
+
+ /* e-164 */
+ /* strspn(dest, "1234567890*#,") == strlen(dest)*/
+ /* Dialed digits test*/
+ for(i=0; *(alias+i) != '\0'; i++)
+ {
+ if(!isdigit(alias[i]) && alias[i] != '#' && alias[i] != '*' &&
+ alias[i] != ',')
+ break;
+ }
+ if(*(alias+i) == '\0')
+ {
+ psNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases));
+ if(!psNewAlias)
+ {
+ OOTRACEERR1("Error:Memory - ooParseDestination - psNewAlias\n");
+ return OO_FAILED;
+ }
+ /* memset(psNewAlias, 0, sizeof(ooAliases));*/
+ psNewAlias->type = T_H225AliasAddress_dialedDigits;
+ psNewAlias->value = (char*) memAlloc(pctxt, strlen(alias)+1);
+ if(!psNewAlias->value)
+ {
+ OOTRACEERR1("Error:Memroy - ooParseDestination - "
+ "psNewAlias->value\n");
+ memFreePtr(pctxt, psNewAlias);
+ return OO_FAILED;
+ }
+ strcpy(psNewAlias->value, alias);
+ psNewAlias->next = *aliasList;
+ *aliasList = psNewAlias;
+ OOTRACEINFO2("Destination is parsed as dialed digits %s\n",
+ psNewAlias->value);
+ /* Also set called party number */
+ if(!call->calledPartyNumber)
+ {
+ if(ooCallSetCalledPartyNumber(call, alias) != OO_OK)
+ {
+ OOTRACEWARN3("Warning:Failed to set calling party number."
+ "(%s, %s)\n", call->callType, call->callToken);
+ }
+ }
+ return OO_OK;
+ }
+ /* Evrything else is an h323-id for now */
+ psNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases));
+ if(!psNewAlias)
+ {
+ OOTRACEERR1("Error:Memory - ooParseDestination - psNewAlias\n");
+ return OO_FAILED;
+ }
+ psNewAlias->type = T_H225AliasAddress_h323_ID;
+ psNewAlias->value = (char*) memAlloc(pctxt, strlen(alias)+1);
+ if(!psNewAlias->value)
+ {
+ OOTRACEERR1("Error:Memory - ooParseDestination - psNewAlias->value\n");
+ memFreePtr(pctxt, psNewAlias);
+ return OO_FAILED;
+ }
+ strcpy(psNewAlias->value, alias);
+ psNewAlias->next = *aliasList;
+ *aliasList = psNewAlias;
+ OOTRACEINFO2("Destination for new call is parsed as h323-id %s \n",
+ psNewAlias->value);
+ return OO_OK;
+}
+
+const char* ooGetMsgTypeText (int msgType)
+{
+ static const char *msgTypeText[]={
+ "OOQ931MSG",
+ "OOH245MSG",
+ "OOSetup",
+ "OOCallProceeding",
+ "OOAlert",
+ "OOConnect",
+ "OOReleaseComplete",
+ "OOFacility",
+ "OOInformation",
+ "OOMasterSlaveDetermination",
+ "OOMasterSlaveAck",
+ "OOMasterSlaveReject",
+ "OOMasterSlaveRelease",
+ "OOTerminalCapabilitySet",
+ "OOTerminalCapabilitySetAck",
+ "OOTerminalCapabilitySetReject",
+ "OOTerminalCapabilitySetRelease",
+ "OOOpenLogicalChannel",
+ "OOOpenLogicalChannelAck",
+ "OOOpenLogicalChannelReject",
+ "OOOpenLogicalChannelRelease",
+ "OOOpenLogicalChannelConfirm",
+ "OOCloseLogicalChannel",
+ "OOCloseLogicalChannelAck",
+ "OORequestChannelClose",
+ "OORequestChannelCloseAck",
+ "OORequestChannelCloseReject",
+ "OORequestChannelCloseRelease",
+ "OOEndSessionCommand"
+ };
+ int idx = msgType - OO_MSGTYPE_MIN;
+ return ooUtilsGetText (idx, msgTypeText, OONUMBEROF(msgTypeText));
+}
+
+const char* ooGetQ931CauseValueText(int val)
+{
+ switch(val)
+ {
+ case Q931UnallocatedNumber:
+ return "Q931UnallocatedNumber";
+ case Q931NoRouteToNetwork:
+ return "Q931NoRouteToNetwork";
+ case Q931NoRouteToDestination:
+ return "Q931NoRouteToDestination";
+ case Q931ChannelUnacceptable:
+ return "Q931ChannelUnacceptable";
+ case Q931NormalCallClearing:
+ return "Q931NormalCallClearing";
+ case Q931UserBusy:
+ return "Q931UserBusy";
+ case Q931NoResponse:
+ return "Q931NoResponse";
+ case Q931NoAnswer:
+ return "Q931NoAnswer";
+ case Q931SubscriberAbsent:
+ return "Q931SubscriberAbsent";
+ case Q931CallRejected:
+ return "Q931CallRejected";
+ case Q931NumberChanged:
+ return "Q931NumberChanged";
+ case Q931Redirection:
+ return "Q931Redirection";
+ case Q931DestinationOutOfOrder:
+ return "Q931DestinationOutOfOrder";
+ case Q931InvalidNumberFormat:
+ return "Q931InvalidNumberFormat";
+ case Q931NormalUnspecified:
+ return "Q931NormalUnspecified";
+ case Q931StatusEnquiryResponse:
+ return "Q931StatusEnquiryResponse";
+ case Q931NoCircuitChannelAvailable:
+ return "Q931NoCircuitChannelAvailable";
+ case Q931NetworkOutOfOrder:
+ return "Q931NetworkOutOfOrder";
+ case Q931TemporaryFailure:
+ return "Q931TemporaryFailure";
+ case Q931Congestion:
+ return "Q931Congestion";
+ case Q931RequestedCircuitUnAvailable:
+ return "Q931RequestedCircuitUnavailable";
+ case Q931ResourcesUnavailable:
+ return "Q931ResourcesUnavailable";
+ case Q931IncompatibleDestination:
+ return "Q931IncompatibleDestination";
+ case Q931ProtocolErrorUnspecified:
+ return "Q931ProtocolErrorUnspecified";
+ case Q931RecoveryOnTimerExpiry:
+ return "Q931RecoveryOnTimerExpiry";
+ case Q931InvalidCallReference:
+ return "Q931InvaliedCallReference";
+ default:
+ return "Unsupported Cause Type";
+ }
+ return "Unsupported Cause Type";
+}
+