corrections in gk interface, small fixes in call clearing.
[asterisk/asterisk.git] / addons / ooh323c / src / ooq931.c
1 /*
2  * Copyright (C) 2004-2005 by Objective Systems, Inc.
3  *
4  * This software is furnished under an open source license and may be 
5  * used and copied only in accordance with the terms of this license. 
6  * The text of the license may generally be found in the root 
7  * directory of this installation in the COPYING file.  It 
8  * can also be viewed online at the following URL:
9  *
10  *   http://www.obj-sys.com/open/license.html
11  *
12  * Any redistributions of this file including modified versions must 
13  * maintain this copyright notice.
14  *
15  *****************************************************************************/
16
17 #include "asterisk.h"
18 #include "asterisk/lock.h"
19 #include "asterisk/utils.h"
20 #include <time.h>
21
22 #include "ooq931.h"
23 #include "ootrace.h"
24 #include "ooasn1.h"
25 #include "oochannels.h"
26 #include "printHandler.h"
27 #include "ooCalls.h"
28 #include "ooh323.h"
29 #include "ooh245.h"
30 #include "ooh323ep.h"
31 #include "ooCapability.h"
32 #include "ooGkClient.h"
33 #include "ooUtils.h"
34 #include "ootypes.h"
35 #include <time.h>
36 #include <ctype.h>
37
38 int ooSetFastStartResponse(OOH323CallData *pCall, Q931Message *pQ931msg,
39    ASN1UINT *fsCount, ASN1DynOctStr **fsElem);
40
41 /** Global endpoint structure */
42 extern OOH323EndPoint gH323ep;
43
44 extern ast_mutex_t newCallLock;
45
46 static ASN1OBJID gProtocolID = {
47    6, { 0, 0, 8, 2250, 0, 4 }
48 };
49
50 EXTERN int ooQ931Decode 
51    (OOH323CallData *call, Q931Message* msg, int length, ASN1OCTET *data, int docallbacks)
52 {
53    int offset, x;
54    int rv = ASN_OK;
55    char number[128];
56    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
57    OOCTXT *pctxt = call->msgctxt;
58
59    dListInit (&msg->ies); /* clear information elements list */
60
61    if (length < 5)  /* Packet too short */
62       return Q931_E_TOOSHORT;
63
64    msg->protocolDiscriminator = data[0];
65    OOTRACEDBGB2("   protocolDiscriminator = %d\n", msg->protocolDiscriminator);
66    if (data[1] != 2) /* Call reference must be 2 bytes long */
67       return Q931_E_INVCALLREF;
68
69    msg->callReference = ((data[2] & 0x7f) << 8) | data[3];
70
71    OOTRACEDBGB2("   callReference = %d\n", msg->callReference);
72
73    msg->fromDestination = (data[2] & 0x80) != 0;
74    if(msg->fromDestination)
75       OOTRACEDBGB1("   from = destination\n");
76    else
77       OOTRACEDBGB1("   from = originator\n");   
78
79
80    msg->messageType = data[4];
81    OOTRACEDBGB2("   messageType = %x\n", msg->messageType);
82
83    
84    /* Have preamble, start getting the informationElements into buffers */
85    offset = 5;
86    while (offset < length) {
87       Q931InformationElement *ie;
88       int ieOff = offset;
89       /* Get field discriminator */
90       int discriminator = data[offset++];
91
92       /* For discriminator with high bit set there is no data */
93       if ((discriminator & 0x80) == 0) {
94          int len = data[offset++], alen;
95
96          if (discriminator == Q931UserUserIE) {
97             /* Special case of User-user field, there is some confusion here as
98                the Q931 documentation claims the length is a single byte,
99                unfortunately all H.323 based apps have a 16 bit length here, so
100                we allow for said longer length. There is presumably an addendum
101                to Q931 which describes this, and provides a means to 
102                discriminate between the old 1 byte and the new 2 byte systems. 
103                However, at present we assume it is always 2 bytes until we find
104                something that breaks it. 
105             */
106             len <<= 8;
107             len |= data[offset++];
108
109             /* we also have a protocol discriminator, which we ignore */
110             offset++;
111             len--;
112          }
113
114          /* watch out for negative lengths! (ED, 11/5/03) */
115          if (len < 0) {
116             return Q931_E_INVLENGTH;
117          }
118          else if (offset + len > length) {
119             alen = 0;
120             len = -len;
121             rv = Q931_E_INVLENGTH;
122          }
123          else alen = len;
124
125          ie = (Q931InformationElement*) 
126             memAlloc (pctxt, sizeof(*ie) - sizeof(ie->data) + alen);
127          if(!ie)
128          {
129             OOTRACEERR3("Error:Memory - ooQ931Decode - ie(%s, %s)\n", 
130                          call->callType, call->callToken);
131             return OO_FAILED;
132          }
133          ie->discriminator = discriminator;
134          ie->offset = ieOff;
135          ie->length = len;
136          if (alen != 0) 
137             memcpy(ie->data, data + offset, alen);
138          offset += len;
139       }
140       else {
141          ie = (Q931InformationElement*) memAlloc (pctxt, 
142                                         sizeof(*ie) - sizeof(ie->data));
143          if(!ie)
144          {
145             OOTRACEERR3("Error:Memory - ooQ931Decode - ie(%s, %s)\n", 
146                          call->callType, call->callToken);
147             return OO_FAILED;
148          }
149          ie->discriminator = discriminator;
150          ie->offset = offset;
151          ie->length = 0;
152       }
153       if(ie->discriminator == Q931BearerCapabilityIE)
154       {
155          OOTRACEDBGB1("   Bearer-Capability IE = {\n");
156          for(x=0; x<ie->length; x++)
157          {
158             if(x==0)
159                OOTRACEDBGB2("      %x", ie->data[x]);
160             else
161                OOTRACEDBGB2(", %x", ie->data[x]);
162          }
163          OOTRACEDBGB1("   }\n");
164       }
165       if(ie->discriminator == Q931DisplayIE)
166       {
167          OOTRACEDBGB1("   Display IE = {\n");
168          OOTRACEDBGB2("      %s\n", ie->data);
169          OOTRACEDBGB1("   }\n");
170       }
171
172       if(ie->discriminator == Q931KeypadIE)
173       {
174          OOTRACEDBGB1("   Keypad IE = {\n");
175          OOTRACEDBGB2("      %c\n", ie->data[0]);
176          OOTRACEDBGB1("   }\n");
177          if(docallbacks && gH323ep.h323Callbacks.onReceivedDTMF)
178          {
179             gH323ep.h323Callbacks.onReceivedDTMF(call, (char *)ie->data);
180          }
181       }
182       /* Extract calling party number TODO:Give respect to presentation and 
183          screening indicators ;-) */
184       if(ie->discriminator == Q931CallingPartyNumberIE)
185       {
186          OOTRACEDBGB1("   CallingPartyNumber IE = {\n");
187          if(ie->length < OO_MAX_NUMBER_LENGTH)
188          {
189             int numoffset=1; 
190             if(!(0x80 & ie->data[0])) numoffset = 2;
191             memcpy(number, ie->data+numoffset,ie->length-numoffset);
192             number[ie->length-numoffset]='\0';
193             OOTRACEDBGB2("      %s\n", number);
194             if(!call->callingPartyNumber)
195                ooCallSetCallingPartyNumber(call, number);
196          }
197          else{
198             OOTRACEERR3("Error:Calling party number too long. (%s, %s)\n", 
199                            call->callType, call->callToken);
200          }
201          OOTRACEDBGB1("   }\n");
202       }
203
204       /* Extract called party number */
205       if(ie->discriminator == Q931CalledPartyNumberIE)
206       {
207          OOTRACEDBGB1("   CalledPartyNumber IE = {\n");
208          if(ie->length < OO_MAX_NUMBER_LENGTH)
209          {
210             memcpy(number, ie->data+1,ie->length-1);
211             number[ie->length-1]='\0';
212             OOTRACEDBGB2("      %s\n", number);
213             if(!call->calledPartyNumber)
214                ooCallSetCalledPartyNumber(call, number);
215          }
216          else{
217             OOTRACEERR3("Error:Calling party number too long. (%s, %s)\n", 
218                            call->callType, call->callToken);
219          }
220          OOTRACEDBGB1("   }\n");
221       }
222
223       /* Handle Cause ie */
224       if(ie->discriminator == Q931CauseIE)
225       {
226          msg->causeIE = ie;
227          OOTRACEDBGB1("   Cause IE = {\n");
228          OOTRACEDBGB2("      %s\n", ooGetQ931CauseValueText(ie->data[1]&0x7f));
229          OOTRACEDBGB1("   }\n");
230       }
231
232       /* TODO: Get rid of ie list.*/
233       dListAppend (pctxt, &msg->ies, ie);
234       if (rv != ASN_OK)
235          return rv;
236    }
237    
238    /*cisco router sends Q931Notify without UU ie, 
239      we just ignore notify message as of now as handling is optional for
240      end point*/
241    if(msg->messageType != Q931NotifyMsg && msg->messageType != Q931StatusMsg)
242       rv = ooDecodeUUIE(pctxt, msg);
243    return rv;
244 }
245
246 EXTERN Q931InformationElement* ooQ931GetIE (const Q931Message* q931msg, 
247                                               int ieCode)
248 {
249    DListNode* curNode;
250    unsigned int i;
251
252    for(i = 0, curNode = q931msg->ies.head; i < q931msg->ies.count; i++) {
253       Q931InformationElement *ie = (Q931InformationElement*) curNode->data;
254       if (ie->discriminator == ieCode) {
255          return ie;
256       }
257       curNode = curNode->next;
258    }
259    return NULL;
260 }
261
262 char* ooQ931GetMessageTypeName(int messageType, char* buf) {
263    switch (messageType) {
264       case Q931AlertingMsg :
265          strcpy(buf, "Alerting");
266          break;
267       case Q931CallProceedingMsg :
268          strcpy(buf, "CallProceeding");
269          break;
270       case Q931ConnectMsg :
271          strcpy(buf, "Connect");
272          break;
273       case Q931ConnectAckMsg :
274          strcpy(buf, "ConnectAck");
275          break;
276       case Q931ProgressMsg :
277          strcpy(buf, "Progress");
278          break;
279       case Q931SetupMsg :
280          strcpy(buf, "Setup");
281          break;
282       case Q931SetupAckMsg :
283          strcpy(buf, "SetupAck");
284          break;
285       case Q931FacilityMsg :
286          strcpy(buf, "Facility");
287          break;
288       case Q931ReleaseCompleteMsg :
289          strcpy(buf, "ReleaseComplete");
290          break;
291       case Q931StatusEnquiryMsg :
292          strcpy(buf, "StatusEnquiry");
293          break;
294       case Q931StatusMsg :
295          strcpy(buf, "Status");
296          break;
297       case Q931InformationMsg :
298          strcpy(buf, "Information");
299          break;
300       case Q931NationalEscapeMsg :
301          strcpy(buf, "Escape");
302          break;
303       default:
304          sprintf(buf, "<%u>", messageType);
305    }
306    return buf;
307 }
308
309 char* ooQ931GetIEName(int number, char* buf) {
310    switch (number) {
311       case Q931BearerCapabilityIE :
312          strcpy(buf, "Bearer-Capability");
313          break;
314       case Q931CauseIE :
315          strcpy(buf, "Cause");
316          break;
317       case Q931FacilityIE :
318          strcpy(buf, "Facility");
319          break;
320       case Q931ProgressIndicatorIE :
321          strcpy(buf, "Progress-Indicator");
322          break;
323       case Q931CallStateIE :
324          strcpy(buf, "Call-State");
325          break;
326       case Q931DisplayIE :
327          strcpy(buf, "Display");
328          break;
329       case Q931SignalIE :
330          strcpy(buf, "Signal");
331          break;
332       case Q931CallingPartyNumberIE :
333          strcpy(buf, "Calling-Party-Number");
334          break;
335       case Q931CalledPartyNumberIE :
336          strcpy(buf, "Called-Party-Number");
337          break;
338       case Q931RedirectingNumberIE :
339          strcpy(buf, "Redirecting-Number");
340          break;
341       case Q931UserUserIE :
342          strcpy(buf, "User-User");
343          break;
344       default:
345          sprintf(buf, "0x%02x", number);
346    }
347    return buf;
348 }
349
350 EXTERN void ooQ931Print (const Q931Message* q931msg) {
351    char buf[1000];
352    DListNode* curNode;
353    unsigned int i;
354
355    printf("Q.931 Message:\n");
356    printf("   protocolDiscriminator: %i\n", q931msg->protocolDiscriminator);
357    printf("   callReference: %i\n", q931msg->callReference);
358    printf("   from: %s\n", (q931msg->fromDestination ? 
359                                        "destination" : "originator"));
360    printf("   messageType: %s (0x%X)\n\n", 
361               ooQ931GetMessageTypeName(q931msg->messageType, buf), 
362                                                q931msg->messageType);
363
364    for(i = 0, curNode = q931msg->ies.head; i < q931msg->ies.count; i++) {
365       Q931InformationElement *ie = (Q931InformationElement*) curNode->data;
366       int length = (ie->length >= 0) ? ie->length : -ie->length;
367       printf("   IE[%i] (offset 0x%X):\n", i, ie->offset);
368       printf("      discriminator: %s (0x%X)\n", 
369                ooQ931GetIEName(ie->discriminator, buf), ie->discriminator);
370       printf("      data length: %i\n", length);
371  
372       curNode = curNode->next;
373       printf("\n");
374    }
375 }
376
377 int ooCreateQ931Message(OOCTXT* pctxt, Q931Message **q931msg, int msgType)
378 {
379    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
380    
381    *q931msg = (Q931Message*)memAllocZ(pctxt, sizeof(Q931Message));
382                 
383    if(!*q931msg)
384    {
385       OOTRACEERR1("Error:Memory -  ooCreateQ931Message - q931msg\n");
386       return OO_FAILED;
387    }
388    else
389    {
390       (*q931msg)->protocolDiscriminator = 8;
391       (*q931msg)->fromDestination = FALSE;
392       (*q931msg)->messageType = msgType;
393       (*q931msg)->tunneledMsgType = msgType;
394       (*q931msg)->logicalChannelNo = 0;
395       (*q931msg)->bearerCapabilityIE = NULL;
396       (*q931msg)->callingPartyNumberIE = NULL;
397       (*q931msg)->calledPartyNumberIE = NULL;
398       (*q931msg)->causeIE = NULL;
399       return OO_OK;
400    }
401 }
402
403
404 int ooGenerateCallToken (char *callToken, size_t size)
405 {
406    static int counter = 1;
407    char aCallToken[200];
408    int  ret = 0;
409
410    ast_mutex_lock(&newCallLock);
411    sprintf (aCallToken, "ooh323c_%d", counter++);
412
413    if (counter > OO_MAX_CALL_TOKEN)
414       counter = 1;
415    ast_mutex_unlock(&newCallLock);
416
417    if ((strlen(aCallToken)+1) < size)
418       strcpy (callToken, aCallToken);
419    else {
420       OOTRACEERR1 ("Error: Insufficient buffer size to generate call token");
421       ret = OO_FAILED;
422    }
423
424
425    return ret;
426 }
427
428 /* CallReference is a two octet field, thus max value can be 0xffff
429    or 65535 decimal. We restrict max value to 32760, however, this should
430    not cause any problems as there won't be those many simultaneous calls
431    CallRef has to be locally unique and generated by caller.
432 */
433 ASN1USINT ooGenerateCallReference()
434 {
435    static ASN1USINT lastCallRef=0;
436    ASN1USINT newCallRef=0;
437
438
439    if(lastCallRef == 0)
440    {
441       /* Generate a new random callRef */
442       srand((unsigned)time(0));
443       lastCallRef = (ASN1USINT)(rand()%100);
444    }
445    else
446       lastCallRef++;
447
448    /* Note callReference can be at the most 15 bits that is from 0 to 32767.
449       if we generate number bigger than that, bring it in range.
450    */
451    if(lastCallRef>=32766)
452       lastCallRef=1;
453
454    newCallRef = lastCallRef;
455
456
457    OOTRACEDBGC2("Generated callRef %d\n", newCallRef);
458    return newCallRef;
459 }
460
461
462 int ooGenerateCallIdentifier(H225CallIdentifier *callid)
463 {
464    ASN1INT64 timestamp;
465    int i=0;
466 #ifdef _WIN32
467    
468    SYSTEMTIME systemTime;
469    GetLocalTime(&systemTime);
470    SystemTimeToFileTime(&systemTime, (LPFILETIME)&timestamp);
471 #else
472    struct timeval systemTime;
473    gettimeofday(&systemTime, NULL);
474    timestamp = systemTime.tv_sec * 10000000 + systemTime.tv_usec*10;
475 #endif
476
477    callid->guid.numocts = 16;
478    callid->guid.data[0] = 'o';
479    callid->guid.data[1] = 'o';
480    callid->guid.data[2] = 'h';
481    callid->guid.data[3] = '3';
482    callid->guid.data[4] = '2';
483    callid->guid.data[5] = '3';
484    callid->guid.data[6] = 'c';
485    callid->guid.data[7] = '-';
486
487    for (i = 8; i < 16; i++)
488        callid->guid.data[i] = (ASN1OCTET)((timestamp>>((i-8+1)*8))&0xff);
489
490    return OO_OK;
491
492 }
493
494 int ooFreeQ931Message(OOCTXT* pctxt, Q931Message *q931Msg)
495 {
496    if(!q931Msg)
497    {
498       /* memReset(&gH323ep.msgctxt); */
499       memReset(pctxt);
500    }
501    return OO_OK;
502 }
503
504 int ooEncodeUUIE(OOCTXT* pctxt, Q931Message *q931msg)
505 {
506    ASN1OCTET msgbuf[1024];
507    ASN1OCTET * msgptr=NULL;
508    int  len;
509    ASN1BOOL aligned = TRUE;
510    Q931InformationElement* ie=NULL;
511    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
512    memset(msgbuf, 0, sizeof(msgbuf));
513    if(!q931msg)
514    {
515       OOTRACEERR1("ERROR: Invalid Q931 message in add user-user IE\n");
516       return OO_FAILED;
517    }
518         
519    if(!q931msg->userInfo)
520    {
521       OOTRACEERR1("ERROR: No User-User IE to encode\n");
522       return OO_FAILED;
523    }
524
525    setPERBuffer(pctxt, msgbuf, sizeof(msgbuf), aligned);
526    
527    if(asn1PE_H225H323_UserInformation (pctxt, 
528                                            q931msg->userInfo)==ASN_OK)
529    {
530       OOTRACEDBGC1("UserInfo encoding - successful\n");
531    }
532    else{
533       OOTRACEERR1("ERROR: UserInfo encoding failed\n");
534       return OO_FAILED;
535    }
536    msgptr = encodeGetMsgPtr(pctxt, &len);
537
538    /* Allocate memory to hold complete UserUser Information */
539    ie = (Q931InformationElement*)memAlloc (pctxt,
540                                      sizeof(*ie) - sizeof(ie->data) + len);
541    if(ie == NULL)
542    {
543       OOTRACEERR1("Error: Memory -  ooEncodeUUIE - ie\n");
544       return OO_FAILED;
545    }
546    ie->discriminator = Q931UserUserIE;
547    ie->length = len;
548    memcpy(ie->data, msgptr, len);
549    /* Add the user to user IE NOTE: ALL IEs SHOULD BE IN ASCENDING ORDER OF 
550       THEIR DISCRIMINATOR AS PER SPEC. 
551    */
552    dListInit (&(q931msg->ies));
553    if((dListAppend (pctxt, 
554                       &(q931msg->ies), ie)) == NULL)
555    {
556       OOTRACEERR1("Error: Failed to add UUIE in outgoing message\n");
557       return OO_FAILED;
558    }
559
560    return OO_OK;
561 }
562
563 int ooDecodeUUIE(OOCTXT* pctxt, Q931Message *q931Msg)
564 {
565    DListNode* curNode;
566    unsigned int i;
567    ASN1BOOL aligned=TRUE;
568    int stat;
569    Q931InformationElement *ie;
570    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
571    if(q931Msg ==NULL)
572    {
573       OOTRACEERR1("Error: ooDecodeUUIE failed - NULL q931 message\n");
574       return OO_FAILED;
575    }
576         
577    /* Search for UserUser IE */
578    for(i = 0, curNode = q931Msg->ies.head; i < q931Msg->ies.count; 
579                                              i++, curNode = curNode->next) 
580    {
581       ie = (Q931InformationElement*) curNode->data;
582       if(ie && ie->discriminator == Q931UserUserIE)
583          break;
584    }
585    if(i == q931Msg->ies.count)
586    {
587       OOTRACEERR1("No UserUser IE found in ooDecodeUUIE\n");
588       return OO_FAILED;
589    }
590         
591    /* Decode user-user ie */
592    q931Msg->userInfo = (H225H323_UserInformation *) memAlloc(pctxt,
593                                              sizeof(H225H323_UserInformation));
594    if(!q931Msg->userInfo)
595    {
596       OOTRACEERR1("ERROR:Memory - ooDecodeUUIE - userInfo\n");
597       return OO_FAILED;
598    }
599    memset(q931Msg->userInfo, 0, sizeof(H225H323_UserInformation));
600
601    setPERBuffer (pctxt, ie->data, ie->length, aligned);
602
603    stat = asn1PD_H225H323_UserInformation (pctxt, q931Msg->userInfo);
604    if(stat != ASN_OK)
605    {
606       OOTRACEERR1("Error: UserUser IE decode failed\n");
607       return OO_FAILED;
608    }
609    OOTRACEDBGC1("UUIE decode successful\n");
610    return OO_OK;
611 }
612
613 #ifndef _COMPACT
614 static void ooQ931PrintMessage 
615    (OOH323CallData* call, ASN1OCTET *msgbuf, ASN1UINT msglen)
616 {
617
618    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
619    OOCTXT *pctxt = call->msgctxt;
620    Q931Message q931Msg;
621    int ret;
622
623    initializePrintHandler(&printHandler, "Q931 Message");
624
625    /* Set event handler */
626    setEventHandler (pctxt, &printHandler);
627
628    setPERBuffer (pctxt, msgbuf, msglen, TRUE);
629
630    ret = ooQ931Decode (call, &q931Msg, msglen, msgbuf, 0);
631    if(ret != OO_OK)
632    {
633       OOTRACEERR3("Error:Failed decoding Q931 message. (%s, %s)\n", 
634                  call->callType, call->callToken);
635    }
636    finishPrint();
637    removeEventHandler(pctxt);
638
639 }
640 #endif
641
642
643
644 int ooEncodeH225Message(OOH323CallData *call, Q931Message *pq931Msg, 
645                         char *msgbuf, int size)
646 {
647    int len=0, i=0, j=0, ieLen=0;
648    int stat=0;
649    DListNode* curNode=NULL;
650
651    if(!msgbuf || size<200)
652    {
653       OOTRACEERR3("Error: Invalid message buffer/size for ooEncodeH245Message."
654                   " (%s, %s)\n", call->callType, call->callToken);
655       return OO_FAILED;
656    }
657
658    if(pq931Msg->messageType == Q931SetupMsg){
659       msgbuf[i++] = OOSetup;
660    }
661    else if(pq931Msg->messageType == Q931ConnectMsg){
662       msgbuf[i++] = OOConnect;
663    }
664    else if(pq931Msg->messageType == Q931CallProceedingMsg){
665       msgbuf[i++] = OOCallProceeding;
666    }
667    else if(pq931Msg->messageType == Q931AlertingMsg || 
668            pq931Msg->messageType == Q931ProgressMsg){
669       msgbuf[i++] = OOAlert;
670    }
671    else if(pq931Msg->messageType == Q931ReleaseCompleteMsg){
672       msgbuf[i++] = OOReleaseComplete;
673    }
674    else if(pq931Msg->messageType == Q931InformationMsg){
675       msgbuf[i++] = OOInformationMessage;
676    }
677    else if(pq931Msg->messageType == Q931FacilityMsg){
678       msgbuf[i++] = OOFacility;
679       msgbuf[i++] = pq931Msg->tunneledMsgType;
680       msgbuf[i++] = pq931Msg->logicalChannelNo>>8;
681       msgbuf[i++] = pq931Msg->logicalChannelNo;
682    }
683    else{
684       OOTRACEERR3("Error:Unknow Q931 message type. (%s, %s)\n", call->callType,
685                    call->callToken);
686       return OO_FAILED;
687    }
688
689    stat = ooEncodeUUIE(call->msgctxt, pq931Msg);
690    if(stat != OO_OK)
691    {
692       OOTRACEERR3("Error:Failed to encode uuie. (%s, %s)\n", call->callType, 
693                    call->callToken);
694       return OO_FAILED;
695    }
696    
697    msgbuf[i++] = 3; /* TPKT version */
698    msgbuf[i++] = 0; /* TPKT resevred */
699    /* 1st octet of length, will be populated once len is determined */
700    msgbuf[i++] = 0; 
701    /* 2nd octet of length, will be populated once len is determined */
702    msgbuf[i++] = 0; 
703    /* Q931 protocol discriminator */
704    msgbuf[i++] = pq931Msg->protocolDiscriminator;
705    msgbuf[i++] = 2; /* length of call ref is two octets */
706    msgbuf[i] = (pq931Msg->callReference >> 8); /* populate 1st octet */
707    if(!strcmp(call->callType, "incoming"))
708       msgbuf[i++] |= 0x80;   /* fromDestination*/
709    else
710       i++;   /* fromOriginator*/
711
712   
713    msgbuf[i++] = pq931Msg->callReference; /* populate 2nd octet */
714    msgbuf[i++] = pq931Msg->messageType; /* type of q931 message */
715
716    /* Note: the order in which ies are added is important. It is in the
717       ascending order of ie codes. 
718    */
719    /* Add bearer IE */
720    if(pq931Msg->bearerCapabilityIE)
721    {   
722       msgbuf[i++] = Q931BearerCapabilityIE; /* ie discriminator */
723       msgbuf[i++] = pq931Msg->bearerCapabilityIE->length;
724       memcpy(msgbuf+i, pq931Msg->bearerCapabilityIE->data, 
725                        pq931Msg->bearerCapabilityIE->length);
726       i += pq931Msg->bearerCapabilityIE->length;
727    }   
728
729    /* Add cause IE */
730    if(pq931Msg->causeIE)
731    {
732       msgbuf[i++] = Q931CauseIE;
733       msgbuf[i++] = pq931Msg->causeIE->length;
734       memcpy(msgbuf+i, pq931Msg->causeIE->data, pq931Msg->causeIE->length);
735       i += pq931Msg->causeIE->length;
736    } 
737       
738    /*Add progress indicator IE 
739    if(pq931Msg->messageType == Q931AlertingMsg || pq931Msg->messageType == Q931CallProceedingMsg)
740    {
741       msgbuf[i++] = Q931ProgressIndicatorIE;
742       msgbuf[i++] = 2; //Length is 2 octet
743       msgbuf[i++] = 0x80; //PI=8
744       msgbuf[i++] = 0x88;
745   }*/
746
747    /*Add display ie. */
748    if(!ooUtilsIsStrEmpty(call->ourCallerId))
749    {
750       msgbuf[i++] = Q931DisplayIE;
751       ieLen = strlen(call->ourCallerId)+1;
752       msgbuf[i++] = ieLen;
753       memcpy(msgbuf+i, call->ourCallerId, ieLen-1);
754       i += ieLen-1;
755       msgbuf[i++] = '\0';
756    }
757
758    /* Add calling Party ie */
759    if(pq931Msg->callingPartyNumberIE)
760    {
761       msgbuf[i++] = Q931CallingPartyNumberIE;
762       msgbuf[i++] = pq931Msg->callingPartyNumberIE->length;
763       memcpy(msgbuf+i, pq931Msg->callingPartyNumberIE->data,
764                        pq931Msg->callingPartyNumberIE->length);
765       i += pq931Msg->callingPartyNumberIE->length;
766    }
767
768     /* Add called Party ie */
769    if(pq931Msg->calledPartyNumberIE)
770    {
771       msgbuf[i++] = Q931CalledPartyNumberIE;
772       msgbuf[i++] = pq931Msg->calledPartyNumberIE->length;
773       memcpy(msgbuf+i, pq931Msg->calledPartyNumberIE->data,
774                        pq931Msg->calledPartyNumberIE->length);
775       i += pq931Msg->calledPartyNumberIE->length;
776    }
777    
778    /* Add keypad ie */
779    if(pq931Msg->keypadIE)
780    {
781       msgbuf[i++] = Q931KeypadIE;
782       msgbuf[i++] = pq931Msg->keypadIE->length;
783       memcpy(msgbuf+i, pq931Msg->keypadIE->data, pq931Msg->keypadIE->length);
784       i += pq931Msg->keypadIE->length;
785    }
786
787    /* Note: Have to fix this, though it works. Need to get rid of ie list. 
788       Right now we only put UUIE in ie list. Can be easily removed.
789    */
790
791    for(j = 0, curNode = pq931Msg->ies.head; j < (int)pq931Msg->ies.count; j++) 
792    {
793       Q931InformationElement *ie = (Q931InformationElement*) curNode->data;
794           
795       ieLen = ie->length;
796
797       /* Add the ie discriminator in message buffer */
798       msgbuf[i++] = ie->discriminator; 
799           
800       /* For user-user IE, we have to add protocol discriminator */
801       if (ie->discriminator == Q931UserUserIE)
802       {
803          ieLen++; /* length includes protocol discriminator octet. */
804          msgbuf[i++] = (ieLen>>8); /* 1st octet for length */
805          msgbuf[i++] = ieLen;      /* 2nd octet for length */
806          ieLen--;
807          msgbuf[i++] = 5; /* protocol discriminator */
808          memcpy((msgbuf + i), ie->data, ieLen);
809
810          i += ieLen;
811          
812       }
813       else
814       {
815          OOTRACEWARN1("Warning: Only UUIE is supported currently\n");
816          return OO_FAILED;
817       }
818    }
819    //   len = i+1-4; /* complete message length */
820    
821
822    /* Tpkt length octets populated with total length of the message */
823    if(msgbuf[0] != OOFacility)
824    {
825       len = i-1;
826       msgbuf[3] = (len >> 8); 
827       msgbuf[4] = len;        /* including tpkt header */
828    }
829    else{
830       len = i-4;
831       msgbuf[6] = (len >> 8);
832       msgbuf[7] = len;
833    }
834   
835 #ifndef _COMPACT
836    if(msgbuf[0] != OOFacility)
837       ooQ931PrintMessage (call, (unsigned char *)msgbuf+5, len-4);
838    else
839       ooQ931PrintMessage (call, (unsigned char *)msgbuf+8, len-4);
840 #endif
841    return OO_OK;
842 }
843
844 int ooSetFastStartResponse(OOH323CallData *pCall, Q931Message *pQ931msg, 
845    ASN1UINT *fsCount, ASN1DynOctStr **fsElem)
846 {
847    /* OOCTXT *pctxt = &gH323ep.msgctxt;    */
848    OOCTXT *pctxt = pCall->msgctxt;   
849    int ret = 0, i=0, j=0, remoteMediaPort=0, remoteMediaControlPort = 0, dir=0;
850    char remoteMediaIP[20], remoteMediaControlIP[20];
851    DListNode *pNode = NULL;
852    H245OpenLogicalChannel *olc = NULL, printOlc;
853    ooH323EpCapability *epCap = NULL;
854    ASN1DynOctStr *pFS=NULL;
855    H245H2250LogicalChannelParameters *h2250lcp = NULL;  
856    ooLogicalChannel* pChannel;
857
858
859    if(pCall->pFastStartRes) {
860       ASN1UINT k = 0;
861       ASN1OCTET* pData;
862
863       /* copy the stored fast start response to structure */
864       *fsCount = pCall->pFastStartRes->n;
865       *fsElem = (ASN1DynOctStr*)
866          memAlloc(pctxt, pCall->pFastStartRes->n * sizeof(ASN1DynOctStr));
867
868       for(k = 0; k < pCall->pFastStartRes->n; k ++) {
869          (*fsElem)[k].numocts = pCall->pFastStartRes->elem[k].numocts;
870          pData = (ASN1OCTET*) memAlloc(
871             pctxt, (*fsElem)[k].numocts * sizeof(ASN1OCTET));
872          memcpy(pData, 
873             pCall->pFastStartRes->elem[k].data, 
874             pCall->pFastStartRes->elem[k].numocts);
875          (*fsElem)[k].data = pData;
876       }
877
878       return ASN_OK;
879    }
880    
881       
882    /* If fast start supported and remote endpoint has sent faststart element */
883    if(OO_TESTFLAG(pCall->flags, OO_M_FASTSTART) && 
884       pCall->remoteFastStartOLCs.count>0)
885    {
886       pFS = (ASN1DynOctStr*)memAlloc(pctxt, 
887                         pCall->remoteFastStartOLCs.count*sizeof(ASN1DynOctStr));
888       if(!pFS)
889       {
890          OOTRACEERR3("Error:Memory - ooSetFastStartResponse - pFS (%s, %s)\n", 
891                       pCall->callType, pCall->callToken);    
892          return OO_FAILED;
893       }
894       memset(pFS, 0, pCall->remoteFastStartOLCs.count*sizeof(ASN1DynOctStr));
895
896       /* Go though all the proposed channels */
897       for(i=0, j=0; i<(int)pCall->remoteFastStartOLCs.count; i++)
898       {
899
900          pNode = dListFindByIndex(&pCall->remoteFastStartOLCs, i);
901          olc = (H245OpenLogicalChannel*)pNode->data;
902
903          /* Don't support both direction channel */
904          if(olc->forwardLogicalChannelParameters.dataType.t != 
905                                                    T_H245DataType_nullData &&
906             olc->m.reverseLogicalChannelParametersPresent)
907          {
908             OOTRACEINFO3("Ignoring bidirectional OLC as it is not supported."
909                          "(%s, %s)\n", pCall->callType, pCall->callToken);
910             continue;
911          }
912
913          /* Check forward logic channel */
914          if(olc->forwardLogicalChannelParameters.dataType.t != 
915                                                    T_H245DataType_nullData)
916          {
917             /* Forward Channel - remote transmits - local receives */
918             OOTRACEDBGC4("Processing received forward olc %d (%s, %s)\n", 
919                           olc->forwardLogicalChannelNumber, pCall->callType, 
920                           pCall->callToken);
921             dir = OORX;
922             epCap = ooIsDataTypeSupported(pCall, 
923                                 &olc->forwardLogicalChannelParameters.dataType,
924                                 OORX);
925             
926             if(!epCap) { continue; } /* Not Supported Channel */
927
928             OOTRACEINFO1("Receive Channel data type supported\n");
929             if(olc->forwardLogicalChannelParameters.multiplexParameters.t !=
930                T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
931             {
932                OOTRACEERR4("ERROR:Unknown multiplex parameter type for "
933                            "channel %d (%s, %s)\n", 
934                            olc->forwardLogicalChannelNumber, 
935                            pCall->callType, pCall->callToken);
936                memFreePtr(pCall->pctxt, epCap);
937                epCap = NULL;
938                continue;
939             }
940             h2250lcp = olc->forwardLogicalChannelParameters.multiplexParameters.u.h2250LogicalChannelParameters;
941
942             /* Check session is Not already established */
943             if(ooIsSessionEstablished(pCall, olc->forwardLogicalChannelParameters.multiplexParameters.u.h2250LogicalChannelParameters->sessionID, "receive"))
944             {
945
946                OOTRACEINFO4("Receive channel with sessionID %d already "
947                             "established.(%s, %s)\n", olc->forwardLogicalChannelParameters.multiplexParameters.u.h2250LogicalChannelParameters->sessionID, 
948                             pCall->callType, pCall->callToken);
949                memFreePtr(pCall->pctxt, epCap);
950                epCap = NULL;
951                continue;
952             }
953
954             /* Extract mediaControlChannel info, if supplied */
955             if(h2250lcp->m.mediaControlChannelPresent)
956             {
957                if(OO_OK != ooGetIpPortFromH245TransportAddress(pCall, 
958                                 &h2250lcp->mediaControlChannel, 
959                                 remoteMediaControlIP, &remoteMediaControlPort))
960                {
961                   OOTRACEERR3("Error: Invalid media control channel address "
962                               "(%s, %s)\n", pCall->callType, pCall->callToken);
963                   memFreePtr(pCall->pctxt, epCap);
964                   epCap = NULL;
965                   continue;
966                }
967             }
968          }
969          /* Check reverse logical channel */
970          else if(olc->m.reverseLogicalChannelParametersPresent)
971          {
972             /* Reverse channel - remote receives - local transmits */
973             OOTRACEDBGC4("Processing received reverse olc %d (%s, %s)\n", 
974                           olc->forwardLogicalChannelNumber, pCall->callType, 
975                           pCall->callToken);
976             dir = OOTX;
977             epCap = ooIsDataTypeSupported(pCall, 
978                                 &olc->reverseLogicalChannelParameters.dataType,
979                                 OOTX);
980
981             if(!epCap) { continue; } /* Capability not supported */
982
983             OOTRACEINFO1("Transmit Channel data type supported\n");
984
985             if(olc->reverseLogicalChannelParameters.multiplexParameters.t != 
986                T_H245OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
987             {
988                OOTRACEERR4("ERROR:Unknown multiplex parameter type for "
989                            "channel %d (%s, %s)\n", 
990                            olc->forwardLogicalChannelNumber, 
991                            pCall->callType, pCall->callToken);
992                memFreePtr(pCall->pctxt, epCap);
993                epCap = NULL;
994                continue;
995             }
996
997             /* Check session is not established */
998             if(ooIsSessionEstablished(pCall, olc->reverseLogicalChannelParameters.multiplexParameters.u.h2250LogicalChannelParameters->sessionID, "transmit"))
999             {
1000
1001                OOTRACEINFO4("Transmit session with sessionID %d already "
1002                             "established.(%s, %s)\n", olc->reverseLogicalChannelParameters.multiplexParameters.u.h2250LogicalChannelParameters->sessionID, pCall->callType, pCall->callToken);
1003
1004                memFreePtr(pCall->pctxt, epCap);
1005                epCap = NULL;
1006                continue;
1007             }
1008             
1009             /* Extract the remote media endpoint address */
1010             h2250lcp = olc->reverseLogicalChannelParameters.multiplexParameters.u.h2250LogicalChannelParameters;
1011             if(!h2250lcp)
1012             {
1013                OOTRACEERR3("ERROR:Invalid OLC received in fast start. No "
1014                            "reverse Logical Channel Parameters found. "
1015                            "(%s, %s)\n", pCall->callType, pCall->callToken);
1016                memFreePtr(pCall->pctxt, epCap);
1017                epCap = NULL;
1018                return OO_FAILED;
1019             }
1020             
1021             /* Reverse Channel info will be always present, crash proof */
1022             if(!h2250lcp->m.mediaChannelPresent)
1023             {
1024                OOTRACEERR3("ERROR:Invalid OLC received in fast start. No "
1025                            "reverse media channel information found. "
1026                            "(%s, %s)\n", pCall->callType, pCall->callToken);
1027                memFreePtr(pCall->pctxt, epCap);
1028                epCap = NULL;
1029                return OO_FAILED;
1030             }
1031
1032             /* Get IP, PORT of reverse channel */
1033             if(OO_OK != ooGetIpPortFromH245TransportAddress(pCall, 
1034                                 &h2250lcp->mediaChannel, 
1035                                 remoteMediaIP, &remoteMediaPort))
1036             {
1037                OOTRACEERR3("Error: Invalid media  channel address "
1038                            "(%s, %s)\n", pCall->callType, pCall->callToken);
1039                memFreePtr(pCall->pctxt, epCap);
1040                epCap = NULL;
1041                continue;
1042             }
1043
1044             /* Extract mediaControlChannel info, if supplied */
1045             if(h2250lcp->m.mediaControlChannelPresent)
1046             {
1047                if(OO_OK != ooGetIpPortFromH245TransportAddress(pCall, 
1048                                 &h2250lcp->mediaControlChannel, 
1049                                 remoteMediaControlIP, &remoteMediaControlPort))
1050                {
1051                   OOTRACEERR3("Error: Invalid media control channel address "
1052                               "(%s, %s)\n", pCall->callType, pCall->callToken);
1053                   memFreePtr(pCall->pctxt, epCap);
1054                   epCap = NULL;
1055                   continue;
1056                }
1057             }
1058          }
1059
1060          if(dir & OOTX)
1061          {  
1062             /* According to the spec if we are accepting olc for transmission
1063                from called endpoint to calling endpoint, called endpoint should
1064                insert a unqiue forwardLogicalChannelNumber into olc
1065             */
1066             olc->forwardLogicalChannelNumber =  pCall->logicalChanNoCur++;
1067             if(pCall->logicalChanNoCur > pCall->logicalChanNoMax)
1068                pCall->logicalChanNoCur = pCall->logicalChanNoBase;
1069          }
1070
1071          
1072          ooBuildFastStartOLC(pCall, olc, epCap, pctxt, dir);
1073          
1074          pChannel = ooFindLogicalChannelByLogicalChannelNo
1075                       (pCall, olc->forwardLogicalChannelNumber);
1076    
1077          /* start receive and tramsmit channel listening */
1078          if(dir & OORX)
1079          {
1080             strcpy(pChannel->remoteIP, remoteMediaControlIP);
1081             pChannel->remoteMediaControlPort = remoteMediaControlPort;
1082             if(epCap->startReceiveChannel)
1083             {   
1084                epCap->startReceiveChannel(pCall, pChannel);      
1085                OOTRACEINFO4("Receive channel of type %s started (%s, %s)\n", 
1086                         (epCap->capType == OO_CAP_TYPE_AUDIO)?"audio":"video",
1087                         pCall->callType, pCall->callToken);
1088             }
1089             else{
1090                OOTRACEERR4("ERROR:No callback registered to start receive %s"
1091                           " channel (%s, %s)\n", 
1092                         (epCap->capType == OO_CAP_TYPE_AUDIO)?"audio":"video", 
1093                            pCall->callType, pCall->callToken);
1094                return OO_FAILED;
1095             }
1096          }
1097          if(dir & OOTX)
1098          {
1099             pChannel->remoteMediaPort = remoteMediaPort;
1100             strcpy(pChannel->remoteIP, remoteMediaIP);
1101             pChannel->remoteMediaControlPort = remoteMediaControlPort;
1102
1103             if(epCap->startTransmitChannel)
1104             {   
1105                epCap->startTransmitChannel(pCall, pChannel);      
1106                OOTRACEINFO3("Transmit channel of type audio started "
1107                             "(%s, %s)\n", pCall->callType, pCall->callToken);
1108                /*OO_SETFLAG (pCall->flags, OO_M_AUDIO);*/
1109             }
1110             else{
1111                OOTRACEERR3("ERROR:No callback registered to start transmit"
1112                            " audio channel (%s, %s)\n", pCall->callType, 
1113                            pCall->callToken);
1114                return OO_FAILED;
1115             }
1116          }
1117
1118          /* Encode fast start element */
1119          setPERBuffer(pctxt, NULL, 0, 1);
1120          if(asn1PE_H245OpenLogicalChannel(pctxt, olc) != ASN_OK)
1121          {
1122             OOTRACEERR3("ERROR:Encoding of olc failed for faststart "
1123                         "(%s, %s)\n", pCall->callType, pCall->callToken);
1124             ooFreeQ931Message(pctxt, pQ931msg);
1125             if(pCall->callState < OO_CALL_CLEAR)
1126             {
1127                pCall->callEndReason = OO_REASON_LOCAL_CLEARED;
1128                pCall->callState = OO_CALL_CLEAR;
1129             }
1130             return OO_FAILED;
1131          }
1132          pFS[j].data = (unsigned char *) encodeGetMsgPtr(pctxt, (int *)&(pFS[j].numocts));
1133
1134
1135          /* start print call */
1136          setPERBuffer(pctxt,  (unsigned char*)pFS[j].data, pFS[j].numocts, 1);
1137          initializePrintHandler(&printHandler, "FastStart Element");
1138          setEventHandler (pctxt, &printHandler);
1139          memset(&printOlc, 0, sizeof(printOlc));
1140          ret = asn1PD_H245OpenLogicalChannel(pctxt, &(printOlc));
1141          if(ret != ASN_OK)
1142          {
1143             OOTRACEERR3("Error: Failed decoding FastStart Element (%s, %s)\n", 
1144                         pCall->callType, pCall->callToken);
1145             ooFreeQ931Message(pctxt, pQ931msg);
1146             if(pCall->callState < OO_CALL_CLEAR)
1147             {
1148                pCall->callEndReason = OO_REASON_LOCAL_CLEARED;
1149                pCall->callState = OO_CALL_CLEAR;
1150             }
1151             return OO_FAILED;
1152          }
1153          finishPrint();
1154          removeEventHandler(pctxt); 
1155          /* end print call */
1156
1157          olc = NULL;
1158          j++;
1159          epCap = NULL;
1160       }
1161       OOTRACEDBGA4("Added %d fast start elements to message "
1162                    "(%s, %s)\n",  j, pCall->callType, pCall->callToken);
1163       if(j != 0)
1164       {
1165          ASN1UINT k = 0;
1166          ASN1OCTET* pData;
1167          //*fsPresent = TRUE;
1168          *fsCount = j;
1169          *fsElem = pFS; 
1170
1171          /* save the fast start response for later use in ALERTING, CONNECT */
1172          pCall->pFastStartRes = (FastStartResponse*)
1173             memAlloc(pCall->pctxt, sizeof(FastStartResponse));
1174          pCall->pFastStartRes->n = j;
1175          pCall->pFastStartRes->elem = (ASN1DynOctStr*) memAlloc(pCall->pctxt, 
1176             pCall->pFastStartRes->n * sizeof(ASN1DynOctStr));
1177
1178          for(k = 0; k < pCall->pFastStartRes->n; k ++) {
1179             pCall->pFastStartRes->elem[k].numocts = (*fsElem)[k].numocts;
1180             pData = (ASN1OCTET*) memAlloc(pCall->pctxt, 
1181                pCall->pFastStartRes->elem[k].numocts * sizeof(ASN1OCTET));
1182             memcpy(pData, (*fsElem)[k].data, (*fsElem)[k].numocts);
1183             pCall->pFastStartRes->elem[k].data = pData;
1184          }
1185       }
1186       else{
1187          OOTRACEINFO3("None of the faststart elements received in setup can be"
1188                       " supported, rejecting faststart.(%s, %s)\n", 
1189                       pCall->callType, pCall->callToken);
1190          //*fsPresent = FALSE;
1191          OO_CLRFLAG(pCall->flags, OO_M_FASTSTART);
1192          OOTRACEDBGC3("Faststart for pCall is disabled by local endpoint."
1193                       "(%s, %s)\n", pCall->callType, pCall->callToken);
1194       }
1195    }
1196    return ASN_OK;
1197 }
1198
1199 /*
1200
1201 H225 CapSet/MS determination helper function
1202
1203 */
1204
1205 int ooSendTCSandMSD(OOH323CallData *call)
1206 {
1207         int ret;
1208         if(call->localTermCapState == OO_LocalTermCapExchange_Idle) {
1209                 ret = ooSendTermCapMsg(call);
1210                 if(ret != OO_OK) {
1211                         OOTRACEERR3("ERROR:Sending Terminal capability message (%s, %s)\n",
1212                                 call->callType, call->callToken);
1213                         return ret;
1214                 }
1215         }
1216         if(call->masterSlaveState == OO_MasterSlave_Idle) {
1217                 ret = ooSendMasterSlaveDetermination(call);
1218                 if(ret != OO_OK) {
1219                         OOTRACEERR3("ERROR:Sending Master-slave determination message "
1220                                 "(%s, %s)\n", call->callType, call->callToken);
1221                         return ret;
1222                 }
1223         }
1224
1225         return OO_OK;
1226 }
1227
1228
1229 /*
1230
1231 */
1232
1233 int ooSendCallProceeding(OOH323CallData *call)
1234 {
1235    int ret;    
1236    H225VendorIdentifier *vendor;
1237    H225CallProceeding_UUIE *callProceeding;
1238    Q931Message *q931msg=NULL;
1239    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
1240    OOCTXT *pctxt = call->msgctxt;
1241
1242    OOTRACEDBGC3("Building CallProceeding (%s, %s)\n", call->callType, 
1243                  call->callToken);
1244    ret = ooCreateQ931Message(pctxt, &q931msg, Q931CallProceedingMsg);
1245    if(ret != OO_OK)
1246    {      
1247       OOTRACEERR1("Error: In allocating memory for - H225 Call "
1248                            "Proceeding message\n");
1249       return OO_FAILED;
1250    }
1251    
1252    q931msg->callReference = call->callReference;
1253
1254    q931msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
1255                              sizeof(H225H323_UserInformation));
1256    if(!q931msg->userInfo)
1257    {
1258       OOTRACEERR1("ERROR:Memory - ooSendCallProceeding - userInfo\n");
1259       return OO_FAILED;
1260    }
1261    memset (q931msg->userInfo, 0, sizeof(H225H323_UserInformation));
1262    q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
1263    q931msg->userInfo->h323_uu_pdu.h245Tunneling = 
1264                                    OO_TESTFLAG(call->flags, OO_M_TUNNELING); 
1265    q931msg->userInfo->h323_uu_pdu.h323_message_body.t = 
1266          T_H225H323_UU_PDU_h323_message_body_callProceeding;
1267    
1268    callProceeding = (H225CallProceeding_UUIE*)memAlloc(pctxt,
1269                                              sizeof(H225CallProceeding_UUIE));
1270    if(!callProceeding)
1271    {
1272       OOTRACEERR1("ERROR:Memory - ooSendCallProceeding - callProceeding\n");
1273       return OO_FAILED;
1274    }
1275    memset(callProceeding, 0, sizeof(H225CallProceeding_UUIE));
1276    q931msg->userInfo->h323_uu_pdu.h323_message_body.u.callProceeding = callProceeding;
1277    callProceeding->m.multipleCallsPresent = 1;
1278    callProceeding->m.maintainConnectionPresent = 1;
1279    callProceeding->multipleCalls = FALSE;
1280    callProceeding->maintainConnection = FALSE;
1281
1282    callProceeding->m.callIdentifierPresent = 1;
1283    callProceeding->callIdentifier.guid.numocts = 
1284                                    call->callIdentifier.guid.numocts;
1285    memcpy(callProceeding->callIdentifier.guid.data, 
1286           call->callIdentifier.guid.data, 
1287           call->callIdentifier.guid.numocts);
1288    callProceeding->protocolIdentifier = gProtocolID;  
1289
1290    /* Pose as Terminal or Gateway */
1291    if(gH323ep.isGateway)
1292       callProceeding->destinationInfo.m.gatewayPresent = TRUE;
1293    else
1294       callProceeding->destinationInfo.m.terminalPresent = TRUE;
1295
1296    callProceeding->destinationInfo.m.vendorPresent = 1;
1297    vendor = &callProceeding->destinationInfo.vendor;
1298    if(gH323ep.productID)
1299    {
1300       vendor->m.productIdPresent = 1;
1301       vendor->productId.numocts = ASN1MIN(strlen(gH323ep.productID), 
1302                                     sizeof(vendor->productId.data));
1303       strncpy((char *)vendor->productId.data, gH323ep.productID, 
1304               vendor->productId.numocts);
1305    }
1306    if(gH323ep.versionID)
1307    {
1308       vendor->m.versionIdPresent = 1;
1309       vendor->versionId.numocts = ASN1MIN(strlen(gH323ep.versionID), 
1310                                      sizeof(vendor->versionId.data));
1311       strncpy((char *)vendor->versionId.data, gH323ep.versionID, 
1312               vendor->versionId.numocts); 
1313    }
1314
1315    vendor->vendor.t35CountryCode = gH323ep.t35CountryCode;
1316    vendor->vendor.t35Extension = gH323ep.t35Extension;
1317    vendor->vendor.manufacturerCode = gH323ep.manufacturerCode;
1318       
1319    OOTRACEDBGA3("Built Call Proceeding(%s, %s)\n", call->callType, 
1320                  call->callToken);   
1321    ret = ooSendH225Msg(call, q931msg);
1322    if(ret != OO_OK)
1323    {
1324       OOTRACEERR3("Error:Failed to enqueue CallProceeding message to outbound queue.(%s, %s)\n", call->callType, call->callToken);
1325    }
1326
1327    /* memReset(&gH323ep.msgctxt); */
1328    memReset(call->msgctxt);
1329
1330    return ret;
1331 }
1332
1333 int ooSendAlerting(OOH323CallData *call)
1334 {
1335    int ret;    
1336    H225Alerting_UUIE *alerting;
1337    H225VendorIdentifier *vendor;
1338    Q931Message *q931msg=NULL;
1339    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
1340    OOCTXT *pctxt = call->msgctxt;
1341
1342    ret = ooCreateQ931Message(pctxt, &q931msg, Q931AlertingMsg);
1343    if(ret != OO_OK)
1344    {      
1345       OOTRACEERR1("Error: In allocating memory for - H225 "
1346                   "Alerting message\n");
1347       return OO_FAILED;
1348    }
1349
1350    call->alertingTime = (H235TimeStamp) time(NULL);
1351
1352    q931msg->callReference = call->callReference;
1353
1354    q931msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
1355                              sizeof(H225H323_UserInformation));
1356    if(!q931msg->userInfo)
1357    {
1358       OOTRACEERR1("ERROR:Memory -  ooSendAlerting - userInfo\n");
1359       return OO_FAILED;
1360    }
1361    memset (q931msg->userInfo, 0, sizeof(H225H323_UserInformation));
1362    q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
1363    q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(call->flags, 
1364                                                               OO_M_TUNNELING); 
1365    q931msg->userInfo->h323_uu_pdu.h323_message_body.t = 
1366          T_H225H323_UU_PDU_h323_message_body_alerting;
1367    
1368    alerting = (H225Alerting_UUIE*)memAlloc(pctxt, 
1369                                              sizeof(H225Alerting_UUIE));
1370    if(!alerting)
1371    {
1372       OOTRACEERR1("ERROR:Memory -  ooSendAlerting - alerting\n");
1373       return OO_FAILED;
1374    }
1375    memset(alerting, 0, sizeof(H225Alerting_UUIE));
1376    q931msg->userInfo->h323_uu_pdu.h323_message_body.u.alerting = alerting;
1377    alerting->m.multipleCallsPresent = 1;
1378    alerting->m.maintainConnectionPresent = 1;
1379    alerting->multipleCalls = FALSE;
1380    alerting->maintainConnection = FALSE;
1381
1382    /*Populate aliases */
1383    alerting->m.alertingAddressPresent = TRUE;
1384    if(call->ourAliases)
1385       ret = ooPopulateAliasList(pctxt, call->ourAliases, 
1386                                        &alerting->alertingAddress, 0);
1387    else
1388       ret = ooPopulateAliasList(pctxt, gH323ep.aliases,
1389                                        &alerting->alertingAddress, 0);
1390    if(OO_OK != ret)
1391    {
1392       OOTRACEERR1("Error:Failed to populate alias list in Alert message\n");
1393       memReset(pctxt);
1394       return OO_FAILED;
1395    }
1396    alerting->m.presentationIndicatorPresent = TRUE;
1397    alerting->presentationIndicator.t = 
1398                              T_H225PresentationIndicator_presentationAllowed;
1399    alerting->m.screeningIndicatorPresent = TRUE;
1400    alerting->screeningIndicator = userProvidedNotScreened;
1401
1402
1403
1404    alerting->m.callIdentifierPresent = 1;
1405    alerting->callIdentifier.guid.numocts = 
1406                                    call->callIdentifier.guid.numocts;
1407    memcpy(alerting->callIdentifier.guid.data, 
1408           call->callIdentifier.guid.data, 
1409           call->callIdentifier.guid.numocts);
1410    alerting->protocolIdentifier = gProtocolID;  
1411
1412    /* Pose as Terminal or Gateway */
1413    if(gH323ep.isGateway)
1414       alerting->destinationInfo.m.gatewayPresent = TRUE;
1415    else
1416       alerting->destinationInfo.m.terminalPresent = TRUE;
1417
1418    alerting->destinationInfo.m.vendorPresent = 1;
1419    vendor = &alerting->destinationInfo.vendor;
1420    if(gH323ep.productID)
1421    {
1422       vendor->m.productIdPresent = 1;
1423       vendor->productId.numocts = ASN1MIN(strlen(gH323ep.productID), 
1424                                         sizeof(vendor->productId.data));
1425       strncpy((char *)vendor->productId.data, gH323ep.productID, 
1426                                         vendor->productId.numocts);
1427    }
1428    if(gH323ep.versionID)
1429    {
1430       vendor->m.versionIdPresent = 1;
1431       vendor->versionId.numocts = ASN1MIN(strlen(gH323ep.versionID), 
1432                                         sizeof(vendor->versionId.data));
1433       strncpy((char *)vendor->versionId.data, gH323ep.versionID, 
1434               vendor->versionId.numocts); 
1435    }
1436       
1437    vendor->vendor.t35CountryCode = gH323ep.t35CountryCode;
1438    vendor->vendor.t35Extension = gH323ep.t35Extension;
1439    vendor->vendor.manufacturerCode = gH323ep.manufacturerCode;
1440    
1441    if (!call->fsSent) {
1442     ret = ooSetFastStartResponse(call, q931msg, 
1443        &alerting->fastStart.n, &alerting->fastStart.elem);
1444     if(ret != ASN_OK) { return ret; }
1445     if(alerting->fastStart.n > 0) {
1446        alerting->m.fastStartPresent = TRUE;
1447        call->fsSent = TRUE;
1448     } else
1449       alerting->m.fastStartPresent = FALSE;
1450    } else {
1451       alerting->m.fastStartPresent = FALSE;
1452    }
1453
1454    OOTRACEDBGA3("Built Alerting (%s, %s)\n", call->callType, call->callToken);
1455    
1456    ret = ooSendH225Msg(call, q931msg);
1457    if(ret != OO_OK)
1458    {
1459       OOTRACEERR3("Error: Failed to enqueue Alerting message to outbound queue. (%s, %s)\n", call->callType, call->callToken);
1460    }
1461
1462    ooSendTCSandMSD(call);
1463    memReset (call->msgctxt);
1464
1465    return ret;
1466 }
1467
1468 int ooSendProgress(OOH323CallData *call)
1469 {
1470    int ret;    
1471    H225Progress_UUIE *progress;
1472    H225VendorIdentifier *vendor;
1473    Q931Message *q931msg=NULL;
1474    H225TransportAddress_ipAddress *h245IpAddr;
1475    OOCTXT *pctxt = call->msgctxt;
1476
1477    ret = ooCreateQ931Message(pctxt, &q931msg, Q931ProgressMsg);
1478    if(ret != OO_OK)
1479    {      
1480       OOTRACEERR1("Error: In allocating memory for - H225 "
1481                   "Alerting message\n");
1482       return OO_FAILED;
1483    }
1484
1485    q931msg->callReference = call->callReference;
1486
1487    q931msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
1488                              sizeof(H225H323_UserInformation));
1489    if(!q931msg->userInfo)
1490    {
1491       OOTRACEERR1("ERROR:Memory -  ooSendAlerting - userInfo\n");
1492       return OO_FAILED;
1493    }
1494    memset (q931msg->userInfo, 0, sizeof(H225H323_UserInformation));
1495    q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
1496    q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(call->flags, 
1497                                                               OO_M_TUNNELING); 
1498    q931msg->userInfo->h323_uu_pdu.h323_message_body.t = 
1499          T_H225H323_UU_PDU_h323_message_body_progress;
1500    
1501    progress = (H225Progress_UUIE*)memAlloc(pctxt, 
1502                                              sizeof(H225Progress_UUIE));
1503    if(!progress)
1504    {
1505       OOTRACEERR1("ERROR:Memory -  ooSendProgress- alerting\n");
1506       return OO_FAILED;
1507    }
1508    memset(progress, 0, sizeof(H225Progress_UUIE));
1509    q931msg->userInfo->h323_uu_pdu.h323_message_body.u.progress = progress;
1510    progress->m.multipleCallsPresent = 1;
1511    progress->m.maintainConnectionPresent = 1;
1512    progress->multipleCalls = FALSE;
1513    progress->maintainConnection = FALSE;
1514
1515    progress->callIdentifier.guid.numocts = 
1516                                    call->callIdentifier.guid.numocts;
1517    memcpy(progress->callIdentifier.guid.data, 
1518           call->callIdentifier.guid.data, 
1519           call->callIdentifier.guid.numocts);
1520    progress->protocolIdentifier = gProtocolID;  
1521
1522    /* Pose as Terminal or Gateway */
1523    if(gH323ep.isGateway)
1524       progress->destinationInfo.m.gatewayPresent = TRUE;
1525    else
1526       progress->destinationInfo.m.terminalPresent = TRUE;
1527
1528    progress->destinationInfo.m.vendorPresent = 1;
1529    vendor = &progress->destinationInfo.vendor;
1530    if(gH323ep.productID)
1531    {
1532       vendor->m.productIdPresent = 1;
1533       vendor->productId.numocts = ASN1MIN(strlen(gH323ep.productID), 
1534                                         sizeof(vendor->productId.data));
1535       strncpy((char *)vendor->productId.data, gH323ep.productID, 
1536                                         vendor->productId.numocts);
1537    }
1538    if(gH323ep.versionID)
1539    {
1540       vendor->m.versionIdPresent = 1;
1541       vendor->versionId.numocts = ASN1MIN(strlen(gH323ep.versionID), 
1542                                         sizeof(vendor->versionId.data));
1543       strncpy((char *)vendor->versionId.data, gH323ep.versionID, 
1544               vendor->versionId.numocts); 
1545    }
1546       
1547    vendor->vendor.t35CountryCode = gH323ep.t35CountryCode;
1548    vendor->vendor.t35Extension = gH323ep.t35Extension;
1549    vendor->vendor.manufacturerCode = gH323ep.manufacturerCode;
1550    
1551    if (!call->fsSent) {
1552     ret = ooSetFastStartResponse(call, q931msg, 
1553        &progress->fastStart.n, &progress->fastStart.elem);
1554     if(ret != ASN_OK) { return ret; }
1555     if(progress->fastStart.n > 0) {
1556        progress->m.fastStartPresent = TRUE;
1557        call->fsSent = TRUE;
1558     } else
1559       progress->m.fastStartPresent = FALSE;
1560    } else {
1561       progress->m.fastStartPresent = FALSE;
1562    }
1563
1564    /* Add h245 listener address. Do not add H245 listener address in case
1565       of tunneling. */
1566    if (/* (!OO_TESTFLAG(call->flags, OO_M_FASTSTART) || 
1567         call->remoteFastStartOLCs.count == 0) && */
1568        !OO_TESTFLAG (call->flags, OO_M_TUNNELING) &&
1569        !call->h245listener && ooCreateH245Listener(call) == OO_OK)
1570    {
1571       progress->m.h245AddressPresent = TRUE;
1572       progress->h245Address.t = T_H225TransportAddress_ipAddress;
1573    
1574       h245IpAddr = (H225TransportAddress_ipAddress*)
1575          memAllocZ (pctxt, sizeof(H225TransportAddress_ipAddress));
1576       if(!h245IpAddr)
1577       {
1578          OOTRACEERR3("Error:Memory - ooAcceptCall - h245IpAddr"
1579                      "(%s, %s)\n", call->callType, call->callToken);
1580          return OO_FAILED;
1581       }
1582       ooSocketConvertIpToNwAddr(call->localIP, h245IpAddr->ip.data);
1583       h245IpAddr->ip.numocts=4;
1584       h245IpAddr->port = *(call->h245listenport);
1585       progress->h245Address.u.ipAddress = h245IpAddr;
1586    }
1587
1588    OOTRACEDBGA3("Built Progress (%s, %s)\n", call->callType, call->callToken);
1589    
1590    ret = ooSendH225Msg(call, q931msg);
1591    if(ret != OO_OK)
1592    {
1593       OOTRACEERR3("Error: Failed to enqueue Alerting message to outbound queue. (%s, %s)\n", call->callType, call->callToken);
1594    }
1595
1596    ooSendTCSandMSD(call);
1597    memReset (call->msgctxt);
1598
1599    return ret;
1600 }
1601
1602
1603 int ooSendStartH245Facility(OOH323CallData *call)
1604 {
1605    int ret=0;
1606    Q931Message *pQ931Msg = NULL;
1607    H225Facility_UUIE *facility=NULL;
1608    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
1609    OOCTXT *pctxt = call->msgctxt;
1610    H225TransportAddress_ipAddress *h245IpAddr;
1611
1612    OOTRACEDBGA3("Building Facility message (%s, %s)\n", call->callType,
1613                  call->callToken);
1614    ret = ooCreateQ931Message(pctxt, &pQ931Msg, Q931FacilityMsg);
1615    if(ret != OO_OK)
1616    {
1617       OOTRACEERR3
1618          ("ERROR: In allocating memory for facility message (%s, %s)\n",
1619           call->callType, call->callToken);
1620       return OO_FAILED;
1621    }
1622
1623    pQ931Msg->callReference = call->callReference;
1624
1625    pQ931Msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
1626                              sizeof(H225H323_UserInformation));
1627    if(!pQ931Msg->userInfo)
1628    {
1629       OOTRACEERR3("ERROR:Memory - ooSendFacility - userInfo(%s, %s)\n", 
1630                    call->callType, call->callToken);
1631       return OO_FAILED;
1632    }
1633    memset (pQ931Msg->userInfo, 0, sizeof(H225H323_UserInformation));
1634    pQ931Msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
1635
1636    pQ931Msg->userInfo->h323_uu_pdu.h245Tunneling = 
1637       OO_TESTFLAG (call->flags, OO_M_TUNNELING); 
1638
1639    pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.t = 
1640       T_H225H323_UU_PDU_h323_message_body_facility;
1641    
1642    facility = (H225Facility_UUIE*) 
1643       memAllocZ (pctxt, sizeof(H225Facility_UUIE));
1644
1645    if(!facility)
1646    {
1647       OOTRACEERR3("ERROR:Memory - ooSendFacility - facility (%s, %s)"
1648                   "\n", call->callType, call->callToken);
1649       return OO_FAILED;
1650    }
1651
1652    pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.u.facility = facility;
1653
1654    /* Populate Facility UUIE */
1655    facility->protocolIdentifier = gProtocolID;  
1656    facility->m.callIdentifierPresent = 1;
1657    facility->callIdentifier.guid.numocts = 
1658                                    call->callIdentifier.guid.numocts;
1659    memcpy(facility->callIdentifier.guid.data, 
1660           call->callIdentifier.guid.data, 
1661           call->callIdentifier.guid.numocts);
1662    facility->reason.t = T_H225FacilityReason_startH245;
1663
1664    if (!call->h245listener && ooCreateH245Listener(call) != OO_OK) {
1665         OOTRACEERR3("Error:No H245Listener, can't send startH245 facility (%s, %s)\n",
1666                     call->callType, call->callToken);
1667         return OO_FAILED;
1668    }
1669
1670    facility->m.h245AddressPresent = TRUE;
1671    facility->h245Address.t = T_H225TransportAddress_ipAddress;
1672
1673    h245IpAddr = (H225TransportAddress_ipAddress*)
1674         memAllocZ (pctxt, sizeof(H225TransportAddress_ipAddress));
1675    if(!h245IpAddr) {
1676          OOTRACEERR3("Error:Memory - ooSendFacility - h245IpAddr"
1677                      "(%s, %s)\n", call->callType, call->callToken);
1678          return OO_FAILED;
1679    }
1680    ooSocketConvertIpToNwAddr(call->localIP, h245IpAddr->ip.data);
1681    h245IpAddr->ip.numocts=4;
1682    h245IpAddr->port = *(call->h245listenport);
1683    facility->h245Address.u.ipAddress = h245IpAddr;
1684
1685    OOTRACEDBGA3("Built Facility message to send (%s, %s)\n", call->callType,
1686                  call->callToken);
1687
1688    ret = ooSendH225Msg(call, pQ931Msg);
1689    if(ret != OO_OK)
1690    {
1691       OOTRACEERR3
1692          ("Error:Failed to enqueue Facility message to outbound "
1693          "queue.(%s, %s)\n", call->callType, call->callToken);
1694    }
1695    /* memReset (&gH323ep.msgctxt); */
1696    memReset (call->msgctxt);
1697    return ret;
1698 }
1699
1700 int ooSendReleaseComplete(OOH323CallData *call)
1701 {
1702    int ret;   
1703    Q931Message *q931msg=NULL;
1704    H225ReleaseComplete_UUIE *releaseComplete;
1705    enum Q931CauseValues cause = Q931ErrorInCauseIE;
1706    unsigned h225ReasonCode = T_H225ReleaseCompleteReason_undefinedReason;
1707
1708    /* OOCTXT *pctxt = &gH323ep.msgctxt;    */
1709    OOCTXT *pctxt = call->msgctxt;
1710    OOTRACEDBGA3("Building Release Complete message to send(%s, %s)\n",
1711                 call->callType, call->callToken);
1712    ret = ooCreateQ931Message(pctxt, &q931msg, Q931ReleaseCompleteMsg);
1713    if(ret != OO_OK)
1714    {      
1715       OOTRACEERR3("Error: In ooCreateQ931Message - H225 Release Complete "
1716                   "message(%s, %s)\n", call->callType, call->callToken);
1717       if(call->callState < OO_CALL_CLEAR)
1718       {
1719          call->callEndReason = OO_REASON_LOCAL_CLEARED;
1720          call->callState = OO_CALL_CLEAR;
1721       }
1722       return OO_FAILED;
1723    }
1724
1725    q931msg->callReference = call->callReference;
1726
1727    q931msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
1728                              sizeof(H225H323_UserInformation));
1729    if(!q931msg->userInfo)
1730    {
1731       OOTRACEERR1("ERROR:Memory - ooSendReleaseComplete - userInfo\n");
1732       return OO_FAILED;
1733    }
1734    memset (q931msg->userInfo, 0, sizeof(H225H323_UserInformation));
1735
1736    releaseComplete = (H225ReleaseComplete_UUIE*)memAlloc(pctxt,
1737                                              sizeof(H225ReleaseComplete_UUIE));
1738    if(!releaseComplete)
1739    {
1740       OOTRACEERR3("Error:Memory - ooSendReleaseComplete - releaseComplete"
1741                   "(%s, %s)\n", call->callType, call->callToken);
1742       return OO_FAILED;
1743    }
1744    memset(releaseComplete, 0, sizeof(H225ReleaseComplete_UUIE));
1745    q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
1746    q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(call->flags, 
1747                                                               OO_M_TUNNELING); 
1748    q931msg->userInfo->h323_uu_pdu.h323_message_body.t = 
1749          T_H225H323_UU_PDU_h323_message_body_releaseComplete;
1750    
1751    /* Get cause value and h225 reason code corresponding to OOCallClearReason*/
1752    ooQ931GetCauseAndReasonCodeFromCallClearReason(call->callEndReason, 
1753                                                      &cause, &h225ReasonCode);
1754    if (call->q931cause == 0)
1755         call->q931cause = cause;
1756    /* Set Cause IE */
1757    ooQ931SetCauseIE(pctxt, q931msg, call->q931cause, 0, 0);
1758    
1759    /* Set H225 releaseComplete reasonCode */
1760    releaseComplete->m.reasonPresent = TRUE;
1761    releaseComplete->reason.t = h225ReasonCode;
1762
1763    /* Add user-user ie */
1764    q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=TRUE; 
1765    q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG (call->flags, OO_M_TUNNELING);
1766    q931msg->userInfo->h323_uu_pdu.h323_message_body.t = 
1767            T_H225H323_UU_PDU_h323_message_body_releaseComplete;
1768    
1769    q931msg->userInfo->h323_uu_pdu.h323_message_body.u.releaseComplete = 
1770                                                              releaseComplete;
1771    releaseComplete->m.callIdentifierPresent = 1;
1772    releaseComplete->protocolIdentifier = gProtocolID;
1773    releaseComplete->callIdentifier.guid.numocts = 
1774            call->callIdentifier.guid.numocts;
1775    memcpy(releaseComplete->callIdentifier.guid.data, 
1776                                   call->callIdentifier.guid.data,
1777                                   call->callIdentifier.guid.numocts);
1778
1779    OOTRACEDBGA3("Built Release Complete message (%s, %s)\n",
1780                 call->callType, call->callToken);
1781    /* Send H225 message */   
1782    ret = ooSendH225Msg(call, q931msg);
1783    if(ret != OO_OK)
1784    {
1785       OOTRACEERR3("Error:Failed to enqueue ReleaseComplete message to outbound"
1786                   " queue.(%s, %s)\n", call->callType, call->callToken);
1787    }
1788    /* memReset(&gH323ep.msgctxt); */
1789    memReset(call->msgctxt);
1790
1791    return ret;
1792 }
1793
1794 int ooSendConnect(OOH323CallData *call)
1795 {
1796
1797   call->connectTime = (H235TimeStamp) time(NULL);
1798
1799   if(gH323ep.gkClient && !OO_TESTFLAG(call->flags, OO_M_DISABLEGK)) {
1800      if(gH323ep.gkClient->state == GkClientRegistered) {
1801           ooGkClientSendIRR(gH323ep.gkClient, call);
1802      }
1803   }
1804
1805    ooAcceptCall(call);
1806    return OO_OK;
1807 }
1808
1809 /*TODO: Need to clean logical channel in case of failure after creating one */
1810 int ooAcceptCall(OOH323CallData *call)
1811 {
1812    int ret = 0, i=0;
1813    H225Connect_UUIE *connect;
1814    H225TransportAddress_ipAddress *h245IpAddr;
1815    H225VendorIdentifier *vendor;
1816    Q931Message *q931msg=NULL;
1817    /* OOCTXT *pctxt = &gH323ep.msgctxt;   */
1818    OOCTXT *pctxt = call->msgctxt;   
1819
1820    ret = ooCreateQ931Message(pctxt, &q931msg, Q931ConnectMsg);
1821    if(ret != OO_OK)
1822    {      
1823       OOTRACEERR1("Error: In allocating memory for - H225 "
1824                   "Connect message\n");
1825       return OO_FAILED;
1826    }
1827    q931msg->callReference = call->callReference;
1828
1829    /* Set bearer capability */
1830    if(OO_OK != ooSetBearerCapabilityIE(pctxt, q931msg, Q931CCITTStd, 
1831      //                  Q931TransferUnrestrictedDigital, Q931TransferPacketMode,
1832      //                  Q931TransferRatePacketMode, Q931UserInfoLayer1G722G725))
1833                                Q931TransferSpeech, Q931TransferCircuitMode,
1834                         Q931TransferRate64Kbps, Q931UserInfoLayer1G711ALaw))
1835    {
1836       OOTRACEERR3("Error: Failed to set bearer capability ie. (%s, %s)\n",
1837                    call->callType, call->callToken);
1838       return OO_FAILED;
1839    }
1840
1841    q931msg->userInfo = (H225H323_UserInformation*)
1842       memAllocZ (pctxt,sizeof(H225H323_UserInformation));
1843
1844    if(!q931msg->userInfo)
1845    {
1846       OOTRACEERR1("ERROR:Memory - ooAcceptCall - userInfo\n");
1847       return OO_FAILED;
1848    }   
1849
1850    q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=TRUE; 
1851
1852    q931msg->userInfo->h323_uu_pdu.h245Tunneling = 
1853       OO_TESTFLAG (call->flags, OO_M_TUNNELING); 
1854
1855    q931msg->userInfo->h323_uu_pdu.h323_message_body.t = 
1856       T_H225H323_UU_PDU_h323_message_body_connect;
1857    
1858    connect = (H225Connect_UUIE*)
1859       memAllocZ (pctxt, sizeof(H225Connect_UUIE));
1860
1861    if(!connect)
1862    {
1863       OOTRACEERR1("ERROR:Memory - ooAcceptCall - connect\n");
1864       return OO_FAILED;
1865    }
1866
1867    q931msg->userInfo->h323_uu_pdu.h323_message_body.u.connect = connect;
1868    connect->m.fastStartPresent = 0;
1869    connect->m.multipleCallsPresent = 1;
1870    connect->m.maintainConnectionPresent = 1;
1871    connect->multipleCalls = FALSE;
1872    connect->maintainConnection = FALSE;
1873    
1874    
1875    connect->conferenceID.numocts = 16;
1876    for (i = 0; i < 16; i++)
1877       connect->conferenceID.data[i] = i + 1;
1878
1879    connect->m.callIdentifierPresent = 1;
1880    connect->callIdentifier.guid.numocts = 
1881                                  call->callIdentifier.guid.numocts;
1882    memcpy(connect->callIdentifier.guid.data, call->callIdentifier.guid.data, 
1883                                          call->callIdentifier.guid.numocts);
1884    
1885    connect->conferenceID.numocts = call->confIdentifier.numocts;
1886    memcpy(connect->conferenceID.data, call->confIdentifier.data,
1887           call->confIdentifier.numocts);
1888    /* Populate alias addresses */
1889    connect->m.connectedAddressPresent = TRUE;
1890    if(call->ourAliases)
1891       ret = ooPopulateAliasList(pctxt, call->ourAliases, 
1892                                       &connect->connectedAddress, 0);
1893    else
1894       ret =  ooPopulateAliasList(pctxt, gH323ep.aliases, 
1895                                         &connect->connectedAddress, 0);
1896    if(OO_OK != ret)
1897    {
1898       OOTRACEERR1("Error:Failed to populate alias list in Connect message\n");
1899       memReset(pctxt);
1900       return OO_FAILED;
1901    }
1902    connect->m.presentationIndicatorPresent = TRUE;
1903    connect->presentationIndicator.t = 
1904                              T_H225PresentationIndicator_presentationAllowed;
1905    connect->m.screeningIndicatorPresent = TRUE;
1906    connect->screeningIndicator = userProvidedNotScreened;
1907
1908    connect->protocolIdentifier = gProtocolID;  
1909
1910    /* Pose as Terminal or Gateway */
1911    if(gH323ep.isGateway)
1912       connect->destinationInfo.m.gatewayPresent = TRUE;
1913    else
1914       connect->destinationInfo.m.terminalPresent = TRUE;
1915
1916    
1917    connect->destinationInfo.m.vendorPresent = 1;
1918    vendor = &connect->destinationInfo.vendor;
1919       
1920    vendor->vendor.t35CountryCode = gH323ep.t35CountryCode;
1921    vendor->vendor.t35Extension = gH323ep.t35Extension;
1922    vendor->vendor.manufacturerCode = gH323ep.manufacturerCode;
1923    if(gH323ep.productID)
1924    {
1925       vendor->m.productIdPresent = 1;
1926       vendor->productId.numocts = ASN1MIN(strlen(gH323ep.productID), 
1927                                             sizeof(vendor->productId.data));
1928       strncpy((char *)vendor->productId.data, gH323ep.productID, 
1929                                                    vendor->productId.numocts);
1930    }
1931    if(gH323ep.versionID)
1932    {
1933       vendor->m.versionIdPresent = 1;
1934       vendor->versionId.numocts = ASN1MIN(strlen(gH323ep.versionID), 
1935                                            sizeof(vendor->versionId.data));
1936       strncpy((char *)vendor->versionId.data, gH323ep.versionID, 
1937                                                    vendor->versionId.numocts); 
1938    }
1939
1940    if (!call->fsSent) {
1941     ret = ooSetFastStartResponse(call, q931msg, 
1942        &connect->fastStart.n, &connect->fastStart.elem);
1943     if(ret != ASN_OK) { return ret; }
1944     if(connect->fastStart.n > 0) {
1945        connect->m.fastStartPresent = TRUE;
1946        call->fsSent = TRUE;
1947     } else
1948       connect->m.fastStartPresent = FALSE;
1949    } else {
1950       connect->m.fastStartPresent = FALSE;
1951    }
1952
1953    /* free the stored fast start response */
1954    if(call->pFastStartRes) {
1955       int k;
1956       for(k = 0; k < call->pFastStartRes->n; k ++) {
1957          memFreePtr(call->pctxt, call->pFastStartRes->elem[k].data);
1958       }
1959       memFreePtr(call->pctxt, call->pFastStartRes->elem);
1960       memFreePtr(call->pctxt, call->pFastStartRes);
1961       call->pFastStartRes = NULL;
1962    }
1963
1964
1965    /* Add h245 listener address. Do not add H245 listener address in case
1966       of fast-start. */
1967    if (/* (!OO_TESTFLAG(call->flags, OO_M_FASTSTART) || 
1968         call->remoteFastStartOLCs.count == 0) && */
1969        !OO_TESTFLAG (call->flags, OO_M_TUNNELING) &&
1970        !call->h245listener && ooCreateH245Listener(call) == OO_OK)
1971    {
1972       connect->m.h245AddressPresent = TRUE;
1973       connect->h245Address.t = T_H225TransportAddress_ipAddress;
1974    
1975       h245IpAddr = (H225TransportAddress_ipAddress*)
1976          memAllocZ (pctxt, sizeof(H225TransportAddress_ipAddress));
1977       if(!h245IpAddr)
1978       {
1979          OOTRACEERR3("Error:Memory - ooAcceptCall - h245IpAddr"
1980                      "(%s, %s)\n", call->callType, call->callToken);
1981          return OO_FAILED;
1982       }
1983       ooSocketConvertIpToNwAddr(call->localIP, h245IpAddr->ip.data);
1984       h245IpAddr->ip.numocts=4;
1985       h245IpAddr->port = *(call->h245listenport);
1986       connect->h245Address.u.ipAddress = h245IpAddr;
1987    }
1988
1989    OOTRACEDBGA3("Built H.225 Connect message (%s, %s)\n", call->callType,
1990                  call->callToken);
1991
1992    /* H225 message callback */
1993    if(gH323ep.h225Callbacks.onBuiltConnect)
1994       gH323ep.h225Callbacks.onBuiltConnect(call, q931msg);
1995
1996    ret=ooSendH225Msg(call, q931msg);
1997    if(ret != OO_OK)
1998    {
1999       OOTRACEERR3("Error:Failed to enqueue Connect message to outbound queue.(%s, %s)\n", call->callType, call->callToken);
2000       /* memReset(&gH323ep.msgctxt);*/
2001       memReset(call->msgctxt);
2002       return OO_FAILED;
2003    }
2004    /* memReset(&gH323ep.msgctxt); */
2005    memReset(call->msgctxt);
2006
2007    call->callState = OO_CALL_CONNECTED;
2008    
2009    if (call->rtdrCount > 0 && call->rtdrInterval > 0) {
2010         return ooSendRoundTripDelayRequest(call);
2011    }
2012    return OO_OK;
2013 }
2014
2015 int ooH323HandleCallFwdRequest(OOH323CallData *call)
2016 {
2017    OOH323CallData *fwdedCall=NULL;
2018    OOCTXT *pctxt;
2019    ooAliases *pNewAlias=NULL, *alias=NULL;
2020    struct timespec ts;
2021    struct timeval tv;
2022    int i=0, irand=0, ret = OO_OK;
2023    /* Note: We keep same callToken, for new call which is going
2024       to replace an existing call, thus treating it as a single call.*/
2025
2026    fwdedCall = ooCreateCall("outgoing", call->callToken);
2027
2028    pctxt = fwdedCall->pctxt;
2029
2030    /* Retrieve new destination info from original call */
2031    if(!ooUtilsIsStrEmpty(call->pCallFwdData->ip))
2032    {
2033       strcpy(fwdedCall->remoteIP, call->pCallFwdData->ip);
2034    }
2035    fwdedCall->remotePort = call->pCallFwdData->port;
2036    
2037    if(call->pCallFwdData->aliases)
2038    {
2039       alias = call->pCallFwdData->aliases;
2040       while(alias)
2041       {
2042          pNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases));
2043          pNewAlias->value = (char*) memAlloc(pctxt, strlen(alias->value)+1);
2044          if(!pNewAlias || !pNewAlias->value)
2045          {
2046             OOTRACEERR3("Error:Memory - ooH323HandleCallFwdRequest - "
2047                         "pNewAlias/pNewAlias->value"
2048                         "(%s, %s)\n", call->callType, call->callToken);
2049             ooCleanCall(fwdedCall);
2050             return OO_FAILED;
2051          }
2052          pNewAlias->type = alias->type;
2053          strcpy(pNewAlias->value, alias->value);
2054          pNewAlias->next = fwdedCall->remoteAliases;
2055          fwdedCall->remoteAliases = pNewAlias;
2056          alias = alias->next;
2057          pNewAlias = NULL;
2058       }
2059    }
2060
2061    fwdedCall->callReference = ooGenerateCallReference();
2062    ooGenerateCallIdentifier(&fwdedCall->callIdentifier);
2063    fwdedCall->confIdentifier.numocts = 16;
2064    irand = rand();
2065    for (i = 0; i < 16; i++) {
2066       fwdedCall->confIdentifier.data[i] = irand++;
2067    }
2068       
2069
2070    if(gH323ep.gkClient && !OO_TESTFLAG(fwdedCall->flags, OO_M_DISABLEGK))
2071    {
2072      /* No need to check registration status here as it is already checked for
2073         MakeCall command */
2074       ret = ooGkClientSendAdmissionRequest(gH323ep.gkClient, fwdedCall, FALSE);
2075       fwdedCall->callState = OO_CALL_WAITING_ADMISSION;
2076       ast_mutex_lock(&fwdedCall->Lock);
2077           tv = ast_tvnow();
2078       ts.tv_sec += tv.tv_sec + 24;
2079           ts.tv_nsec = tv.tv_usec * 1000;
2080       ast_cond_timedwait(&fwdedCall->gkWait, &fwdedCall->Lock, &ts);
2081       if (fwdedCall->callState == OO_CALL_WAITING_ADMISSION) /* GK is not responding */
2082           fwdedCall->callState = OO_CALL_CLEAR;
2083       ast_mutex_unlock(&fwdedCall->Lock);
2084
2085    }
2086    if (fwdedCall->callState < OO_CALL_CLEAR) {
2087       ast_mutex_lock(&fwdedCall->Lock);
2088       ret = ooH323CallAdmitted (fwdedCall);
2089       ast_mutex_unlock(&fwdedCall->Lock);
2090    }
2091
2092    return OO_OK;
2093
2094 }
2095
2096 int ooH323NewCall(char *callToken) {
2097    OOH323CallData* call;
2098    if(!callToken)
2099    {
2100       OOTRACEERR1("ERROR: Invalid callToken parameter to make call\n");
2101       return OO_FAILED;
2102    }
2103    call = ooCreateCall("outgoing", callToken);
2104    if (!call)
2105    {
2106       OOTRACEERR1("ERROR: Can't create call %s\n");
2107       return OO_FAILED;
2108    }
2109
2110    return OO_OK;
2111 }
2112
2113 int ooH323MakeCall(char *dest, char *callToken, ooCallOptions *opts)
2114 {
2115    OOCTXT *pctxt;
2116    OOH323CallData *call;
2117    int ret=OO_OK, i=0, irand=0;
2118    char tmp[30]="\0";
2119    char *ip=NULL, *port = NULL;
2120    struct timeval tv;
2121    struct timespec ts;
2122
2123    if(!dest)
2124    {
2125       OOTRACEERR1("ERROR:Invalid destination for new call\n");
2126       return OO_FAILED;
2127    }
2128    if(!callToken)
2129    {
2130       OOTRACEERR1("ERROR: Invalid callToken parameter to make call\n");
2131       return OO_FAILED;
2132    }
2133
2134    /* call = ooCreateCall("outgoing", callToken); */
2135    call = ooFindCallByToken(callToken);
2136    if (!call)
2137    {
2138       OOTRACEERR1("ERROR: Can't create call %s\n");
2139       return OO_FAILED;
2140    }
2141
2142    pctxt = call->pctxt;
2143    if(opts)
2144    {
2145       if(opts->fastStart)
2146          OO_SETFLAG(call->flags, OO_M_FASTSTART);
2147       else
2148          OO_CLRFLAG(call->flags, OO_M_FASTSTART);
2149
2150       if(opts->tunneling)
2151          OO_SETFLAG(call->flags, OO_M_TUNNELING);
2152       else
2153          OO_CLRFLAG(call->flags, OO_M_TUNNELING);
2154
2155       if(opts->disableGk)
2156          OO_SETFLAG(call->flags, OO_M_DISABLEGK);
2157       else
2158          OO_CLRFLAG(call->flags, OO_M_DISABLEGK);
2159
2160       call->callMode = opts->callMode;
2161       call->transfercap = opts->transfercap;
2162    }
2163
2164
2165    ret = ooParseDestination(call, dest, tmp, 24, &call->remoteAliases);
2166    if(ret != OO_OK)
2167    {
2168       OOTRACEERR2("Error: Failed to parse the destination string %s for "
2169                   "new call\n", dest);
2170       ooCleanCall(call);
2171       return OO_FAILED;
2172    }
2173    
2174    /* Check whether we have ip address */
2175    if(!ooUtilsIsStrEmpty(tmp)) {
2176       ip = tmp;
2177       port = strchr(tmp, ':');
2178       *port = '\0';
2179       port++;
2180       strcpy(call->remoteIP, ip);
2181       call->remotePort = atoi(port);
2182    }
2183
2184    strcpy(callToken, call->callToken);
2185    call->callReference = ooGenerateCallReference();
2186    ooGenerateCallIdentifier(&call->callIdentifier);
2187    call->confIdentifier.numocts = 16;
2188    irand = rand();
2189    for (i = 0; i < 16; i++) {
2190       call->confIdentifier.data[i] = irand++;
2191    }
2192       
2193
2194    if(gH323ep.gkClient && !OO_TESTFLAG(call->flags, OO_M_DISABLEGK))
2195    {
2196      /* No need to check registration status here as it is already checked for
2197         MakeCall command */
2198
2199      call->callState = OO_CALL_WAITING_ADMISSION;
2200      ast_mutex_lock(&call->Lock);
2201      ret = ooGkClientSendAdmissionRequest(gH323ep.gkClient, call, FALSE);
2202          tv = ast_tvnow();
2203      ts.tv_sec = tv.tv_sec + 24;
2204          ts.tv_nsec = tv.tv_usec * 1000;
2205      ast_cond_timedwait(&call->gkWait, &call->Lock, &ts);
2206      if (call->callState == OO_CALL_WAITING_ADMISSION)
2207                 call->callState = OO_CALL_CLEAR;
2208      ast_mutex_unlock(&call->Lock);
2209
2210    }
2211
2212    /* Send as H225 message to calling endpoint */
2213    ast_mutex_lock(&call->Lock);
2214    if (call->callState < OO_CALL_CLEAR) {
2215     if ((ret = ooH323CallAdmitted (call)) != OO_OK) {
2216      ast_mutex_unlock(&call->Lock);
2217      return ret;
2218     }
2219    } else ret = OO_FAILED;
2220    ast_mutex_unlock(&call->Lock);
2221
2222    return ret;
2223 }
2224
2225
2226 int ooH323CallAdmitted(OOH323CallData *call)
2227 {
2228    int ret=0;
2229       
2230    if(!call)
2231    {
2232       /* Call not supplied. Must locate it in list */
2233       OOTRACEERR1("ERROR: Invalid call parameter to ooH323CallAdmitted");
2234       return OO_FAILED; 
2235    }
2236
2237    if(!strcmp(call->callType, "outgoing")) {
2238       ret = ooCreateH225Connection(call);
2239       if(ret != OO_OK)
2240       {
2241          OOTRACEERR3("ERROR:Failed to create H225 connection to %s:%d\n", 
2242                       call->remoteIP, call->remotePort);
2243          if(call->callState< OO_CALL_CLEAR)
2244          {
2245             call->callState = OO_CALL_CLEAR;
2246             call->callEndReason = OO_REASON_UNKNOWN;
2247          }
2248          return OO_FAILED;
2249       }
2250
2251       if(gH323ep.h323Callbacks.onOutgoingCall) {
2252          /* Outgoing call callback function */
2253          gH323ep.h323Callbacks.onOutgoingCall(call);
2254       }
2255       
2256       ret = ooH323MakeCall_helper(call);
2257    } 
2258    else { 
2259       /* incoming call */
2260       if(gH323ep.h323Callbacks.onIncomingCall) {
2261          /* Incoming call callback function */
2262          gH323ep.h323Callbacks.onIncomingCall(call);
2263       }
2264
2265       /* Check for manual ringback generation */
2266       if(!OO_TESTFLAG(gH323ep.flags, OO_M_MANUALRINGBACK))
2267       {
2268          ooSendAlerting(call); /* Send alerting message */
2269
2270          if(OO_TESTFLAG(gH323ep.flags, OO_M_AUTOANSWER)) {
2271             ooSendConnect(call); /* Send connect message - call accepted */
2272          }
2273       }
2274    }
2275    
2276    return OO_OK;
2277 }
2278
2279 int ooH323MakeCall_helper(OOH323CallData *call)
2280 {
2281    int ret=0,i=0, k;
2282    Q931Message *q931msg = NULL;
2283    H225Setup_UUIE *setup;
2284
2285    ASN1DynOctStr *pFS=NULL;
2286    H225TransportAddress_ipAddress *destCallSignalIpAddress;
2287
2288    H225TransportAddress_ipAddress *srcCallSignalIpAddress;
2289    ooH323EpCapability *epCap=NULL;
2290    OOCTXT *pctxt = NULL;
2291    H245OpenLogicalChannel *olc, printOlc;
2292    ASN1BOOL aligned = 1;
2293    ooAliases *pAlias = NULL;
2294
2295    /* pctxt = &gH323ep.msgctxt; */
2296    pctxt = call->msgctxt;
2297      
2298    ret = ooCreateQ931Message(pctxt, &q931msg, Q931SetupMsg);
2299    if(ret != OO_OK)
2300    {
2301       OOTRACEERR1("ERROR:Failed to Create Q931 SETUP Message\n ");
2302       return OO_FAILED;
2303    }
2304
2305    q931msg->callReference = call->callReference;
2306
2307    /* Set bearer capability */
2308    if(OO_OK != ooSetBearerCapabilityIE(pctxt, q931msg, Q931CCITTStd, 
2309                           // Q931TransferUnrestrictedDigital, Q931TransferPacketMode,
2310                           call->transfercap, Q931TransferCircuitMode,
2311                           // Q931TransferRatePacketMode, Q931UserInfoLayer1G722G725))
2312                           Q931TransferRate64Kbps, Q931UserInfoLayer1G711ALaw))
2313    {
2314       OOTRACEERR3("Error: Failed to set bearer capability ie.(%s, %s)\n",
2315                    call->callType, call->callToken);
2316       return OO_FAILED;
2317    }
2318
2319    /* Set calling party number  Q931 IE */
2320    if(call->callingPartyNumber && call->callingPartyNumber[0])
2321      ooQ931SetCallingPartyNumberIE(pctxt, q931msg,
2322                             (const char*)call->callingPartyNumber, 1, 0, 0, 0);
2323    
2324
2325    /* Set called party number Q931 IE */
2326    if(call->calledPartyNumber)
2327       ooQ931SetCalledPartyNumberIE(pctxt, q931msg, 
2328                             (const char*)call->calledPartyNumber, 1, 0);
2329    else if(call->remoteAliases) {
2330       pAlias = call->remoteAliases;
2331       while(pAlias) {
2332          if(pAlias->type == T_H225AliasAddress_dialedDigits)
2333             break;
2334          pAlias = pAlias->next;
2335       }
2336       if(pAlias)
2337       {
2338          call->calledPartyNumber = (char*)memAlloc(call->pctxt, 
2339                                                    strlen(pAlias->value)+1);
2340          if(!call->calledPartyNumber)
2341          {
2342             OOTRACEERR3("Error:Memory - ooH323MakeCall_helper - "
2343                         "calledPartyNumber(%s, %s)\n", call->callType, 
2344                         call->callToken);
2345             return OO_FAILED;
2346          }
2347          strcpy(call->calledPartyNumber, pAlias->value);
2348          ooQ931SetCalledPartyNumberIE(pctxt, q931msg, 
2349                             (const char*)call->calledPartyNumber, 1, 0);
2350       }
2351
2352    }
2353
2354    q931msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
2355                              sizeof(H225H323_UserInformation));
2356    if(!q931msg->userInfo)
2357    {
2358       OOTRACEERR1("ERROR:Memory - ooH323MakeCall_helper - userInfo\n");
2359       return OO_FAILED;
2360    }
2361    memset(q931msg->userInfo, 0, sizeof(H225H323_UserInformation));
2362
2363    setup = (H225Setup_UUIE*) memAlloc(pctxt, sizeof(H225Setup_UUIE));
2364    if(!setup)
2365    {
2366       OOTRACEERR3("Error:Memory -  ooH323MakeCall_helper - setup (%s, %s)\n",
2367                  call->callType, call->callToken);
2368       return OO_FAILED;
2369    }
2370    memset (setup, 0, sizeof(H225Setup_UUIE));
2371    setup->protocolIdentifier = gProtocolID;
2372    
2373    /* Populate Alias Address.*/
2374
2375    if(call->ourAliases || gH323ep.aliases)
2376    {   
2377       setup->m.sourceAddressPresent = TRUE;
2378       if(call->ourAliases)
2379          ret = ooPopulateAliasList(pctxt, call->ourAliases, 
2380                                                        &setup->sourceAddress, 0);
2381       else if(gH323ep.aliases)
2382          ret =  ooPopulateAliasList(pctxt, gH323ep.aliases, 
2383                                                        &setup->sourceAddress, 0);
2384       if(OO_OK != ret)
2385       {
2386          OOTRACEERR1("Error:Failed to populate alias list in SETUP message\n");
2387          memReset(pctxt);
2388          return OO_FAILED;
2389       }
2390    }
2391
2392    setup->m.presentationIndicatorPresent = TRUE;
2393    setup->presentationIndicator.t = 
2394                              T_H225PresentationIndicator_presentationAllowed;
2395    setup->m.screeningIndicatorPresent = TRUE;
2396    setup->screeningIndicator = userProvidedNotScreened;
2397
2398    setup->m.multipleCallsPresent = TRUE;
2399    setup->multipleCalls = FALSE;
2400    setup->m.maintainConnectionPresent = TRUE;
2401    setup->maintainConnection = FALSE;
2402
2403    /* Populate Destination aliases */
2404    if(call->remoteAliases)
2405    {
2406       setup->m.destinationAddressPresent = TRUE;
2407       ret = ooPopulateAliasList(pctxt, call->remoteAliases, 
2408                                                  &setup->destinationAddress, 0);
2409       if(OO_OK != ret)
2410       {
2411          OOTRACEERR1("Error:Failed to populate destination alias list in SETUP"
2412                      "message\n");
2413          memReset(pctxt);
2414          return OO_FAILED;
2415       }
2416    }
2417
2418    /* Populate the vendor information */
2419    if(gH323ep.isGateway)
2420       setup->sourceInfo.m.gatewayPresent = TRUE;
2421    else
2422       setup->sourceInfo.m.terminalPresent = TRUE;
2423
2424    setup->sourceInfo.m.vendorPresent=TRUE;
2425    setup->sourceInfo.vendor.vendor.t35CountryCode = gH323ep.t35CountryCode;
2426    setup->sourceInfo.vendor.vendor.t35Extension = gH323ep.t35Extension;
2427    setup->sourceInfo.vendor.vendor.manufacturerCode= gH323ep.manufacturerCode;
2428    
2429    if(gH323ep.productID)
2430    {
2431       setup->sourceInfo.vendor.m.productIdPresent=TRUE;
2432       setup->sourceInfo.vendor.productId.numocts = ASN1MIN(
2433                               strlen(gH323ep.productID), 
2434                               sizeof(setup->sourceInfo.vendor.productId.data));
2435       strncpy((char*)setup->sourceInfo.vendor.productId.data, 
2436                 gH323ep.productID, setup->sourceInfo.vendor.productId.numocts);
2437    }
2438    else
2439       setup->sourceInfo.vendor.m.productIdPresent=FALSE;
2440    
2441    if(gH323ep.versionID)
2442    {
2443       setup->sourceInfo.vendor.m.versionIdPresent=TRUE;
2444       setup->sourceInfo.vendor.versionId.numocts = ASN1MIN(
2445                               strlen(gH323ep.versionID), 
2446                               sizeof(setup->sourceInfo.vendor.versionId.data));
2447       strncpy((char*)setup->sourceInfo.vendor.versionId.data, 
2448               gH323ep.versionID, setup->sourceInfo.vendor.versionId.numocts);
2449    }
2450    else
2451       setup->sourceInfo.vendor.m.versionIdPresent=FALSE;
2452    
2453    setup->sourceInfo.mc = FALSE;
2454    setup->sourceInfo.undefinedNode = FALSE;
2455
2456    /* Populate the destination Call Signal Address */
2457    setup->destCallSignalAddress.t=T_H225TransportAddress_ipAddress;
2458    destCallSignalIpAddress = (H225TransportAddress_ipAddress*)memAlloc(pctxt,
2459                                   sizeof(H225TransportAddress_ipAddress));
2460    if(!destCallSignalIpAddress)
2461    {
2462       OOTRACEERR3("Error:Memory -  ooH323MakeCall_helper - "
2463                  "destCallSignalAddress. (%s, %s)\n", call->callType, 
2464                  call->callToken);
2465       return OO_FAILED;
2466    }
2467    ooSocketConvertIpToNwAddr(call->remoteIP, destCallSignalIpAddress->ip.data);
2468
2469    destCallSignalIpAddress->ip.numocts=4;
2470    destCallSignalIpAddress->port = call->remotePort;
2471
2472    setup->destCallSignalAddress.u.ipAddress = destCallSignalIpAddress;
2473    setup->m.destCallSignalAddressPresent=TRUE;
2474    setup->activeMC=FALSE;
2475
2476    /* Populate the source Call Signal Address */
2477    setup->sourceCallSignalAddress.t=T_H225TransportAddress_ipAddress;
2478    srcCallSignalIpAddress = (H225TransportAddress_ipAddress*)memAlloc(pctxt,
2479                                   sizeof(H225TransportAddress_ipAddress));
2480    if(!srcCallSignalIpAddress)
2481    {
2482       OOTRACEERR3("Error:Memory - ooH323MakeCall_helper - srcCallSignalAddress"
2483                   "(%s, %s)\n", call->callType, call->callToken);
2484       return OO_FAILED;
2485    }
2486    ooSocketConvertIpToNwAddr(call->localIP, srcCallSignalIpAddress->ip.data);
2487
2488    srcCallSignalIpAddress->ip.numocts=4;
2489    srcCallSignalIpAddress->port= call->pH225Channel->port;
2490    setup->sourceCallSignalAddress.u.ipAddress = srcCallSignalIpAddress;
2491    setup->m.sourceCallSignalAddressPresent=TRUE;
2492    /* No fast start */
2493    if(!OO_TESTFLAG(call->flags, OO_M_FASTSTART))
2494    {
2495       setup->m.fastStartPresent = FALSE;
2496    }
2497    else{
2498       setup->m.fastStartPresent = TRUE;
2499       pFS = (ASN1DynOctStr*)memAlloc(pctxt, gH323ep.noOfCaps*
2500                                        sizeof(ASN1DynOctStr));
2501       if(!pFS)
2502       {
2503          OOTRACEERR3("Error:Memory - ooH323MakeCall_helper - pFS(%s, %s)\n",
2504                      call->callType, call->callToken);
2505          return OO_FAILED;
2506       }
2507
2508       /* Use preference order of codecs */
2509       i=0;
2510       for(k=0; k< call->capPrefs.index; k++)
2511       {
2512          OOTRACEDBGC5("Preffered capability at index %d is %s. (%s, %s)\n",
2513                       k, ooGetCapTypeText(call->capPrefs.order[k]), 
2514                       call->callType, call->callToken);
2515
2516          if(call->ourCaps) {
2517             epCap = call->ourCaps;
2518             OOTRACEDBGC3("Using call specific capabilities in faststart of "
2519                          "setup message. (%s, %s)\n", call->callType, 
2520                          call->callToken);
2521          }
2522          else{
2523             epCap = gH323ep.myCaps;
2524             OOTRACEDBGC3("Using end-point capabilities for faststart of setup"
2525                          "message. (%s, %s)\n", call->callType, 
2526                          call->callToken);
2527          }
2528
2529          while(epCap){
2530             if(epCap->cap == call->capPrefs.order[k]) break;
2531             else epCap = epCap->next;
2532          }
2533          if(!epCap)
2534          {
2535             OOTRACEWARN4("Warn:Preferred capability %s is abscent in "
2536                          "capability list. (%s, %s)\n", 
2537                          ooGetCapTypeText(call->capPrefs.order[k]), 
2538                          call->callType, call->callToken);
2539             continue;
2540          }
2541
2542 /* don't send t38/other data caps in fasstart olcs */
2543
2544          if (epCap->capType == OO_CAP_TYPE_DATA)
2545                 continue;
2546
2547          OOTRACEDBGC4("Building olcs with capability %s. (%s, %s)\n", 
2548                       ooGetCapTypeText(epCap->cap), call->callType, 
2549                       call->callToken);
2550          if(epCap->dir & OORX)
2551          {
2552             olc = (H245OpenLogicalChannel*)memAlloc(pctxt, 
2553                                              sizeof(H245OpenLogicalChannel));
2554             if(!olc)
2555             {
2556                OOTRACEERR3("ERROR:Memory - ooH323MakeCall_helper - olc(%s, %s)"
2557                            "\n", call->callType, call->callToken);
2558                ooFreeQ931Message(pctxt, q931msg);
2559                if(call->callState < OO_CALL_CLEAR)
2560                {
2561                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2562                   call->callState = OO_CALL_CLEAR;
2563                }
2564                return OO_FAILED;
2565             }
2566             memset(olc, 0, sizeof(H245OpenLogicalChannel));
2567             olc->forwardLogicalChannelNumber = call->logicalChanNoCur++; 
2568             if(call->logicalChanNoCur > call->logicalChanNoMax)
2569                call->logicalChanNoCur = call->logicalChanNoBase;
2570         
2571             ooBuildFastStartOLC(call, olc, epCap, pctxt, OORX);
2572             /* Do not specify msg buffer let automatic allocation work */
2573             setPERBuffer(pctxt, NULL, 0, aligned);
2574             if(asn1PE_H245OpenLogicalChannel(pctxt, olc) != ASN_OK)
2575             {
2576                OOTRACEERR3("ERROR:Encoding of olc failed for faststart(%s, %s)"
2577                            "\n", call->callType, call->callToken);
2578                ooFreeQ931Message(pctxt, q931msg);
2579                if(call->callState < OO_CALL_CLEAR)
2580                {
2581                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2582                   call->callState = OO_CALL_CLEAR;
2583                }
2584                return OO_FAILED;
2585             }
2586             pFS[i].data = (unsigned char *)encodeGetMsgPtr(pctxt, (int *)&(pFS[i].numocts));
2587
2588
2589             /* Dump faststart element in logfile for debugging purpose */
2590             setPERBuffer(pctxt,  (unsigned char*)pFS[i].data, pFS[i].numocts, 1);
2591             initializePrintHandler(&printHandler, "FastStart Element");
2592             setEventHandler (pctxt, &printHandler);
2593             memset(&printOlc, 0, sizeof(printOlc));
2594             ret = asn1PD_H245OpenLogicalChannel(pctxt, &(printOlc));
2595             if(ret != ASN_OK)
2596             {
2597                OOTRACEERR3("Error: Failed decoding FastStart Element."
2598                            "(%s, %s)\n", call->callType, call->callToken);
2599                ooFreeQ931Message(pctxt, q931msg);
2600                if(call->callState < OO_CALL_CLEAR)
2601                {
2602                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2603                   call->callState = OO_CALL_CLEAR;
2604                }
2605                return OO_FAILED;
2606             }
2607             finishPrint();
2608             removeEventHandler(pctxt); 
2609
2610
2611             olc = NULL;
2612             i++;
2613             OOTRACEDBGC5("Added RX fs element %d with capability %s(%s, %s)\n",
2614                           i, ooGetCapTypeText(epCap->cap), call->callType, 
2615                           call->callToken);
2616          }
2617
2618          if(epCap->dir & OOTX)
2619          {
2620             olc = (H245OpenLogicalChannel*)memAlloc(pctxt, 
2621                                              sizeof(H245OpenLogicalChannel));
2622             if(!olc)
2623             {
2624                OOTRACEERR3("ERROR:Memory - ooH323MakeCall_helper - olc(%s, %s)"
2625                            "\n", call->callType, call->callToken);
2626                ooFreeQ931Message(pctxt, q931msg);
2627                if(call->callState < OO_CALL_CLEAR)
2628                {
2629                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2630                   call->callState = OO_CALL_CLEAR;
2631                }
2632                return OO_FAILED;
2633             }
2634             memset(olc, 0, sizeof(H245OpenLogicalChannel));
2635             olc->forwardLogicalChannelNumber = call->logicalChanNoCur++; 
2636             if(call->logicalChanNoCur > call->logicalChanNoMax)
2637                call->logicalChanNoCur = call->logicalChanNoBase;
2638         
2639             ooBuildFastStartOLC(call, olc, epCap, pctxt, OOTX);
2640             /* Do not specify msg buffer let automatic allocation work */
2641             setPERBuffer(pctxt, NULL, 0, aligned);
2642             if(asn1PE_H245OpenLogicalChannel(pctxt, olc) != ASN_OK)
2643             {
2644                OOTRACEERR3("ERROR:Encoding of olc failed for faststart(%s, %s)"
2645                            "\n", call->callType, call->callToken);
2646                ooFreeQ931Message(pctxt, q931msg);
2647                if(call->callState < OO_CALL_CLEAR)
2648                {
2649                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2650                   call->callState = OO_CALL_CLEAR;
2651                }
2652                return OO_FAILED;
2653             }
2654             pFS[i].data = (unsigned char *)encodeGetMsgPtr(pctxt, (int *)&(pFS[i].numocts));
2655
2656             /* Dump faststart element in logfile for debugging purpose */
2657             setPERBuffer(pctxt,  (unsigned char*)pFS[i].data, pFS[i].numocts, 1);
2658             initializePrintHandler(&printHandler, "FastStart Element");
2659             setEventHandler (pctxt, &printHandler);
2660             memset(&printOlc, 0, sizeof(printOlc));
2661             ret = asn1PD_H245OpenLogicalChannel(pctxt, &(printOlc));
2662             if(ret != ASN_OK)
2663             {
2664                OOTRACEERR3("Error: Failed decoding FastStart Element."
2665                            "(%s, %s)\n", call->callType, call->callToken);
2666                ooFreeQ931Message(pctxt, q931msg);
2667                if(call->callState < OO_CALL_CLEAR)
2668                {
2669                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2670                   call->callState = OO_CALL_CLEAR;
2671                }
2672                return OO_FAILED;
2673             }
2674             finishPrint();
2675             removeEventHandler(pctxt); 
2676
2677
2678             olc = NULL;
2679             i++;
2680             OOTRACEDBGC5("Added TX fs element %d with capability %s(%s, %s)\n",
2681                           i, ooGetCapTypeText(epCap->cap), call->callType, 
2682                           call->callToken);
2683          }
2684
2685       }
2686       OOTRACEDBGA4("Added %d fast start elements to SETUP message (%s, %s)\n",
2687                    i, call->callType, call->callToken);
2688       setup->fastStart.n = i;
2689       setup->fastStart.elem = pFS; 
2690    }
2691
2692    setup->conferenceID.numocts= call->confIdentifier.numocts;
2693    memcpy(setup->conferenceID.data, call->confIdentifier.data,
2694           call->confIdentifier.numocts);
2695
2696    setup->conferenceGoal.t = T_H225Setup_UUIE_conferenceGoal_create;
2697    /* H.225 point to point call */
2698    setup->callType.t = T_H225CallType_pointToPoint;
2699  
2700    /* Populate optional fields */
2701    setup->m.callIdentifierPresent = TRUE;
2702    /*ooGenerateCallIdentifier(&setup->callIdentifier);*/
2703    setup->callIdentifier.guid.numocts = call->callIdentifier.guid.numocts;
2704    memcpy(setup->callIdentifier.guid.data, call->callIdentifier.guid.data, 
2705                                call->callIdentifier.guid.numocts);
2706    
2707    setup->m.mediaWaitForConnectPresent = TRUE;
2708    if(OO_TESTFLAG(call->flags, OO_M_MEDIAWAITFORCONN)) {
2709       setup->mediaWaitForConnect = TRUE;
2710    }
2711    else {
2712       setup->mediaWaitForConnect = FALSE;
2713    }
2714    setup->m.canOverlapSendPresent = TRUE;
2715    setup->canOverlapSend = FALSE;
2716
2717    /* Populate the userInfo structure with the setup UUIE */ 
2718    
2719    q931msg->userInfo->h323_uu_pdu.h323_message_body.t = 
2720          T_H225H323_UU_PDU_h323_message_body_setup;
2721    q931msg->userInfo->h323_uu_pdu.h323_message_body.u.setup = setup;
2722    q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
2723    
2724    q931msg->userInfo->h323_uu_pdu.h245Tunneling = 
2725       OO_TESTFLAG (call->flags, OO_M_TUNNELING);
2726
2727    /* For H.323 version 4 and higher, if fast connect, tunneling should be 
2728       supported.
2729    */
2730    if(OO_TESTFLAG(call->flags, OO_M_FASTSTART)) {
2731       q931msg->userInfo->h323_uu_pdu.h245Tunneling = TRUE;
2732       OO_SETFLAG(call->flags, OO_M_TUNNELING);
2733    }
2734
2735    OOTRACEDBGA3("Built SETUP message (%s, %s)\n", call->callType, 
2736                  call->callToken);
2737    
2738    /* H225 message callback */
2739    if(gH323ep.h225Callbacks.onBuiltSetup)
2740       gH323ep.h225Callbacks.onBuiltSetup(call, q931msg);
2741
2742    ret=ooSendH225Msg(call, q931msg);
2743    if(ret != OO_OK)
2744    {
2745      OOTRACEERR3("Error:Failed to enqueue SETUP message to outbound queue. (%s, %s)\n", call->callType, call->callToken);
2746    }
2747    /* memReset(&gH323ep.msgctxt);*/
2748    memReset(call->msgctxt);
2749
2750    return ret;
2751 }
2752
2753
2754
2755 int ooQ931SendDTMFAsKeyPadIE(OOH323CallData *call, const char* data)
2756 {
2757    int ret;    
2758    H225Information_UUIE *information=NULL;
2759    Q931Message *q931msg=NULL;
2760    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
2761    OOCTXT *pctxt = call->msgctxt;
2762
2763    ret = ooCreateQ931Message(pctxt, &q931msg, Q931InformationMsg);
2764    if(ret != OO_OK)
2765    {      
2766       OOTRACEERR3("Error: In allocating memory for - H225 Information message."
2767                   "(%s, %s)\n", call->callType, call->callToken);
2768       return OO_FAILED;
2769    }
2770
2771    q931msg->callReference = call->callReference;
2772
2773    q931msg->userInfo = (H225H323_UserInformation*)memAllocZ(pctxt,
2774                              sizeof(H225H323_UserInformation));
2775    if(!q931msg->userInfo)
2776    {
2777       OOTRACEERR3("ERROR:Memory -  ooQ931SendDTMFAsKeypadIE - userInfo"
2778                   "(%s, %s)\n", call->callType, call->callToken);
2779       /* memReset(&gH323ep.msgctxt); */
2780       memReset(call->msgctxt);
2781       return OO_FAILED;
2782    }
2783    q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
2784    q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(call->flags, 
2785                                                               OO_M_TUNNELING); 
2786    q931msg->userInfo->h323_uu_pdu.h323_message_body.t = 
2787          T_H225H323_UU_PDU_h323_message_body_information;
2788    
2789    information = (H225Information_UUIE*)memAllocZ(pctxt, 
2790                                              sizeof(H225Information_UUIE));
2791    if(!information)
2792    {
2793       OOTRACEERR3("ERROR:Memory -  ooQ931SendDTMFAsKeypadIE - information"
2794                   "(%s, %s)\n", call->callType, call->callToken);
2795       /* memReset(&gH323ep.msgctxt); */
2796       memReset(call->msgctxt);
2797       return OO_FAILED;
2798    }
2799    q931msg->userInfo->h323_uu_pdu.h323_message_body.u.information = 
2800                                                                   information; 
2801    information->m.callIdentifierPresent = 1;
2802    information->callIdentifier.guid.numocts = 
2803                                    call->callIdentifier.guid.numocts;
2804    memcpy(information->callIdentifier.guid.data, 
2805           call->callIdentifier.guid.data, 
2806           call->callIdentifier.guid.numocts);
2807    information->protocolIdentifier = gProtocolID;
2808    
2809    /*Add keypad IE*/
2810    ret = ooQ931SetKeypadIE(pctxt, q931msg, data);
2811    if(ret != OO_OK)
2812    {
2813       OOTRACEERR3("Error:Creating keypad IE for (%s, %s)\n", call->callType, 
2814                    call->callToken);
2815       /* memReset(&gH323ep.msgctxt); */
2816       memReset(call->msgctxt);
2817       return OO_FAILED;
2818    }
2819
2820    ret=ooSendH225Msg(call, q931msg);
2821    if(ret != OO_OK)
2822    {
2823       OOTRACEERR3("Error:Failed to enqueue Information message to outbound "
2824                   "queue. (%s, %s)\n", call->callType, call->callToken);
2825    }
2826    /* memReset(&gH323ep.msgctxt); */
2827    memReset(call->msgctxt);
2828
2829    return ret;
2830
2831 }
2832
2833 int ooH323ForwardCall(char* callToken, char *dest)
2834 {
2835    int ret=0;
2836    Q931Message *pQ931Msg = NULL;
2837    H225Facility_UUIE *facility=NULL;
2838    OOCTXT *pctxt = &gH323ep.msgctxt;
2839    OOH323CallData *call;
2840    char ip[30]="\0", *pcPort=NULL;
2841    H225TransportAddress_ipAddress *fwdCallSignalIpAddress;
2842
2843    call= ooFindCallByToken(callToken);
2844    if(!call)
2845    {
2846       OOTRACEERR2("ERROR: Invalid call token for forward - %s\n", callToken);
2847       return OO_FAILED;
2848    }
2849    OOTRACEDBGA3("Building Facility message for call forward (%s, %s)\n", 
2850                                               call->callType, call->callToken);
2851    call->pCallFwdData = (OOCallFwdData*)memAllocZ(call->pctxt, 
2852                                                      sizeof(OOCallFwdData));
2853    if(!call->pCallFwdData)
2854    {
2855      OOTRACEERR3("Error:Memory - ooH323ForwardCall - pCallFwdData (%s, %s)\n",
2856      call->callType, call->callToken);
2857      return OO_FAILED;
2858    }
2859
2860    ret = ooParseDestination(call, dest, ip, 20, 
2861                                              &call->pCallFwdData->aliases);
2862    if(ret != OO_OK)
2863    {
2864       OOTRACEERR4("Error:Failed to parse the destination %s for call fwd."
2865                   "(%s, %s)\n", dest, call->callType, call->callToken);
2866       memFreePtr(call->pctxt, call->pCallFwdData);
2867       return OO_FAILED;
2868    }
2869
2870    if(!ooUtilsIsStrEmpty(ip))
2871    {
2872       pcPort = strchr(ip, ':');
2873       if(pcPort)
2874       {
2875          *pcPort = '\0';
2876          pcPort++;
2877          call->pCallFwdData->port = atoi(pcPort);
2878       }
2879       strcpy(call->pCallFwdData->ip, ip);
2880    }
2881
2882    ret = ooCreateQ931Message(pctxt, &pQ931Msg, Q931FacilityMsg);
2883    if(ret != OO_OK)
2884    {
2885       OOTRACEERR3
2886          ("ERROR: In allocating memory for call transfer facility message "
2887           "(%s, %s)\n", call->callType, call->callToken);
2888       return OO_FAILED;
2889    }
2890
2891    pQ931Msg->callReference = call->callReference;
2892
2893    pQ931Msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
2894                              sizeof(H225H323_UserInformation));
2895    if(!pQ931Msg->userInfo)
2896    {
2897       OOTRACEERR3("ERROR:Memory - ooH323ForwardCall - userInfo(%s, %s)\n", 
2898                    call->callType, call->callToken);
2899       return OO_FAILED;
2900    }
2901    memset (pQ931Msg->userInfo, 0, sizeof(H225H323_UserInformation));
2902    pQ931Msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
2903
2904    pQ931Msg->userInfo->h323_uu_pdu.h245Tunneling = 
2905                                    OO_TESTFLAG (call->flags, OO_M_TUNNELING); 
2906
2907    pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.t = 
2908       T_H225H323_UU_PDU_h323_message_body_facility;
2909    
2910    facility = (H225Facility_UUIE*) 
2911       memAllocZ (pctxt, sizeof(H225Facility_UUIE));
2912
2913    if(!facility)
2914    {
2915       OOTRACEERR3("ERROR:Memory - ooH323ForwardCall - facility (%s, %s)"
2916                   "\n", call->callType, call->callToken);
2917       return OO_FAILED;
2918    }
2919
2920    pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.u.facility = facility;
2921    
2922    facility->protocolIdentifier = gProtocolID;  
2923    facility->m.callIdentifierPresent = 1;
2924    facility->callIdentifier.guid.numocts = 
2925       call->callIdentifier.guid.numocts;
2926
2927    memcpy(facility->callIdentifier.guid.data, 
2928           call->callIdentifier.guid.data, 
2929           call->callIdentifier.guid.numocts);
2930
2931    facility->reason.t = T_H225FacilityReason_callForwarded;
2932    
2933    if(!ooUtilsIsStrEmpty(call->pCallFwdData->ip))
2934    {
2935       facility->m.alternativeAddressPresent = TRUE;
2936       facility->alternativeAddress.t=T_H225TransportAddress_ipAddress;
2937       fwdCallSignalIpAddress = (H225TransportAddress_ipAddress*)memAlloc(pctxt,
2938                                   sizeof(H225TransportAddress_ipAddress));
2939       if(!fwdCallSignalIpAddress)
2940       {
2941          OOTRACEERR3("Error:Memory - ooH323ForwardCall - fwdCallSignalAddress"
2942                      "(%s, %s)\n", call->callType, call->callToken);
2943          return OO_FAILED;
2944       }
2945       ooSocketConvertIpToNwAddr(call->pCallFwdData->ip, 
2946                                           fwdCallSignalIpAddress->ip.data);
2947
2948       fwdCallSignalIpAddress->ip.numocts=4;
2949       fwdCallSignalIpAddress->port = call->pCallFwdData->port;
2950       facility->alternativeAddress.u.ipAddress = fwdCallSignalIpAddress;
2951    }
2952
2953    if(call->pCallFwdData->aliases)
2954    {    
2955       facility->m.alternativeAliasAddressPresent = TRUE;
2956       ret = ooPopulateAliasList(pctxt, call->pCallFwdData->aliases, 
2957                                         &facility->alternativeAliasAddress, 0);
2958       if(ret != OO_OK)
2959       {
2960          OOTRACEERR3("Error:Failed to populate alternate aliases in "
2961                      "ooH323ForwardCall. (%s, %s)\n", call->callType, 
2962                      call->callToken);
2963          return OO_FAILED;
2964       }
2965    }
2966
2967    ret = ooSendH225Msg(call, pQ931Msg);
2968    if(ret != OO_OK)
2969    {
2970       OOTRACEERR3
2971          ("Error:Failed to enqueue Forward Facility message to outbound "
2972          "queue.(%s, %s)\n", call->callType, call->callToken);
2973    }
2974    call->callEndReason = OO_REASON_LOCAL_FWDED;
2975    memReset (&gH323ep.msgctxt);
2976    return ret;
2977 }
2978
2979 int ooH323HangCall(char * callToken, OOCallClearReason reason, int q931cause)
2980 {
2981    OOH323CallData *call;
2982
2983    call= ooFindCallByToken(callToken);
2984    if(!call)
2985    {
2986       OOTRACEWARN2("WARN: Call hangup failed - Call %s not present\n", 
2987                     callToken);
2988       return OO_FAILED;
2989    }
2990    OOTRACEINFO3("Hanging up call (%s, %s)\n", call->callType, call->callToken);
2991    if(call->callState < OO_CALL_CLEAR)
2992    {
2993       call->callEndReason = reason;
2994       call->q931cause = q931cause;
2995       call->callState = OO_CALL_CLEAR;
2996    }
2997    return OO_OK;
2998 }
2999
3000 int ooSetBearerCapabilityIE
3001    (OOCTXT* pctxt, Q931Message *pmsg, enum Q931CodingStandard codingStandard, 
3002     enum Q931InformationTransferCapability capability, 
3003     enum Q931TransferMode transferMode, enum Q931TransferRate transferRate,
3004     enum Q931UserInfoLayer1Protocol userInfoLayer1)
3005 {
3006    unsigned size = 3;
3007    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3008
3009    if(pmsg->bearerCapabilityIE)
3010    {
3011       memFreePtr(pctxt, pmsg->bearerCapabilityIE);
3012       pmsg->bearerCapabilityIE = NULL;
3013    }
3014
3015    pmsg->bearerCapabilityIE = (Q931InformationElement*) 
3016                       memAlloc(pctxt, sizeof(Q931InformationElement)+size-1);
3017    if(!pmsg->bearerCapabilityIE)
3018    {
3019       OOTRACEERR1("Error:Memory - ooSetBearerCapabilityIE - bearerCapabilityIE"
3020                   "\n");
3021       return OO_FAILED;
3022    }
3023
3024    pmsg->bearerCapabilityIE->discriminator = Q931BearerCapabilityIE;
3025    pmsg->bearerCapabilityIE->length = size;
3026    pmsg->bearerCapabilityIE->data[0] = (ASN1OCTET)(0x80 | ((codingStandard&3) << 5) | (capability&31));
3027
3028    pmsg->bearerCapabilityIE->data[1] = (0x80 | ((transferMode & 3) << 5) | (transferRate & 31));
3029    
3030    pmsg->bearerCapabilityIE->data[2] = (0x80 | (1<<5) | userInfoLayer1);
3031
3032    return OO_OK;
3033 }
3034
3035 int ooQ931SetKeypadIE(OOCTXT* pctxt, Q931Message *pmsg, const char* data)
3036 {
3037    unsigned len = 0;
3038    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3039
3040    len = strlen(data);
3041    pmsg->keypadIE = (Q931InformationElement*) 
3042                       memAlloc(pctxt, sizeof(Q931InformationElement)+len-1);
3043    if(!pmsg->keypadIE)
3044    {
3045       OOTRACEERR1("Error:Memory - ooQ931SetKeypadIE - keypadIE\n");
3046       return OO_FAILED;
3047    }
3048
3049    pmsg->keypadIE->discriminator = Q931KeypadIE;
3050    pmsg->keypadIE->length = len;
3051    memcpy(pmsg->keypadIE->data, data, len);
3052    return OO_OK;
3053 }
3054
3055
3056
3057
3058 int ooQ931SetCallingPartyNumberIE
3059    (OOCTXT* pctxt, Q931Message *pmsg, const char *number, unsigned plan, unsigned type, 
3060     unsigned presentation, unsigned screening)
3061 {
3062    unsigned len = 0;
3063    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3064
3065    if(pmsg->callingPartyNumberIE)
3066    {
3067       memFreePtr(pctxt, pmsg->callingPartyNumberIE);
3068       pmsg->callingPartyNumberIE = NULL;
3069    }
3070
3071    len = strlen(number);
3072    pmsg->callingPartyNumberIE = (Q931InformationElement*) 
3073                       memAlloc(pctxt, sizeof(Q931InformationElement)+len+2-1);
3074    if(!pmsg->callingPartyNumberIE)
3075    {
3076       OOTRACEERR1("Error:Memory - ooQ931SetCallingPartyNumberIE - "
3077                   "callingPartyNumberIE\n");
3078       return OO_FAILED;
3079    }
3080    pmsg->callingPartyNumberIE->discriminator = Q931CallingPartyNumberIE;
3081    pmsg->callingPartyNumberIE->length = len+2;
3082    pmsg->callingPartyNumberIE->data[0] = (((type&7)<<4)|(plan&15));
3083    pmsg->callingPartyNumberIE->data[1] = (0x80|((presentation&3)<<5)|(screening&3));
3084    memcpy(pmsg->callingPartyNumberIE->data+2, number, len);
3085
3086    return OO_OK;
3087 }
3088
3089 int ooQ931SetCalledPartyNumberIE
3090    (OOCTXT* pctxt, Q931Message *pmsg, const char *number, unsigned plan, unsigned type)
3091 {
3092    unsigned len = 0;
3093    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3094
3095    if(pmsg->calledPartyNumberIE)
3096    {
3097       memFreePtr(pctxt, pmsg->calledPartyNumberIE);
3098       pmsg->calledPartyNumberIE = NULL;
3099    }
3100
3101    len = strlen(number);
3102    pmsg->calledPartyNumberIE = (Q931InformationElement*) 
3103                       memAlloc(pctxt, sizeof(Q931InformationElement)+len+1-1);
3104    if(!pmsg->calledPartyNumberIE)
3105    {
3106       OOTRACEERR1("Error:Memory - ooQ931SetCalledPartyNumberIE - "
3107                   "calledPartyNumberIE\n");
3108       return OO_FAILED;
3109    }
3110    pmsg->calledPartyNumberIE->discriminator = Q931CalledPartyNumberIE;
3111    pmsg->calledPartyNumberIE->length = len+1;
3112    pmsg->calledPartyNumberIE->data[0] = (0x80|((type&7)<<4)|(plan&15));
3113    memcpy(pmsg->calledPartyNumberIE->data+1, number, len);
3114
3115    return OO_OK;
3116 }
3117
3118 int ooQ931SetCauseIE
3119    (OOCTXT* pctxt, Q931Message *pmsg, enum Q931CauseValues cause, unsigned coding, 
3120     unsigned location)
3121 {
3122    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3123
3124    if(pmsg->causeIE){
3125       memFreePtr(pctxt, pmsg->causeIE);
3126       pmsg->causeIE = NULL;
3127    }
3128
3129    pmsg->causeIE = (Q931InformationElement*) 
3130                       memAlloc(pctxt, sizeof(Q931InformationElement)+1);
3131    if(!pmsg->causeIE)
3132    {
3133       OOTRACEERR1("Error:Memory - ooQ931SetCauseIE - causeIE\n");
3134       return OO_FAILED;
3135    }
3136    pmsg->causeIE->discriminator = Q931CauseIE;
3137    pmsg->causeIE->length = 2;
3138    pmsg->causeIE->data[0] = (0x80 | ((coding & 0x03) <<5) | (location & 0x0F));
3139
3140    pmsg->causeIE->data[1] = (0x80 | cause);
3141   
3142    return OO_OK;
3143 }
3144
3145
3146 /* Build a Facility message and tunnel H.245 message through it */
3147 int ooSendAsTunneledMessage(OOH323CallData *call, ASN1OCTET* msgbuf, 
3148                             int h245Len, int h245MsgType, int associatedChan)
3149 {
3150    Q931Message *pQ931Msg = NULL;
3151    H225H323_UU_PDU *pH323UUPDU = NULL;
3152    H225H323_UU_PDU_h245Control *pH245Control = NULL;
3153    ASN1DynOctStr * elem;
3154    int ret =0;
3155    H225Facility_UUIE *facility=NULL;
3156    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3157    OOCTXT *pctxt = call->msgctxt;
3158
3159    OOTRACEDBGA4("Building Facility message for tunneling %s (%s, %s)\n", 
3160                  ooGetMsgTypeText(h245MsgType), call->callType, call->callToken);
3161
3162    ret = ooCreateQ931Message(pctxt, &pQ931Msg, Q931FacilityMsg);
3163    if(ret != OO_OK)
3164    {
3165       OOTRACEERR3("ERROR: In allocating memory for facility message "
3166                   "(%s, %s)\n", call->callType, call->callToken);
3167       return OO_FAILED;
3168    }
3169
3170    pQ931Msg->callReference = call->callReference;
3171
3172    pQ931Msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
3173                              sizeof(H225H323_UserInformation));
3174    if(!pQ931Msg->userInfo)
3175    {
3176       OOTRACEERR3("ERROR:Memory - ooSendAsTunneledMessage - userInfo"
3177                 " (%s, %s)\n", call->callType, call->callToken);
3178       /* memReset(&gH323ep.msgctxt);*/
3179       memReset(call->msgctxt);
3180       return OO_FAILED;
3181    }
3182    memset (pQ931Msg->userInfo, 0, sizeof(H225H323_UserInformation));
3183    pQ931Msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
3184
3185    pQ931Msg->userInfo->h323_uu_pdu.h245Tunneling = 
3186       OO_TESTFLAG (call->flags, OO_M_TUNNELING);
3187
3188    pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.t = 
3189          T_H225H323_UU_PDU_h323_message_body_facility;
3190    
3191    facility = (H225Facility_UUIE*)
3192       memAllocZ (pctxt, sizeof(H225Facility_UUIE));
3193
3194    if(!facility)
3195    {
3196       OOTRACEERR3("ERROR:Memory - ooSendAsTunneledMessage - facility (%s, %s)"
3197                   "\n", call->callType, call->callToken);
3198       /* memReset(&gH323ep.msgctxt); */
3199       memReset(call->msgctxt);
3200       return OO_FAILED;
3201    }
3202
3203    pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.u.facility = facility;
3204    /* Populate Facility UUIE */
3205    facility->protocolIdentifier = gProtocolID;  
3206    facility->m.callIdentifierPresent = 1;
3207    facility->callIdentifier.guid.numocts = 
3208       call->callIdentifier.guid.numocts;
3209
3210    memcpy(facility->callIdentifier.guid.data, 
3211           call->callIdentifier.guid.data, 
3212           call->callIdentifier.guid.numocts);
3213
3214    facility->reason.t = T_H225FacilityReason_transportedInformation;
3215
3216    pH323UUPDU = (H225H323_UU_PDU*) &pQ931Msg->userInfo->h323_uu_pdu;
3217    pH323UUPDU->m.h245TunnelingPresent = TRUE;
3218    pH323UUPDU->m.h245ControlPresent = TRUE;
3219    pH323UUPDU->h245Tunneling = TRUE;
3220    pH245Control = (H225H323_UU_PDU_h245Control*)
3221                    &pH323UUPDU->h245Control;
3222
3223    elem = (ASN1DynOctStr*) memAlloc(pctxt, 
3224                                       sizeof(ASN1DynOctStr));
3225    if(!elem)
3226    {
3227       OOTRACEERR3("ERROR:Memory - ooSendAsTunneledMessage - elem "
3228                   "(%s, %s)\n", call->callType, call->callToken);
3229       return OO_FAILED;
3230    }
3231    elem->data = msgbuf;
3232    elem->numocts = h245Len;
3233    pH245Control->elem = elem;
3234    pH245Control->n = 1;
3235    pQ931Msg->tunneledMsgType = h245MsgType;
3236    pQ931Msg->logicalChannelNo = associatedChan;
3237
3238    
3239    ret = ooSendH225Msg(call, pQ931Msg);
3240    if(ret != OO_OK)
3241    {
3242      OOTRACEERR3("Error:Failed to enqueue Facility(tunneling) message to "
3243                  "outbound queue.(%s, %s)\n", call->callType, call->callToken);
3244    }
3245
3246    /* Can't do memReset here because if we are sending H.245 message as a 
3247       response to received tunneled h.245 message, we can't reset unless the \
3248       main received H225 message processing is finished. Rule. No reset when
3249       tunneling
3250    */
3251    /* memFreePtr(&gH323ep.msgctxt, pQ931Msg); */
3252    memFreePtr(call->msgctxt, pQ931Msg);
3253    return ret;
3254 }
3255
3256 int ooCallEstbTimerExpired(void *data)
3257 {
3258
3259    ooTimerCallback *cbData = (ooTimerCallback*) data;
3260    OOH323CallData *call = cbData->call;
3261    OOTRACEINFO3("Call Establishment timer expired. (%s, %s)\n", 
3262                                             call->callType, call->callToken); 
3263    memFreePtr(call->pctxt, cbData);
3264    if(call->callState < OO_CALL_CLEAR){
3265       call->callState = OO_CALL_CLEAR;
3266       call->callEndReason = OO_REASON_LOCAL_CLEARED;      
3267    }
3268
3269    return OO_OK;
3270 }
3271
3272
3273 int ooQ931GetCauseAndReasonCodeFromCallClearReason
3274    (OOCallClearReason clearReason, enum Q931CauseValues *cause, 
3275     unsigned *reasonCode)
3276 {
3277    switch(clearReason)
3278    {
3279    case OO_REASON_INVALIDMESSAGE:
3280    case OO_REASON_TRANSPORTFAILURE:
3281       *reasonCode =  T_H225ReleaseCompleteReason_undefinedReason;
3282       *cause = Q931ProtocolErrorUnspecified;
3283       break;
3284    case OO_REASON_NOBW:
3285       *reasonCode = T_H225ReleaseCompleteReason_noBandwidth;
3286       *cause = Q931ErrorInCauseIE;
3287       break;
3288    case OO_REASON_GK_NOCALLEDUSER:
3289       *reasonCode = T_H225ReleaseCompleteReason_calledPartyNotRegistered;
3290       *cause = Q931SubscriberAbsent;
3291       break;
3292    case OO_REASON_GK_NOCALLERUSER:
3293       *reasonCode = T_H225ReleaseCompleteReason_callerNotRegistered;
3294       *cause = Q931SubscriberAbsent;      
3295       break;
3296    case OO_REASON_GK_UNREACHABLE:
3297       *reasonCode = T_H225ReleaseCompleteReason_unreachableGatekeeper;
3298       *cause = Q931TemporaryFailure;
3299       break;
3300    case OO_REASON_GK_NORESOURCES:
3301    case OO_REASON_GK_CLEARED:
3302       *reasonCode = T_H225ReleaseCompleteReason_gatekeeperResources;
3303       *cause = Q931Congestion;
3304       break;
3305    case OO_REASON_NOCOMMON_CAPABILITIES:
3306       *reasonCode =  T_H225ReleaseCompleteReason_undefinedReason;
3307       *cause = Q931IncompatibleDestination;
3308       break;
3309    case OO_REASON_LOCAL_FWDED:
3310    case OO_REASON_REMOTE_FWDED:
3311       *reasonCode =  T_H225ReleaseCompleteReason_facilityCallDeflection;
3312       *cause = Q931Redirection;
3313       break;
3314    case OO_REASON_REMOTE_CLEARED:
3315    case OO_REASON_LOCAL_CLEARED:
3316       *reasonCode = T_H225ReleaseCompleteReason_undefinedReason;
3317       *cause = Q931NormalCallClearing;
3318       break;
3319    case OO_REASON_REMOTE_BUSY:
3320    case OO_REASON_LOCAL_BUSY:
3321       *reasonCode =  T_H225ReleaseCompleteReason_inConf;
3322       *cause = Q931UserBusy;
3323       break;
3324    case OO_REASON_REMOTE_NOANSWER:
3325    case OO_REASON_LOCAL_NOTANSWERED:
3326       *reasonCode =  T_H225ReleaseCompleteReason_undefinedReason;
3327       *cause = Q931NoAnswer;
3328       break;
3329    case OO_REASON_REMOTE_REJECTED:
3330    case OO_REASON_LOCAL_REJECTED:
3331       *reasonCode = T_H225ReleaseCompleteReason_destinationRejection;
3332       *cause = Q931CallRejected;
3333       break;
3334    case OO_REASON_REMOTE_CONGESTED:
3335    case OO_REASON_LOCAL_CONGESTED:
3336       *reasonCode =  T_H225ReleaseCompleteReason_noBandwidth;
3337       *cause = Q931Congestion;
3338       break;
3339    case OO_REASON_NOROUTE:
3340       *reasonCode = T_H225ReleaseCompleteReason_unreachableDestination;
3341       *cause = Q931NoRouteToDestination;
3342       break;
3343    case OO_REASON_NOUSER:
3344       *reasonCode = T_H225ReleaseCompleteReason_undefinedReason;      
3345       *cause = Q931SubscriberAbsent;
3346       break;
3347    case OO_REASON_UNKNOWN:
3348    default:
3349       *reasonCode = T_H225ReleaseCompleteReason_undefinedReason;
3350       *cause = Q931NormalUnspecified;
3351    }
3352
3353    return OO_OK;
3354 }
3355
3356 enum OOCallClearReason ooGetCallClearReasonFromCauseAndReasonCode
3357    (enum Q931CauseValues cause, unsigned reasonCode)
3358 {
3359    switch(cause)
3360    {
3361       case Q931NormalCallClearing:
3362          return OO_REASON_REMOTE_CLEARED;
3363
3364       case Q931UserBusy:
3365          return OO_REASON_REMOTE_BUSY;
3366
3367       case Q931NoResponse:
3368       case Q931NoAnswer:
3369          return OO_REASON_REMOTE_NOANSWER;
3370
3371       case Q931CallRejected:
3372          return OO_REASON_REMOTE_REJECTED;
3373
3374       case Q931Redirection:
3375          return OO_REASON_REMOTE_FWDED;
3376
3377       case Q931NetworkOutOfOrder:
3378       case Q931TemporaryFailure:
3379          return OO_REASON_TRANSPORTFAILURE;
3380
3381       case Q931NoCircuitChannelAvailable:
3382       case Q931Congestion:
3383       case Q931RequestedCircuitUnAvailable:
3384       case Q931ResourcesUnavailable:
3385          return OO_REASON_REMOTE_CONGESTED;
3386
3387       case Q931NoRouteToDestination:
3388       case Q931NoRouteToNetwork:
3389          return OO_REASON_NOROUTE;
3390       case Q931NumberChanged:
3391       case Q931UnallocatedNumber:
3392       case Q931SubscriberAbsent:
3393          return OO_REASON_NOUSER;
3394       case Q931ChannelUnacceptable:
3395       case Q931DestinationOutOfOrder:
3396       case Q931InvalidNumberFormat:
3397       case Q931NormalUnspecified:
3398       case Q931StatusEnquiryResponse:
3399       case Q931IncompatibleDestination:
3400       case Q931ProtocolErrorUnspecified:
3401       case Q931RecoveryOnTimerExpiry:
3402       case Q931InvalidCallReference:
3403       default:
3404          switch(reasonCode)
3405          {
3406             case T_H225ReleaseCompleteReason_noBandwidth:
3407                return OO_REASON_NOBW;
3408             case T_H225ReleaseCompleteReason_gatekeeperResources:
3409                return OO_REASON_GK_NORESOURCES;
3410             case T_H225ReleaseCompleteReason_unreachableDestination:
3411                return OO_REASON_NOROUTE;
3412             case T_H225ReleaseCompleteReason_destinationRejection:
3413                return OO_REASON_REMOTE_REJECTED;
3414             case T_H225ReleaseCompleteReason_inConf:
3415                return OO_REASON_REMOTE_BUSY;
3416             case T_H225ReleaseCompleteReason_facilityCallDeflection:
3417                return OO_REASON_REMOTE_FWDED;
3418             case T_H225ReleaseCompleteReason_calledPartyNotRegistered:
3419                return OO_REASON_GK_NOCALLEDUSER;
3420             case T_H225ReleaseCompleteReason_callerNotRegistered:
3421                return OO_REASON_GK_NOCALLERUSER;
3422             case T_H225ReleaseCompleteReason_gatewayResources:
3423                return OO_REASON_GK_NORESOURCES;
3424             case T_H225ReleaseCompleteReason_unreachableGatekeeper:
3425                return OO_REASON_GK_UNREACHABLE;
3426             case T_H225ReleaseCompleteReason_invalidRevision:
3427             case T_H225ReleaseCompleteReason_noPermission:
3428             case T_H225ReleaseCompleteReason_badFormatAddress:
3429             case T_H225ReleaseCompleteReason_adaptiveBusy:
3430             case T_H225ReleaseCompleteReason_undefinedReason:
3431             case T_H225ReleaseCompleteReason_securityDenied:
3432             case T_H225ReleaseCompleteReason_newConnectionNeeded:
3433             case T_H225ReleaseCompleteReason_nonStandardReason:
3434             case T_H225ReleaseCompleteReason_replaceWithConferenceInvite:
3435             case T_H225ReleaseCompleteReason_genericDataReason:
3436             case T_H225ReleaseCompleteReason_neededFeatureNotSupported:
3437             case T_H225ReleaseCompleteReason_tunnelledSignallingRejected:
3438             case T_H225ReleaseCompleteReason_invalidCID:
3439             case T_H225ReleaseCompleteReason_securityError:
3440             case T_H225ReleaseCompleteReason_hopCountExceeded:
3441             case T_H225ReleaseCompleteReason_extElem1:
3442             default:
3443                return OO_REASON_UNKNOWN;
3444          }
3445    }
3446    return OO_REASON_UNKNOWN;
3447 }
3448
3449 /**
3450  This function is used to parse destination string passed to ooH323MakeCall and
3451  ooH323ForwardCall. If the string contains ip address and port, it is returned
3452  in the parsedIP buffer and if it contains alias, it is added to aliasList
3453 */
3454 int ooParseDestination
3455    (struct OOH323CallData *call, char *dest, char* parsedIP, unsigned len,
3456     ooAliases** aliasList)
3457 {
3458    int iEk=-1, iDon=-1, iTeen=-1, iChaar=-1, iPort = -1, i;
3459    ooAliases * psNewAlias = NULL;
3460    char *cAt = NULL, *host=NULL;
3461    char tmp[256], buf[30];
3462    char *alias=NULL;
3463    OOCTXT *pctxt = call->pctxt;
3464    parsedIP[0] = '\0';
3465
3466    OOTRACEINFO2("Parsing destination %s\n", dest);
3467   
3468    /* Test for an IP address:Note that only supports dotted IPv4.
3469       IPv6 won't pass the test and so will numeric IP representation*/
3470    
3471    sscanf(dest, "%d.%d.%d.%d:%d", &iEk, &iDon, &iTeen, &iChaar, &iPort);
3472    if((iEk > 0            && iEk <= 255)    &&
3473       (iDon >= 0          && iDon <= 255)   &&
3474       (iTeen >=0          && iTeen <= 255)  &&
3475       (iChaar >= 0        && iChaar <= 255) &&
3476       (!strchr(dest, ':') || iPort != -1))
3477    {
3478       if(!strchr(dest, ':'))
3479          iPort = 1720; /*Default h.323 port */
3480
3481       sprintf(buf, "%d.%d.%d.%d:%d", iEk, iDon, iTeen, iChaar, iPort);
3482       if(strlen(buf)+1>len)
3483       {
3484          OOTRACEERR1("Error:Insufficient buffer space for parsed ip - "
3485                      "ooParseDestination\n");
3486          return OO_FAILED;
3487       }
3488          
3489       strcpy(parsedIP, buf);
3490       return OO_OK;
3491    }
3492
3493    /* alias@host */
3494    strncpy(tmp, dest, sizeof(tmp)-1);
3495    tmp[sizeof(tmp)-1]='\0';
3496    if((host=strchr(tmp, '@')) != NULL)
3497    {
3498       *host = '\0';
3499       host++;
3500       sscanf(host, "%d.%d.%d.%d:%d", &iEk, &iDon, &iTeen, &iChaar, &iPort);
3501       if((iEk > 0            && iEk <= 255)    &&
3502          (iDon >= 0          && iDon <= 255)   &&
3503          (iTeen >=0          && iTeen <= 255)  &&
3504          (iChaar >= 0        && iChaar <= 255) &&
3505          (!strchr(host, ':') || iPort != -1))
3506       {
3507          if(!strchr(dest, ':'))
3508             iPort = 1720; /*Default h.323 port */
3509
3510          sprintf(buf, "%d.%d.%d.%d:%d", iEk, iDon, iTeen, iChaar, iPort);
3511          if(strlen(buf)+1>len)
3512          {
3513             OOTRACEERR1("Error:Insufficient buffer space for parsed ip - "
3514                         "ooParseDestination\n");
3515             return OO_FAILED;
3516          }
3517
3518          strncpy(parsedIP, buf, len-1);
3519          parsedIP[len-1]='\0';
3520          alias = tmp;
3521       }
3522    }
3523
3524    if(!alias)
3525    {
3526      alias = dest;
3527    }
3528    /* url test */
3529    if(alias == strstr(alias, "http://"))
3530    {
3531       psNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases));
3532       if(!psNewAlias)
3533       {
3534          OOTRACEERR1("Error:Memory - ooParseDestination - psNewAlias\n");
3535          return OO_FAILED;
3536       }
3537       psNewAlias->type = T_H225AliasAddress_url_ID;
3538       psNewAlias->value = (char*) memAlloc(pctxt, strlen(alias)+1);
3539       if(!psNewAlias->value)
3540       {
3541          OOTRACEERR1("Error:Memory - ooParseDestination - "
3542                      "psNewAlias->value\n");
3543          memFreePtr(pctxt, psNewAlias);
3544          return OO_FAILED;
3545       }
3546       strcpy(psNewAlias->value, alias);
3547       psNewAlias->next = *aliasList;
3548       *aliasList = psNewAlias;
3549       OOTRACEINFO2("Destination parsed as url %s\n", psNewAlias->value);
3550       return OO_OK;
3551    }
3552
3553    /* E-mail ID test */
3554    if((cAt = strchr(alias, '@')) && alias != strchr(alias, '@'))
3555    {
3556       if(strchr(cAt, '.'))
3557       {
3558          psNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases));
3559          if(!psNewAlias)
3560          {
3561             OOTRACEERR1("Error:Memory - ooParseDestination - psNewAlias\n");
3562             return OO_FAILED;
3563          }
3564          psNewAlias->type = T_H225AliasAddress_email_ID;
3565          psNewAlias->value = (char*) memAlloc(pctxt, strlen(alias)+1);
3566          if(!psNewAlias->value)
3567          {
3568             OOTRACEERR1("Error:Memory - ooParseDestination - "
3569                         "psNewAlias->value\n");
3570             memFreePtr(pctxt, psNewAlias);
3571             return OO_FAILED;
3572          }
3573          strcpy(psNewAlias->value, alias);
3574          psNewAlias->next = *aliasList;
3575          *aliasList = psNewAlias;
3576          OOTRACEINFO2("Destination is parsed as email %s\n",psNewAlias->value);
3577          return OO_OK;
3578       }
3579    }
3580
3581   
3582    /* e-164 */
3583    /* strspn(dest, "1234567890*#,") == strlen(dest)*/
3584    /* Dialed digits test*/
3585    for(i=0; *(alias+i) != '\0'; i++)
3586    {
3587       if(!isdigit(alias[i]) && alias[i] != '#' && alias[i] != '*' && 
3588          alias[i] != ',')
3589          break;
3590    }
3591    if(*(alias+i) == '\0')
3592    {
3593       psNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases));
3594       if(!psNewAlias)
3595       {
3596          OOTRACEERR1("Error:Memory - ooParseDestination - psNewAlias\n");
3597          return OO_FAILED;
3598       }
3599       /*      memset(psNewAlias, 0, sizeof(ooAliases));*/
3600       psNewAlias->type = T_H225AliasAddress_dialedDigits;
3601       psNewAlias->value = (char*) memAlloc(pctxt, strlen(alias)+1);
3602       if(!psNewAlias->value)
3603       {
3604          OOTRACEERR1("Error:Memroy - ooParseDestination - "
3605                      "psNewAlias->value\n");
3606          memFreePtr(pctxt, psNewAlias);
3607          return OO_FAILED;
3608       }
3609       strcpy(psNewAlias->value, alias);
3610       psNewAlias->next = *aliasList;
3611       *aliasList = psNewAlias;
3612       OOTRACEINFO2("Destination is parsed as dialed digits %s\n",
3613                   psNewAlias->value);
3614       /* Also set called party number */
3615       if(!call->calledPartyNumber)
3616       {
3617          if(ooCallSetCalledPartyNumber(call, alias) != OO_OK)
3618          {
3619             OOTRACEWARN3("Warning:Failed to set calling party number."
3620                          "(%s, %s)\n", call->callType, call->callToken);
3621          }
3622       }
3623       return OO_OK;
3624    }
3625    /* Evrything else is an h323-id for now */
3626    psNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases));
3627    if(!psNewAlias)
3628    {
3629       OOTRACEERR1("Error:Memory - ooParseDestination - psNewAlias\n");
3630       return OO_FAILED;
3631    }
3632    psNewAlias->type = T_H225AliasAddress_h323_ID;
3633    psNewAlias->value = (char*) memAlloc(pctxt, strlen(alias)+1);
3634    if(!psNewAlias->value)
3635    {
3636       OOTRACEERR1("Error:Memory - ooParseDestination - psNewAlias->value\n");
3637       memFreePtr(pctxt, psNewAlias);
3638       return OO_FAILED;
3639    }
3640    strcpy(psNewAlias->value, alias);
3641    psNewAlias->next = *aliasList;
3642    *aliasList = psNewAlias;
3643    OOTRACEINFO2("Destination for new call is parsed as h323-id %s \n",
3644                psNewAlias->value);
3645    return OO_OK;
3646 }
3647
3648 const char* ooGetMsgTypeText (int msgType)
3649 {
3650    static const char *msgTypeText[]={
3651       "OOQ931MSG",
3652       "OOH245MSG",
3653       "OOSetup",
3654       "OOCallProceeding",
3655       "OOAlert",
3656       "OOConnect",
3657       "OOReleaseComplete",
3658       "OOFacility",
3659       "OOInformation",
3660       "OOMasterSlaveDetermination",
3661       "OOMasterSlaveAck",
3662       "OOMasterSlaveReject",
3663       "OOMasterSlaveRelease",
3664       "OOTerminalCapabilitySet",
3665       "OOTerminalCapabilitySetAck",
3666       "OOTerminalCapabilitySetReject",
3667       "OOTerminalCapabilitySetRelease",
3668       "OOOpenLogicalChannel",
3669       "OOOpenLogicalChannelAck",
3670       "OOOpenLogicalChannelReject",
3671       "OOOpenLogicalChannelRelease",
3672       "OOOpenLogicalChannelConfirm",
3673       "OOCloseLogicalChannel",
3674       "OOCloseLogicalChannelAck",
3675       "OORequestChannelClose",
3676       "OORequestChannelCloseAck",
3677       "OORequestChannelCloseReject",
3678       "OORequestChannelCloseRelease",
3679       "OOEndSessionCommand",
3680       "OOUserInputIndication",
3681       "OORequestModeAck",
3682       "OORequestModeReject",
3683       "OORequestMode",
3684       "OORequestDelayResponse",
3685       "OORequestDelayRequest"
3686    };
3687    int idx = msgType - OO_MSGTYPE_MIN;
3688    return ooUtilsGetText (idx, msgTypeText, OONUMBEROF(msgTypeText));
3689 }
3690
3691 const char* ooGetQ931CauseValueText(int val)
3692 {
3693    switch(val)
3694    {
3695       case Q931UnallocatedNumber:   
3696          return "Q931UnallocatedNumber";
3697       case Q931NoRouteToNetwork:
3698          return "Q931NoRouteToNetwork";
3699       case Q931NoRouteToDestination:
3700          return "Q931NoRouteToDestination";
3701       case Q931ChannelUnacceptable: 
3702          return "Q931ChannelUnacceptable";
3703       case Q931NormalCallClearing:
3704          return "Q931NormalCallClearing";
3705       case Q931UserBusy:
3706          return "Q931UserBusy";
3707       case Q931NoResponse:
3708          return "Q931NoResponse";
3709       case Q931NoAnswer:
3710          return "Q931NoAnswer";
3711       case Q931SubscriberAbsent:
3712          return "Q931SubscriberAbsent";
3713       case Q931CallRejected:
3714          return "Q931CallRejected";
3715       case Q931NumberChanged:
3716          return "Q931NumberChanged";
3717       case Q931Redirection:
3718          return "Q931Redirection";
3719       case Q931DestinationOutOfOrder:
3720          return "Q931DestinationOutOfOrder";
3721       case Q931InvalidNumberFormat:
3722          return "Q931InvalidNumberFormat";
3723       case Q931NormalUnspecified:
3724          return "Q931NormalUnspecified";
3725       case Q931StatusEnquiryResponse:
3726          return "Q931StatusEnquiryResponse";
3727       case Q931NoCircuitChannelAvailable:
3728          return "Q931NoCircuitChannelAvailable";
3729       case Q931NetworkOutOfOrder:
3730          return "Q931NetworkOutOfOrder";
3731       case Q931TemporaryFailure:
3732          return "Q931TemporaryFailure";
3733       case Q931Congestion:
3734          return "Q931Congestion";
3735       case Q931RequestedCircuitUnAvailable:
3736          return "Q931RequestedCircuitUnavailable";
3737       case Q931ResourcesUnavailable:
3738          return "Q931ResourcesUnavailable";
3739       case Q931IncompatibleDestination:
3740          return "Q931IncompatibleDestination";
3741       case Q931ProtocolErrorUnspecified:
3742          return "Q931ProtocolErrorUnspecified";
3743       case Q931RecoveryOnTimerExpiry:
3744          return "Q931RecoveryOnTimerExpiry";
3745       case Q931InvalidCallReference:
3746          return "Q931InvaliedCallReference";
3747       default:
3748          return "Unsupported Cause Type";
3749    }
3750    return "Unsupported Cause Type";
3751 }
3752