generate roundtrip delay requests and responses
[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, int docallbacks)
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("      %c\n", ie->data[0]);
175          OOTRACEDBGB1("   }\n");
176          if(docallbacks && 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 && msg->messageType != Q931StatusMsg)
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, 0);
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    call->callState = OO_CALL_CONNECTED;
2007    
2008    if (call->rtdrCount > 0 && call->rtdrInterval > 0) {
2009         return ooSendRoundTripDelayRequest(call);
2010    }
2011    return OO_OK;
2012 }
2013
2014 int ooH323HandleCallFwdRequest(OOH323CallData *call)
2015 {
2016    OOH323CallData *fwdedCall=NULL;
2017    OOCTXT *pctxt;
2018    ooAliases *pNewAlias=NULL, *alias=NULL;
2019    struct timespec ts;
2020    int i=0, irand=0, ret = OO_OK;
2021    /* Note: We keep same callToken, for new call which is going
2022       to replace an existing call, thus treating it as a single call.*/
2023
2024    fwdedCall = ooCreateCall("outgoing", call->callToken);
2025
2026    pctxt = fwdedCall->pctxt;
2027
2028    /* Retrieve new destination info from original call */
2029    if(!ooUtilsIsStrEmpty(call->pCallFwdData->ip))
2030    {
2031       strcpy(fwdedCall->remoteIP, call->pCallFwdData->ip);
2032    }
2033    fwdedCall->remotePort = call->pCallFwdData->port;
2034    
2035    if(call->pCallFwdData->aliases)
2036    {
2037       alias = call->pCallFwdData->aliases;
2038       while(alias)
2039       {
2040          pNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases));
2041          pNewAlias->value = (char*) memAlloc(pctxt, strlen(alias->value)+1);
2042          if(!pNewAlias || !pNewAlias->value)
2043          {
2044             OOTRACEERR3("Error:Memory - ooH323HandleCallFwdRequest - "
2045                         "pNewAlias/pNewAlias->value"
2046                         "(%s, %s)\n", call->callType, call->callToken);
2047             ooCleanCall(fwdedCall);
2048             return OO_FAILED;
2049          }
2050          pNewAlias->type = alias->type;
2051          strcpy(pNewAlias->value, alias->value);
2052          pNewAlias->next = fwdedCall->remoteAliases;
2053          fwdedCall->remoteAliases = pNewAlias;
2054          alias = alias->next;
2055          pNewAlias = NULL;
2056       }
2057    }
2058
2059    fwdedCall->callReference = ooGenerateCallReference();
2060    ooGenerateCallIdentifier(&fwdedCall->callIdentifier);
2061    fwdedCall->confIdentifier.numocts = 16;
2062    irand = rand();
2063    for (i = 0; i < 16; i++) {
2064       fwdedCall->confIdentifier.data[i] = irand++;
2065    }
2066       
2067
2068    if(gH323ep.gkClient && !OO_TESTFLAG(fwdedCall->flags, OO_M_DISABLEGK))
2069    {
2070      /* No need to check registration status here as it is already checked for
2071         MakeCall command */
2072       ret = ooGkClientSendAdmissionRequest(gH323ep.gkClient, fwdedCall, FALSE);
2073       fwdedCall->callState = OO_CALL_WAITING_ADMISSION;
2074       ast_mutex_lock(&fwdedCall->Lock);
2075       clock_gettime(CLOCK_REALTIME, &ts);
2076       ts.tv_sec += 24;
2077       ast_cond_timedwait(&fwdedCall->gkWait, &fwdedCall->Lock, &ts);
2078       if (fwdedCall->callState == OO_CALL_WAITING_ADMISSION) /* GK is not responding */
2079           fwdedCall->callState = OO_CALL_CLEAR;
2080       ast_mutex_unlock(&fwdedCall->Lock);
2081
2082    }
2083    if (fwdedCall->callState < OO_CALL_CLEAR) {
2084       ast_mutex_lock(&fwdedCall->Lock);
2085       ret = ooH323CallAdmitted (fwdedCall);
2086       ast_mutex_unlock(&fwdedCall->Lock);
2087    }
2088
2089    return OO_OK;
2090
2091 }
2092
2093 int ooH323NewCall(char *callToken) {
2094    OOH323CallData* call;
2095    if(!callToken)
2096    {
2097       OOTRACEERR1("ERROR: Invalid callToken parameter to make call\n");
2098       return OO_FAILED;
2099    }
2100    call = ooCreateCall("outgoing", callToken);
2101    if (!call)
2102    {
2103       OOTRACEERR1("ERROR: Can't create call %s\n");
2104       return OO_FAILED;
2105    }
2106
2107    return OO_OK;
2108 }
2109
2110 int ooH323MakeCall(char *dest, char *callToken, ooCallOptions *opts)
2111 {
2112    OOCTXT *pctxt;
2113    OOH323CallData *call;
2114    int ret=0, i=0, irand=0;
2115    char tmp[30]="\0";
2116    char *ip=NULL, *port = NULL;
2117    struct timespec ts;
2118
2119    if(!dest)
2120    {
2121       OOTRACEERR1("ERROR:Invalid destination for new call\n");
2122       return OO_FAILED;
2123    }
2124    if(!callToken)
2125    {
2126       OOTRACEERR1("ERROR: Invalid callToken parameter to make call\n");
2127       return OO_FAILED;
2128    }
2129
2130    /* call = ooCreateCall("outgoing", callToken); */
2131    call = ooFindCallByToken(callToken);
2132    if (!call)
2133    {
2134       OOTRACEERR1("ERROR: Can't create call %s\n");
2135       return OO_FAILED;
2136    }
2137
2138    pctxt = call->pctxt;
2139    if(opts)
2140    {
2141       if(opts->fastStart)
2142          OO_SETFLAG(call->flags, OO_M_FASTSTART);
2143       else
2144          OO_CLRFLAG(call->flags, OO_M_FASTSTART);
2145
2146       if(opts->tunneling)
2147          OO_SETFLAG(call->flags, OO_M_TUNNELING);
2148       else
2149          OO_CLRFLAG(call->flags, OO_M_TUNNELING);
2150
2151       if(opts->disableGk)
2152          OO_SETFLAG(call->flags, OO_M_DISABLEGK);
2153       else
2154          OO_CLRFLAG(call->flags, OO_M_DISABLEGK);
2155
2156       call->callMode = opts->callMode;
2157       call->transfercap = opts->transfercap;
2158    }
2159
2160
2161    ret = ooParseDestination(call, dest, tmp, 24, &call->remoteAliases);
2162    if(ret != OO_OK)
2163    {
2164       OOTRACEERR2("Error: Failed to parse the destination string %s for "
2165                   "new call\n", dest);
2166       ooCleanCall(call);
2167       return OO_FAILED;
2168    }
2169    
2170    /* Check whether we have ip address */
2171    if(!ooUtilsIsStrEmpty(tmp)) {
2172       ip = tmp;
2173       port = strchr(tmp, ':');
2174       *port = '\0';
2175       port++;
2176       strcpy(call->remoteIP, ip);
2177       call->remotePort = atoi(port);
2178    }
2179
2180    strcpy(callToken, call->callToken);
2181    call->callReference = ooGenerateCallReference();
2182    ooGenerateCallIdentifier(&call->callIdentifier);
2183    call->confIdentifier.numocts = 16;
2184    irand = rand();
2185    for (i = 0; i < 16; i++) {
2186       call->confIdentifier.data[i] = irand++;
2187    }
2188       
2189
2190    if(gH323ep.gkClient && !OO_TESTFLAG(call->flags, OO_M_DISABLEGK))
2191    {
2192      /* No need to check registration status here as it is already checked for
2193         MakeCall command */
2194
2195      call->callState = OO_CALL_WAITING_ADMISSION;
2196      ast_mutex_lock(&call->Lock);
2197      ret = ooGkClientSendAdmissionRequest(gH323ep.gkClient, call, FALSE);
2198      clock_gettime(CLOCK_REALTIME, &ts);
2199      ts.tv_sec += 24;
2200      ast_cond_timedwait(&call->gkWait, &call->Lock, &ts);
2201      if (call->callState == OO_CALL_WAITING_ADMISSION)
2202                 call->callState = OO_CALL_CLEAR;
2203      ast_mutex_unlock(&call->Lock);
2204
2205    }
2206
2207    /* Send as H225 message to calling endpoint */
2208    ast_mutex_lock(&call->Lock);
2209    if (call->callState < OO_CALL_CLEAR) 
2210     if ((ret = ooH323CallAdmitted (call)) != OO_OK) {
2211      ast_mutex_unlock(&call->Lock);
2212      return ret;
2213     }
2214    ast_mutex_unlock(&call->Lock);
2215
2216    return OO_OK;
2217 }
2218
2219
2220 int ooH323CallAdmitted(OOH323CallData *call)
2221 {
2222    int ret=0;
2223       
2224    if(!call)
2225    {
2226       /* Call not supplied. Must locate it in list */
2227       OOTRACEERR1("ERROR: Invalid call parameter to ooH323CallAdmitted");
2228       return OO_FAILED; 
2229    }
2230
2231    if(!strcmp(call->callType, "outgoing")) {
2232       ret = ooCreateH225Connection(call);
2233       if(ret != OO_OK)
2234       {
2235          OOTRACEERR3("ERROR:Failed to create H225 connection to %s:%d\n", 
2236                       call->remoteIP, call->remotePort);
2237          if(call->callState< OO_CALL_CLEAR)
2238          {
2239             call->callState = OO_CALL_CLEAR;
2240             call->callEndReason = OO_REASON_UNKNOWN;
2241          }
2242          return OO_FAILED;
2243       }
2244
2245       if(gH323ep.h323Callbacks.onOutgoingCall) {
2246          /* Outgoing call callback function */
2247          gH323ep.h323Callbacks.onOutgoingCall(call);
2248       }
2249       
2250       ret = ooH323MakeCall_helper(call);
2251    } 
2252    else { 
2253       /* incoming call */
2254       if(gH323ep.h323Callbacks.onIncomingCall) {
2255          /* Incoming call callback function */
2256          gH323ep.h323Callbacks.onIncomingCall(call);
2257       }
2258
2259       /* Check for manual ringback generation */
2260       if(!OO_TESTFLAG(gH323ep.flags, OO_M_MANUALRINGBACK))
2261       {
2262          ooSendAlerting(call); /* Send alerting message */
2263
2264          if(OO_TESTFLAG(gH323ep.flags, OO_M_AUTOANSWER)) {
2265             ooSendConnect(call); /* Send connect message - call accepted */
2266          }
2267       }
2268    }
2269    
2270    return OO_OK;
2271 }
2272
2273 int ooH323MakeCall_helper(OOH323CallData *call)
2274 {
2275    int ret=0,i=0, k;
2276    Q931Message *q931msg = NULL;
2277    H225Setup_UUIE *setup;
2278
2279    ASN1DynOctStr *pFS=NULL;
2280    H225TransportAddress_ipAddress *destCallSignalIpAddress;
2281
2282    H225TransportAddress_ipAddress *srcCallSignalIpAddress;
2283    ooH323EpCapability *epCap=NULL;
2284    OOCTXT *pctxt = NULL;
2285    H245OpenLogicalChannel *olc, printOlc;
2286    ASN1BOOL aligned = 1;
2287    ooAliases *pAlias = NULL;
2288
2289    /* pctxt = &gH323ep.msgctxt; */
2290    pctxt = call->msgctxt;
2291      
2292    ret = ooCreateQ931Message(pctxt, &q931msg, Q931SetupMsg);
2293    if(ret != OO_OK)
2294    {
2295       OOTRACEERR1("ERROR:Failed to Create Q931 SETUP Message\n ");
2296       return OO_FAILED;
2297    }
2298
2299    q931msg->callReference = call->callReference;
2300
2301    /* Set bearer capability */
2302    if(OO_OK != ooSetBearerCapabilityIE(pctxt, q931msg, Q931CCITTStd, 
2303                           // Q931TransferUnrestrictedDigital, Q931TransferPacketMode,
2304                           call->transfercap, Q931TransferCircuitMode,
2305                           // Q931TransferRatePacketMode, Q931UserInfoLayer1G722G725))
2306                           Q931TransferRate64Kbps, Q931UserInfoLayer1G711ALaw))
2307    {
2308       OOTRACEERR3("Error: Failed to set bearer capability ie.(%s, %s)\n",
2309                    call->callType, call->callToken);
2310       return OO_FAILED;
2311    }
2312
2313    /* Set calling party number  Q931 IE */
2314    if(call->callingPartyNumber && call->callingPartyNumber[0])
2315      ooQ931SetCallingPartyNumberIE(pctxt, q931msg,
2316                             (const char*)call->callingPartyNumber, 1, 0, 0, 0);
2317    
2318
2319    /* Set called party number Q931 IE */
2320    if(call->calledPartyNumber)
2321       ooQ931SetCalledPartyNumberIE(pctxt, q931msg, 
2322                             (const char*)call->calledPartyNumber, 1, 0);
2323    else if(call->remoteAliases) {
2324       pAlias = call->remoteAliases;
2325       while(pAlias) {
2326          if(pAlias->type == T_H225AliasAddress_dialedDigits)
2327             break;
2328          pAlias = pAlias->next;
2329       }
2330       if(pAlias)
2331       {
2332          call->calledPartyNumber = (char*)memAlloc(call->pctxt, 
2333                                                    strlen(pAlias->value)+1);
2334          if(!call->calledPartyNumber)
2335          {
2336             OOTRACEERR3("Error:Memory - ooH323MakeCall_helper - "
2337                         "calledPartyNumber(%s, %s)\n", call->callType, 
2338                         call->callToken);
2339             return OO_FAILED;
2340          }
2341          strcpy(call->calledPartyNumber, pAlias->value);
2342          ooQ931SetCalledPartyNumberIE(pctxt, q931msg, 
2343                             (const char*)call->calledPartyNumber, 1, 0);
2344       }
2345
2346    }
2347
2348    q931msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
2349                              sizeof(H225H323_UserInformation));
2350    if(!q931msg->userInfo)
2351    {
2352       OOTRACEERR1("ERROR:Memory - ooH323MakeCall_helper - userInfo\n");
2353       return OO_FAILED;
2354    }
2355    memset(q931msg->userInfo, 0, sizeof(H225H323_UserInformation));
2356
2357    setup = (H225Setup_UUIE*) memAlloc(pctxt, sizeof(H225Setup_UUIE));
2358    if(!setup)
2359    {
2360       OOTRACEERR3("Error:Memory -  ooH323MakeCall_helper - setup (%s, %s)\n",
2361                  call->callType, call->callToken);
2362       return OO_FAILED;
2363    }
2364    memset (setup, 0, sizeof(H225Setup_UUIE));
2365    setup->protocolIdentifier = gProtocolID;
2366    
2367    /* Populate Alias Address.*/
2368
2369    if(call->ourAliases || gH323ep.aliases)
2370    {   
2371       setup->m.sourceAddressPresent = TRUE;
2372       if(call->ourAliases)
2373          ret = ooPopulateAliasList(pctxt, call->ourAliases, 
2374                                                        &setup->sourceAddress);
2375       else if(gH323ep.aliases)
2376          ret =  ooPopulateAliasList(pctxt, gH323ep.aliases, 
2377                                                        &setup->sourceAddress);
2378       if(OO_OK != ret)
2379       {
2380          OOTRACEERR1("Error:Failed to populate alias list in SETUP message\n");
2381          memReset(pctxt);
2382          return OO_FAILED;
2383       }
2384    }
2385
2386    setup->m.presentationIndicatorPresent = TRUE;
2387    setup->presentationIndicator.t = 
2388                              T_H225PresentationIndicator_presentationAllowed;
2389    setup->m.screeningIndicatorPresent = TRUE;
2390    setup->screeningIndicator = userProvidedNotScreened;
2391
2392    setup->m.multipleCallsPresent = TRUE;
2393    setup->multipleCalls = FALSE;
2394    setup->m.maintainConnectionPresent = TRUE;
2395    setup->maintainConnection = FALSE;
2396
2397    /* Populate Destination aliases */
2398    if(call->remoteAliases)
2399    {
2400       setup->m.destinationAddressPresent = TRUE;
2401       ret = ooPopulateAliasList(pctxt, call->remoteAliases, 
2402                                                  &setup->destinationAddress);
2403       if(OO_OK != ret)
2404       {
2405          OOTRACEERR1("Error:Failed to populate destination alias list in SETUP"
2406                      "message\n");
2407          memReset(pctxt);
2408          return OO_FAILED;
2409       }
2410    }
2411
2412    /* Populate the vendor information */
2413    if(gH323ep.isGateway)
2414       setup->sourceInfo.m.gatewayPresent = TRUE;
2415    else
2416       setup->sourceInfo.m.terminalPresent = TRUE;
2417
2418    setup->sourceInfo.m.vendorPresent=TRUE;
2419    setup->sourceInfo.vendor.vendor.t35CountryCode = gH323ep.t35CountryCode;
2420    setup->sourceInfo.vendor.vendor.t35Extension = gH323ep.t35Extension;
2421    setup->sourceInfo.vendor.vendor.manufacturerCode= gH323ep.manufacturerCode;
2422    
2423    if(gH323ep.productID)
2424    {
2425       setup->sourceInfo.vendor.m.productIdPresent=TRUE;
2426       setup->sourceInfo.vendor.productId.numocts = ASN1MIN(
2427                               strlen(gH323ep.productID), 
2428                               sizeof(setup->sourceInfo.vendor.productId.data));
2429       strncpy((char*)setup->sourceInfo.vendor.productId.data, 
2430                 gH323ep.productID, setup->sourceInfo.vendor.productId.numocts);
2431    }
2432    else
2433       setup->sourceInfo.vendor.m.productIdPresent=FALSE;
2434    
2435    if(gH323ep.versionID)
2436    {
2437       setup->sourceInfo.vendor.m.versionIdPresent=TRUE;
2438       setup->sourceInfo.vendor.versionId.numocts = ASN1MIN(
2439                               strlen(gH323ep.versionID), 
2440                               sizeof(setup->sourceInfo.vendor.versionId.data));
2441       strncpy((char*)setup->sourceInfo.vendor.versionId.data, 
2442               gH323ep.versionID, setup->sourceInfo.vendor.versionId.numocts);
2443    }
2444    else
2445       setup->sourceInfo.vendor.m.versionIdPresent=FALSE;
2446    
2447    setup->sourceInfo.mc = FALSE;
2448    setup->sourceInfo.undefinedNode = FALSE;
2449
2450    /* Populate the destination Call Signal Address */
2451    setup->destCallSignalAddress.t=T_H225TransportAddress_ipAddress;
2452    destCallSignalIpAddress = (H225TransportAddress_ipAddress*)memAlloc(pctxt,
2453                                   sizeof(H225TransportAddress_ipAddress));
2454    if(!destCallSignalIpAddress)
2455    {
2456       OOTRACEERR3("Error:Memory -  ooH323MakeCall_helper - "
2457                  "destCallSignalAddress. (%s, %s)\n", call->callType, 
2458                  call->callToken);
2459       return OO_FAILED;
2460    }
2461    ooSocketConvertIpToNwAddr(call->remoteIP, destCallSignalIpAddress->ip.data);
2462
2463    destCallSignalIpAddress->ip.numocts=4;
2464    destCallSignalIpAddress->port = call->remotePort;
2465
2466    setup->destCallSignalAddress.u.ipAddress = destCallSignalIpAddress;
2467    setup->m.destCallSignalAddressPresent=TRUE;
2468    setup->activeMC=FALSE;
2469
2470    /* Populate the source Call Signal Address */
2471    setup->sourceCallSignalAddress.t=T_H225TransportAddress_ipAddress;
2472    srcCallSignalIpAddress = (H225TransportAddress_ipAddress*)memAlloc(pctxt,
2473                                   sizeof(H225TransportAddress_ipAddress));
2474    if(!srcCallSignalIpAddress)
2475    {
2476       OOTRACEERR3("Error:Memory - ooH323MakeCall_helper - srcCallSignalAddress"
2477                   "(%s, %s)\n", call->callType, call->callToken);
2478       return OO_FAILED;
2479    }
2480    ooSocketConvertIpToNwAddr(call->localIP, srcCallSignalIpAddress->ip.data);
2481
2482    srcCallSignalIpAddress->ip.numocts=4;
2483    srcCallSignalIpAddress->port= call->pH225Channel->port;
2484    setup->sourceCallSignalAddress.u.ipAddress = srcCallSignalIpAddress;
2485    setup->m.sourceCallSignalAddressPresent=TRUE;
2486    /* No fast start */
2487    if(!OO_TESTFLAG(call->flags, OO_M_FASTSTART))
2488    {
2489       setup->m.fastStartPresent = FALSE;
2490    }
2491    else{
2492       setup->m.fastStartPresent = TRUE;
2493       pFS = (ASN1DynOctStr*)memAlloc(pctxt, gH323ep.noOfCaps*
2494                                        sizeof(ASN1DynOctStr));
2495       if(!pFS)
2496       {
2497          OOTRACEERR3("Error:Memory - ooH323MakeCall_helper - pFS(%s, %s)\n",
2498                      call->callType, call->callToken);
2499          return OO_FAILED;
2500       }
2501
2502       /* Use preference order of codecs */
2503       i=0;
2504       for(k=0; k< call->capPrefs.index; k++)
2505       {
2506          OOTRACEDBGC5("Preffered capability at index %d is %s. (%s, %s)\n",
2507                       k, ooGetCapTypeText(call->capPrefs.order[k]), 
2508                       call->callType, call->callToken);
2509
2510          if(call->ourCaps) {
2511             epCap = call->ourCaps;
2512             OOTRACEDBGC3("Using call specific capabilities in faststart of "
2513                          "setup message. (%s, %s)\n", call->callType, 
2514                          call->callToken);
2515          }
2516          else{
2517             epCap = gH323ep.myCaps;
2518             OOTRACEDBGC3("Using end-point capabilities for faststart of setup"
2519                          "message. (%s, %s)\n", call->callType, 
2520                          call->callToken);
2521          }
2522
2523          while(epCap){
2524             if(epCap->cap == call->capPrefs.order[k]) break;
2525             else epCap = epCap->next;
2526          }
2527          if(!epCap)
2528          {
2529             OOTRACEWARN4("Warn:Preferred capability %s is abscent in "
2530                          "capability list. (%s, %s)\n", 
2531                          ooGetCapTypeText(call->capPrefs.order[k]), 
2532                          call->callType, call->callToken);
2533             continue;
2534          }
2535
2536 /* don't send t38/other data caps in fasstart olcs */
2537
2538          if (epCap->capType == OO_CAP_TYPE_DATA)
2539                 continue;
2540
2541          OOTRACEDBGC4("Building olcs with capability %s. (%s, %s)\n", 
2542                       ooGetCapTypeText(epCap->cap), call->callType, 
2543                       call->callToken);
2544          if(epCap->dir & OORX)
2545          {
2546             olc = (H245OpenLogicalChannel*)memAlloc(pctxt, 
2547                                              sizeof(H245OpenLogicalChannel));
2548             if(!olc)
2549             {
2550                OOTRACEERR3("ERROR:Memory - ooH323MakeCall_helper - olc(%s, %s)"
2551                            "\n", call->callType, call->callToken);
2552                ooFreeQ931Message(pctxt, q931msg);
2553                if(call->callState < OO_CALL_CLEAR)
2554                {
2555                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2556                   call->callState = OO_CALL_CLEAR;
2557                }
2558                return OO_FAILED;
2559             }
2560             memset(olc, 0, sizeof(H245OpenLogicalChannel));
2561             olc->forwardLogicalChannelNumber = call->logicalChanNoCur++; 
2562             if(call->logicalChanNoCur > call->logicalChanNoMax)
2563                call->logicalChanNoCur = call->logicalChanNoBase;
2564         
2565             ooBuildFastStartOLC(call, olc, epCap, pctxt, OORX);
2566             /* Do not specify msg buffer let automatic allocation work */
2567             setPERBuffer(pctxt, NULL, 0, aligned);
2568             if(asn1PE_H245OpenLogicalChannel(pctxt, olc) != ASN_OK)
2569             {
2570                OOTRACEERR3("ERROR:Encoding of olc failed for faststart(%s, %s)"
2571                            "\n", call->callType, call->callToken);
2572                ooFreeQ931Message(pctxt, q931msg);
2573                if(call->callState < OO_CALL_CLEAR)
2574                {
2575                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2576                   call->callState = OO_CALL_CLEAR;
2577                }
2578                return OO_FAILED;
2579             }
2580             pFS[i].data = (unsigned char *)encodeGetMsgPtr(pctxt, (int *)&(pFS[i].numocts));
2581
2582
2583             /* Dump faststart element in logfile for debugging purpose */
2584             setPERBuffer(pctxt,  (unsigned char*)pFS[i].data, pFS[i].numocts, 1);
2585             initializePrintHandler(&printHandler, "FastStart Element");
2586             setEventHandler (pctxt, &printHandler);
2587             memset(&printOlc, 0, sizeof(printOlc));
2588             ret = asn1PD_H245OpenLogicalChannel(pctxt, &(printOlc));
2589             if(ret != ASN_OK)
2590             {
2591                OOTRACEERR3("Error: Failed decoding FastStart Element."
2592                            "(%s, %s)\n", call->callType, call->callToken);
2593                ooFreeQ931Message(pctxt, q931msg);
2594                if(call->callState < OO_CALL_CLEAR)
2595                {
2596                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2597                   call->callState = OO_CALL_CLEAR;
2598                }
2599                return OO_FAILED;
2600             }
2601             finishPrint();
2602             removeEventHandler(pctxt); 
2603
2604
2605             olc = NULL;
2606             i++;
2607             OOTRACEDBGC5("Added RX fs element %d with capability %s(%s, %s)\n",
2608                           i, ooGetCapTypeText(epCap->cap), call->callType, 
2609                           call->callToken);
2610          }
2611
2612          if(epCap->dir & OOTX)
2613          {
2614             olc = (H245OpenLogicalChannel*)memAlloc(pctxt, 
2615                                              sizeof(H245OpenLogicalChannel));
2616             if(!olc)
2617             {
2618                OOTRACEERR3("ERROR:Memory - ooH323MakeCall_helper - olc(%s, %s)"
2619                            "\n", call->callType, call->callToken);
2620                ooFreeQ931Message(pctxt, q931msg);
2621                if(call->callState < OO_CALL_CLEAR)
2622                {
2623                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2624                   call->callState = OO_CALL_CLEAR;
2625                }
2626                return OO_FAILED;
2627             }
2628             memset(olc, 0, sizeof(H245OpenLogicalChannel));
2629             olc->forwardLogicalChannelNumber = call->logicalChanNoCur++; 
2630             if(call->logicalChanNoCur > call->logicalChanNoMax)
2631                call->logicalChanNoCur = call->logicalChanNoBase;
2632         
2633             ooBuildFastStartOLC(call, olc, epCap, pctxt, OOTX);
2634             /* Do not specify msg buffer let automatic allocation work */
2635             setPERBuffer(pctxt, NULL, 0, aligned);
2636             if(asn1PE_H245OpenLogicalChannel(pctxt, olc) != ASN_OK)
2637             {
2638                OOTRACEERR3("ERROR:Encoding of olc failed for faststart(%s, %s)"
2639                            "\n", call->callType, call->callToken);
2640                ooFreeQ931Message(pctxt, q931msg);
2641                if(call->callState < OO_CALL_CLEAR)
2642                {
2643                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2644                   call->callState = OO_CALL_CLEAR;
2645                }
2646                return OO_FAILED;
2647             }
2648             pFS[i].data = (unsigned char *)encodeGetMsgPtr(pctxt, (int *)&(pFS[i].numocts));
2649
2650             /* Dump faststart element in logfile for debugging purpose */
2651             setPERBuffer(pctxt,  (unsigned char*)pFS[i].data, pFS[i].numocts, 1);
2652             initializePrintHandler(&printHandler, "FastStart Element");
2653             setEventHandler (pctxt, &printHandler);
2654             memset(&printOlc, 0, sizeof(printOlc));
2655             ret = asn1PD_H245OpenLogicalChannel(pctxt, &(printOlc));
2656             if(ret != ASN_OK)
2657             {
2658                OOTRACEERR3("Error: Failed decoding FastStart Element."
2659                            "(%s, %s)\n", call->callType, call->callToken);
2660                ooFreeQ931Message(pctxt, q931msg);
2661                if(call->callState < OO_CALL_CLEAR)
2662                {
2663                   call->callEndReason = OO_REASON_LOCAL_CLEARED;
2664                   call->callState = OO_CALL_CLEAR;
2665                }
2666                return OO_FAILED;
2667             }
2668             finishPrint();
2669             removeEventHandler(pctxt); 
2670
2671
2672             olc = NULL;
2673             i++;
2674             OOTRACEDBGC5("Added TX fs element %d with capability %s(%s, %s)\n",
2675                           i, ooGetCapTypeText(epCap->cap), call->callType, 
2676                           call->callToken);
2677          }
2678
2679       }
2680       OOTRACEDBGA4("Added %d fast start elements to SETUP message (%s, %s)\n",
2681                    i, call->callType, call->callToken);
2682       setup->fastStart.n = i;
2683       setup->fastStart.elem = pFS; 
2684    }
2685
2686    setup->conferenceID.numocts= call->confIdentifier.numocts;
2687    memcpy(setup->conferenceID.data, call->confIdentifier.data,
2688           call->confIdentifier.numocts);
2689
2690    setup->conferenceGoal.t = T_H225Setup_UUIE_conferenceGoal_create;
2691    /* H.225 point to point call */
2692    setup->callType.t = T_H225CallType_pointToPoint;
2693  
2694    /* Populate optional fields */
2695    setup->m.callIdentifierPresent = TRUE;
2696    /*ooGenerateCallIdentifier(&setup->callIdentifier);*/
2697    setup->callIdentifier.guid.numocts = call->callIdentifier.guid.numocts;
2698    memcpy(setup->callIdentifier.guid.data, call->callIdentifier.guid.data, 
2699                                call->callIdentifier.guid.numocts);
2700    
2701    setup->m.mediaWaitForConnectPresent = TRUE;
2702    if(OO_TESTFLAG(call->flags, OO_M_MEDIAWAITFORCONN)) {
2703       setup->mediaWaitForConnect = TRUE;
2704    }
2705    else {
2706       setup->mediaWaitForConnect = FALSE;
2707    }
2708    setup->m.canOverlapSendPresent = TRUE;
2709    setup->canOverlapSend = FALSE;
2710
2711    /* Populate the userInfo structure with the setup UUIE */ 
2712    
2713    q931msg->userInfo->h323_uu_pdu.h323_message_body.t = 
2714          T_H225H323_UU_PDU_h323_message_body_setup;
2715    q931msg->userInfo->h323_uu_pdu.h323_message_body.u.setup = setup;
2716    q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
2717    
2718    q931msg->userInfo->h323_uu_pdu.h245Tunneling = 
2719       OO_TESTFLAG (call->flags, OO_M_TUNNELING);
2720
2721    /* For H.323 version 4 and higher, if fast connect, tunneling should be 
2722       supported.
2723    */
2724    if(OO_TESTFLAG(call->flags, OO_M_FASTSTART)) {
2725       q931msg->userInfo->h323_uu_pdu.h245Tunneling = TRUE;
2726       OO_SETFLAG(call->flags, OO_M_TUNNELING);
2727    }
2728
2729    OOTRACEDBGA3("Built SETUP message (%s, %s)\n", call->callType, 
2730                  call->callToken);
2731    
2732    /* H225 message callback */
2733    if(gH323ep.h225Callbacks.onBuiltSetup)
2734       gH323ep.h225Callbacks.onBuiltSetup(call, q931msg);
2735
2736    ret=ooSendH225Msg(call, q931msg);
2737    if(ret != OO_OK)
2738    {
2739      OOTRACEERR3("Error:Failed to enqueue SETUP message to outbound queue. (%s, %s)\n", call->callType, call->callToken);
2740    }
2741    /* memReset(&gH323ep.msgctxt);*/
2742    memReset(call->msgctxt);
2743
2744    return ret;
2745 }
2746
2747
2748
2749 int ooQ931SendDTMFAsKeyPadIE(OOH323CallData *call, const char* data)
2750 {
2751    int ret;    
2752    H225Information_UUIE *information=NULL;
2753    Q931Message *q931msg=NULL;
2754    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
2755    OOCTXT *pctxt = call->msgctxt;
2756
2757    ret = ooCreateQ931Message(pctxt, &q931msg, Q931InformationMsg);
2758    if(ret != OO_OK)
2759    {      
2760       OOTRACEERR3("Error: In allocating memory for - H225 Information message."
2761                   "(%s, %s)\n", call->callType, call->callToken);
2762       return OO_FAILED;
2763    }
2764
2765    q931msg->callReference = call->callReference;
2766
2767    q931msg->userInfo = (H225H323_UserInformation*)memAllocZ(pctxt,
2768                              sizeof(H225H323_UserInformation));
2769    if(!q931msg->userInfo)
2770    {
2771       OOTRACEERR3("ERROR:Memory -  ooQ931SendDTMFAsKeypadIE - userInfo"
2772                   "(%s, %s)\n", call->callType, call->callToken);
2773       /* memReset(&gH323ep.msgctxt); */
2774       memReset(call->msgctxt);
2775       return OO_FAILED;
2776    }
2777    q931msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
2778    q931msg->userInfo->h323_uu_pdu.h245Tunneling = OO_TESTFLAG(call->flags, 
2779                                                               OO_M_TUNNELING); 
2780    q931msg->userInfo->h323_uu_pdu.h323_message_body.t = 
2781          T_H225H323_UU_PDU_h323_message_body_information;
2782    
2783    information = (H225Information_UUIE*)memAllocZ(pctxt, 
2784                                              sizeof(H225Information_UUIE));
2785    if(!information)
2786    {
2787       OOTRACEERR3("ERROR:Memory -  ooQ931SendDTMFAsKeypadIE - information"
2788                   "(%s, %s)\n", call->callType, call->callToken);
2789       /* memReset(&gH323ep.msgctxt); */
2790       memReset(call->msgctxt);
2791       return OO_FAILED;
2792    }
2793    q931msg->userInfo->h323_uu_pdu.h323_message_body.u.information = 
2794                                                                   information; 
2795    information->m.callIdentifierPresent = 1;
2796    information->callIdentifier.guid.numocts = 
2797                                    call->callIdentifier.guid.numocts;
2798    memcpy(information->callIdentifier.guid.data, 
2799           call->callIdentifier.guid.data, 
2800           call->callIdentifier.guid.numocts);
2801    information->protocolIdentifier = gProtocolID;
2802    
2803    /*Add keypad IE*/
2804    ret = ooQ931SetKeypadIE(pctxt, q931msg, data);
2805    if(ret != OO_OK)
2806    {
2807       OOTRACEERR3("Error:Creating keypad IE for (%s, %s)\n", call->callType, 
2808                    call->callToken);
2809       /* memReset(&gH323ep.msgctxt); */
2810       memReset(call->msgctxt);
2811       return OO_FAILED;
2812    }
2813
2814    ret=ooSendH225Msg(call, q931msg);
2815    if(ret != OO_OK)
2816    {
2817       OOTRACEERR3("Error:Failed to enqueue Information message to outbound "
2818                   "queue. (%s, %s)\n", call->callType, call->callToken);
2819    }
2820    /* memReset(&gH323ep.msgctxt); */
2821    memReset(call->msgctxt);
2822
2823    return ret;
2824
2825 }
2826
2827 int ooH323ForwardCall(char* callToken, char *dest)
2828 {
2829    int ret=0;
2830    Q931Message *pQ931Msg = NULL;
2831    H225Facility_UUIE *facility=NULL;
2832    OOCTXT *pctxt = &gH323ep.msgctxt;
2833    OOH323CallData *call;
2834    char ip[30]="\0", *pcPort=NULL;
2835    H225TransportAddress_ipAddress *fwdCallSignalIpAddress;
2836
2837    call= ooFindCallByToken(callToken);
2838    if(!call)
2839    {
2840       OOTRACEERR2("ERROR: Invalid call token for forward - %s\n", callToken);
2841       return OO_FAILED;
2842    }
2843    OOTRACEDBGA3("Building Facility message for call forward (%s, %s)\n", 
2844                                               call->callType, call->callToken);
2845    call->pCallFwdData = (OOCallFwdData*)memAllocZ(call->pctxt, 
2846                                                      sizeof(OOCallFwdData));
2847    if(!call->pCallFwdData)
2848    {
2849      OOTRACEERR3("Error:Memory - ooH323ForwardCall - pCallFwdData (%s, %s)\n",
2850      call->callType, call->callToken);
2851      return OO_FAILED;
2852    }
2853
2854    ret = ooParseDestination(call, dest, ip, 20, 
2855                                              &call->pCallFwdData->aliases);
2856    if(ret != OO_OK)
2857    {
2858       OOTRACEERR4("Error:Failed to parse the destination %s for call fwd."
2859                   "(%s, %s)\n", dest, call->callType, call->callToken);
2860       memFreePtr(call->pctxt, call->pCallFwdData);
2861       return OO_FAILED;
2862    }
2863
2864    if(!ooUtilsIsStrEmpty(ip))
2865    {
2866       pcPort = strchr(ip, ':');
2867       if(pcPort)
2868       {
2869          *pcPort = '\0';
2870          pcPort++;
2871          call->pCallFwdData->port = atoi(pcPort);
2872       }
2873       strcpy(call->pCallFwdData->ip, ip);
2874    }
2875
2876    ret = ooCreateQ931Message(pctxt, &pQ931Msg, Q931FacilityMsg);
2877    if(ret != OO_OK)
2878    {
2879       OOTRACEERR3
2880          ("ERROR: In allocating memory for call transfer facility message "
2881           "(%s, %s)\n", call->callType, call->callToken);
2882       return OO_FAILED;
2883    }
2884
2885    pQ931Msg->callReference = call->callReference;
2886
2887    pQ931Msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
2888                              sizeof(H225H323_UserInformation));
2889    if(!pQ931Msg->userInfo)
2890    {
2891       OOTRACEERR3("ERROR:Memory - ooH323ForwardCall - userInfo(%s, %s)\n", 
2892                    call->callType, call->callToken);
2893       return OO_FAILED;
2894    }
2895    memset (pQ931Msg->userInfo, 0, sizeof(H225H323_UserInformation));
2896    pQ931Msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
2897
2898    pQ931Msg->userInfo->h323_uu_pdu.h245Tunneling = 
2899                                    OO_TESTFLAG (call->flags, OO_M_TUNNELING); 
2900
2901    pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.t = 
2902       T_H225H323_UU_PDU_h323_message_body_facility;
2903    
2904    facility = (H225Facility_UUIE*) 
2905       memAllocZ (pctxt, sizeof(H225Facility_UUIE));
2906
2907    if(!facility)
2908    {
2909       OOTRACEERR3("ERROR:Memory - ooH323ForwardCall - facility (%s, %s)"
2910                   "\n", call->callType, call->callToken);
2911       return OO_FAILED;
2912    }
2913
2914    pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.u.facility = facility;
2915    
2916    facility->protocolIdentifier = gProtocolID;  
2917    facility->m.callIdentifierPresent = 1;
2918    facility->callIdentifier.guid.numocts = 
2919       call->callIdentifier.guid.numocts;
2920
2921    memcpy(facility->callIdentifier.guid.data, 
2922           call->callIdentifier.guid.data, 
2923           call->callIdentifier.guid.numocts);
2924
2925    facility->reason.t = T_H225FacilityReason_callForwarded;
2926    
2927    if(!ooUtilsIsStrEmpty(call->pCallFwdData->ip))
2928    {
2929       facility->m.alternativeAddressPresent = TRUE;
2930       facility->alternativeAddress.t=T_H225TransportAddress_ipAddress;
2931       fwdCallSignalIpAddress = (H225TransportAddress_ipAddress*)memAlloc(pctxt,
2932                                   sizeof(H225TransportAddress_ipAddress));
2933       if(!fwdCallSignalIpAddress)
2934       {
2935          OOTRACEERR3("Error:Memory - ooH323ForwardCall - fwdCallSignalAddress"
2936                      "(%s, %s)\n", call->callType, call->callToken);
2937          return OO_FAILED;
2938       }
2939       ooSocketConvertIpToNwAddr(call->pCallFwdData->ip, 
2940                                           fwdCallSignalIpAddress->ip.data);
2941
2942       fwdCallSignalIpAddress->ip.numocts=4;
2943       fwdCallSignalIpAddress->port = call->pCallFwdData->port;
2944       facility->alternativeAddress.u.ipAddress = fwdCallSignalIpAddress;
2945    }
2946
2947    if(call->pCallFwdData->aliases)
2948    {    
2949       facility->m.alternativeAliasAddressPresent = TRUE;
2950       ret = ooPopulateAliasList(pctxt, call->pCallFwdData->aliases, 
2951                                         &facility->alternativeAliasAddress);
2952       if(ret != OO_OK)
2953       {
2954          OOTRACEERR3("Error:Failed to populate alternate aliases in "
2955                      "ooH323ForwardCall. (%s, %s)\n", call->callType, 
2956                      call->callToken);
2957          return OO_FAILED;
2958       }
2959    }
2960
2961    ret = ooSendH225Msg(call, pQ931Msg);
2962    if(ret != OO_OK)
2963    {
2964       OOTRACEERR3
2965          ("Error:Failed to enqueue Forward Facility message to outbound "
2966          "queue.(%s, %s)\n", call->callType, call->callToken);
2967    }
2968    call->callEndReason = OO_REASON_LOCAL_FWDED;
2969    memReset (&gH323ep.msgctxt);
2970    return ret;
2971 }
2972
2973 int ooH323HangCall(char * callToken, OOCallClearReason reason, int q931cause)
2974 {
2975    OOH323CallData *call;
2976
2977    call= ooFindCallByToken(callToken);
2978    if(!call)
2979    {
2980       OOTRACEWARN2("WARN: Call hangup failed - Call %s not present\n", 
2981                     callToken);
2982       return OO_FAILED;
2983    }
2984    OOTRACEINFO3("Hanging up call (%s, %s)\n", call->callType, call->callToken);
2985    if(call->callState < OO_CALL_CLEAR)
2986    {
2987       call->callEndReason = reason;
2988       call->q931cause = q931cause;
2989       call->callState = OO_CALL_CLEAR;
2990    }
2991    return OO_OK;
2992 }
2993
2994 int ooSetBearerCapabilityIE
2995    (OOCTXT* pctxt, Q931Message *pmsg, enum Q931CodingStandard codingStandard, 
2996     enum Q931InformationTransferCapability capability, 
2997     enum Q931TransferMode transferMode, enum Q931TransferRate transferRate,
2998     enum Q931UserInfoLayer1Protocol userInfoLayer1)
2999 {
3000    unsigned size = 3;
3001    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3002
3003    if(pmsg->bearerCapabilityIE)
3004    {
3005       memFreePtr(pctxt, pmsg->bearerCapabilityIE);
3006       pmsg->bearerCapabilityIE = NULL;
3007    }
3008
3009    pmsg->bearerCapabilityIE = (Q931InformationElement*) 
3010                       memAlloc(pctxt, sizeof(Q931InformationElement)+size-1);
3011    if(!pmsg->bearerCapabilityIE)
3012    {
3013       OOTRACEERR1("Error:Memory - ooSetBearerCapabilityIE - bearerCapabilityIE"
3014                   "\n");
3015       return OO_FAILED;
3016    }
3017
3018    pmsg->bearerCapabilityIE->discriminator = Q931BearerCapabilityIE;
3019    pmsg->bearerCapabilityIE->length = size;
3020    pmsg->bearerCapabilityIE->data[0] = (ASN1OCTET)(0x80 | ((codingStandard&3) << 5) | (capability&31));
3021
3022    pmsg->bearerCapabilityIE->data[1] = (0x80 | ((transferMode & 3) << 5) | (transferRate & 31));
3023    
3024    pmsg->bearerCapabilityIE->data[2] = (0x80 | (1<<5) | userInfoLayer1);
3025
3026    return OO_OK;
3027 }
3028
3029 int ooQ931SetKeypadIE(OOCTXT* pctxt, Q931Message *pmsg, const char* data)
3030 {
3031    unsigned len = 0;
3032    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3033
3034    len = strlen(data);
3035    pmsg->keypadIE = (Q931InformationElement*) 
3036                       memAlloc(pctxt, sizeof(Q931InformationElement)+len-1);
3037    if(!pmsg->keypadIE)
3038    {
3039       OOTRACEERR1("Error:Memory - ooQ931SetKeypadIE - keypadIE\n");
3040       return OO_FAILED;
3041    }
3042
3043    pmsg->keypadIE->discriminator = Q931KeypadIE;
3044    pmsg->keypadIE->length = len;
3045    memcpy(pmsg->keypadIE->data, data, len);
3046    return OO_OK;
3047 }
3048
3049
3050
3051
3052 int ooQ931SetCallingPartyNumberIE
3053    (OOCTXT* pctxt, Q931Message *pmsg, const char *number, unsigned plan, unsigned type, 
3054     unsigned presentation, unsigned screening)
3055 {
3056    unsigned len = 0;
3057    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3058
3059    if(pmsg->callingPartyNumberIE)
3060    {
3061       memFreePtr(pctxt, pmsg->callingPartyNumberIE);
3062       pmsg->callingPartyNumberIE = NULL;
3063    }
3064
3065    len = strlen(number);
3066    pmsg->callingPartyNumberIE = (Q931InformationElement*) 
3067                       memAlloc(pctxt, sizeof(Q931InformationElement)+len+2-1);
3068    if(!pmsg->callingPartyNumberIE)
3069    {
3070       OOTRACEERR1("Error:Memory - ooQ931SetCallingPartyNumberIE - "
3071                   "callingPartyNumberIE\n");
3072       return OO_FAILED;
3073    }
3074    pmsg->callingPartyNumberIE->discriminator = Q931CallingPartyNumberIE;
3075    pmsg->callingPartyNumberIE->length = len+2;
3076    pmsg->callingPartyNumberIE->data[0] = (((type&7)<<4)|(plan&15));
3077    pmsg->callingPartyNumberIE->data[1] = (0x80|((presentation&3)<<5)|(screening&3));
3078    memcpy(pmsg->callingPartyNumberIE->data+2, number, len);
3079
3080    return OO_OK;
3081 }
3082
3083 int ooQ931SetCalledPartyNumberIE
3084    (OOCTXT* pctxt, Q931Message *pmsg, const char *number, unsigned plan, unsigned type)
3085 {
3086    unsigned len = 0;
3087    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3088
3089    if(pmsg->calledPartyNumberIE)
3090    {
3091       memFreePtr(pctxt, pmsg->calledPartyNumberIE);
3092       pmsg->calledPartyNumberIE = NULL;
3093    }
3094
3095    len = strlen(number);
3096    pmsg->calledPartyNumberIE = (Q931InformationElement*) 
3097                       memAlloc(pctxt, sizeof(Q931InformationElement)+len+1-1);
3098    if(!pmsg->calledPartyNumberIE)
3099    {
3100       OOTRACEERR1("Error:Memory - ooQ931SetCalledPartyNumberIE - "
3101                   "calledPartyNumberIE\n");
3102       return OO_FAILED;
3103    }
3104    pmsg->calledPartyNumberIE->discriminator = Q931CalledPartyNumberIE;
3105    pmsg->calledPartyNumberIE->length = len+1;
3106    pmsg->calledPartyNumberIE->data[0] = (0x80|((type&7)<<4)|(plan&15));
3107    memcpy(pmsg->calledPartyNumberIE->data+1, number, len);
3108
3109    return OO_OK;
3110 }
3111
3112 int ooQ931SetCauseIE
3113    (OOCTXT* pctxt, Q931Message *pmsg, enum Q931CauseValues cause, unsigned coding, 
3114     unsigned location)
3115 {
3116    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3117
3118    if(pmsg->causeIE){
3119       memFreePtr(pctxt, pmsg->causeIE);
3120       pmsg->causeIE = NULL;
3121    }
3122
3123    pmsg->causeIE = (Q931InformationElement*) 
3124                       memAlloc(pctxt, sizeof(Q931InformationElement)+1);
3125    if(!pmsg->causeIE)
3126    {
3127       OOTRACEERR1("Error:Memory - ooQ931SetCauseIE - causeIE\n");
3128       return OO_FAILED;
3129    }
3130    pmsg->causeIE->discriminator = Q931CauseIE;
3131    pmsg->causeIE->length = 2;
3132    pmsg->causeIE->data[0] = (0x80 | ((coding & 0x03) <<5) | (location & 0x0F));
3133
3134    pmsg->causeIE->data[1] = (0x80 | cause);
3135   
3136    return OO_OK;
3137 }
3138
3139
3140 /* Build a Facility message and tunnel H.245 message through it */
3141 int ooSendAsTunneledMessage(OOH323CallData *call, ASN1OCTET* msgbuf, 
3142                             int h245Len, int h245MsgType, int associatedChan)
3143 {
3144    Q931Message *pQ931Msg = NULL;
3145    H225H323_UU_PDU *pH323UUPDU = NULL;
3146    H225H323_UU_PDU_h245Control *pH245Control = NULL;
3147    ASN1DynOctStr * elem;
3148    int ret =0;
3149    H225Facility_UUIE *facility=NULL;
3150    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
3151    OOCTXT *pctxt = call->msgctxt;
3152
3153    OOTRACEDBGA4("Building Facility message for tunneling %s (%s, %s)\n", 
3154                  ooGetMsgTypeText(h245MsgType), call->callType, call->callToken);
3155
3156    ret = ooCreateQ931Message(pctxt, &pQ931Msg, Q931FacilityMsg);
3157    if(ret != OO_OK)
3158    {
3159       OOTRACEERR3("ERROR: In allocating memory for facility message "
3160                   "(%s, %s)\n", call->callType, call->callToken);
3161       return OO_FAILED;
3162    }
3163
3164    pQ931Msg->callReference = call->callReference;
3165
3166    pQ931Msg->userInfo = (H225H323_UserInformation*)memAlloc(pctxt,
3167                              sizeof(H225H323_UserInformation));
3168    if(!pQ931Msg->userInfo)
3169    {
3170       OOTRACEERR3("ERROR:Memory - ooSendAsTunneledMessage - userInfo"
3171                 " (%s, %s)\n", call->callType, call->callToken);
3172       /* memReset(&gH323ep.msgctxt);*/
3173       memReset(call->msgctxt);
3174       return OO_FAILED;
3175    }
3176    memset (pQ931Msg->userInfo, 0, sizeof(H225H323_UserInformation));
3177    pQ931Msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent=1; 
3178
3179    pQ931Msg->userInfo->h323_uu_pdu.h245Tunneling = 
3180       OO_TESTFLAG (call->flags, OO_M_TUNNELING);
3181
3182    pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.t = 
3183          T_H225H323_UU_PDU_h323_message_body_facility;
3184    
3185    facility = (H225Facility_UUIE*)
3186       memAllocZ (pctxt, sizeof(H225Facility_UUIE));
3187
3188    if(!facility)
3189    {
3190       OOTRACEERR3("ERROR:Memory - ooSendAsTunneledMessage - facility (%s, %s)"
3191                   "\n", call->callType, call->callToken);
3192       /* memReset(&gH323ep.msgctxt); */
3193       memReset(call->msgctxt);
3194       return OO_FAILED;
3195    }
3196
3197    pQ931Msg->userInfo->h323_uu_pdu.h323_message_body.u.facility = facility;
3198    /* Populate Facility UUIE */
3199    facility->protocolIdentifier = gProtocolID;  
3200    facility->m.callIdentifierPresent = 1;
3201    facility->callIdentifier.guid.numocts = 
3202       call->callIdentifier.guid.numocts;
3203
3204    memcpy(facility->callIdentifier.guid.data, 
3205           call->callIdentifier.guid.data, 
3206           call->callIdentifier.guid.numocts);
3207
3208    facility->reason.t = T_H225FacilityReason_transportedInformation;
3209
3210    pH323UUPDU = (H225H323_UU_PDU*) &pQ931Msg->userInfo->h323_uu_pdu;
3211    pH323UUPDU->m.h245TunnelingPresent = TRUE;
3212    pH323UUPDU->m.h245ControlPresent = TRUE;
3213    pH323UUPDU->h245Tunneling = TRUE;
3214    pH245Control = (H225H323_UU_PDU_h245Control*)
3215                    &pH323UUPDU->h245Control;
3216
3217    elem = (ASN1DynOctStr*) memAlloc(pctxt, 
3218                                       sizeof(ASN1DynOctStr));
3219    if(!elem)
3220    {
3221       OOTRACEERR3("ERROR:Memory - ooSendAsTunneledMessage - elem "
3222                   "(%s, %s)\n", call->callType, call->callToken);
3223       return OO_FAILED;
3224    }
3225    elem->data = msgbuf;
3226    elem->numocts = h245Len;
3227    pH245Control->elem = elem;
3228    pH245Control->n = 1;
3229    pQ931Msg->tunneledMsgType = h245MsgType;
3230    pQ931Msg->logicalChannelNo = associatedChan;
3231
3232    
3233    ret = ooSendH225Msg(call, pQ931Msg);
3234    if(ret != OO_OK)
3235    {
3236      OOTRACEERR3("Error:Failed to enqueue Facility(tunneling) message to "
3237                  "outbound queue.(%s, %s)\n", call->callType, call->callToken);
3238    }
3239
3240    /* Can't do memReset here because if we are sending H.245 message as a 
3241       response to received tunneled h.245 message, we can't reset unless the \
3242       main received H225 message processing is finished. Rule. No reset when
3243       tunneling
3244    */
3245    /* memFreePtr(&gH323ep.msgctxt, pQ931Msg); */
3246    memFreePtr(call->msgctxt, pQ931Msg);
3247    return ret;
3248 }
3249
3250 int ooCallEstbTimerExpired(void *data)
3251 {
3252
3253    ooTimerCallback *cbData = (ooTimerCallback*) data;
3254    OOH323CallData *call = cbData->call;
3255    OOTRACEINFO3("Call Establishment timer expired. (%s, %s)\n", 
3256                                             call->callType, call->callToken); 
3257    memFreePtr(call->pctxt, cbData);
3258    if(call->callState < OO_CALL_CLEAR){
3259       call->callState = OO_CALL_CLEAR;
3260       call->callEndReason = OO_REASON_LOCAL_CLEARED;      
3261    }
3262
3263    return OO_OK;
3264 }
3265
3266
3267 int ooQ931GetCauseAndReasonCodeFromCallClearReason
3268    (OOCallClearReason clearReason, enum Q931CauseValues *cause, 
3269     unsigned *reasonCode)
3270 {
3271    switch(clearReason)
3272    {
3273    case OO_REASON_INVALIDMESSAGE:
3274    case OO_REASON_TRANSPORTFAILURE:
3275       *reasonCode =  T_H225ReleaseCompleteReason_undefinedReason;
3276       *cause = Q931ProtocolErrorUnspecified;
3277       break;
3278    case OO_REASON_NOBW:
3279       *reasonCode = T_H225ReleaseCompleteReason_noBandwidth;
3280       *cause = Q931ErrorInCauseIE;
3281       break;
3282    case OO_REASON_GK_NOCALLEDUSER:
3283       *reasonCode = T_H225ReleaseCompleteReason_calledPartyNotRegistered;
3284       *cause = Q931SubscriberAbsent;
3285       break;
3286    case OO_REASON_GK_NOCALLERUSER:
3287       *reasonCode = T_H225ReleaseCompleteReason_callerNotRegistered;
3288       *cause = Q931SubscriberAbsent;      
3289       break;
3290    case OO_REASON_GK_UNREACHABLE:
3291       *reasonCode = T_H225ReleaseCompleteReason_unreachableGatekeeper;
3292       *cause = Q931TemporaryFailure;
3293       break;
3294    case OO_REASON_GK_NORESOURCES:
3295    case OO_REASON_GK_CLEARED:
3296       *reasonCode = T_H225ReleaseCompleteReason_gatekeeperResources;
3297       *cause = Q931Congestion;
3298       break;
3299    case OO_REASON_NOCOMMON_CAPABILITIES:
3300       *reasonCode =  T_H225ReleaseCompleteReason_undefinedReason;
3301       *cause = Q931IncompatibleDestination;
3302       break;
3303    case OO_REASON_LOCAL_FWDED:
3304    case OO_REASON_REMOTE_FWDED:
3305       *reasonCode =  T_H225ReleaseCompleteReason_facilityCallDeflection;
3306       *cause = Q931Redirection;
3307       break;
3308    case OO_REASON_REMOTE_CLEARED:
3309    case OO_REASON_LOCAL_CLEARED:
3310       *reasonCode = T_H225ReleaseCompleteReason_undefinedReason;
3311       *cause = Q931NormalCallClearing;
3312       break;
3313    case OO_REASON_REMOTE_BUSY:
3314    case OO_REASON_LOCAL_BUSY:
3315       *reasonCode =  T_H225ReleaseCompleteReason_inConf;
3316       *cause = Q931UserBusy;
3317       break;
3318    case OO_REASON_REMOTE_NOANSWER:
3319    case OO_REASON_LOCAL_NOTANSWERED:
3320       *reasonCode =  T_H225ReleaseCompleteReason_undefinedReason;
3321       *cause = Q931NoAnswer;
3322       break;
3323    case OO_REASON_REMOTE_REJECTED:
3324    case OO_REASON_LOCAL_REJECTED:
3325       *reasonCode = T_H225ReleaseCompleteReason_destinationRejection;
3326       *cause = Q931CallRejected;
3327       break;
3328    case OO_REASON_REMOTE_CONGESTED:
3329    case OO_REASON_LOCAL_CONGESTED:
3330       *reasonCode =  T_H225ReleaseCompleteReason_noBandwidth;
3331       *cause = Q931Congestion;
3332       break;
3333    case OO_REASON_NOROUTE:
3334       *reasonCode = T_H225ReleaseCompleteReason_unreachableDestination;
3335       *cause = Q931NoRouteToDestination;
3336       break;
3337    case OO_REASON_NOUSER:
3338       *reasonCode = T_H225ReleaseCompleteReason_undefinedReason;      
3339       *cause = Q931SubscriberAbsent;
3340       break;
3341    case OO_REASON_UNKNOWN:
3342    default:
3343       *reasonCode = T_H225ReleaseCompleteReason_undefinedReason;
3344       *cause = Q931NormalUnspecified;
3345    }
3346
3347    return OO_OK;
3348 }
3349
3350 enum OOCallClearReason ooGetCallClearReasonFromCauseAndReasonCode
3351    (enum Q931CauseValues cause, unsigned reasonCode)
3352 {
3353    switch(cause)
3354    {
3355       case Q931NormalCallClearing:
3356          return OO_REASON_REMOTE_CLEARED;
3357
3358       case Q931UserBusy:
3359          return OO_REASON_REMOTE_BUSY;
3360
3361       case Q931NoResponse:
3362       case Q931NoAnswer:
3363          return OO_REASON_REMOTE_NOANSWER;
3364
3365       case Q931CallRejected:
3366          return OO_REASON_REMOTE_REJECTED;
3367
3368       case Q931Redirection:
3369          return OO_REASON_REMOTE_FWDED;
3370
3371       case Q931NetworkOutOfOrder:
3372       case Q931TemporaryFailure:
3373          return OO_REASON_TRANSPORTFAILURE;
3374
3375       case Q931NoCircuitChannelAvailable:
3376       case Q931Congestion:
3377       case Q931RequestedCircuitUnAvailable:
3378       case Q931ResourcesUnavailable:
3379          return OO_REASON_REMOTE_CONGESTED;
3380
3381       case Q931NoRouteToDestination:
3382       case Q931NoRouteToNetwork:
3383          return OO_REASON_NOROUTE;
3384       case Q931NumberChanged:
3385       case Q931UnallocatedNumber:
3386       case Q931SubscriberAbsent:
3387          return OO_REASON_NOUSER;
3388       case Q931ChannelUnacceptable:
3389       case Q931DestinationOutOfOrder:
3390       case Q931InvalidNumberFormat:
3391       case Q931NormalUnspecified:
3392       case Q931StatusEnquiryResponse:
3393       case Q931IncompatibleDestination:
3394       case Q931ProtocolErrorUnspecified:
3395       case Q931RecoveryOnTimerExpiry:
3396       case Q931InvalidCallReference:
3397       default:
3398          switch(reasonCode)
3399          {
3400             case T_H225ReleaseCompleteReason_noBandwidth:
3401                return OO_REASON_NOBW;
3402             case T_H225ReleaseCompleteReason_gatekeeperResources:
3403                return OO_REASON_GK_NORESOURCES;
3404             case T_H225ReleaseCompleteReason_unreachableDestination:
3405                return OO_REASON_NOROUTE;
3406             case T_H225ReleaseCompleteReason_destinationRejection:
3407                return OO_REASON_REMOTE_REJECTED;
3408             case T_H225ReleaseCompleteReason_inConf:
3409                return OO_REASON_REMOTE_BUSY;
3410             case T_H225ReleaseCompleteReason_facilityCallDeflection:
3411                return OO_REASON_REMOTE_FWDED;
3412             case T_H225ReleaseCompleteReason_calledPartyNotRegistered:
3413                return OO_REASON_GK_NOCALLEDUSER;
3414             case T_H225ReleaseCompleteReason_callerNotRegistered:
3415                return OO_REASON_GK_NOCALLERUSER;
3416             case T_H225ReleaseCompleteReason_gatewayResources:
3417                return OO_REASON_GK_NORESOURCES;
3418             case T_H225ReleaseCompleteReason_unreachableGatekeeper:
3419                return OO_REASON_GK_UNREACHABLE;
3420             case T_H225ReleaseCompleteReason_invalidRevision:
3421             case T_H225ReleaseCompleteReason_noPermission:
3422             case T_H225ReleaseCompleteReason_badFormatAddress:
3423             case T_H225ReleaseCompleteReason_adaptiveBusy:
3424             case T_H225ReleaseCompleteReason_undefinedReason:
3425             case T_H225ReleaseCompleteReason_securityDenied:
3426             case T_H225ReleaseCompleteReason_newConnectionNeeded:
3427             case T_H225ReleaseCompleteReason_nonStandardReason:
3428             case T_H225ReleaseCompleteReason_replaceWithConferenceInvite:
3429             case T_H225ReleaseCompleteReason_genericDataReason:
3430             case T_H225ReleaseCompleteReason_neededFeatureNotSupported:
3431             case T_H225ReleaseCompleteReason_tunnelledSignallingRejected:
3432             case T_H225ReleaseCompleteReason_invalidCID:
3433             case T_H225ReleaseCompleteReason_securityError:
3434             case T_H225ReleaseCompleteReason_hopCountExceeded:
3435             case T_H225ReleaseCompleteReason_extElem1:
3436             default:
3437                return OO_REASON_UNKNOWN;
3438          }
3439    }
3440    return OO_REASON_UNKNOWN;
3441 }
3442
3443 /**
3444  This function is used to parse destination string passed to ooH323MakeCall and
3445  ooH323ForwardCall. If the string contains ip address and port, it is returned
3446  in the parsedIP buffer and if it contains alias, it is added to aliasList
3447 */
3448 int ooParseDestination
3449    (struct OOH323CallData *call, char *dest, char* parsedIP, unsigned len,
3450     ooAliases** aliasList)
3451 {
3452    int iEk=-1, iDon=-1, iTeen=-1, iChaar=-1, iPort = -1, i;
3453    ooAliases * psNewAlias = NULL;
3454    char *cAt = NULL, *host=NULL;
3455    char tmp[256], buf[30];
3456    char *alias=NULL;
3457    OOCTXT *pctxt = call->pctxt;
3458    parsedIP[0] = '\0';
3459
3460    OOTRACEINFO2("Parsing destination %s\n", dest);
3461   
3462    /* Test for an IP address:Note that only supports dotted IPv4.
3463       IPv6 won't pass the test and so will numeric IP representation*/
3464    
3465    sscanf(dest, "%d.%d.%d.%d:%d", &iEk, &iDon, &iTeen, &iChaar, &iPort);
3466    if((iEk > 0            && iEk <= 255)    &&
3467       (iDon >= 0          && iDon <= 255)   &&
3468       (iTeen >=0          && iTeen <= 255)  &&
3469       (iChaar >= 0        && iChaar <= 255) &&
3470       (!strchr(dest, ':') || iPort != -1))
3471    {
3472       if(!strchr(dest, ':'))
3473          iPort = 1720; /*Default h.323 port */
3474
3475       sprintf(buf, "%d.%d.%d.%d:%d", iEk, iDon, iTeen, iChaar, iPort);
3476       if(strlen(buf)+1>len)
3477       {
3478          OOTRACEERR1("Error:Insufficient buffer space for parsed ip - "
3479                      "ooParseDestination\n");
3480          return OO_FAILED;
3481       }
3482          
3483       strcpy(parsedIP, buf);
3484       return OO_OK;
3485    }
3486
3487    /* alias@host */
3488    strncpy(tmp, dest, sizeof(tmp)-1);
3489    tmp[sizeof(tmp)-1]='\0';
3490    if((host=strchr(tmp, '@')) != NULL)
3491    {
3492       *host = '\0';
3493       host++;
3494       sscanf(host, "%d.%d.%d.%d:%d", &iEk, &iDon, &iTeen, &iChaar, &iPort);
3495       if((iEk > 0            && iEk <= 255)    &&
3496          (iDon >= 0          && iDon <= 255)   &&
3497          (iTeen >=0          && iTeen <= 255)  &&
3498          (iChaar >= 0        && iChaar <= 255) &&
3499          (!strchr(host, ':') || iPort != -1))
3500       {
3501          if(!strchr(dest, ':'))
3502             iPort = 1720; /*Default h.323 port */
3503
3504          sprintf(buf, "%d.%d.%d.%d:%d", iEk, iDon, iTeen, iChaar, iPort);
3505          if(strlen(buf)+1>len)
3506          {
3507             OOTRACEERR1("Error:Insufficient buffer space for parsed ip - "
3508                         "ooParseDestination\n");
3509             return OO_FAILED;
3510          }
3511
3512          strncpy(parsedIP, buf, len-1);
3513          parsedIP[len-1]='\0';
3514          alias = tmp;
3515       }
3516    }
3517
3518    if(!alias)
3519    {
3520      alias = dest;
3521    }
3522    /* url test */
3523    if(alias == strstr(alias, "http://"))
3524    {
3525       psNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases));
3526       if(!psNewAlias)
3527       {
3528          OOTRACEERR1("Error:Memory - ooParseDestination - psNewAlias\n");
3529          return OO_FAILED;
3530       }
3531       psNewAlias->type = T_H225AliasAddress_url_ID;
3532       psNewAlias->value = (char*) memAlloc(pctxt, strlen(alias)+1);
3533       if(!psNewAlias->value)
3534       {
3535          OOTRACEERR1("Error:Memory - ooParseDestination - "
3536                      "psNewAlias->value\n");
3537          memFreePtr(pctxt, psNewAlias);
3538          return OO_FAILED;
3539       }
3540       strcpy(psNewAlias->value, alias);
3541       psNewAlias->next = *aliasList;
3542       *aliasList = psNewAlias;
3543       OOTRACEINFO2("Destination parsed as url %s\n", psNewAlias->value);
3544       return OO_OK;
3545    }
3546
3547    /* E-mail ID test */
3548    if((cAt = strchr(alias, '@')) && alias != strchr(alias, '@'))
3549    {
3550       if(strchr(cAt, '.'))
3551       {
3552          psNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases));
3553          if(!psNewAlias)
3554          {
3555             OOTRACEERR1("Error:Memory - ooParseDestination - psNewAlias\n");
3556             return OO_FAILED;
3557          }
3558          psNewAlias->type = T_H225AliasAddress_email_ID;
3559          psNewAlias->value = (char*) memAlloc(pctxt, strlen(alias)+1);
3560          if(!psNewAlias->value)
3561          {
3562             OOTRACEERR1("Error:Memory - ooParseDestination - "
3563                         "psNewAlias->value\n");
3564             memFreePtr(pctxt, psNewAlias);
3565             return OO_FAILED;
3566          }
3567          strcpy(psNewAlias->value, alias);
3568          psNewAlias->next = *aliasList;
3569          *aliasList = psNewAlias;
3570          OOTRACEINFO2("Destination is parsed as email %s\n",psNewAlias->value);
3571          return OO_OK;
3572       }
3573    }
3574
3575   
3576    /* e-164 */
3577    /* strspn(dest, "1234567890*#,") == strlen(dest)*/
3578    /* Dialed digits test*/
3579    for(i=0; *(alias+i) != '\0'; i++)
3580    {
3581       if(!isdigit(alias[i]) && alias[i] != '#' && alias[i] != '*' && 
3582          alias[i] != ',')
3583          break;
3584    }
3585    if(*(alias+i) == '\0')
3586    {
3587       psNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases));
3588       if(!psNewAlias)
3589       {
3590          OOTRACEERR1("Error:Memory - ooParseDestination - psNewAlias\n");
3591          return OO_FAILED;
3592       }
3593       /*      memset(psNewAlias, 0, sizeof(ooAliases));*/
3594       psNewAlias->type = T_H225AliasAddress_dialedDigits;
3595       psNewAlias->value = (char*) memAlloc(pctxt, strlen(alias)+1);
3596       if(!psNewAlias->value)
3597       {
3598          OOTRACEERR1("Error:Memroy - ooParseDestination - "
3599                      "psNewAlias->value\n");
3600          memFreePtr(pctxt, psNewAlias);
3601          return OO_FAILED;
3602       }
3603       strcpy(psNewAlias->value, alias);
3604       psNewAlias->next = *aliasList;
3605       *aliasList = psNewAlias;
3606       OOTRACEINFO2("Destination is parsed as dialed digits %s\n",
3607                   psNewAlias->value);
3608       /* Also set called party number */
3609       if(!call->calledPartyNumber)
3610       {
3611          if(ooCallSetCalledPartyNumber(call, alias) != OO_OK)
3612          {
3613             OOTRACEWARN3("Warning:Failed to set calling party number."
3614                          "(%s, %s)\n", call->callType, call->callToken);
3615          }
3616       }
3617       return OO_OK;
3618    }
3619    /* Evrything else is an h323-id for now */
3620    psNewAlias = (ooAliases*) memAlloc(pctxt, sizeof(ooAliases));
3621    if(!psNewAlias)
3622    {
3623       OOTRACEERR1("Error:Memory - ooParseDestination - psNewAlias\n");
3624       return OO_FAILED;
3625    }
3626    psNewAlias->type = T_H225AliasAddress_h323_ID;
3627    psNewAlias->value = (char*) memAlloc(pctxt, strlen(alias)+1);
3628    if(!psNewAlias->value)
3629    {
3630       OOTRACEERR1("Error:Memory - ooParseDestination - psNewAlias->value\n");
3631       memFreePtr(pctxt, psNewAlias);
3632       return OO_FAILED;
3633    }
3634    strcpy(psNewAlias->value, alias);
3635    psNewAlias->next = *aliasList;
3636    *aliasList = psNewAlias;
3637    OOTRACEINFO2("Destination for new call is parsed as h323-id %s \n",
3638                psNewAlias->value);
3639    return OO_OK;
3640 }
3641
3642 const char* ooGetMsgTypeText (int msgType)
3643 {
3644    static const char *msgTypeText[]={
3645       "OOQ931MSG",
3646       "OOH245MSG",
3647       "OOSetup",
3648       "OOCallProceeding",
3649       "OOAlert",
3650       "OOConnect",
3651       "OOReleaseComplete",
3652       "OOFacility",
3653       "OOInformation",
3654       "OOMasterSlaveDetermination",
3655       "OOMasterSlaveAck",
3656       "OOMasterSlaveReject",
3657       "OOMasterSlaveRelease",
3658       "OOTerminalCapabilitySet",
3659       "OOTerminalCapabilitySetAck",
3660       "OOTerminalCapabilitySetReject",
3661       "OOTerminalCapabilitySetRelease",
3662       "OOOpenLogicalChannel",
3663       "OOOpenLogicalChannelAck",
3664       "OOOpenLogicalChannelReject",
3665       "OOOpenLogicalChannelRelease",
3666       "OOOpenLogicalChannelConfirm",
3667       "OOCloseLogicalChannel",
3668       "OOCloseLogicalChannelAck",
3669       "OORequestChannelClose",
3670       "OORequestChannelCloseAck",
3671       "OORequestChannelCloseReject",
3672       "OORequestChannelCloseRelease",
3673       "OOEndSessionCommand",
3674       "OOUserInputIndication",
3675       "OORequestModeAck",
3676       "OORequestModeReject",
3677       "OORequestMode",
3678       "OORequestDelayResponse",
3679       "OORequestDelayRequest"
3680    };
3681    int idx = msgType - OO_MSGTYPE_MIN;
3682    return ooUtilsGetText (idx, msgTypeText, OONUMBEROF(msgTypeText));
3683 }
3684
3685 const char* ooGetQ931CauseValueText(int val)
3686 {
3687    switch(val)
3688    {
3689       case Q931UnallocatedNumber:   
3690          return "Q931UnallocatedNumber";
3691       case Q931NoRouteToNetwork:
3692          return "Q931NoRouteToNetwork";
3693       case Q931NoRouteToDestination:
3694          return "Q931NoRouteToDestination";
3695       case Q931ChannelUnacceptable: 
3696          return "Q931ChannelUnacceptable";
3697       case Q931NormalCallClearing:
3698          return "Q931NormalCallClearing";
3699       case Q931UserBusy:
3700          return "Q931UserBusy";
3701       case Q931NoResponse:
3702          return "Q931NoResponse";
3703       case Q931NoAnswer:
3704          return "Q931NoAnswer";
3705       case Q931SubscriberAbsent:
3706          return "Q931SubscriberAbsent";
3707       case Q931CallRejected:
3708          return "Q931CallRejected";
3709       case Q931NumberChanged:
3710          return "Q931NumberChanged";
3711       case Q931Redirection:
3712          return "Q931Redirection";
3713       case Q931DestinationOutOfOrder:
3714          return "Q931DestinationOutOfOrder";
3715       case Q931InvalidNumberFormat:
3716          return "Q931InvalidNumberFormat";
3717       case Q931NormalUnspecified:
3718          return "Q931NormalUnspecified";
3719       case Q931StatusEnquiryResponse:
3720          return "Q931StatusEnquiryResponse";
3721       case Q931NoCircuitChannelAvailable:
3722          return "Q931NoCircuitChannelAvailable";
3723       case Q931NetworkOutOfOrder:
3724          return "Q931NetworkOutOfOrder";
3725       case Q931TemporaryFailure:
3726          return "Q931TemporaryFailure";
3727       case Q931Congestion:
3728          return "Q931Congestion";
3729       case Q931RequestedCircuitUnAvailable:
3730          return "Q931RequestedCircuitUnavailable";
3731       case Q931ResourcesUnavailable:
3732          return "Q931ResourcesUnavailable";
3733       case Q931IncompatibleDestination:
3734          return "Q931IncompatibleDestination";
3735       case Q931ProtocolErrorUnspecified:
3736          return "Q931ProtocolErrorUnspecified";
3737       case Q931RecoveryOnTimerExpiry:
3738          return "Q931RecoveryOnTimerExpiry";
3739       case Q931InvalidCallReference:
3740          return "Q931InvaliedCallReference";
3741       default:
3742          return "Unsupported Cause Type";
3743    }
3744    return "Unsupported Cause Type";
3745 }
3746