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