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