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