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