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