Fix chan_ooh323 so it works on Mac OS X, as well.
[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);
1387    else
1388       ret = ooPopulateAliasList(pctxt, gH323ep.aliases,
1389                                        &alerting->alertingAddress);
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);
1893    else
1894       ret =  ooPopulateAliasList(pctxt, gH323ep.aliases, 
1895                                         &connect->connectedAddress);
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=0, 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    ast_mutex_unlock(&call->Lock);
2220
2221    return OO_OK;
2222 }
2223
2224
2225 int ooH323CallAdmitted(OOH323CallData *call)
2226 {
2227    int ret=0;
2228       
2229    if(!call)
2230    {
2231       /* Call not supplied. Must locate it in list */
2232       OOTRACEERR1("ERROR: Invalid call parameter to ooH323CallAdmitted");
2233       return OO_FAILED; 
2234    }
2235
2236    if(!strcmp(call->callType, "outgoing")) {
2237       ret = ooCreateH225Connection(call);
2238       if(ret != OO_OK)
2239       {
2240          OOTRACEERR3("ERROR:Failed to create H225 connection to %s:%d\n", 
2241                       call->remoteIP, call->remotePort);
2242          if(call->callState< OO_CALL_CLEAR)
2243          {
2244             call->callState = OO_CALL_CLEAR;
2245             call->callEndReason = OO_REASON_UNKNOWN;
2246          }
2247          return OO_FAILED;
2248       }
2249
2250       if(gH323ep.h323Callbacks.onOutgoingCall) {
2251          /* Outgoing call callback function */
2252          gH323ep.h323Callbacks.onOutgoingCall(call);
2253       }
2254       
2255       ret = ooH323MakeCall_helper(call);
2256    } 
2257    else { 
2258       /* incoming call */
2259       if(gH323ep.h323Callbacks.onIncomingCall) {
2260          /* Incoming call callback function */
2261          gH323ep.h323Callbacks.onIncomingCall(call);
2262       }
2263
2264       /* Check for manual ringback generation */
2265       if(!OO_TESTFLAG(gH323ep.flags, OO_M_MANUALRINGBACK))
2266       {
2267          ooSendAlerting(call); /* Send alerting message */
2268
2269          if(OO_TESTFLAG(gH323ep.flags, OO_M_AUTOANSWER)) {
2270             ooSendConnect(call); /* Send connect message - call accepted */
2271          }
2272       }
2273    }
2274    
2275    return OO_OK;
2276 }
2277
2278 int ooH323MakeCall_helper(OOH323CallData *call)
2279 {
2280    int ret=0,i=0, k;
2281    Q931Message *q931msg = NULL;
2282    H225Setup_UUIE *setup;
2283
2284    ASN1DynOctStr *pFS=NULL;
2285    H225TransportAddress_ipAddress *destCallSignalIpAddress;
2286
2287    H225TransportAddress_ipAddress *srcCallSignalIpAddress;
2288    ooH323EpCapability *epCap=NULL;
2289    OOCTXT *pctxt = NULL;
2290    H245OpenLogicalChannel *olc, printOlc;
2291    ASN1BOOL aligned = 1;
2292    ooAliases *pAlias = NULL;
2293
2294    /* pctxt = &gH323ep.msgctxt; */
2295    pctxt = call->msgctxt;
2296      
2297    ret = ooCreateQ931Message(pctxt, &q931msg, Q931SetupMsg);
2298    if(ret != OO_OK)
2299    {
2300       OOTRACEERR1("ERROR:Failed to Create Q931 SETUP Message\n ");
2301       return OO_FAILED;
2302    }
2303
2304    q931msg->callReference = call->callReference;
2305
2306    /* Set bearer capability */
2307    if(OO_OK != ooSetBearerCapabilityIE(pctxt, q931msg, Q931CCITTStd, 
2308                           // Q931TransferUnrestrictedDigital, Q931TransferPacketMode,
2309                           call->transfercap, Q931TransferCircuitMode,
2310                           // Q931TransferRatePacketMode, Q931UserInfoLayer1G722G725))
2311                           Q931TransferRate64Kbps, Q931UserInfoLayer1G711ALaw))
2312    {
2313       OOTRACEERR3("Error: Failed to set bearer capability ie.(%s, %s)\n",
2314                    call->callType, call->callToken);
2315       return OO_FAILED;
2316    }
2317
2318    /* Set calling party number  Q931 IE */
2319    if(call->callingPartyNumber && call->callingPartyNumber[0])
2320      ooQ931SetCallingPartyNumberIE(pctxt, q931msg,
2321                             (const char*)call->callingPartyNumber, 1, 0, 0, 0);
2322    
2323
2324    /* Set called party number Q931 IE */
2325    if(call->calledPartyNumber)
2326       ooQ931SetCalledPartyNumberIE(pctxt, q931msg, 
2327                             (const char*)call->calledPartyNumber, 1, 0);
2328    else if(call->remoteAliases) {
2329       pAlias = call->remoteAliases;
2330       while(pAlias) {
2331          if(pAlias->type == T_H225AliasAddress_dialedDigits)
2332             break;
2333          pAlias = pAlias->next;
2334       }
2335       if(pAlias)
2336       {
2337          call->calledPartyNumber = (char*)memAlloc(call->pctxt, 
2338                                                    strlen(pAlias->value)+1);
2339          if(!call->calledPartyNumber)
2340          {
2341             OOTRACEERR3("Error:Memory - ooH323MakeCall_helper - "
2342                         "calledPartyNumber(%s, %s)\n", call->callType, 
2343                         call->callToken);
2344             return OO_FAILED;
2345          }
2346          strcpy(call->calledPartyNumber, pAlias->value);
2347          ooQ931SetCalledPartyNumberIE(pctxt, q931msg, 
2348                             (const char*)call->calledPartyNumber, 1, 0);
2349       }
2350
2351    }
2352
2353    q931msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
2354                              sizeof(H225H323_UserInformation));
2355    if(!q931msg->userInfo)
2356    {
2357       OOTRACEERR1("ERROR:Memory - ooH323MakeCall_helper - userInfo\n");
2358       return OO_FAILED;
2359    }
2360    memset(q931msg->userInfo, 0, sizeof(H225H323_UserInformation));
2361
2362    setup = (H225Setup_UUIE*) memAlloc(pctxt, sizeof(H225Setup_UUIE));
2363    if(!setup)
2364    {
2365       OOTRACEERR3("Error:Memory -  ooH323MakeCall_helper - setup (%s, %s)\n",
2366                  call->callType, call->callToken);
2367       return OO_FAILED;
2368    }
2369    memset (setup, 0, sizeof(H225Setup_UUIE));
2370    setup->protocolIdentifier = gProtocolID;
2371    
2372    /* Populate Alias Address.*/
2373
2374    if(call->ourAliases || gH323ep.aliases)
2375    {   
2376       setup->m.sourceAddressPresent = TRUE;
2377       if(call->ourAliases)
2378          ret = ooPopulateAliasList(pctxt, call->ourAliases, 
2379                                                        &setup->sourceAddress);
2380       else if(gH323ep.aliases)
2381          ret =  ooPopulateAliasList(pctxt, gH323ep.aliases, 
2382                                                        &setup->sourceAddress);
2383       if(OO_OK != ret)
2384       {
2385          OOTRACEERR1("Error:Failed to populate alias list in SETUP message\n");
2386          memReset(pctxt);
2387          return OO_FAILED;
2388       }
2389    }
2390
2391    setup->m.presentationIndicatorPresent = TRUE;
2392    setup->presentationIndicator.t = 
2393                              T_H225PresentationIndicator_presentationAllowed;
2394    setup->m.screeningIndicatorPresent = TRUE;
2395    setup->screeningIndicator = userProvidedNotScreened;
2396
2397    setup->m.multipleCallsPresent = TRUE;
2398    setup->multipleCalls = FALSE;
2399    setup->m.maintainConnectionPresent = TRUE;
2400    setup->maintainConnection = FALSE;
2401
2402    /* Populate Destination aliases */
2403    if(call->remoteAliases)
2404    {
2405       setup->m.destinationAddressPresent = TRUE;
2406       ret = ooPopulateAliasList(pctxt, call->remoteAliases, 
2407                                                  &setup->destinationAddress);
2408       if(OO_OK != ret)
2409       {
2410          OOTRACEERR1("Error:Failed to populate destination alias list in SETUP"
2411                      "message\n");
2412          memReset(pctxt);
2413          return OO_FAILED;
2414       }
2415    }
2416
2417    /* Populate the vendor information */
2418    if(gH323ep.isGateway)
2419       setup->sourceInfo.m.gatewayPresent = TRUE;
2420    else
2421       setup->sourceInfo.m.terminalPresent = TRUE;
2422
2423    setup->sourceInfo.m.vendorPresent=TRUE;
2424    setup->sourceInfo.vendor.vendor.t35CountryCode = gH323ep.t35CountryCode;
2425    setup->sourceInfo.vendor.vendor.t35Extension = gH323ep.t35Extension;
2426    setup->sourceInfo.vendor.vendor.manufacturerCode= gH323ep.manufacturerCode;
2427    
2428    if(gH323ep.productID)
2429    {
2430       setup->sourceInfo.vendor.m.productIdPresent=TRUE;
2431       setup->sourceInfo.vendor.productId.numocts = ASN1MIN(
2432                               strlen(gH323ep.productID), 
2433                               sizeof(setup->sourceInfo.vendor.productId.data));
2434       strncpy((char*)setup->sourceInfo.vendor.productId.data, 
2435                 gH323ep.productID, setup->sourceInfo.vendor.productId.numocts);
2436    }
2437    else
2438       setup->sourceInfo.vendor.m.productIdPresent=FALSE;
2439    
2440    if(gH323ep.versionID)
2441    {
2442       setup->sourceInfo.vendor.m.versionIdPresent=TRUE;
2443       setup->sourceInfo.vendor.versionId.numocts = ASN1MIN(
2444                               strlen(gH323ep.versionID), 
2445                               sizeof(setup->sourceInfo.vendor.versionId.data));
2446       strncpy((char*)setup->sourceInfo.vendor.versionId.data, 
2447               gH323ep.versionID, setup->sourceInfo.vendor.versionId.numocts);
2448    }
2449    else
2450       setup->sourceInfo.vendor.m.versionIdPresent=FALSE;
2451    
2452    setup->sourceInfo.mc = FALSE;
2453    setup->sourceInfo.undefinedNode = FALSE;
2454
2455    /* Populate the destination Call Signal Address */
2456    setup->destCallSignalAddress.t=T_H225TransportAddress_ipAddress;
2457    destCallSignalIpAddress = (H225TransportAddress_ipAddress*)memAlloc(pctxt,
2458                                   sizeof(H225TransportAddress_ipAddress));
2459    if(!destCallSignalIpAddress)
2460    {
2461       OOTRACEERR3("Error:Memory -  ooH323MakeCall_helper - "
2462                  "destCallSignalAddress. (%s, %s)\n", call->callType, 
2463                  call->callToken);
2464       return OO_FAILED;
2465    }
2466    ooSocketConvertIpToNwAddr(call->remoteIP, destCallSignalIpAddress->ip.data);
2467
2468    destCallSignalIpAddress->ip.numocts=4;
2469    destCallSignalIpAddress->port = call->remotePort;
2470
2471    setup->destCallSignalAddress.u.ipAddress = destCallSignalIpAddress;
2472    setup->m.destCallSignalAddressPresent=TRUE;
2473    setup->activeMC=FALSE;
2474
2475    /* Populate the source Call Signal Address */
2476    setup->sourceCallSignalAddress.t=T_H225TransportAddress_ipAddress;
2477    srcCallSignalIpAddress = (H225TransportAddress_ipAddress*)memAlloc(pctxt,
2478                                   sizeof(H225TransportAddress_ipAddress));
2479    if(!srcCallSignalIpAddress)
2480    {
2481       OOTRACEERR3("Error:Memory - ooH323MakeCall_helper - srcCallSignalAddress"
2482                   "(%s, %s)\n", call->callType, call->callToken);
2483       return OO_FAILED;
2484    }
2485    ooSocketConvertIpToNwAddr(call->localIP, srcCallSignalIpAddress->ip.data);
2486
2487    srcCallSignalIpAddress->ip.numocts=4;
2488    srcCallSignalIpAddress->port= call->pH225Channel->port;
2489    setup->sourceCallSignalAddress.u.ipAddress = srcCallSignalIpAddress;
2490    setup->m.sourceCallSignalAddressPresent=TRUE;
2491    /* No fast start */
2492    if(!OO_TESTFLAG(call->flags, OO_M_FASTSTART))
2493    {
2494       setup->m.fastStartPresent = FALSE;
2495    }
2496    else{
2497       setup->m.fastStartPresent = TRUE;
2498       pFS = (ASN1DynOctStr*)memAlloc(pctxt, gH323ep.noOfCaps*
2499                                        sizeof(ASN1DynOctStr));
2500       if(!pFS)
2501       {
2502          OOTRACEERR3("Error:Memory - ooH323MakeCall_helper - pFS(%s, %s)\n",
2503                      call->callType, call->callToken);
2504          return OO_FAILED;
2505       }
2506
2507       /* Use preference order of codecs */
2508       i=0;
2509       for(k=0; k< call->capPrefs.index; k++)
2510       {
2511          OOTRACEDBGC5("Preffered capability at index %d is %s. (%s, %s)\n",
2512                       k, ooGetCapTypeText(call->capPrefs.order[k]), 
2513                       call->callType, call->callToken);
2514
2515          if(call->ourCaps) {
2516             epCap = call->ourCaps;
2517             OOTRACEDBGC3("Using call specific capabilities in faststart of "
2518                          "setup message. (%s, %s)\n", call->callType, 
2519                          call->callToken);
2520          }
2521          else{
2522             epCap = gH323ep.myCaps;
2523             OOTRACEDBGC3("Using end-point capabilities for faststart of setup"
2524                          "message. (%s, %s)\n", call->callType, 
2525                          call->callToken);
2526          }
2527
2528          while(epCap){
2529             if(epCap->cap == call->capPrefs.order[k]) break;
2530             else epCap = epCap->next;
2531          }
2532          if(!epCap)
2533          {
2534             OOTRACEWARN4("Warn:Preferred capability %s is abscent in "
2535                          "capability list. (%s, %s)\n", 
2536                          ooGetCapTypeText(call->capPrefs.order[k]), 
2537                          call->callType, call->callToken);
2538             continue;
2539          }
2540
2541 /* don't send t38/other data caps in fasstart olcs */
2542
2543          if (epCap->capType == OO_CAP_TYPE_DATA)
2544                 continue;
2545
2546          OOTRACEDBGC4("Building olcs with capability %s. (%s, %s)\n", 
2547                       ooGetCapTypeText(epCap->cap), call->callType, 
2548                       call->callToken);
2549          if(epCap->dir & OORX)
2550          {
2551             olc = (H245OpenLogicalChannel*)memAlloc(pctxt, 
2552                                              sizeof(H245OpenLogicalChannel));
2553             if(!olc)
2554             {
2555                OOTRACEERR3("ERROR:Memory - ooH323MakeCall_helper - olc(%s, %s)"
2556                            "\n", call->callType, call->callToken);
2557                ooFreeQ931Message(pctxt, q931msg);
2558                if(call->callState < OO_CALL_CLEAR)
2559                {
2560                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2561                   call->callState = OO_CALL_CLEAR;
2562                }
2563                return OO_FAILED;
2564             }
2565             memset(olc, 0, sizeof(H245OpenLogicalChannel));
2566             olc->forwardLogicalChannelNumber = call->logicalChanNoCur++; 
2567             if(call->logicalChanNoCur > call->logicalChanNoMax)
2568                call->logicalChanNoCur = call->logicalChanNoBase;
2569         
2570             ooBuildFastStartOLC(call, olc, epCap, pctxt, OORX);
2571             /* Do not specify msg buffer let automatic allocation work */
2572             setPERBuffer(pctxt, NULL, 0, aligned);
2573             if(asn1PE_H245OpenLogicalChannel(pctxt, olc) != ASN_OK)
2574             {
2575                OOTRACEERR3("ERROR:Encoding of olc failed for faststart(%s, %s)"
2576                            "\n", call->callType, call->callToken);
2577                ooFreeQ931Message(pctxt, q931msg);
2578                if(call->callState < OO_CALL_CLEAR)
2579                {
2580                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2581                   call->callState = OO_CALL_CLEAR;
2582                }
2583                return OO_FAILED;
2584             }
2585             pFS[i].data = (unsigned char *)encodeGetMsgPtr(pctxt, (int *)&(pFS[i].numocts));
2586
2587
2588             /* Dump faststart element in logfile for debugging purpose */
2589             setPERBuffer(pctxt,  (unsigned char*)pFS[i].data, pFS[i].numocts, 1);
2590             initializePrintHandler(&printHandler, "FastStart Element");
2591             setEventHandler (pctxt, &printHandler);
2592             memset(&printOlc, 0, sizeof(printOlc));
2593             ret = asn1PD_H245OpenLogicalChannel(pctxt, &(printOlc));
2594             if(ret != ASN_OK)
2595             {
2596                OOTRACEERR3("Error: Failed decoding FastStart Element."
2597                            "(%s, %s)\n", call->callType, call->callToken);
2598                ooFreeQ931Message(pctxt, q931msg);
2599                if(call->callState < OO_CALL_CLEAR)
2600                {
2601                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2602                   call->callState = OO_CALL_CLEAR;
2603                }
2604                return OO_FAILED;
2605             }
2606             finishPrint();
2607             removeEventHandler(pctxt); 
2608
2609
2610             olc = NULL;
2611             i++;
2612             OOTRACEDBGC5("Added RX fs element %d with capability %s(%s, %s)\n",
2613                           i, ooGetCapTypeText(epCap->cap), call->callType, 
2614                           call->callToken);
2615          }
2616
2617          if(epCap->dir & OOTX)
2618          {
2619             olc = (H245OpenLogicalChannel*)memAlloc(pctxt, 
2620                                              sizeof(H245OpenLogicalChannel));
2621             if(!olc)
2622             {
2623                OOTRACEERR3("ERROR:Memory - ooH323MakeCall_helper - olc(%s, %s)"
2624                            "\n", call->callType, call->callToken);
2625                ooFreeQ931Message(pctxt, q931msg);
2626                if(call->callState < OO_CALL_CLEAR)
2627                {
2628                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2629                   call->callState = OO_CALL_CLEAR;
2630                }
2631                return OO_FAILED;
2632             }
2633             memset(olc, 0, sizeof(H245OpenLogicalChannel));
2634             olc->forwardLogicalChannelNumber = call->logicalChanNoCur++; 
2635             if(call->logicalChanNoCur > call->logicalChanNoMax)
2636                call->logicalChanNoCur = call->logicalChanNoBase;
2637         
2638             ooBuildFastStartOLC(call, olc, epCap, pctxt, OOTX);
2639             /* Do not specify msg buffer let automatic allocation work */
2640             setPERBuffer(pctxt, NULL, 0, aligned);
2641             if(asn1PE_H245OpenLogicalChannel(pctxt, olc) != ASN_OK)
2642             {
2643                OOTRACEERR3("ERROR:Encoding of olc failed for faststart(%s, %s)"
2644                            "\n", call->callType, call->callToken);
2645                ooFreeQ931Message(pctxt, q931msg);
2646                if(call->callState < OO_CALL_CLEAR)
2647                {
2648                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2649                   call->callState = OO_CALL_CLEAR;
2650                }
2651                return OO_FAILED;
2652             }
2653             pFS[i].data = (unsigned char *)encodeGetMsgPtr(pctxt, (int *)&(pFS[i].numocts));
2654
2655             /* Dump faststart element in logfile for debugging purpose */
2656             setPERBuffer(pctxt,  (unsigned char*)pFS[i].data, pFS[i].numocts, 1);
2657             initializePrintHandler(&printHandler, "FastStart Element");
2658             setEventHandler (pctxt, &printHandler);
2659             memset(&printOlc, 0, sizeof(printOlc));
2660             ret = asn1PD_H245OpenLogicalChannel(pctxt, &(printOlc));
2661             if(ret != ASN_OK)
2662             {
2663                OOTRACEERR3("Error: Failed decoding FastStart Element."
2664                            "(%s, %s)\n", call->callType, call->callToken);
2665                ooFreeQ931Message(pctxt, q931msg);
2666                if(call->callState < OO_CALL_CLEAR)
2667                {
2668                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2669                   call->callState = OO_CALL_CLEAR;
2670                }
2671                return OO_FAILED;
2672             }
2673             finishPrint();
2674             removeEventHandler(pctxt); 
2675
2676
2677             olc = NULL;
2678             i++;
2679             OOTRACEDBGC5("Added TX fs element %d with capability %s(%s, %s)\n",
2680                           i, ooGetCapTypeText(epCap->cap), call->callType, 
2681                           call->callToken);
2682          }
2683
2684       }
2685       OOTRACEDBGA4("Added %d fast start elements to SETUP message (%s, %s)\n",
2686                    i, call->callType, call->callToken);
2687       setup->fastStart.n = i;
2688       setup->fastStart.elem = pFS; 
2689    }
2690
2691    setup->conferenceID.numocts= call->confIdentifier.numocts;
2692    memcpy(setup->conferenceID.data, call->confIdentifier.data,
2693           call->confIdentifier.numocts);
2694
2695    setup->conferenceGoal.t = T_H225Setup_UUIE_conferenceGoal_create;
2696    /* H.225 point to point call */
2697    setup->callType.t = T_H225CallType_pointToPoint;
2698  
2699    /* Populate optional fields */
2700    setup->m.callIdentifierPresent = TRUE;
2701    /*ooGenerateCallIdentifier(&setup->callIdentifier);*/
2702    setup->callIdentifier.guid.numocts = call->callIdentifier.guid.numocts;
2703    memcpy(setup->callIdentifier.guid.data, call->callIdentifier.guid.data, 
2704                                call->callIdentifier.guid.numocts);
2705    
2706    setup->m.mediaWaitForConnectPresent = TRUE;
2707    if(OO_TESTFLAG(call->flags, OO_M_MEDIAWAITFORCONN)) {
2708       setup->mediaWaitForConnect = TRUE;
2709    }
2710    else {
2711       setup->mediaWaitForConnect = FALSE;
2712    }
2713    setup->m.canOverlapSendPresent = TRUE;
2714    setup->canOverlapSend = FALSE;
2715
2716    /* Populate the userInfo structure with the setup UUIE */ 
2717    
2718    q931msg->userInfo->h323_uu_pdu.h323_message_body.t = 
2719          T_H225H323_UU_PDU_h323_message_body_setup;
2720    q931msg->userInfo->h323_uu_pdu.h323_message_body.u.setup = setup;
2721    q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
2722    
2723    q931msg->userInfo->h323_uu_pdu.h245Tunneling = 
2724       OO_TESTFLAG (call->flags, OO_M_TUNNELING);
2725
2726    /* For H.323 version 4 and higher, if fast connect, tunneling should be 
2727       supported.
2728    */
2729    if(OO_TESTFLAG(call->flags, OO_M_FASTSTART)) {
2730       q931msg->userInfo->h323_uu_pdu.h245Tunneling = TRUE;
2731       OO_SETFLAG(call->flags, OO_M_TUNNELING);
2732    }
2733
2734    OOTRACEDBGA3("Built SETUP message (%s, %s)\n", call->callType, 
2735                  call->callToken);
2736    
2737    /* H225 message callback */
2738    if(gH323ep.h225Callbacks.onBuiltSetup)
2739       gH323ep.h225Callbacks.onBuiltSetup(call, q931msg);
2740
2741    ret=ooSendH225Msg(call, q931msg);
2742    if(ret != OO_OK)
2743    {
2744      OOTRACEERR3("Error:Failed to enqueue SETUP message to outbound queue. (%s, %s)\n", call->callType, call->callToken);
2745    }
2746    /* memReset(&gH323ep.msgctxt);*/
2747    memReset(call->msgctxt);
2748
2749    return ret;
2750 }
2751
2752
2753
2754 int ooQ931SendDTMFAsKeyPadIE(OOH323CallData *call, const char* data)
2755 {
2756    int ret;    
2757    H225Information_UUIE *information=NULL;
2758    Q931Message *q931msg=NULL;
2759    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
2760    OOCTXT *pctxt = call->msgctxt;
2761
2762    ret = ooCreateQ931Message(pctxt, &q931msg, Q931InformationMsg);
2763    if(ret != OO_OK)
2764    {      
2765       OOTRACEERR3("Error: In allocating memory for - H225 Information message."
2766                   "(%s, %s)\n", call->callType, call->callToken);
2767       return OO_FAILED;
2768    }
2769
2770    q931msg->callReference = call->callReference;
2771
2772    q931msg->userInfo = (H225H323_UserInformation*)memAllocZ(pctxt,
2773                              sizeof(H225H323_UserInformation));
2774    if(!q931msg->userInfo)
2775    {
2776       OOTRACEERR3("ERROR:Memory -  ooQ931SendDTMFAsKeypadIE - userInfo"
2777                   "(%s, %s)\n", call->callType, call->callToken);
2778       /* memReset(&gH323ep.msgctxt); */
2779       memReset(call->msgctxt);
2780       return OO_FAILED;
2781    }
2782    q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
2783    q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(call->flags, 
2784                                                               OO_M_TUNNELING); 
2785    q931msg->userInfo->h323_uu_pdu.h323_message_body.t = 
2786          T_H225H323_UU_PDU_h323_message_body_information;
2787    
2788    information = (H225Information_UUIE*)memAllocZ(pctxt, 
2789                                              sizeof(H225Information_UUIE));
2790    if(!information)
2791    {
2792       OOTRACEERR3("ERROR:Memory -  ooQ931SendDTMFAsKeypadIE - information"
2793                   "(%s, %s)\n", call->callType, call->callToken);
2794       /* memReset(&gH323ep.msgctxt); */
2795       memReset(call->msgctxt);
2796       return OO_FAILED;
2797    }
2798    q931msg->userInfo->h323_uu_pdu.h323_message_body.u.information = 
2799                                                                   information; 
2800    information->m.callIdentifierPresent = 1;
2801    information->callIdentifier.guid.numocts = 
2802                                    call->callIdentifier.guid.numocts;
2803    memcpy(information->callIdentifier.guid.data, 
2804           call->callIdentifier.guid.data, 
2805           call->callIdentifier.guid.numocts);
2806    information->protocolIdentifier = gProtocolID;
2807    
2808    /*Add keypad IE*/
2809    ret = ooQ931SetKeypadIE(pctxt, q931msg, data);
2810    if(ret != OO_OK)
2811    {
2812       OOTRACEERR3("Error:Creating keypad IE for (%s, %s)\n", call->callType, 
2813                    call->callToken);
2814       /* memReset(&gH323ep.msgctxt); */
2815       memReset(call->msgctxt);
2816       return OO_FAILED;
2817    }
2818
2819    ret=ooSendH225Msg(call, q931msg);
2820    if(ret != OO_OK)
2821    {
2822       OOTRACEERR3("Error:Failed to enqueue Information message to outbound "
2823                   "queue. (%s, %s)\n", call->callType, call->callToken);
2824    }
2825    /* memReset(&gH323ep.msgctxt); */
2826    memReset(call->msgctxt);
2827
2828    return ret;
2829
2830 }
2831
2832 int ooH323ForwardCall(char* callToken, char *dest)
2833 {
2834    int ret=0;
2835    Q931Message *pQ931Msg = NULL;
2836    H225Facility_UUIE *facility=NULL;
2837    OOCTXT *pctxt = &gH323ep.msgctxt;
2838    OOH323CallData *call;
2839    char ip[30]="\0", *pcPort=NULL;
2840    H225TransportAddress_ipAddress *fwdCallSignalIpAddress;
2841
2842    call= ooFindCallByToken(callToken);
2843    if(!call)
2844    {
2845       OOTRACEERR2("ERROR: Invalid call token for forward - %s\n", callToken);
2846       return OO_FAILED;
2847    }
2848    OOTRACEDBGA3("Building Facility message for call forward (%s, %s)\n", 
2849                                               call->callType, call->callToken);
2850    call->pCallFwdData = (OOCallFwdData*)memAllocZ(call->pctxt, 
2851                                                      sizeof(OOCallFwdData));
2852    if(!call->pCallFwdData)
2853    {
2854      OOTRACEERR3("Error:Memory - ooH323ForwardCall - pCallFwdData (%s, %s)\n",
2855      call->callType, call->callToken);
2856      return OO_FAILED;
2857    }
2858
2859    ret = ooParseDestination(call, dest, ip, 20, 
2860                                              &call->pCallFwdData->aliases);
2861    if(ret != OO_OK)
2862    {
2863       OOTRACEERR4("Error:Failed to parse the destination %s for call fwd."
2864                   "(%s, %s)\n", dest, call->callType, call->callToken);
2865       memFreePtr(call->pctxt, call->pCallFwdData);
2866       return OO_FAILED;
2867    }
2868
2869    if(!ooUtilsIsStrEmpty(ip))
2870    {
2871       pcPort = strchr(ip, ':');
2872       if(pcPort)
2873       {
2874          *pcPort = '\0';
2875          pcPort++;
2876          call->pCallFwdData->port = atoi(pcPort);
2877       }
2878       strcpy(call->pCallFwdData->ip, ip);
2879    }
2880
2881    ret = ooCreateQ931Message(pctxt, &pQ931Msg, Q931FacilityMsg);
2882    if(ret != OO_OK)
2883    {
2884       OOTRACEERR3
2885          ("ERROR: In allocating memory for call transfer facility message "
2886           "(%s, %s)\n", call->callType, call->callToken);
2887       return OO_FAILED;
2888    }
2889
2890    pQ931Msg->callReference = call->callReference;
2891
2892    pQ931Msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
2893                              sizeof(H225H323_UserInformation));
2894    if(!pQ931Msg->userInfo)
2895    {
2896       OOTRACEERR3("ERROR:Memory - ooH323ForwardCall - userInfo(%s, %s)\n", 
2897                    call->callType, call->callToken);
2898       return OO_FAILED;
2899    }
2900    memset (pQ931Msg->userInfo, 0, sizeof(H225H323_UserInformation));
2901    pQ931Msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
2902
2903    pQ931Msg->userInfo->h323_uu_pdu.h245Tunneling = 
2904                                    OO_TESTFLAG (call->flags, OO_M_TUNNELING); 
2905
2906    pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.t = 
2907       T_H225H323_UU_PDU_h323_message_body_facility;
2908    
2909    facility = (H225Facility_UUIE*) 
2910       memAllocZ (pctxt, sizeof(H225Facility_UUIE));
2911
2912    if(!facility)
2913    {
2914       OOTRACEERR3("ERROR:Memory - ooH323ForwardCall - facility (%s, %s)"
2915                   "\n", call->callType, call->callToken);
2916       return OO_FAILED;
2917    }
2918
2919    pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.u.facility = facility;
2920    
2921    facility->protocolIdentifier = gProtocolID;  
2922    facility->m.callIdentifierPresent = 1;
2923    facility->callIdentifier.guid.numocts = 
2924       call->callIdentifier.guid.numocts;
2925
2926    memcpy(facility->callIdentifier.guid.data, 
2927           call->callIdentifier.guid.data, 
2928           call->callIdentifier.guid.numocts);
2929
2930    facility->reason.t = T_H225FacilityReason_callForwarded;
2931    
2932    if(!ooUtilsIsStrEmpty(call->pCallFwdData->ip))
2933    {
2934       facility->m.alternativeAddressPresent = TRUE;
2935       facility->alternativeAddress.t=T_H225TransportAddress_ipAddress;
2936       fwdCallSignalIpAddress = (H225TransportAddress_ipAddress*)memAlloc(pctxt,
2937                                   sizeof(H225TransportAddress_ipAddress));
2938       if(!fwdCallSignalIpAddress)
2939       {
2940          OOTRACEERR3("Error:Memory - ooH323ForwardCall - fwdCallSignalAddress"
2941                      "(%s, %s)\n", call->callType, call->callToken);
2942          return OO_FAILED;
2943       }
2944       ooSocketConvertIpToNwAddr(call->pCallFwdData->ip, 
2945                                           fwdCallSignalIpAddress->ip.data);
2946
2947       fwdCallSignalIpAddress->ip.numocts=4;
2948       fwdCallSignalIpAddress->port = call->pCallFwdData->port;
2949       facility->alternativeAddress.u.ipAddress = fwdCallSignalIpAddress;
2950    }
2951
2952    if(call->pCallFwdData->aliases)
2953    {    
2954       facility->m.alternativeAliasAddressPresent = TRUE;
2955       ret = ooPopulateAliasList(pctxt, call->pCallFwdData->aliases, 
2956                                         &facility->alternativeAliasAddress);
2957       if(ret != OO_OK)
2958       {
2959          OOTRACEERR3("Error:Failed to populate alternate aliases in "
2960                      "ooH323ForwardCall. (%s, %s)\n", call->callType, 
2961                      call->callToken);
2962          return OO_FAILED;
2963       }
2964    }
2965
2966    ret = ooSendH225Msg(call, pQ931Msg);
2967    if(ret != OO_OK)
2968    {
2969       OOTRACEERR3
2970          ("Error:Failed to enqueue Forward Facility message to outbound "
2971          "queue.(%s, %s)\n", call->callType, call->callToken);
2972    }
2973    call->callEndReason = OO_REASON_LOCAL_FWDED;
2974    memReset (&gH323ep.msgctxt);
2975    return ret;
2976 }
2977
2978 int ooH323HangCall(char * callToken, OOCallClearReason reason, int q931cause)
2979 {
2980    OOH323CallData *call;
2981
2982    call= ooFindCallByToken(callToken);
2983    if(!call)
2984    {
2985       OOTRACEWARN2("WARN: Call hangup failed - Call %s not present\n", 
2986                     callToken);
2987       return OO_FAILED;
2988    }
2989    OOTRACEINFO3("Hanging up call (%s, %s)\n", call->callType, call->callToken);
2990    if(call->callState < OO_CALL_CLEAR)
2991    {
2992       call->callEndReason = reason;
2993       call->q931cause = q931cause;
2994       call->callState = OO_CALL_CLEAR;
2995    }
2996    return OO_OK;
2997 }
2998
2999 int ooSetBearerCapabilityIE
3000    (OOCTXT* pctxt, Q931Message *pmsg, enum Q931CodingStandard codingStandard, 
3001     enum Q931InformationTransferCapability capability, 
3002     enum Q931TransferMode transferMode, enum Q931TransferRate transferRate,
3003     enum Q931UserInfoLayer1Protocol userInfoLayer1)
3004 {
3005    unsigned size = 3;
3006    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3007
3008    if(pmsg->bearerCapabilityIE)
3009    {
3010       memFreePtr(pctxt, pmsg->bearerCapabilityIE);
3011       pmsg->bearerCapabilityIE = NULL;
3012    }
3013
3014    pmsg->bearerCapabilityIE = (Q931InformationElement*) 
3015                       memAlloc(pctxt, sizeof(Q931InformationElement)+size-1);
3016    if(!pmsg->bearerCapabilityIE)
3017    {
3018       OOTRACEERR1("Error:Memory - ooSetBearerCapabilityIE - bearerCapabilityIE"
3019                   "\n");
3020       return OO_FAILED;
3021    }
3022
3023    pmsg->bearerCapabilityIE->discriminator = Q931BearerCapabilityIE;
3024    pmsg->bearerCapabilityIE->length = size;
3025    pmsg->bearerCapabilityIE->data[0] = (ASN1OCTET)(0x80 | ((codingStandard&3) << 5) | (capability&31));
3026
3027    pmsg->bearerCapabilityIE->data[1] = (0x80 | ((transferMode & 3) << 5) | (transferRate & 31));
3028    
3029    pmsg->bearerCapabilityIE->data[2] = (0x80 | (1<<5) | userInfoLayer1);
3030
3031    return OO_OK;
3032 }
3033
3034 int ooQ931SetKeypadIE(OOCTXT* pctxt, Q931Message *pmsg, const char* data)
3035 {
3036    unsigned len = 0;
3037    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3038
3039    len = strlen(data);
3040    pmsg->keypadIE = (Q931InformationElement*) 
3041                       memAlloc(pctxt, sizeof(Q931InformationElement)+len-1);
3042    if(!pmsg->keypadIE)
3043    {
3044       OOTRACEERR1("Error:Memory - ooQ931SetKeypadIE - keypadIE\n");
3045       return OO_FAILED;
3046    }
3047
3048    pmsg->keypadIE->discriminator = Q931KeypadIE;
3049    pmsg->keypadIE->length = len;
3050    memcpy(pmsg->keypadIE->data, data, len);
3051    return OO_OK;
3052 }
3053
3054
3055
3056
3057 int ooQ931SetCallingPartyNumberIE
3058    (OOCTXT* pctxt, Q931Message *pmsg, const char *number, unsigned plan, unsigned type, 
3059     unsigned presentation, unsigned screening)
3060 {
3061    unsigned len = 0;
3062    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3063
3064    if(pmsg->callingPartyNumberIE)
3065    {
3066       memFreePtr(pctxt, pmsg->callingPartyNumberIE);
3067       pmsg->callingPartyNumberIE = NULL;
3068    }
3069
3070    len = strlen(number);
3071    pmsg->callingPartyNumberIE = (Q931InformationElement*) 
3072                       memAlloc(pctxt, sizeof(Q931InformationElement)+len+2-1);
3073    if(!pmsg->callingPartyNumberIE)
3074    {
3075       OOTRACEERR1("Error:Memory - ooQ931SetCallingPartyNumberIE - "
3076                   "callingPartyNumberIE\n");
3077       return OO_FAILED;
3078    }
3079    pmsg->callingPartyNumberIE->discriminator = Q931CallingPartyNumberIE;
3080    pmsg->callingPartyNumberIE->length = len+2;
3081    pmsg->callingPartyNumberIE->data[0] = (((type&7)<<4)|(plan&15));
3082    pmsg->callingPartyNumberIE->data[1] = (0x80|((presentation&3)<<5)|(screening&3));
3083    memcpy(pmsg->callingPartyNumberIE->data+2, number, len);
3084
3085    return OO_OK;
3086 }
3087
3088 int ooQ931SetCalledPartyNumberIE
3089    (OOCTXT* pctxt, Q931Message *pmsg, const char *number, unsigned plan, unsigned type)
3090 {
3091    unsigned len = 0;
3092    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3093
3094    if(pmsg->calledPartyNumberIE)
3095    {
3096       memFreePtr(pctxt, pmsg->calledPartyNumberIE);
3097       pmsg->calledPartyNumberIE = NULL;
3098    }
3099
3100    len = strlen(number);
3101    pmsg->calledPartyNumberIE = (Q931InformationElement*) 
3102                       memAlloc(pctxt, sizeof(Q931InformationElement)+len+1-1);
3103    if(!pmsg->calledPartyNumberIE)
3104    {
3105       OOTRACEERR1("Error:Memory - ooQ931SetCalledPartyNumberIE - "
3106                   "calledPartyNumberIE\n");
3107       return OO_FAILED;
3108    }
3109    pmsg->calledPartyNumberIE->discriminator = Q931CalledPartyNumberIE;
3110    pmsg->calledPartyNumberIE->length = len+1;
3111    pmsg->calledPartyNumberIE->data[0] = (0x80|((type&7)<<4)|(plan&15));
3112    memcpy(pmsg->calledPartyNumberIE->data+1, number, len);
3113
3114    return OO_OK;
3115 }
3116
3117 int ooQ931SetCauseIE
3118    (OOCTXT* pctxt, Q931Message *pmsg, enum Q931CauseValues cause, unsigned coding, 
3119     unsigned location)
3120 {
3121    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3122
3123    if(pmsg->causeIE){
3124       memFreePtr(pctxt, pmsg->causeIE);
3125       pmsg->causeIE = NULL;
3126    }
3127
3128    pmsg->causeIE = (Q931InformationElement*) 
3129                       memAlloc(pctxt, sizeof(Q931InformationElement)+1);
3130    if(!pmsg->causeIE)
3131    {
3132       OOTRACEERR1("Error:Memory - ooQ931SetCauseIE - causeIE\n");
3133       return OO_FAILED;
3134    }
3135    pmsg->causeIE->discriminator = Q931CauseIE;
3136    pmsg->causeIE->length = 2;
3137    pmsg->causeIE->data[0] = (0x80 | ((coding & 0x03) <<5) | (location & 0x0F));
3138
3139    pmsg->causeIE->data[1] = (0x80 | cause);
3140   
3141    return OO_OK;
3142 }
3143
3144
3145 /* Build a Facility message and tunnel H.245 message through it */
3146 int ooSendAsTunneledMessage(OOH323CallData *call, ASN1OCTET* msgbuf, 
3147                             int h245Len, int h245MsgType, int associatedChan)
3148 {
3149    Q931Message *pQ931Msg = NULL;
3150    H225H323_UU_PDU *pH323UUPDU = NULL;
3151    H225H323_UU_PDU_h245Control *pH245Control = NULL;
3152    ASN1DynOctStr * elem;
3153    int ret =0;
3154    H225Facility_UUIE *facility=NULL;
3155    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3156    OOCTXT *pctxt = call->msgctxt;
3157
3158    OOTRACEDBGA4("Building Facility message for tunneling %s (%s, %s)\n", 
3159                  ooGetMsgTypeText(h245MsgType), call->callType, call->callToken);
3160
3161    ret = ooCreateQ931Message(pctxt, &pQ931Msg, Q931FacilityMsg);
3162    if(ret != OO_OK)
3163    {
3164       OOTRACEERR3("ERROR: In allocating memory for facility message "
3165                   "(%s, %s)\n", call->callType, call->callToken);
3166       return OO_FAILED;
3167    }
3168
3169    pQ931Msg->callReference = call->callReference;
3170
3171    pQ931Msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
3172                              sizeof(H225H323_UserInformation));
3173    if(!pQ931Msg->userInfo)
3174    {
3175       OOTRACEERR3("ERROR:Memory - ooSendAsTunneledMessage - userInfo"
3176                 " (%s, %s)\n", call->callType, call->callToken);
3177       /* memReset(&gH323ep.msgctxt);*/
3178       memReset(call->msgctxt);
3179       return OO_FAILED;
3180    }
3181    memset (pQ931Msg->userInfo, 0, sizeof(H225H323_UserInformation));
3182    pQ931Msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
3183
3184    pQ931Msg->userInfo->h323_uu_pdu.h245Tunneling = 
3185       OO_TESTFLAG (call->flags, OO_M_TUNNELING);
3186
3187    pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.t = 
3188          T_H225H323_UU_PDU_h323_message_body_facility;
3189    
3190    facility = (H225Facility_UUIE*)
3191       memAllocZ (pctxt, sizeof(H225Facility_UUIE));
3192
3193    if(!facility)
3194    {
3195       OOTRACEERR3("ERROR:Memory - ooSendAsTunneledMessage - facility (%s, %s)"
3196                   "\n", call->callType, call->callToken);
3197       /* memReset(&gH323ep.msgctxt); */
3198       memReset(call->msgctxt);
3199       return OO_FAILED;
3200    }
3201
3202    pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.u.facility = facility;
3203    /* Populate Facility UUIE */
3204    facility->protocolIdentifier = gProtocolID;  
3205    facility->m.callIdentifierPresent = 1;
3206    facility->callIdentifier.guid.numocts = 
3207       call->callIdentifier.guid.numocts;
3208
3209    memcpy(facility->callIdentifier.guid.data, 
3210           call->callIdentifier.guid.data, 
3211           call->callIdentifier.guid.numocts);
3212
3213    facility->reason.t = T_H225FacilityReason_transportedInformation;
3214
3215    pH323UUPDU = (H225H323_UU_PDU*) &pQ931Msg->userInfo->h323_uu_pdu;
3216    pH323UUPDU->m.h245TunnelingPresent = TRUE;
3217    pH323UUPDU->m.h245ControlPresent = TRUE;
3218    pH323UUPDU->h245Tunneling = TRUE;
3219    pH245Control = (H225H323_UU_PDU_h245Control*)
3220                    &pH323UUPDU->h245Control;
3221
3222    elem = (ASN1DynOctStr*) memAlloc(pctxt, 
3223                                       sizeof(ASN1DynOctStr));
3224    if(!elem)
3225    {
3226       OOTRACEERR3("ERROR:Memory - ooSendAsTunneledMessage - elem "
3227                   "(%s, %s)\n", call->callType, call->callToken);
3228       return OO_FAILED;
3229    }
3230    elem->data = msgbuf;
3231    elem->numocts = h245Len;
3232    pH245Control->elem = elem;
3233    pH245Control->n = 1;
3234    pQ931Msg->tunneledMsgType = h245MsgType;
3235    pQ931Msg->logicalChannelNo = associatedChan;
3236
3237    
3238    ret = ooSendH225Msg(call, pQ931Msg);
3239    if(ret != OO_OK)
3240    {
3241      OOTRACEERR3("Error:Failed to enqueue Facility(tunneling) message to "
3242                  "outbound queue.(%s, %s)\n", call->callType, call->callToken);
3243    }
3244
3245    /* Can't do memReset here because if we are sending H.245 message as a 
3246       response to received tunneled h.245 message, we can't reset unless the \
3247       main received H225 message processing is finished. Rule. No reset when
3248       tunneling
3249    */
3250    /* memFreePtr(&gH323ep.msgctxt, pQ931Msg); */
3251    memFreePtr(call->msgctxt, pQ931Msg);
3252    return ret;
3253 }
3254
3255 int ooCallEstbTimerExpired(void *data)
3256 {
3257
3258    ooTimerCallback *cbData = (ooTimerCallback*) data;
3259    OOH323CallData *call = cbData->call;
3260    OOTRACEINFO3("Call Establishment timer expired. (%s, %s)\n", 
3261                                             call->callType, call->callToken); 
3262    memFreePtr(call->pctxt, cbData);
3263    if(call->callState < OO_CALL_CLEAR){
3264       call->callState = OO_CALL_CLEAR;
3265       call->callEndReason = OO_REASON_LOCAL_CLEARED;      
3266    }
3267
3268    return OO_OK;
3269 }
3270
3271
3272 int ooQ931GetCauseAndReasonCodeFromCallClearReason
3273    (OOCallClearReason clearReason, enum Q931CauseValues *cause, 
3274     unsigned *reasonCode)
3275 {
3276    switch(clearReason)
3277    {
3278    case OO_REASON_INVALIDMESSAGE:
3279    case OO_REASON_TRANSPORTFAILURE:
3280       *reasonCode =  T_H225ReleaseCompleteReason_undefinedReason;
3281       *cause = Q931ProtocolErrorUnspecified;
3282       break;
3283    case OO_REASON_NOBW:
3284       *reasonCode = T_H225ReleaseCompleteReason_noBandwidth;
3285       *cause = Q931ErrorInCauseIE;
3286       break;
3287    case OO_REASON_GK_NOCALLEDUSER:
3288       *reasonCode = T_H225ReleaseCompleteReason_calledPartyNotRegistered;
3289       *cause = Q931SubscriberAbsent;
3290       break;
3291    case OO_REASON_GK_NOCALLERUSER:
3292       *reasonCode = T_H225ReleaseCompleteReason_callerNotRegistered;
3293       *cause = Q931SubscriberAbsent;      
3294       break;
3295    case OO_REASON_GK_UNREACHABLE:
3296       *reasonCode = T_H225ReleaseCompleteReason_unreachableGatekeeper;
3297       *cause = Q931TemporaryFailure;
3298       break;
3299    case OO_REASON_GK_NORESOURCES:
3300    case OO_REASON_GK_CLEARED:
3301       *reasonCode = T_H225ReleaseCompleteReason_gatekeeperResources;
3302       *cause = Q931Congestion;
3303       break;
3304    case OO_REASON_NOCOMMON_CAPABILITIES:
3305       *reasonCode =  T_H225ReleaseCompleteReason_undefinedReason;
3306       *cause = Q931IncompatibleDestination;
3307       break;
3308    case OO_REASON_LOCAL_FWDED:
3309    case OO_REASON_REMOTE_FWDED:
3310       *reasonCode =  T_H225ReleaseCompleteReason_facilityCallDeflection;
3311       *cause = Q931Redirection;
3312       break;
3313    case OO_REASON_REMOTE_CLEARED:
3314    case OO_REASON_LOCAL_CLEARED:
3315       *reasonCode = T_H225ReleaseCompleteReason_undefinedReason;
3316       *cause = Q931NormalCallClearing;
3317       break;
3318    case OO_REASON_REMOTE_BUSY:
3319    case OO_REASON_LOCAL_BUSY:
3320       *reasonCode =  T_H225ReleaseCompleteReason_inConf;
3321       *cause = Q931UserBusy;
3322       break;
3323    case OO_REASON_REMOTE_NOANSWER:
3324    case OO_REASON_LOCAL_NOTANSWERED:
3325       *reasonCode =  T_H225ReleaseCompleteReason_undefinedReason;
3326       *cause = Q931NoAnswer;
3327       break;
3328    case OO_REASON_REMOTE_REJECTED:
3329    case OO_REASON_LOCAL_REJECTED:
3330       *reasonCode = T_H225ReleaseCompleteReason_destinationRejection;
3331       *cause = Q931CallRejected;
3332       break;
3333    case OO_REASON_REMOTE_CONGESTED:
3334    case OO_REASON_LOCAL_CONGESTED:
3335       *reasonCode =  T_H225ReleaseCompleteReason_noBandwidth;
3336       *cause = Q931Congestion;
3337       break;
3338    case OO_REASON_NOROUTE:
3339       *reasonCode = T_H225ReleaseCompleteReason_unreachableDestination;
3340       *cause = Q931NoRouteToDestination;
3341       break;
3342    case OO_REASON_NOUSER:
3343       *reasonCode = T_H225ReleaseCompleteReason_undefinedReason;      
3344       *cause = Q931SubscriberAbsent;
3345       break;
3346    case OO_REASON_UNKNOWN:
3347    default:
3348       *reasonCode = T_H225ReleaseCompleteReason_undefinedReason;
3349       *cause = Q931NormalUnspecified;
3350    }
3351
3352    return OO_OK;
3353 }
3354
3355 enum OOCallClearReason ooGetCallClearReasonFromCauseAndReasonCode
3356    (enum Q931CauseValues cause, unsigned reasonCode)
3357 {
3358    switch(cause)
3359    {
3360       case Q931NormalCallClearing:
3361          return OO_REASON_REMOTE_CLEARED;
3362
3363       case Q931UserBusy:
3364          return OO_REASON_REMOTE_BUSY;
3365
3366       case Q931NoResponse:
3367       case Q931NoAnswer:
3368          return OO_REASON_REMOTE_NOANSWER;
3369
3370       case Q931CallRejected:
3371          return OO_REASON_REMOT