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