d42f8bbc1760341a110efa333d1576938f602cf0
[asterisk/asterisk.git] / addons / ooh323c / src / ooh245.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 #include "asterisk.h"
17 #include "asterisk/lock.h"
18 #include "ooh245.h"
19 #include "ooCalls.h"
20 #include "printHandler.h"
21 #include "ooh323ep.h"
22 #include "ooCapability.h"
23 #include "ooTimer.h"
24 #ifdef _WIN32
25 #include <stdlib.h>
26 #include <process.h>
27 #define getpid _getpid
28 #endif
29 #include <time.h>
30
31 /** Global endpoint structure */
32 extern ooEndPoint gH323ep;
33
34 static ASN1OBJID gh245ProtocolID = {
35   6, { 0, 0, 8, 245, 0, 8 }
36 };
37
38 int ooCreateH245Message(OOH323CallData* call, H245Message **pph245msg, int type)
39 {
40    /* OOCTXT* pctxt = &gH323ep.msgctxt; */
41    OOCTXT* pctxt = call->msgctxt;
42
43    *pph245msg = (H245Message*) memAlloc (pctxt, sizeof(H245Message));
44
45    if(!(*pph245msg))
46    {
47       OOTRACEERR1("ERROR:Failed to allocate memory for h245 message\n");
48       return OO_FAILED;
49    }
50    else
51    {
52       (*pph245msg)->h245Msg.t = type;
53       (*pph245msg)->logicalChannelNo = 0;
54       switch(type)
55       {
56          case  T_H245MultimediaSystemControlMessage_request:
57             (*pph245msg)->h245Msg.u.request = (H245RequestMessage*) 
58             memAllocZ (pctxt, sizeof(H245RequestMessage));
59
60             /*Check for successful mem allocation, and if successful initialize
61               mem to zero*/
62             if(!(*pph245msg)->h245Msg.u.request)
63             {
64                OOTRACEERR1("ERROR:Memory allocation for H.245 request"
65                                      " message failed\n");
66                return OO_FAILED;
67             }
68             break;
69
70          case T_H245MultimediaSystemControlMessage_response:
71             (*pph245msg)->h245Msg.u.response = (H245ResponseMessage*)
72             memAllocZ (pctxt, sizeof(H245ResponseMessage));
73
74             /*Check for successful mem allocation, and if successful initialize
75               mem to zero*/
76             if(!(*pph245msg)->h245Msg.u.response)
77             {
78                OOTRACEERR1("ERROR:Memory allocation for H.245 response"
79                                      " message failed\n");
80                return OO_FAILED;
81             }
82             break;
83
84          case T_H245MultimediaSystemControlMessage_command:
85             (*pph245msg)->h245Msg.u.command = (H245CommandMessage*)
86             memAllocZ (pctxt, sizeof(H245CommandMessage));
87
88             /*Check for successful mem allocation, and if successful initialize
89               mem to zero*/
90             if(!(*pph245msg)->h245Msg.u.command)
91             {
92                OOTRACEERR1("ERROR:Memory allocation for H.245 command"
93                                      " message failed\n");
94                return OO_FAILED;
95             }
96             break;
97
98          case T_H245MultimediaSystemControlMessage_indication:
99             (*pph245msg)->h245Msg.u.indication = (H245IndicationMessage*)
100             memAllocZ (pctxt, sizeof(H245IndicationMessage));
101
102             /*Check for successful mem allocation, and if successful initialize
103               mem to zero*/
104             if(!(*pph245msg)->h245Msg.u.indication)
105             {
106                OOTRACEERR1("ERROR:Memory allocation for H.245 indication"
107                                      " message failed\n");
108                return OO_FAILED;
109             }
110             break;
111
112          default:
113             OOTRACEERR1("ERROR: H245 message type not supported\n");
114       }
115
116       return OO_OK;
117    }
118 }
119
120 int ooFreeH245Message(OOH323CallData *call, H245Message *pmsg)
121 {
122   /* In case of tunneling, memory is freed when corresponding Q931 message is freed.*/
123    OOTRACEDBGC1("msgCtxt Reset?");
124    if (0 != pmsg) {
125      if(!OO_TESTFLAG (call->flags, OO_M_TUNNELING)){
126          /* memReset (&gH323ep.msgctxt); */
127          memReset (call->msgctxt);
128          OOTRACEDBGC3(" Done (%s, %s)\n", call->callType, call->callToken);
129          return OO_OK;
130      }
131    }
132    OOTRACEDBGC3("Not Done (%s, %s)\n", call->callType, call->callToken);
133    return OO_OK;
134 }
135
136 #ifndef _COMPACT
137 static void ooPrintH245Message 
138    (OOH323CallData* call, ASN1OCTET* msgbuf, ASN1UINT msglen)
139 {
140    OOCTXT ctxt;
141    H245MultimediaSystemControlMessage mmMsg;
142    int ret;
143
144    initContext (&ctxt);
145
146    setPERBuffer (&ctxt, msgbuf, msglen, TRUE);
147
148    initializePrintHandler(&printHandler, "Sending H.245 Message");
149
150    /* Set event handler */
151    setEventHandler (&ctxt, &printHandler);
152
153    ret = asn1PD_H245MultimediaSystemControlMessage(&ctxt, &mmMsg);
154    if(ret != ASN_OK)
155    {
156       OOTRACEERR3("Error decoding H245 message (%s, %s)\n", 
157                   call->callType, call->callToken);
158       OOTRACEERR1 (errGetText (&ctxt));
159    }
160    finishPrint();
161    freeContext(&ctxt);   
162 }
163 #endif
164
165 int ooEncodeH245Message
166    (OOH323CallData *call, H245Message *ph245Msg, char *msgbuf, int size)
167 {
168    int len=0, encodeLen=0, i=0;
169    int stat=0;
170    ASN1OCTET* encodePtr=NULL;
171    H245MultimediaSystemControlMessage *multimediaMsg;
172    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
173    OOCTXT *pctxt = call->msgctxt;
174    multimediaMsg = &(ph245Msg->h245Msg);
175
176    if(!msgbuf || size<200)
177    {
178       OOTRACEERR3("Error: Invalid message buffer/size for "
179                   "ooEncodeH245Message. (%s, %s)\n", 
180                    call->callType, call->callToken);
181       return OO_FAILED;
182    }
183
184    msgbuf[i++] = ph245Msg->msgType;
185    msgbuf[i++] = (ph245Msg->logicalChannelNo>>8);
186    msgbuf[i++] = ph245Msg->logicalChannelNo;
187    /* This will contain the total length of the encoded message */
188    msgbuf[i++] = 0;
189    msgbuf[i++] = 0;
190    
191    if(!OO_TESTFLAG (call->flags, OO_M_TUNNELING))
192    {
193       /* Populate message buffer to be returned */
194       len =  4;
195       msgbuf[i++] = 3; /* TPKT version */
196       msgbuf[i++] = 0; /* TPKT resevred */
197       /* 1st octet of length, will be populated once len is determined */
198       msgbuf[i++] = 0; 
199       /* 2nd octet of length, will be populated once len is determined */
200       msgbuf[i++] = 0;
201    }
202    
203    setPERBuffer (pctxt, (unsigned char*) msgbuf+i, (size-i), TRUE);
204
205    /* stat = asn1PE_H245MultimediaSystemControlMessage (&gH323ep.msgctxt,  */
206    stat = asn1PE_H245MultimediaSystemControlMessage (call->msgctxt, 
207                                                             multimediaMsg);
208
209    if (stat != ASN_OK) {
210       OOTRACEERR3 ("ERROR: H245 Message encoding failed (%s, %s)\n", 
211                    call->callType, call->callToken);
212       /* OOTRACEERR1 (errGetText (&gH323ep.msgctxt)); */
213       OOTRACEERR1 (errGetText (call->msgctxt));
214       return OO_FAILED;
215    }
216    
217    encodePtr = encodeGetMsgPtr(pctxt, &encodeLen);
218    len +=encodeLen;
219    msgbuf[3] = (len>>8);
220    msgbuf[4] = len;
221    if(!OO_TESTFLAG (call->flags, OO_M_TUNNELING))
222    {
223       msgbuf[7] = len>>8;
224       msgbuf[8] = len;
225    }
226 #ifndef _COMPACT
227    ooPrintH245Message (call, encodePtr, encodeLen);
228 #endif
229    return OO_OK;
230 }
231
232 int ooSendH245Msg(OOH323CallData *call, H245Message *msg)
233 {
234    int iRet=0,  len=0, msgType=0, logicalChannelNo = 0;
235    ASN1OCTET * encodebuf;
236
237
238    if(!call)
239       return OO_FAILED;
240
241    encodebuf = (ASN1OCTET*) memAlloc (call->pctxt, MAXMSGLEN);
242    if(!encodebuf)
243    {
244       OOTRACEERR3("Error:Failed to allocate memory for encoding H245 "
245                   "message(%s, %s)\n", call->callType, call->callToken);
246       return OO_FAILED;
247    }
248    iRet = ooEncodeH245Message(call, msg, (char*) encodebuf, MAXMSGLEN);
249
250    if(iRet != OO_OK)
251    {
252       OOTRACEERR3("Error:Failed to encode H245 message. (%s, %s)\n", 
253                                              call->callType, call->callToken);
254       memFreePtr (call->pctxt, encodebuf);
255       return OO_FAILED;
256    }
257    if(!call->pH245Channel)
258    {
259       call->pH245Channel =  
260               (OOH323Channel*) memAllocZ (call->pctxt, sizeof(OOH323Channel));
261       if(!call->pH245Channel)
262       {
263          OOTRACEERR3("Error:Failed to allocate memory for H245Channel "
264                      "structure. (%s, %s)\n", call->callType, call->callToken);
265          memFreePtr (call->pctxt, encodebuf);
266          return OO_FAILED;
267       }
268    }
269
270    /* We need to send EndSessionCommand immediately.*/      
271    if(!OO_TESTFLAG(call->flags, OO_M_TUNNELING)){
272       if(encodebuf[0]== OOEndSessionCommand) /* High priority message */
273       {
274          dListFreeAll(call->pctxt, &call->pH245Channel->outQueue);
275          dListAppend (call->pctxt, &call->pH245Channel->outQueue, encodebuf);
276          ooSendMsg(call, OOH245MSG);
277       }
278       else{
279          dListAppend (call->pctxt, &call->pH245Channel->outQueue, encodebuf);
280          OOTRACEDBGC4("Queued H245 messages %d. (%s, %s)\n", 
281          call->pH245Channel->outQueue.count, 
282          call->callType, call->callToken);   
283       }
284    }
285    else{
286       msgType = encodebuf[0];
287
288       logicalChannelNo = encodebuf[1];
289       logicalChannelNo = logicalChannelNo << 8;
290       logicalChannelNo = (logicalChannelNo | encodebuf[2]);
291
292       len = encodebuf[3];
293       len = len<<8;
294       len = (len | encodebuf[4]);
295
296       iRet = ooSendAsTunneledMessage
297          (call, encodebuf+5,len,msgType, logicalChannelNo);
298
299       if(iRet != OO_OK)
300       {
301          memFreePtr (call->pctxt, encodebuf);
302          OOTRACEERR3("ERROR:Failed to tunnel H.245 message (%s, %s)\n",
303                       call->callType, call->callToken);
304          if(call->callState < OO_CALL_CLEAR)
305          {
306             call->callEndReason = OO_REASON_INVALIDMESSAGE;
307             call->callState = OO_CALL_CLEAR;
308          }
309          return OO_FAILED;
310       }
311       memFreePtr (call->pctxt, encodebuf);
312       return OO_OK;
313    }
314
315    return OO_OK;
316 }
317
318 int ooSendTermCapMsg(OOH323CallData *call)
319 {
320    int ret;
321    H245RequestMessage *request=NULL;
322    OOCTXT *pctxt=NULL;
323    ooH323EpCapability *epCap=NULL;
324    H245TerminalCapabilitySet *termCap=NULL;
325    H245AudioCapability *audioCap=NULL;
326    H245DataApplicationCapability *t38Cap, *rtdCap = NULL;
327    H245AudioTelephonyEventCapability *ateCap=NULL;
328    H245UserInputCapability *userInputCap = NULL;
329    H245CapabilityTableEntry *entry=NULL;
330    H245AlternativeCapabilitySet *altSetAudio=NULL, *altSetVideo=NULL, *altSetDtmf=NULL;
331    H245CapabilityDescriptor *capDesc=NULL;
332    H245Message *ph245msg=NULL;
333    H245VideoCapability *videoCap=NULL;
334
335    int i=0,k=0;
336    if(call->localTermCapState == OO_LocalTermCapSetSent)
337    {
338       OOTRACEINFO3("TerminalCapabilitySet exchange procedure already in "
339                    "progress. (%s, %s)\n", call->callType, call->callToken);
340       return OO_OK;
341    }
342  
343    ret = ooCreateH245Message(call, &ph245msg,  
344                              T_H245MultimediaSystemControlMessage_request);
345  
346    if(ret == OO_FAILED)
347    {
348       OOTRACEERR3("Error:Failed to create H245 message for Terminal "
349                   "CapabilitySet (%s, %s)\n", call->callType,call->callToken);
350       return OO_FAILED;
351    }
352
353   /* Set request type as TerminalCapabilitySet */
354    request = ph245msg->h245Msg.u.request;
355    /* pctxt = &gH323ep.msgctxt; */
356    pctxt = call->msgctxt;
357    ph245msg->msgType = OOTerminalCapabilitySet;
358    memset(request, 0, sizeof(H245RequestMessage));
359    if(request == NULL)
360    {
361       OOTRACEERR3("ERROR: No memory allocated for request message (%s, %s)\n",
362                    call->callType, call->callToken);
363       return OO_FAILED;
364    }
365    
366    request->t = T_H245RequestMessage_terminalCapabilitySet;
367    request->u.terminalCapabilitySet = (H245TerminalCapabilitySet*)
368                   memAlloc(pctxt, sizeof(H245TerminalCapabilitySet)); 
369    termCap = request->u.terminalCapabilitySet;
370    memset(termCap, 0, sizeof(H245TerminalCapabilitySet));
371    termCap->m.multiplexCapabilityPresent = 0;
372    termCap->m.capabilityTablePresent = 1;
373    termCap->m.capabilityDescriptorsPresent = 1;
374    termCap->sequenceNumber = ++(call->localTermCapSeqNo);  
375    termCap->protocolIdentifier = gh245ProtocolID; /* protocol id */
376
377    /* Initialize alternate sets */
378    altSetAudio = (H245AlternativeCapabilitySet*)
379              memAlloc(pctxt, sizeof(H245AlternativeCapabilitySet));
380    altSetVideo = (H245AlternativeCapabilitySet*)
381             memAlloc(pctxt, sizeof(H245AlternativeCapabilitySet));
382    altSetDtmf = (H245AlternativeCapabilitySet*)
383             memAlloc(pctxt, sizeof(H245AlternativeCapabilitySet));
384    if(!altSetAudio || !altSetVideo || !altSetDtmf)
385    {
386     OOTRACEERR3("Error:Memory - ooSendTermCapMsg - altSet."
387                 "(%s, %s)\n", call->callType, call->callToken);
388     return OO_FAILED;
389    }
390    memset(altSetDtmf, 0, sizeof(H245AlternativeCapabilitySet));
391    memset(altSetVideo, 0, sizeof(H245AlternativeCapabilitySet));
392    memset(altSetAudio, 0, sizeof(H245AlternativeCapabilitySet));
393
394
395    /* Add audio Capabilities */
396  
397    dListInit(&(termCap->capabilityTable));
398    for(k=0; k<(int)call->capPrefs.index; k++)
399    {
400       if(call->ourCaps)
401          epCap = call->ourCaps;
402       else
403          epCap = gH323ep.myCaps;
404       while(epCap) { 
405          if(epCap->cap == call->capPrefs.order[k]) 
406             break;
407          epCap = epCap->next;
408       }
409       if(!epCap)
410       {
411          OOTRACEWARN4("WARN:Preferred capability %d not supported.(%s, %s)\n",
412                      call->capPrefs.order[k],call->callType, call->callToken);
413          continue;
414       }
415
416       if(epCap->capType == OO_CAP_TYPE_AUDIO)
417       {
418
419          /* Create audio capability. If capability supports receive, we only 
420             add it as receive capability in TCS. However, if it supports only 
421             transmit, we add it as transmit capability in TCS.
422          */
423          if((epCap->dir & OORX))
424          {
425
426             OOTRACEDBGC4("Sending receive capability %s in TCS.(%s, %s)\n",
427                 ooGetCapTypeText(epCap->cap), call->callType, call->callToken);
428
429             audioCap = ooCapabilityCreateAudioCapability(epCap, pctxt, OORX);
430             if(!audioCap)
431             {
432                OOTRACEWARN4("WARN:Failed to create audio capability %s "
433                             "(%s, %s)\n", ooGetCapTypeText(epCap->cap), 
434                             call->callType, call->callToken);
435                continue;
436             }
437          }
438          else if(epCap->dir & OOTX)
439          {
440             OOTRACEDBGC4("Sending transmit capability %s in TCS.(%s, %s)\n",
441                 ooGetCapTypeText(epCap->cap), call->callType, call->callToken);
442             audioCap = ooCapabilityCreateAudioCapability(epCap, pctxt, OOTX);
443             if(!audioCap)
444             {
445                OOTRACEWARN4("WARN:Failed to create audio capability %s "
446                             "(%s, %s)\n", ooGetCapTypeText(epCap->cap),
447                             call->callType, call->callToken);
448                continue;
449             }     
450          }
451          else{
452             OOTRACEWARN3("Warn:Capability is not RX/TX/RXANDTX. Symmetric "
453                          "capabilities are not supported.(%s, %s)\n", 
454                          call->callType, call->callToken);
455             continue;
456          }
457          /* Add  Capabilities to Capability Table */
458          entry = (H245CapabilityTableEntry*) memAlloc(pctxt,
459                          sizeof(H245CapabilityTableEntry));
460          if(!entry)
461          {
462             OOTRACEERR3("Error:Memory - ooSendTermCapMsg - entry(audio Cap)."
463                         "(%s, %s)\n", call->callType, call->callToken);
464             return OO_FAILED;
465          }
466          memset(entry, 0, sizeof(H245CapabilityTableEntry));
467          entry->m.capabilityPresent = 1;
468          if((epCap->dir & OORX))
469          {
470             entry->capability.t = T_H245Capability_receiveAudioCapability;
471             entry->capability.u.receiveAudioCapability = audioCap;
472          }
473          else{
474             entry->capability.t = T_H245Capability_transmitAudioCapability;
475             entry->capability.u.transmitAudioCapability = audioCap;
476          }
477          entry->capabilityTableEntryNumber = i+1;
478          dListAppend(pctxt , &(termCap->capabilityTable), entry);
479          altSetAudio->elem[altSetAudio->n] = i+1;
480          altSetAudio->n++;
481          i++;
482       }
483       else if(epCap->capType == OO_CAP_TYPE_DATA)
484       {
485
486          /* Create t.38 capability. If capability supports receive, we only 
487             add it as receive capability in TCS. However, if it supports only 
488             transmit, we add it as transmit capability in TCS.
489          */
490          if((epCap->dir & OORX) && !(epCap->dir & OOTX))
491          {
492
493             OOTRACEDBGC3("Sending receive capability t38 in TCS.(%s, %s)\n",
494                 call->callType, call->callToken);
495
496             t38Cap = ooCapabilityCreateT38Capability(epCap, pctxt, OORX);
497             if(!t38Cap)
498             {
499                OOTRACEWARN3("WARN:Failed to create t38 capability for"
500                             "%s, %s\n",
501                             call->callType, call->callToken);
502                continue;
503             }
504          }
505          else if((epCap->dir & OOTX) && !(epCap->dir & OORX))
506          {
507             OOTRACEDBGC3("Sending transmit capability t38 in TCS.(%s, %s)\n",
508                 call->callType, call->callToken);
509             t38Cap = ooCapabilityCreateT38Capability(epCap, pctxt, OOTX);
510             if(!t38Cap)
511             {
512                OOTRACEWARN3("WARN:Failed to create capability t38 "
513                             "(%s, %s)\n",
514                             call->callType, call->callToken);
515                continue;
516             }     
517          }
518          else{
519             OOTRACEDBGC3("Sending transmit&recevie capability t38 in TCS.(%s, %s)\n",
520                 call->callType, call->callToken);
521             t38Cap = ooCapabilityCreateT38Capability(epCap, pctxt, OOTX&OORX);
522             if(!t38Cap)
523             {
524                OOTRACEWARN3("WARN:Failed to create capability t38 "
525                             "(%s, %s)\n",
526                             call->callType, call->callToken);
527                continue;
528             }     
529          }
530          /* Add  Capabilities to Capability Table */
531          entry = (H245CapabilityTableEntry*) memAlloc(pctxt,
532                          sizeof(H245CapabilityTableEntry));
533          if(!entry)
534          {
535             OOTRACEERR3("Error:Memory - ooSendTermCapMsg - entry(audio Cap)."
536                         "(%s, %s)\n", call->callType, call->callToken);
537             return OO_FAILED;
538          }
539          memset(entry, 0, sizeof(H245CapabilityTableEntry));
540          entry->m.capabilityPresent = 1;
541          if((epCap->dir & OORX) && (epCap->dir & OOTX)) {
542             entry->capability.t = T_H245Capability_receiveAndTransmitDataApplicationCapability;
543             entry->capability.u.receiveAndTransmitDataApplicationCapability = t38Cap;
544          } else if((epCap->dir & OORX)) {
545             entry->capability.t = T_H245Capability_receiveDataApplicationCapability;
546             entry->capability.u.receiveDataApplicationCapability = t38Cap;
547          }else{
548             entry->capability.t = T_H245Capability_transmitDataApplicationCapability;
549             entry->capability.u.transmitDataApplicationCapability = t38Cap;
550          }
551          entry->capabilityTableEntryNumber = i+1;
552          dListAppend(pctxt , &(termCap->capabilityTable), entry);
553          altSetAudio->elem[altSetAudio->n] = i+1;
554          altSetAudio->n++;
555          i++;
556       }
557       else if(epCap->capType == OO_CAP_TYPE_VIDEO)
558       {
559          if((epCap->dir & OORX))
560          {
561             OOTRACEDBGC4("Sending receive capability %s in TCS.(%s, %s)\n",
562                 ooGetCapTypeText(epCap->cap), call->callType, call->callToken);
563             videoCap = ooCapabilityCreateVideoCapability(epCap, pctxt, OORX);
564             if(!videoCap)
565             {
566                OOTRACEWARN4("WARN:Failed to create Video capability %s "
567                             "(%s, %s)\n", ooGetCapTypeText(epCap->cap),
568                            call->callType, call->callToken);
569                continue;
570             }
571          }
572          else if(epCap->dir & OOTX)
573          {
574             OOTRACEDBGC4("Sending transmit capability %s in TCS.(%s, %s)\n",
575                 ooGetCapTypeText(epCap->cap), call->callType, call->callToken);
576             videoCap = ooCapabilityCreateVideoCapability(epCap, pctxt, OOTX);
577             if(!videoCap)
578             {
579                OOTRACEWARN4("WARN:Failed to create video capability %s "
580                             "(%s, %s)\n", ooGetCapTypeText(epCap->cap),
581                            call->callType, call->callToken);
582                continue;
583             }     
584          }
585          else{
586             OOTRACEWARN3("Warn:Capability is not RX/TX/RXANDTX. Symmetric "
587                          "capabilities are not supported.(%s, %s)\n", 
588                          call->callType, call->callToken);
589             continue;
590          }
591          /* Add Video capabilities to Capability Table */
592          entry = (H245CapabilityTableEntry*) memAlloc(pctxt,
593                             sizeof(H245CapabilityTableEntry));
594          if(!entry)
595          {
596             OOTRACEERR3("Error:Memory - ooSendTermCapMsg - entry(video Cap)."
597                         "(%s, %s)\n", call->callType, call->callToken);
598             return OO_FAILED;
599          }
600          memset(entry, 0, sizeof(H245CapabilityTableEntry));
601          entry->m.capabilityPresent = 1;
602          if((epCap->dir & OORX))
603          {
604             entry->capability.t = T_H245Capability_receiveVideoCapability;
605             entry->capability.u.receiveVideoCapability = videoCap;
606          }
607          else{
608             entry->capability.t = T_H245Capability_transmitVideoCapability;
609             entry->capability.u.transmitVideoCapability = videoCap;
610          }
611          entry->capabilityTableEntryNumber = i+1;
612          dListAppend(pctxt , &(termCap->capabilityTable), entry);
613          altSetVideo->elem[altSetVideo->n] = i+1;
614          altSetVideo->n++;
615          i++;
616       }
617    }
618    /* Add dtmf capability, if any */
619    if(call->dtmfmode & OO_CAP_DTMF_RFC2833)
620    {
621       ateCap = (H245AudioTelephonyEventCapability*)
622                   ooCapabilityCreateDTMFCapability(OO_CAP_DTMF_RFC2833, call->dtmfcodec, pctxt);
623       if(!ateCap)
624       {
625          OOTRACEWARN3("WARN:Failed to add RFC2833 cap to TCS(%s, %s)\n",
626                      call->callType, call->callToken);
627       }
628       else {
629          entry = (H245CapabilityTableEntry*) memAlloc(pctxt,
630                       sizeof(H245CapabilityTableEntry));
631          if(!entry)
632          {
633             OOTRACEERR3("Error:Failed to allocate memory for new capability "
634                         "table entry. (%s, %s)\n", call->callType, 
635                         call->callToken);
636             ooFreeH245Message(call, ph245msg);
637             return OO_FAILED;
638          }
639             
640          memset(entry, 0, sizeof(H245CapabilityTableEntry));
641          entry->m.capabilityPresent = 1;
642
643          entry->capability.t = T_H245Capability_receiveRTPAudioTelephonyEventCapability;
644          entry->capability.u.receiveRTPAudioTelephonyEventCapability = ateCap;
645       
646          entry->capabilityTableEntryNumber = i+1;
647          dListAppend(pctxt , &(termCap->capabilityTable), entry);
648          altSetDtmf->elem[altSetDtmf->n] = i+1;
649          altSetDtmf->n++;
650
651          i++;
652       }
653    }
654
655    if(call->dtmfmode & OO_CAP_DTMF_CISCO)
656    {
657       rtdCap = (H245DataApplicationCapability*)
658                   ooCapabilityCreateDTMFCapability(OO_CAP_DTMF_CISCO, call->dtmfcodec, pctxt);
659       if(!rtdCap)
660       {
661          OOTRACEWARN3("WARN:Failed to add RTP/CISCO DTMF cap to TCS(%s, %s)\n",
662                      call->callType, call->callToken);
663       }
664       else {
665          entry = (H245CapabilityTableEntry*) memAlloc(pctxt,
666                       sizeof(H245CapabilityTableEntry));
667          if(!entry)
668          {
669             OOTRACEERR3("Error:Failed to allocate memory for new capability "
670                         "table entry. (%s, %s)\n", call->callType, 
671                         call->callToken);
672             ooFreeH245Message(call, ph245msg);
673             return OO_FAILED;
674          }
675             
676          memset(entry, 0, sizeof(H245CapabilityTableEntry));
677          entry->m.capabilityPresent = 1;
678
679          entry->capability.t = T_H245Capability_receiveDataApplicationCapability;
680          entry->capability.u.receiveDataApplicationCapability = rtdCap;
681       
682          entry->capabilityTableEntryNumber = i+1;
683          dListAppend(pctxt , &(termCap->capabilityTable), entry);
684          altSetDtmf->elem[altSetDtmf->n] = i+1;
685          altSetDtmf->n++;
686
687          i++;
688       }
689    }
690
691    if(call->dtmfmode & OO_CAP_DTMF_H245_alphanumeric)
692    {
693       userInputCap = (H245UserInputCapability*)ooCapabilityCreateDTMFCapability
694                                         (OO_CAP_DTMF_H245_alphanumeric, 0, pctxt);
695       if(!userInputCap)
696       {
697          OOTRACEWARN3("WARN:Failed to add H245(alphanumeric) cap to "
698                       "TCS(%s, %s)\n", call->callType, call->callToken);
699       }
700       else {
701          entry = (H245CapabilityTableEntry*) memAlloc(pctxt,
702                       sizeof(H245CapabilityTableEntry));
703          if(!entry)
704          {
705             OOTRACEERR3("Error:Failed to allocate memory for new capability "
706                         "table entry. (%s, %s)\n", call->callType, 
707                         call->callToken);
708             ooFreeH245Message(call, ph245msg);
709             return OO_FAILED;
710          }
711             
712          memset(entry, 0, sizeof(H245CapabilityTableEntry));
713          entry->m.capabilityPresent = 1;
714
715          entry->capability.t = T_H245Capability_receiveUserInputCapability;
716          entry->capability.u.receiveUserInputCapability = userInputCap;
717       
718          entry->capabilityTableEntryNumber = i+1;
719          dListAppend(pctxt , &(termCap->capabilityTable), entry);
720          altSetDtmf->elem[altSetDtmf->n] = i+1;
721          altSetDtmf->n++;
722
723          i++;
724       }
725    }
726    userInputCap = NULL;
727    if(call->dtmfmode & OO_CAP_DTMF_H245_signal)
728    {
729       userInputCap = (H245UserInputCapability*)ooCapabilityCreateDTMFCapability
730                                         (OO_CAP_DTMF_H245_signal, 0, pctxt);
731       if(!userInputCap)
732       {
733          OOTRACEWARN3("WARN:Failed to add H245(signal) cap to "
734                       "TCS(%s, %s)\n", call->callType, call->callToken);
735       }
736       else {
737          entry = (H245CapabilityTableEntry*) memAlloc(pctxt,
738                       sizeof(H245CapabilityTableEntry));
739          if(!entry)
740          {
741             OOTRACEERR3("Error:Failed to allocate memory for new capability "
742                         "table entry. (%s, %s)\n", call->callType, 
743                         call->callToken);
744             ooFreeH245Message(call, ph245msg);
745             return OO_FAILED;
746          }
747             
748          memset(entry, 0, sizeof(H245CapabilityTableEntry));
749          entry->m.capabilityPresent = 1;
750
751          entry->capability.t = T_H245Capability_receiveUserInputCapability;
752          entry->capability.u.receiveUserInputCapability = userInputCap;
753       
754          entry->capabilityTableEntryNumber = i+1;
755          dListAppend(pctxt , &(termCap->capabilityTable), entry);
756          altSetDtmf->elem[altSetDtmf->n] = i+1;
757          altSetDtmf->n++;
758
759          i++;
760       }
761    }
762
763           
764    /*TODO:Add Video and Data capabilities, if required*/
765    if(i==0)
766    {
767       OOTRACEERR3("Error:No capabilities found to send in TCS message."
768                   " (%s, %s)\n", call->callType, call->callToken);
769       ooFreeH245Message(call,ph245msg);
770       return OO_FAILED;
771    }
772       
773    /* Define capability descriptior */
774    capDesc = (H245CapabilityDescriptor*)
775              memAlloc(pctxt, sizeof(H245CapabilityDescriptor));
776    memset(capDesc, 0, sizeof(H245CapabilityDescriptor));
777    capDesc->m.simultaneousCapabilitiesPresent = 1;
778    capDesc->capabilityDescriptorNumber = 1;
779    dListInit(&(capDesc->simultaneousCapabilities));
780    /* Add Alternative Capability Set.
781       TODO: Right now all capabilities are added in separate
782             alternate capabilities set. Need a way for application
783             developer to specify the alternative capability sets.
784    */
785    /* for(j=0; j<i; j++)
786    {
787       altSet = (H245AlternativeCapabilitySet*)
788                memAlloc(pctxt, sizeof(H245AlternativeCapabilitySet));
789       memset(altSet, 0, sizeof(H245AlternativeCapabilitySet));
790       altSet->n = 1;
791       altSet->elem[0] = j+1;
792    
793       dListAppend(pctxt, &(capDesc->simultaneousCapabilities), altSet);
794    } */
795
796    if (altSetAudio->n) dListAppend(pctxt, &(capDesc->simultaneousCapabilities), altSetAudio);
797    if (altSetVideo->n) dListAppend(pctxt, &(capDesc->simultaneousCapabilities), altSetVideo);
798    if (altSetDtmf->n) dListAppend(pctxt, &(capDesc->simultaneousCapabilities), altSetDtmf);
799
800    dListInit(&(termCap->capabilityDescriptors));
801    dListAppend(pctxt, &(termCap->capabilityDescriptors), capDesc);
802
803    OOTRACEDBGA3("Built terminal capability set message (%s, %s)\n", 
804                  call->callType, call->callToken);
805    ret = ooSendH245Msg(call, ph245msg);
806    if(ret != OO_OK)
807    {
808       OOTRACEERR3("Error:Failed to enqueue TCS message to outbound queue. "
809                   "(%s, %s)\n", call->callType, call->callToken);
810    }
811    else {
812       call->localTermCapState = OO_LocalTermCapSetSent;
813    }
814
815    ooFreeH245Message(call,ph245msg);
816
817    return ret;
818 }
819
820
821 ASN1UINT ooGenerateStatusDeterminationNumber()
822 {
823    ASN1UINT statusDeterminationNumber;
824    ASN1UINT random_factor = getpid();
825
826 #ifdef _WIN32
827    SYSTEMTIME systemTime;
828    GetLocalTime(&systemTime);
829    srand((systemTime.wMilliseconds ^ systemTime.wSecond) + random_factor);
830 #else
831    struct timeval tv;
832    gettimeofday(&tv, NULL);
833    srand((tv.tv_usec ^ tv.tv_sec) + random_factor );
834 #endif
835
836    statusDeterminationNumber = rand()%16777215;
837    return statusDeterminationNumber;
838 }
839 /* TODO: Should Send MasterSlave Release when no response from 
840          Remote endpoint after MasterSlaveDetermination sent within
841          timeout.
842 */
843 int ooHandleMasterSlave(OOH323CallData *call, void * pmsg, 
844                           int msgType)
845 {
846    H245MasterSlaveDetermination *masterSlave;
847    H245MasterSlaveDeterminationAck *masterSlaveAck;
848    ASN1UINT statusDeterminationNumber, moduloDiff;
849
850    switch(msgType)
851    {
852       case OOMasterSlaveDetermination:
853          OOTRACEINFO3("Master Slave Determination received (%s, %s)\n",
854                        call->callType, call->callToken);
855          
856          masterSlave = (H245MasterSlaveDetermination*)pmsg;
857
858          if(call->masterSlaveState != OO_MasterSlave_DetermineSent && 
859             OO_TESTFLAG(gH323ep.flags, OO_M_TRYBEMASTER))
860          {
861             ooSendMasterSlaveDeterminationAck(call, "slave");
862             call->masterSlaveState =  OO_MasterSlave_Master;
863             OOTRACEINFO3("MasterSlaveDetermination done - Master(%s, %s)\n",
864                              call->callType, call->callToken);
865             return OO_OK;
866          }
867          if(masterSlave->terminalType < gH323ep.termType)
868          {
869             ooSendMasterSlaveDeterminationAck(call, "slave");
870             call->masterSlaveState =  OO_MasterSlave_Master;
871             OOTRACEINFO3("MasterSlaveDetermination done - Master(%s, %s)\n",
872                              call->callType, call->callToken);
873             return OO_OK;
874          }
875          if(masterSlave->terminalType > gH323ep.termType)
876          {
877             ooSendMasterSlaveDeterminationAck(call, "master");
878             call->masterSlaveState =  OO_MasterSlave_Slave;
879             OOTRACEINFO3("MasterSlaveDetermination done - Slave(%s, %s)\n",
880                              call->callType, call->callToken);
881             return OO_OK;
882          }
883          /* Since term types are same, master slave determination will
884             be done based on statusdetermination number
885          */
886          
887          OOTRACEDBGA3("Determining master-slave based on StatusDetermination"
888                       "Number (%s, %s)\n", call->callType, call->callToken);
889          if(call->masterSlaveState == OO_MasterSlave_DetermineSent)
890             statusDeterminationNumber = call->statusDeterminationNumber;
891          else
892             if (OO_TESTFLAG(gH323ep.flags, OO_M_TRYBEMASTER)) 
893                 statusDeterminationNumber = masterSlave->statusDeterminationNumber - 1;
894             else
895                 statusDeterminationNumber = ooGenerateStatusDeterminationNumber();
896
897          moduloDiff = (masterSlave->statusDeterminationNumber - statusDeterminationNumber)
898                         &0xffffff;
899          
900          /* if(masterSlave->statusDeterminationNumber > 
901                        statusDeterminationNumber) */
902          if (moduloDiff < 0x800000 && moduloDiff != 0)
903          {
904             ooSendMasterSlaveDeterminationAck(call, "slave");
905             call->masterSlaveState =  OO_MasterSlave_Master;
906             OOTRACEINFO3("MasterSlaveDetermination done - Master(%s, %s)\n",
907                              call->callType, call->callToken);
908             return OO_OK;
909          }
910          /* if(masterSlave->statusDeterminationNumber < 
911                          statusDeterminationNumber) */
912          if (moduloDiff > 0x800000)
913          {
914             ooSendMasterSlaveDeterminationAck(call, "master");
915             call->masterSlaveState =  OO_MasterSlave_Slave;
916             OOTRACEINFO3("MasterSlaveDetermination done - Slave(%s, %s)\n",
917                              call->callType, call->callToken);
918             return OO_OK;
919          }
920          /* if(masterSlave->statusDeterminationNumber == 
921                          statusDeterminationNumber) */
922          if (moduloDiff == 0 || moduloDiff == 0x800000)
923          {
924             ooSendMasterSlaveDeterminationReject (call);
925
926             OOTRACEERR3("ERROR:MasterSlaveDetermination failed- identical "
927                         "numbers (%s, %s)\n", call->callType, call->callToken);
928          }
929          break;
930
931       case OOMasterSlaveAck:
932          masterSlaveAck = (H245MasterSlaveDeterminationAck*)pmsg;
933          if(call->masterSlaveState == OO_MasterSlave_DetermineSent)
934          {
935             if(masterSlaveAck->decision.t == 
936                T_H245MasterSlaveDeterminationAck_decision_master)
937             {
938                ooSendMasterSlaveDeterminationAck(call, "slave");
939                call->masterSlaveState =  OO_MasterSlave_Master;
940                OOTRACEINFO3("MasterSlaveDetermination done - Master(%s, %s)\n",
941                              call->callType, call->callToken);
942             }
943             else
944             {
945                ooSendMasterSlaveDeterminationAck(call, "master");
946                call->masterSlaveState = OO_MasterSlave_Slave;
947                OOTRACEINFO3("MasterSlaveDetermination done - Slave(%s, %s)\n",
948                              call->callType, call->callToken);
949             }
950          }
951
952          call->msAckStatus = OO_msAck_remoteReceived;
953          
954          if(call->localTermCapState == OO_LocalTermCapSetAckRecvd &&
955             call->remoteTermCapState == OO_RemoteTermCapSetAckSent)
956          {
957             /*Since Cap exchange and MasterSlave Procedures are done */
958             if(gH323ep.h323Callbacks.openLogicalChannels)
959                gH323ep.h323Callbacks.openLogicalChannels(call);
960             else{
961                if(!ooGetTransmitLogicalChannel(call))
962                   ooOpenLogicalChannels(call);
963             }
964 #if 0
965             if(!call->logicalChans){
966                if(!gH323ep.h323Callbacks.openLogicalChannels)
967                   ooOpenLogicalChannels(call);
968                else
969                   gH323ep.h323Callbacks.openLogicalChannels(call);
970             }
971 #endif
972          }
973          else
974             OOTRACEDBGC1("Not opening logical channels as Cap exchange "
975                          "remaining\n");
976          break;
977        default:
978           OOTRACEWARN3("Warn:Unhandled Master Slave message received - %s - "
979                        "%s\n", call->callType, call->callToken);
980    }
981    return OO_OK;      
982 }
983
984 int ooSendMasterSlaveDetermination(OOH323CallData *call)
985 {
986    int ret;
987    H245Message* ph245msg=NULL;
988    H245RequestMessage *request;
989    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
990    OOCTXT *pctxt=call->msgctxt;
991    H245MasterSlaveDetermination* pMasterSlave;
992
993    /* Check whether Master Slave Determination already in progress */
994    if(call->masterSlaveState != OO_MasterSlave_Idle)
995    {
996       OOTRACEINFO3("MasterSlave determination already in progress (%s, %s)\n",
997                    call->callType, call->callToken);
998       return OO_OK;
999    }
1000
1001    ret = ooCreateH245Message(call, &ph245msg,
1002                    T_H245MultimediaSystemControlMessage_request);
1003    if(ret != OO_OK)
1004    {
1005       OOTRACEERR3("Error: creating H245 message - MasterSlave Determination "
1006                   "(%s, %s)\n", call->callType, call->callToken);
1007       return OO_FAILED;
1008    }
1009    ph245msg->msgType = OOMasterSlaveDetermination;
1010    request = ph245msg->h245Msg.u.request;
1011    request->t = T_H245RequestMessage_masterSlaveDetermination;
1012    request->u.masterSlaveDetermination = (H245MasterSlaveDetermination*)
1013             ASN1MALLOC(pctxt, sizeof(H245MasterSlaveDetermination));
1014
1015    
1016    pMasterSlave = request->u.masterSlaveDetermination;
1017    memset(pMasterSlave, 0, sizeof(H245MasterSlaveDetermination));   
1018    pMasterSlave->terminalType = gH323ep.termType; 
1019    pMasterSlave->statusDeterminationNumber = 
1020                        ooGenerateStatusDeterminationNumber();
1021    call->statusDeterminationNumber = pMasterSlave->statusDeterminationNumber;
1022
1023    OOTRACEDBGA3("Built MasterSlave Determination (%s, %s)\n", call->callType,
1024                  call->callToken); 
1025    ret = ooSendH245Msg(call, ph245msg);
1026
1027    if(ret != OO_OK)
1028    {
1029       OOTRACEERR3("Error:Failed to enqueue MasterSlaveDetermination message to"
1030                   " outbound queue. (%s, %s)\n", call->callType, 
1031                   call->callToken);
1032    }
1033    else
1034       call->masterSlaveState = OO_MasterSlave_DetermineSent;
1035    
1036    ooFreeH245Message(call, ph245msg);
1037
1038    return ret;
1039 }
1040
1041 int ooSendMasterSlaveDeterminationAck(OOH323CallData* call,
1042                                       char * status)
1043 {
1044    int ret=0;
1045    H245ResponseMessage * response=NULL;
1046    H245Message *ph245msg=NULL;
1047    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
1048    OOCTXT *pctxt=call->msgctxt;
1049
1050    ret = ooCreateH245Message(call, &ph245msg, 
1051                       T_H245MultimediaSystemControlMessage_response);
1052    if(ret != OO_OK)
1053    {
1054       OOTRACEERR3("Error:H245 message creation failed for - MasterSlave "
1055                   "Determination Ack (%s, %s)\n",call->callType, 
1056                   call->callToken);
1057       return OO_FAILED;
1058    }
1059    ph245msg->msgType = OOMasterSlaveAck;
1060    response = ph245msg->h245Msg.u.response;
1061    memset(response, 0, sizeof(H245ResponseMessage));
1062    response->t = T_H245ResponseMessage_masterSlaveDeterminationAck;
1063    response->u.masterSlaveDeterminationAck = (H245MasterSlaveDeterminationAck*)
1064                    ASN1MALLOC(pctxt, sizeof(H245MasterSlaveDeterminationAck));
1065    memset(response->u.masterSlaveDeterminationAck, 0, 
1066                              sizeof(H245MasterSlaveDeterminationAck));
1067    if(!strcmp("master", status))
1068       response->u.masterSlaveDeterminationAck->decision.t = 
1069                          T_H245MasterSlaveDeterminationAck_decision_master;
1070    else
1071       response->u.masterSlaveDeterminationAck->decision.t = 
1072                          T_H245MasterSlaveDeterminationAck_decision_slave;
1073    
1074    OOTRACEDBGA3("Built MasterSlave determination Ack (%s, %s)\n", 
1075                 call->callType, call->callToken);
1076    ret = ooSendH245Msg(call, ph245msg);
1077    if(ret != OO_OK)
1078    {
1079       OOTRACEERR3("Error:Failed to enqueue MasterSlaveDeterminationAck message"
1080                   " to outbound queue. (%s, %s)\n", call->callType, 
1081                   call->callToken);
1082    }
1083    
1084    ooFreeH245Message(call, ph245msg);
1085    call->msAckStatus = OO_msAck_localSent;
1086    return ret;
1087 }
1088
1089 int ooSendMasterSlaveDeterminationReject (OOH323CallData* call)
1090 {
1091    int ret=0;
1092    H245ResponseMessage* response=NULL;
1093    H245Message *ph245msg=NULL;
1094    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
1095    OOCTXT *pctxt=call->msgctxt;
1096
1097    ret = ooCreateH245Message
1098       (call, &ph245msg, T_H245MultimediaSystemControlMessage_response);
1099
1100    if (ret != OO_OK) {
1101       OOTRACEERR3("Error:H245 message creation failed for - MasterSlave "
1102                   "Determination Reject (%s, %s)\n",call->callType, 
1103                   call->callToken);
1104       return OO_FAILED;
1105    }
1106    ph245msg->msgType = OOMasterSlaveReject;
1107    response = ph245msg->h245Msg.u.response;
1108
1109    response->t = T_H245ResponseMessage_masterSlaveDeterminationReject;
1110
1111    response->u.masterSlaveDeterminationReject = 
1112       (H245MasterSlaveDeterminationReject*)
1113       memAlloc (pctxt, sizeof(H245MasterSlaveDeterminationReject));
1114
1115    response->u.masterSlaveDeterminationReject->cause.t =
1116       T_H245MasterSlaveDeterminationReject_cause_identicalNumbers;
1117
1118    OOTRACEDBGA3 ("Built MasterSlave determination reject (%s, %s)\n", 
1119                  call->callType, call->callToken);
1120
1121    ret = ooSendH245Msg (call, ph245msg);
1122
1123    if (ret != OO_OK) {
1124       OOTRACEERR3 
1125          ("Error:Failed to enqueue MasterSlaveDeterminationReject "
1126           "message to outbound queue.(%s, %s)\n", call->callType, 
1127           call->callToken);
1128    }
1129    
1130    ooFreeH245Message (call, ph245msg);
1131
1132    return ret;
1133 }
1134
1135 int ooSendMasterSlaveDeterminationRelease(OOH323CallData * call)
1136 {
1137    int ret=0;
1138    H245IndicationMessage* indication=NULL;
1139    H245Message *ph245msg=NULL;
1140    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
1141    OOCTXT *pctxt=call->msgctxt;
1142
1143    ret = ooCreateH245Message
1144       (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication);
1145
1146    if (ret != OO_OK) {
1147       OOTRACEERR3("Error:H245 message creation failed for - MasterSlave "
1148                   "Determination Release (%s, %s)\n",call->callType, 
1149                   call->callToken);
1150       return OO_FAILED;
1151    }
1152    ph245msg->msgType = OOMasterSlaveRelease;
1153    indication = ph245msg->h245Msg.u.indication;
1154
1155    indication->t = T_H245IndicationMessage_masterSlaveDeterminationRelease;
1156
1157    indication->u.masterSlaveDeterminationRelease = 
1158       (H245MasterSlaveDeterminationRelease*)
1159       memAlloc (pctxt, sizeof(H245MasterSlaveDeterminationRelease));
1160
1161    if(!indication->u.masterSlaveDeterminationRelease)
1162    {
1163       OOTRACEERR3("Error: Failed to allocate memory for MSDRelease message."
1164                   " (%s, %s)\n", call->callType, call->callToken);
1165       ooFreeH245Message(call, ph245msg);
1166       return OO_FAILED;
1167    }
1168    OOTRACEDBGA3 ("Built MasterSlave determination Release (%s, %s)\n", 
1169                  call->callType, call->callToken);
1170
1171    ret = ooSendH245Msg (call, ph245msg);
1172
1173    if (ret != OO_OK) {
1174       OOTRACEERR3 
1175         ("Error:Failed to enqueue MasterSlaveDeterminationRelease "
1176         "message to outbound queue.(%s, %s)\n", call->callType, 
1177         call->callToken);
1178    }
1179    
1180    ooFreeH245Message (call, ph245msg);
1181    return ret;
1182 }
1183
1184 int ooHandleMasterSlaveReject
1185    (OOH323CallData *call, H245MasterSlaveDeterminationReject* reject)
1186 {
1187    if(call->msdRetries < DEFAULT_MAX_RETRIES)
1188    {
1189       call->msdRetries++;
1190       OOTRACEDBGA3("Retrying MasterSlaveDetermination. (%s, %s)\n", 
1191                     call->callType, call->callToken);
1192       call->masterSlaveState = OO_MasterSlave_Idle;
1193       ooSendMasterSlaveDetermination(call);
1194       return OO_OK;
1195    }
1196    OOTRACEERR3("Error:Failed to complete MasterSlaveDetermination - "
1197                "Ending call. (%s, %s)\n", call->callType, call->callToken);
1198    if(call->callState < OO_CALL_CLEAR)
1199    {
1200       call->callEndReason = OO_REASON_LOCAL_CLEARED;
1201       call->callState = OO_CALL_CLEAR;
1202    }
1203    return OO_OK;
1204 }
1205
1206 /* handling requestmode routines */
1207
1208 int ooSendRequestModeAck(OOH323CallData* call,
1209                                       H245SequenceNumber sequenceNumber)
1210 {
1211    int ret=0;
1212    H245ResponseMessage* response=NULL;
1213    H245Message *ph245msg=NULL;
1214    OOCTXT *pctxt=call->msgctxt;
1215
1216    ret = ooCreateH245Message(call, &ph245msg, 
1217                       T_H245MultimediaSystemControlMessage_response);
1218    if(ret != OO_OK)
1219    {
1220       OOTRACEERR3("Error:H245 message creation failed for - RequestMode "
1221                   "Ack (%s, %s)\n",call->callType, 
1222                   call->callToken);
1223       return OO_FAILED;
1224    }
1225    ph245msg->msgType = OORequestModeAck;
1226    response = ph245msg->h245Msg.u.response;
1227    memset(response, 0, sizeof(H245ResponseMessage));
1228    response->t = T_H245ResponseMessage_requestModeAck;
1229    response->u.requestModeAck = (H245RequestModeAck *)
1230                    ASN1MALLOC(pctxt, sizeof(H245RequestModeAck));
1231    memset(response->u.requestModeAck, 0, 
1232                              sizeof(H245RequestModeAck));
1233
1234    response->u.requestModeAck->sequenceNumber = sequenceNumber;
1235    response->u.requestModeAck->response.t = 
1236         T_H245RequestModeAck_response_willTransmitMostPreferredMode;
1237
1238    OOTRACEDBGA3("Built RequestModeAck (%s, %s)\n", 
1239                 call->callType, call->callToken);
1240    ret = ooSendH245Msg(call, ph245msg);
1241    if(ret != OO_OK)
1242    {
1243       OOTRACEERR3("Error:Failed to enqueue RequestModeAck message"
1244                   " to outbound queue. (%s, %s)\n", call->callType, 
1245                   call->callToken);
1246    }
1247    
1248    ooFreeH245Message(call, ph245msg);
1249    return ret;
1250 }
1251
1252 int ooSendRequestModeReject(OOH323CallData* call,
1253                                       H245SequenceNumber sequenceNumber)
1254 {
1255    int ret=0;
1256    H245ResponseMessage* response=NULL;
1257    H245Message *ph245msg=NULL;
1258    OOCTXT *pctxt=call->msgctxt;
1259
1260    ret = ooCreateH245Message(call, &ph245msg, 
1261                       T_H245MultimediaSystemControlMessage_response);
1262    if(ret != OO_OK)
1263    {
1264       OOTRACEERR3("Error:H245 message creation failed for - RequstMode "
1265                   "Reject (%s, %s)\n",call->callType, 
1266                   call->callToken);
1267       return OO_FAILED;
1268    }
1269    ph245msg->msgType = OORequestModeReject;
1270    response = ph245msg->h245Msg.u.response;
1271    memset(response, 0, sizeof(H245ResponseMessage));
1272    response->t = T_H245ResponseMessage_requestModeReject;
1273    response->u.requestModeReject = (H245RequestModeReject *)
1274                    ASN1MALLOC(pctxt, sizeof(H245RequestModeReject));
1275    memset(response->u.requestModeReject, 0, 
1276                              sizeof(H245RequestModeReject));
1277
1278    response->u.requestModeReject->sequenceNumber = sequenceNumber;
1279    response->u.requestModeReject->cause.t = 
1280                 T_H245RequestModeReject_cause_modeUnavailable;
1281
1282    OOTRACEDBGA3("Built RequestModeReject (%s, %s)\n", 
1283                 call->callType, call->callToken);
1284    ret = ooSendH245Msg(call, ph245msg);
1285    if(ret != OO_OK)
1286    {
1287       OOTRACEERR3("Error:Failed to enqueue RequestModeReject message"
1288                   " to outbound queue. (%s, %s)\n", call->callType, 
1289                   call->callToken);
1290    }
1291    
1292    ooFreeH245Message(call, ph245msg);
1293    return ret;
1294 }
1295
1296 int ooSendRequestMode(OOH323CallData* call,
1297                                       int isT38Mode)
1298 {
1299    int ret=0;
1300    H245RequestMessage *request;
1301    H245Message *ph245msg=NULL;
1302    OOCTXT *pctxt=call->msgctxt;
1303
1304
1305    H245ModeDescription pModeDesc;
1306    H245ModeElement pModeElem;
1307
1308    if (isT38Mode && !OO_TESTFLAG(call->flags, OO_M_T38SUPPORTED)) /* t38 req but we dont support */
1309         return OO_OK;
1310
1311    ret = ooCreateH245Message(call, &ph245msg, 
1312                       T_H245MultimediaSystemControlMessage_request);
1313    if(ret != OO_OK)
1314    {
1315       OOTRACEERR3("Error:H245 message creation failed for - RequstMode "
1316                   "(%s, %s)\n",call->callType, 
1317                   call->callToken);
1318       return OO_FAILED;
1319    }
1320    ph245msg->msgType = OORequestMode;
1321    request = ph245msg->h245Msg.u.request;
1322    memset(request, 0, sizeof(H245RequestMessage));
1323    request->t = T_H245RequestMessage_requestMode;
1324
1325    request->u.requestMode = (H245RequestMode *)
1326                    ASN1MALLOC(pctxt, sizeof(H245RequestMode));
1327    memset(request->u.requestMode, 0, 
1328                              sizeof(H245RequestMode));
1329
1330    call->requestSequence++;
1331    call->reqFlags = (isT38Mode) ? OO_M_DATASESSION : OO_M_AUDIOSESSION;
1332
1333    request->u.requestMode->sequenceNumber = call->requestSequence;
1334    memset(&pModeElem, 0, sizeof(pModeElem));
1335    memset(&pModeDesc, 0, sizeof(pModeDesc));
1336    dListInit(&(request->u.requestMode->requestedModes));
1337    dListInit(&pModeDesc);
1338
1339    if (isT38Mode) {
1340
1341         pModeElem.type.t = T_H245ModeElementType_dataMode;
1342         pModeElem.type.u.dataMode = (H245DataMode *) memAllocZ(pctxt, sizeof(H245DataMode));
1343         pModeElem.type.u.dataMode->bitRate = 144;
1344         if (!ooCreateT38ApplicationData(pctxt,&(pModeElem.type.u.dataMode->application))) {
1345                 OOTRACEERR3("Error:Memory - ooCapabilityCreateT38Capability - (%s, %s)\n",
1346                                                 call->callType, 
1347                                                 call->callToken);
1348         }
1349    } else {
1350         pModeElem.type.t = T_H245ModeElementType_audioMode;
1351         pModeElem.type.u.audioMode = (H245AudioMode *) memAllocZ(pctxt, sizeof(H245AudioMode));
1352         pModeElem.type.u.audioMode->t = T_H245AudioMode_genericAudioMode;
1353         pModeElem.type.u.audioMode->u.genericAudioMode = (H245GenericCapability *)
1354                                         memAllocZ(pctxt, sizeof(H245GenericCapability));
1355         pModeElem.type.u.audioMode->u.genericAudioMode->capabilityIdentifier.t =
1356                                          T_H245CapabilityIdentifier_domainBased;
1357         pModeElem.type.u.audioMode->u.genericAudioMode->capabilityIdentifier.u.domainBased =
1358                                          "H.323";
1359         pModeElem.type.u.audioMode->u.genericAudioMode->m.maxBitRatePresent = TRUE;
1360         pModeElem.type.u.audioMode->u.genericAudioMode->maxBitRate = 144;
1361    }
1362
1363    dListAppend(pctxt, &pModeDesc, &pModeElem);
1364    dListAppend(pctxt, &(request->u.requestMode->requestedModes), &pModeDesc);
1365
1366    ret = ooSendH245Msg(call, ph245msg);
1367    if(ret != OO_OK)
1368    {
1369       OOTRACEERR3("Error:Failed to enqueue RequestMode message"
1370                   " to outbound queue. (%s, %s)\n", call->callType, 
1371                   call->callToken);
1372    }
1373    
1374    ooFreeH245Message(call, ph245msg);
1375    return ret;
1376 }
1377
1378 void ooOnReceivedRequestModeAck(OOH323CallData* call, H245RequestModeAck * requestModeAck)
1379 {
1380         int t38mode;
1381
1382         if (!call->reqFlags) return;
1383
1384         if (OO_TESTFLAG(call->reqFlags, OO_M_AUDIOSESSION)) {
1385                 OO_SETFLAG(call->flags, OO_M_AUDIOSESSION);
1386                 OO_CLRFLAG(call->flags, OO_M_DATASESSION);
1387                 t38mode = 0;
1388         } else {
1389                 OO_CLRFLAG(call->flags, OO_M_AUDIOSESSION);
1390                 OO_SETFLAG(call->flags, OO_M_DATASESSION);
1391                 t38mode = 1;
1392         }
1393
1394         call->reqFlags = 0; /* don't handle duplicate ack packet */
1395
1396         ooCloseAllLogicalChannels(call, "transmit");
1397         if(gH323ep.h323Callbacks.onModeChanged) {
1398                 OOTRACEDBGA3("Handle RequestModeAck: (%s, %s), calling "
1399                         "callback onModeChanged\n", call->callType, call->callToken);
1400                 gH323ep.h323Callbacks.onModeChanged(call, t38mode);
1401         }
1402 }
1403
1404 int ooHandleRequestMode(OOH323CallData* call,
1405                                 H245RequestMode *requestMode)
1406 {
1407   
1408   H245ModeDescription** pModeRef;
1409   H245ModeElement** pModeElem;
1410   H245ModeElementType* pMode;
1411
1412   pModeRef = (H245ModeDescription**)dListFindByIndex(&requestMode->requestedModes, 0);
1413   pModeElem = (H245ModeElement **) dListFindByIndex(*pModeRef, 0);
1414   pMode = &((*pModeElem)->type);
1415   OOTRACEDBGA5("Handle RequestMode: "
1416                   " modetype: %d/%d for (%s, %s)\n", pMode->t, pMode->u.dataMode->application.t,
1417                   call->callType, 
1418                   call->callToken);
1419   switch (pMode->t) {
1420         case T_H245ModeElementType_dataMode:
1421                 if (pMode->u.dataMode->application.t == T_H245DataMode_application_t38fax &&
1422                     OO_TESTFLAG(call->flags, OO_M_T38SUPPORTED)) {
1423                         if (ooSendRequestModeAck(call, requestMode->sequenceNumber) == OO_OK &&
1424                                 OO_TESTFLAG(call->flags, OO_M_AUDIOSESSION)) {
1425
1426                                 OO_CLRFLAG(call->flags, OO_M_AUDIOSESSION);
1427                                 OO_SETFLAG(call->flags, OO_M_DATASESSION);
1428                                 if(gH323ep.h323Callbacks.onModeChanged) {
1429                                         OOTRACEDBGA3("Handle RequestMode: (%s, %s), calling "
1430                                         "callback onModeChanged\n", call->callType, call->callToken);
1431                                         gH323ep.h323Callbacks.onModeChanged(call, 1);
1432                                 }
1433                         }
1434                 } else {
1435                         ooSendRequestModeReject(call, requestMode->sequenceNumber);
1436                 }
1437                 break;
1438         case T_H245ModeElementType_audioMode:
1439                 if (ooSendRequestModeAck(call, requestMode->sequenceNumber) == OO_OK && 
1440                         OO_TESTFLAG(call->flags, OO_M_DATASESSION)) {
1441
1442                         OO_CLRFLAG(call->flags, OO_M_DATASESSION);
1443                         OO_SETFLAG(call->flags, OO_M_AUDIOSESSION);
1444                         if(gH323ep.h323Callbacks.onModeChanged) {
1445                                 OOTRACEDBGA3("Handle RequestMode: (%s, %s), calling "
1446                                 "callback onModeChanged\n", call->callType, call->callToken);
1447                                 gH323ep.h323Callbacks.onModeChanged(call, 0);
1448                         }
1449                 }
1450                 break;
1451         default:
1452                 ;
1453   }
1454   return OO_OK;
1455   
1456 }
1457
1458 int ooHandleOpenLogicalChannel(OOH323CallData* call, 
1459                                  H245OpenLogicalChannel *olc)
1460 {
1461
1462    H245OpenLogicalChannel_forwardLogicalChannelParameters *flcp =
1463     &(olc->forwardLogicalChannelParameters);
1464    
1465 #if 0
1466    if(!call->logicalChans)
1467       ooOpenLogicalChannels(call);
1468 #endif
1469
1470    /* Check whether channel type is supported. Only supported channel 
1471       type for now is g711ulaw audio channel.
1472    */
1473    switch(flcp->dataType.t)
1474    {
1475    case T_H245DataType_nonStandard:
1476       OOTRACEWARN3("Warn:Media channel data type "
1477                    "'T_H245DataType_nonStandard' not supported (%s, %s)\n",
1478                    call->callType, call->callToken);
1479       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1480              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1481       break;
1482    case T_H245DataType_nullData:
1483       OOTRACEWARN3("Warn:Media channel data type "
1484                    "'T_H245DataType_nullData' not supported (%s, %s)\n",
1485                    call->callType, call->callToken);
1486       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1487              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1488       break;
1489    case T_H245DataType_videoData:
1490    case T_H245DataType_audioData:
1491    case T_H245DataType_data:
1492       ooHandleOpenLogicalChannel_helper(call, olc);
1493       break;
1494    case T_H245DataType_encryptionData:
1495       OOTRACEWARN3("Warn:Media channel data type "
1496                    "'T_H245DataType_encryptionData' not supported (%s, %s)\n",
1497                    call->callType, call->callToken);
1498       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1499              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1500       break;
1501    case T_H245DataType_h235Control:
1502       OOTRACEWARN3("Warn:Media channel data type "
1503                    "'T_H245DataType_h235Control' not supported (%s, %s)\n",
1504                    call->callType, call->callToken);
1505       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1506              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1507       break;
1508    case T_H245DataType_h235Media:
1509       OOTRACEWARN3("Warn:Media channel data type "
1510                    "'T_H245DataType_h235Media' not supported (%s, %s)\n",
1511                    call->callType, call->callToken);
1512       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1513              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1514       break;
1515    case T_H245DataType_multiplexedStream:
1516       OOTRACEWARN3("Warn:Media channel data type "
1517                   "'T_H245DataType_multiplexedStream' not supported(%s, %s)\n",
1518                    call->callType, call->callToken);
1519       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1520              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1521       break;
1522    case T_H245DataType_redundancyEncoding:
1523       OOTRACEWARN3("Warn:Media channel data type "
1524                 "'T_H245DataType_redundancyEncoding' not supported (%s, %s)\n",
1525                   call->callType, call->callToken);
1526       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1527              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1528       break;
1529    case T_H245DataType_multiplePayloadStream:
1530       OOTRACEWARN3("Warn:Media channel data type "
1531              "'T_H245DataType_multiplePayloadStream' not supported (%s, %s)\n",
1532                    call->callType, call->callToken);
1533       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1534              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1535       break;
1536    case T_H245DataType_fec:
1537       OOTRACEWARN3("Warn:Media channel data type 'T_H245DataType_fec' not "
1538                    "supported (%s, %s)\n", call->callType, call->callToken);
1539       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1540              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1541       break;
1542    default:
1543       OOTRACEERR3("ERROR:Unknown media channel data type (%s, %s)\n", 
1544                    call->callType, call->callToken);
1545       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1546              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1547    }
1548    
1549    return OO_OK;
1550 }       
1551
1552 /*TODO: Need to clean logical channel in case of failure after creating one */
1553 int ooHandleOpenLogicalChannel_helper(OOH323CallData *call, 
1554                                     H245OpenLogicalChannel*olc)
1555 {
1556    int ret=0;
1557    H245Message *ph245msg=NULL;
1558    H245ResponseMessage *response;
1559    H245OpenLogicalChannelAck *olcAck;
1560    ooH323EpCapability *epCap=NULL;
1561    H245H2250LogicalChannelAckParameters *h2250lcap=NULL;
1562    OOCTXT *pctxt;
1563    H245UnicastAddress *unicastAddrs, *unicastAddrs1;
1564    H245UnicastAddress_iPAddress *iPAddress, *iPAddress1;
1565    ooLogicalChannel *pLogicalChannel = NULL;
1566    H245H2250LogicalChannelParameters *h2250lcp=NULL;
1567    H245OpenLogicalChannel_forwardLogicalChannelParameters *flcp =
1568     &(olc->forwardLogicalChannelParameters);
1569
1570    if(!flcp || flcp->multiplexParameters.t != T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
1571    {
1572       OOTRACEERR3("Error:ooHandleOpenLogicalChannel_helper - invalid forward "
1573                  "logical channel parameters. (%s, %s)\n", call->callType, 
1574                  call->callToken);
1575       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1576           T_H245OpenLogicalChannelReject_cause_unspecified);
1577       return OO_FAILED;
1578    }
1579
1580    h2250lcp = flcp->multiplexParameters.u.h2250LogicalChannelParameters;
1581
1582    if(!(epCap=ooIsDataTypeSupported(call, &flcp->dataType, OORX)))
1583    {
1584       OOTRACEERR3("ERROR:HandleOpenLogicalChannel_helper - capability not "
1585                   "supported (%s, %s)\n", call->callType, call->callToken);
1586       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1587           T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1588       return OO_FAILED;
1589    }
1590    /* Generate an Ack for the open channel request */
1591    ret = ooCreateH245Message(call, &ph245msg,
1592                              T_H245MultimediaSystemControlMessage_response);
1593    if(ret != OO_OK)
1594    {
1595       OOTRACEERR3("Error: H245 message creation failed for - "
1596                   "OpenLogicalChannel Ack (%s, %s)\n", call->callType, 
1597                   call->callToken);
1598       memFreePtr(call->pctxt, epCap);
1599       epCap = NULL;
1600       return OO_FAILED;
1601    }
1602
1603    ph245msg->msgType = OOOpenLogicalChannelAck;
1604    ph245msg->logicalChannelNo = olc->forwardLogicalChannelNumber;
1605    response = ph245msg->h245Msg.u.response;
1606    /* pctxt = &gH323ep.msgctxt; */
1607    pctxt = call->msgctxt;
1608    memset(response, 0, sizeof(H245ResponseMessage));
1609    response->t = T_H245ResponseMessage_openLogicalChannelAck;
1610    response->u.openLogicalChannelAck = (H245OpenLogicalChannelAck*)
1611                    memAlloc(pctxt, sizeof(H245OpenLogicalChannelAck));   
1612    olcAck = response->u.openLogicalChannelAck;
1613    memset(olcAck, 0, sizeof(H245OpenLogicalChannelAck));
1614    olcAck->forwardLogicalChannelNumber = olc->forwardLogicalChannelNumber;
1615
1616    olcAck->m.forwardMultiplexAckParametersPresent = 1;
1617    olcAck->forwardMultiplexAckParameters.t = 
1618      T_H245OpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters;
1619    olcAck->forwardMultiplexAckParameters.u.h2250LogicalChannelAckParameters = 
1620                       (H245H2250LogicalChannelAckParameters*)ASN1MALLOC(pctxt, 
1621                       sizeof(H245H2250LogicalChannelAckParameters));
1622    h2250lcap = 
1623       olcAck->forwardMultiplexAckParameters.u.h2250LogicalChannelAckParameters;
1624    memset(h2250lcap, 0, sizeof(H245H2250LogicalChannelAckParameters));
1625
1626    h2250lcap->m.mediaChannelPresent = 1;
1627    h2250lcap->m.mediaControlChannelPresent = 1;
1628    h2250lcap->m.sessionIDPresent = 1;
1629
1630    if(h2250lcp->sessionID == 0)
1631       h2250lcap->sessionID = ooCallGenerateSessionID(call, epCap->capType, "receive");
1632    else
1633       h2250lcap->sessionID = h2250lcp->sessionID;
1634    
1635    h2250lcap->mediaChannel.t = 
1636                          T_H245TransportAddress_unicastAddress;
1637    h2250lcap->mediaChannel.u.unicastAddress =  (H245UnicastAddress*)
1638                          ASN1MALLOC(pctxt, sizeof(H245UnicastAddress));
1639
1640    unicastAddrs = h2250lcap->mediaChannel.u.unicastAddress;
1641    memset(unicastAddrs, 0, sizeof(H245UnicastAddress));
1642    unicastAddrs->t = T_H245UnicastAddress_iPAddress;
1643    unicastAddrs->u.iPAddress = (H245UnicastAddress_iPAddress*)
1644                memAlloc(pctxt, sizeof(H245UnicastAddress_iPAddress));
1645    iPAddress = unicastAddrs->u.iPAddress;
1646    memset(iPAddress, 0, sizeof(H245UnicastAddress_iPAddress));
1647
1648    pLogicalChannel = ooAddNewLogicalChannel(call, 
1649                         olc->forwardLogicalChannelNumber, h2250lcap->sessionID,
1650                         "receive", epCap);
1651    if(!pLogicalChannel)
1652    {
1653       OOTRACEERR3("ERROR:Failed to add new logical channel entry to call " 
1654                   "(%s, %s)\n", call->callType, call->callToken);
1655       return OO_FAILED;
1656    }
1657    ooSocketConvertIpToNwAddr(call->localIP, iPAddress->network.data);
1658
1659    iPAddress->network.numocts = 4;
1660    iPAddress->tsapIdentifier = pLogicalChannel->localRtpPort;
1661
1662    /* media contrcol channel */
1663    h2250lcap->mediaControlChannel.t = 
1664                                  T_H245TransportAddress_unicastAddress;
1665    h2250lcap->mediaControlChannel.u.unicastAddress =  (H245UnicastAddress*)
1666                          ASN1MALLOC(pctxt, sizeof(H245UnicastAddress));
1667
1668    unicastAddrs1 = h2250lcap->mediaControlChannel.u.unicastAddress;
1669    memset(unicastAddrs1, 0, sizeof(H245UnicastAddress));
1670    unicastAddrs1->t = T_H245UnicastAddress_iPAddress;
1671    unicastAddrs1->u.iPAddress = (H245UnicastAddress_iPAddress*)
1672                memAlloc(pctxt, sizeof(H245UnicastAddress_iPAddress));
1673    iPAddress1 = unicastAddrs1->u.iPAddress;
1674    memset(iPAddress1, 0, sizeof(H245UnicastAddress_iPAddress));
1675
1676    ooSocketConvertIpToNwAddr(call->localIP, iPAddress1->network.data);
1677
1678    iPAddress1->network.numocts = 4;
1679    iPAddress1->tsapIdentifier = pLogicalChannel->localRtcpPort;
1680
1681    OOTRACEDBGA3("Built OpenLogicalChannelAck (%s, %s)\n", call->callType, 
1682                  call->callToken);
1683    ret = ooSendH245Msg(call, ph245msg);
1684    if(ret != OO_OK)
1685    {
1686       OOTRACEERR3("Error:Failed to enqueue OpenLogicalChannelAck message to "
1687                   "outbound queue. (%s, %s)\n", call->callType, 
1688                   call->callToken);
1689    }
1690    ooFreeH245Message(call, ph245msg);
1691
1692
1693    if(epCap->startReceiveChannel)
1694    {
1695       epCap->startReceiveChannel(call, pLogicalChannel);      
1696       OOTRACEINFO6("Receive channel of type %s started at %s:%d(%s, %s)\n", 
1697                     ooGetCapTypeText(epCap->cap), call->localIP, 
1698                     pLogicalChannel->localRtpPort, call->callType, 
1699                     call->callToken);
1700    }
1701    else{
1702       OOTRACEERR3("ERROR:No callback registered to start receive audio "
1703                   "channel (%s, %s)\n", call->callType, call->callToken);
1704       return OO_FAILED;
1705    }
1706    pLogicalChannel->state = OO_LOGICALCHAN_ESTABLISHED;
1707    return ret;
1708 }
1709
1710 int ooSendOpenLogicalChannelReject
1711    (OOH323CallData *call, ASN1UINT channelNum, ASN1UINT cause)
1712 {
1713    int ret=0;
1714    H245ResponseMessage* response=NULL;
1715    H245Message *ph245msg=NULL;
1716    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
1717    OOCTXT *pctxt=call->msgctxt;
1718
1719    ret = ooCreateH245Message
1720       (call, &ph245msg, T_H245MultimediaSystemControlMessage_response);
1721
1722    if (ret != OO_OK) {
1723       OOTRACEERR3("Error:H245 message creation failed for - OpenLogicalChannel"
1724                   "Reject (%s, %s)\n",call->callType, 
1725                   call->callToken);
1726       return OO_FAILED;
1727    }
1728    ph245msg->msgType = OOOpenLogicalChannelReject;
1729    response = ph245msg->h245Msg.u.response;
1730
1731    response->t = T_H245ResponseMessage_openLogicalChannelReject;
1732
1733    response->u.openLogicalChannelReject = 
1734       (H245OpenLogicalChannelReject*)
1735       memAlloc (pctxt, sizeof(H245OpenLogicalChannelReject));
1736
1737    if(!response->u.openLogicalChannelReject)
1738    {
1739       OOTRACEERR3("Error: Failed to allocate memory for OpenLogicalChannel"
1740                   "Reject message. (%s, %s)\n", call->callType, 
1741                   call->callToken);
1742       ooFreeH245Message(call, ph245msg);
1743       return OO_FAILED;
1744    }
1745    response->u.openLogicalChannelReject->forwardLogicalChannelNumber = 
1746                                                                  channelNum;
1747    response->u.openLogicalChannelReject->cause.t = cause;
1748
1749    OOTRACEDBGA3 ("Built OpenLogicalChannelReject (%s, %s)\n", 
1750                  call->callType, call->callToken);
1751
1752    ret = ooSendH245Msg (call, ph245msg);
1753
1754    if (ret != OO_OK) {
1755       OOTRACEERR3 
1756          ("Error:Failed to enqueue OpenLogicalChannelReject "
1757          "message to outbound queue.(%s, %s)\n", call->callType, 
1758          call->callToken);
1759    }
1760    
1761    ooFreeH245Message (call, ph245msg);
1762
1763    return ret;
1764 }
1765
1766
1767 int ooOnReceivedOpenLogicalChannelAck(OOH323CallData *call,
1768                                       H245OpenLogicalChannelAck *olcAck)
1769 {
1770    char remoteip[20];
1771    regmatch_t pmatch[1];
1772    ooLogicalChannel *pLogicalChannel;
1773    H245H2250LogicalChannelAckParameters *h2250lcap;
1774    H245UnicastAddress *unicastAddr;
1775    H245UnicastAddress_iPAddress *iPAddress;
1776    H245UnicastAddress *unicastAddr1;
1777    H245UnicastAddress_iPAddress *iPAddress1 = NULL;
1778
1779    if(!((olcAck->m.forwardMultiplexAckParametersPresent == 1) &&
1780         (olcAck->forwardMultiplexAckParameters.t == 
1781          T_H245OpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters)))
1782    {
1783       OOTRACEERR3("Error: Processing open logical channel ack - LogicalChannel"
1784                   "Ack parameters absent (%s, %s)\n", call->callType, 
1785                   call->callToken);
1786       return OO_OK;  /* should send CloseLogicalChannel request */
1787    }
1788
1789    h2250lcap = 
1790       olcAck->forwardMultiplexAckParameters.u.h2250LogicalChannelAckParameters;
1791    /* Extract media channel address */
1792    if(h2250lcap->m.mediaChannelPresent != 1)
1793    { 
1794       OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media channel "
1795                   "absent (%s, %s)\n", call->callType, call->callToken);
1796       return OO_FAILED;
1797    }
1798    if(h2250lcap->mediaChannel.t != T_H245TransportAddress_unicastAddress)
1799    {
1800       OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media channel "
1801                   "address type is not unicast (%s, %s)\n", call->callType, 
1802                   call->callToken);
1803       return OO_FAILED;
1804    }
1805    
1806    unicastAddr = h2250lcap->mediaChannel.u.unicastAddress;
1807    if(unicastAddr->t != T_H245UnicastAddress_iPAddress)
1808    {
1809       OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media channel "
1810                   "address type is not IP (%s, %s)\n", call->callType, 
1811                    call->callToken);
1812       return OO_FAILED;
1813    }
1814    iPAddress = unicastAddr->u.iPAddress;
1815    
1816    sprintf(remoteip,"%d.%d.%d.%d", iPAddress->network.data[0],
1817                                   iPAddress->network.data[1], 
1818                                   iPAddress->network.data[2], 
1819                                   iPAddress->network.data[3]);
1820    
1821    /* Extract media control channel address */
1822    if(h2250lcap->m.mediaControlChannelPresent == 1) {
1823         if(h2250lcap->mediaControlChannel.t != 
1824                                      T_H245TransportAddress_unicastAddress)
1825         {
1826          OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media control "
1827                   "channel addres type is not unicast (%s, %s)\n", 
1828                    call->callType, call->callToken);
1829          return OO_FAILED;
1830         }
1831    
1832         unicastAddr1 = h2250lcap->mediaControlChannel.u.unicastAddress;
1833         if(unicastAddr1->t != T_H245UnicastAddress_iPAddress) {
1834                 OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media control "
1835                   "channel address type is not IP (%s, %s)\n", call->callType, 
1836                    call->callToken);
1837         return OO_FAILED;
1838         }
1839
1840         iPAddress1 = unicastAddr1->u.iPAddress;
1841    } else {
1842       OOTRACEDBGA3("Warning: Processing OpenLogicalChannelAck - Missing media "
1843                 "control channel (%s, %s)\n", call->callType, call->callToken);
1844    }
1845
1846    /* Set remote destination address for rtp session */
1847    //   strcpy(call->remoteIP, remoteip);
1848    
1849    /* Start channel here */
1850    pLogicalChannel = ooFindLogicalChannelByLogicalChannelNo(call,olcAck->forwardLogicalChannelNumber);
1851    if(!pLogicalChannel)
1852    {
1853       OOTRACEERR4("ERROR:Logical channel %d not found in the channel list for "
1854                   "call (%s, %s)\n", olcAck->forwardLogicalChannelNumber, 
1855                   call->callType, call->callToken);
1856       return OO_FAILED;
1857    }
1858
1859    /* Update session id if we were waiting for remote to assign one and remote 
1860       did assign one. */
1861    if(pLogicalChannel->sessionID == 0 && h2250lcap->m.sessionIDPresent)
1862       pLogicalChannel->sessionID = h2250lcap->sessionID;   
1863
1864    /* Populate ports &ip  for channel */
1865
1866    if (call->rtpMaskStr[0]) {
1867      if (regexec(&call->rtpMask->regex, remoteip, 1, pmatch, 0)) {
1868                 OOTRACEERR5("ERROR:H245 Address is not matched with filter %s/%s"
1869                         "(%s, %s)\n", remoteip, call->rtpMaskStr, call->callType, call->callToken);
1870          return OO_FAILED;
1871         }
1872    }
1873
1874    strcpy(pLogicalChannel->remoteIP, remoteip);   
1875    pLogicalChannel->remoteMediaPort = iPAddress->tsapIdentifier;
1876    if (iPAddress1)
1877         pLogicalChannel->remoteMediaControlPort = iPAddress1->tsapIdentifier;
1878
1879    if(pLogicalChannel->chanCap->startTransmitChannel)
1880    {
1881       pLogicalChannel->chanCap->startTransmitChannel(call, pLogicalChannel);
1882       OOTRACEINFO4("TransmitLogical Channel of type %s started (%s, %s)\n", 
1883                    ooGetCapTypeText(pLogicalChannel->chanCap->cap),
1884                    call->callType, call->callToken);
1885    }
1886    else{
1887       OOTRACEERR3("ERROR:No callback registered for starting transmit channel "
1888                   "(%s, %s)\n", call->callType, call->callToken);
1889       return OO_FAILED;
1890    }
1891    pLogicalChannel->state = OO_LOGICALCHAN_ESTABLISHED;
1892    return OO_OK;
1893 }
1894
1895 int ooOnReceivedOpenLogicalChannelRejected(OOH323CallData *call, 
1896                                      H245OpenLogicalChannelReject *olcReject)
1897 {
1898    switch(olcReject->cause.t)
1899    {
1900    case T_H245OpenLogicalChannelReject_cause_unspecified:
1901       OOTRACEINFO4("Open logical channel %d rejected - unspecified (%s, %s)\n",
1902                    olcReject->forwardLogicalChannelNumber, call->callType, 
1903                    call->callToken);
1904       break;
1905    case T_H245OpenLogicalChannelReject_cause_unsuitableReverseParameters:
1906       OOTRACEINFO4("Open logical channel %d rejected - "
1907                    "unsuitableReverseParameters (%s, %s)\n", 
1908                    olcReject->forwardLogicalChannelNumber, call->callType, 
1909                    call->callToken);
1910       break;
1911    case T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported:
1912       OOTRACEINFO4("Open logical channel %d rejected - dataTypeNotSupported"
1913                    "(%s, %s)\n", olcReject->forwardLogicalChannelNumber, 
1914                    call->callType, call->callToken);
1915       break;
1916    case T_H245OpenLogicalChannelReject_cause_dataTypeNotAvailable:
1917       OOTRACEINFO4("Open logical channel %d rejected - dataTypeNotAvailable"
1918                    "(%s, %s)\n", olcReject->forwardLogicalChannelNumber, 
1919                    call->callType, call->callToken);
1920       break;
1921    case T_H245OpenLogicalChannelReject_cause_unknownDataType:
1922       OOTRACEINFO4("Open logical channel %d rejected - unknownDataType"
1923                    "(%s, %s)\n", olcReject->forwardLogicalChannelNumber, 
1924                    call->callType, call->callToken);
1925       break;
1926    case T_H245OpenLogicalChannelReject_cause_dataTypeALCombinationNotSupported:
1927       OOTRACEINFO4("Open logical channel %d rejected - "
1928                    "dataTypeALCombinationNotSupported(%s, %s)\n", 
1929                    olcReject->forwardLogicalChannelNumber, 
1930                    call->callType, call->callToken);
1931       break;
1932    case T_H245OpenLogicalChannelReject_cause_multicastChannelNotAllowed:
1933        OOTRACEINFO4("Open logical channel %d rejected - "
1934                     "multicastChannelNotAllowed (%s, %s)\n", 
1935                     olcReject->forwardLogicalChannelNumber, 
1936                     call->callType, call->callToken);
1937       break;
1938    case T_H245OpenLogicalChannelReject_cause_insufficientBandwidth:
1939       OOTRACEINFO4("Open logical channel %d rejected - insufficientBandwidth"
1940                    "(%s, %s)\n", olcReject->forwardLogicalChannelNumber, 
1941                    call->callType, call->callToken);
1942       break;
1943    case T_H245OpenLogicalChannelReject_cause_separateStackEstablishmentFailed:
1944       OOTRACEINFO4("Open logical channel %d rejected - "
1945                     "separateStackEstablishmentFailed (%s, %s)\n", 
1946                     olcReject->forwardLogicalChannelNumber, 
1947                     call->callType, call->callToken);
1948       break;
1949    case T_H245OpenLogicalChannelReject_cause_invalidSessionID:
1950       OOTRACEINFO4("Open logical channel %d rejected - "
1951                     "invalidSessionID (%s, %s)\n", 
1952                     olcReject->forwardLogicalChannelNumber, 
1953                     call->callType, call->callToken);
1954       break;
1955    case T_H245OpenLogicalChannelReject_cause_masterSlaveConflict:
1956       OOTRACEINFO4("Open logical channel %d rejected - "
1957                     "invalidSessionID (%s, %s)\n", 
1958                     olcReject->forwardLogicalChannelNumber, 
1959                     call->callType, call->callToken);
1960       break;
1961    case T_H245OpenLogicalChannelReject_cause_waitForCommunicationMode:
1962       OOTRACEINFO4("Open logical channel %d rejected - "
1963                     "waitForCommunicationMode (%s, %s)\n", 
1964                     olcReject->forwardLogicalChannelNumber, 
1965                     call->callType, call->callToken);
1966       break;
1967    case T_H245OpenLogicalChannelReject_cause_invalidDependentChannel:
1968       OOTRACEINFO4("Open logical channel %d rejected - "
1969                     "invalidDependentChannel (%s, %s)\n", 
1970                     olcReject->forwardLogicalChannelNumber, 
1971                     call->callType, call->callToken);
1972       break;
1973    case T_H245OpenLogicalChannelReject_cause_replacementForRejected:
1974       OOTRACEINFO4("Open logical channel %d rejected - "
1975                     "replacementForRejected (%s, %s)\n", 
1976                     olcReject->forwardLogicalChannelNumber, 
1977                     call->callType, call->callToken);
1978       break;
1979    default:
1980       OOTRACEERR4("Error: OpenLogicalChannel %d rejected - "
1981                   "invalid cause(%s, %s)\n",
1982                    olcReject->forwardLogicalChannelNumber, 
1983                     call->callType, call->callToken);
1984    }
1985    if(call->callState < OO_CALL_CLEAR)
1986    {
1987       call->callState = OO_CALL_CLEAR;
1988       call->callEndReason = OO_REASON_LOCAL_CLEARED;
1989    }
1990    return OO_OK;
1991 }
1992
1993 /**
1994  * Currently only disconnect end session command is supported.
1995  **/
1996 int ooSendEndSessionCommand(OOH323CallData *call)
1997 {
1998    int ret;
1999    H245CommandMessage * command;
2000    OOCTXT *pctxt;
2001    H245Message *ph245msg=NULL;
2002    ret = ooCreateH245Message(call, &ph245msg, 
2003                       T_H245MultimediaSystemControlMessage_command);
2004    if(ret != OO_OK)
2005    {
2006       OOTRACEERR3("Error: H245 message creation failed for - End Session "
2007                   "Command (%s, %s)\n", call->callType, call->callToken);
2008       return OO_FAILED;
2009    }
2010    ph245msg->msgType = OOEndSessionCommand;
2011
2012    command = ph245msg->h245Msg.u.command;
2013    /* pctxt = &gH323ep.msgctxt; */
2014    pctxt = call->msgctxt;
2015    memset(command, 0, sizeof(H245CommandMessage));
2016    command->t = T_H245CommandMessage_endSessionCommand;
2017    command->u.endSessionCommand = (H245EndSessionCommand*) ASN1MALLOC(pctxt,
2018                                   sizeof(H245EndSessionCommand));
2019    memset(command->u.endSessionCommand, 0, sizeof(H245EndSessionCommand));
2020    command->u.endSessionCommand->t = T_H245EndSessionCommand_disconnect;
2021    OOTRACEDBGA3("Built EndSession Command (%s, %s)\n", call->callType,
2022                 call->callToken);
2023    ret = ooSendH245Msg(call, ph245msg);
2024    if(ret != OO_OK)
2025    {
2026       OOTRACEERR3("Error:Failed to enqueue EndSession message to outbound "
2027                   "queue.(%s, %s)\n", call->callType, call->callToken);
2028    }
2029    ooFreeH245Message(call, ph245msg);
2030    return ret;
2031 }
2032
2033
2034 int ooHandleH245Command(OOH323CallData *call, 
2035                         H245CommandMessage *command)
2036 {
2037    ASN1UINT i;
2038    DListNode *pNode = NULL;
2039    OOTimer *pTimer = NULL;
2040    OOTRACEDBGC3("Handling H.245 command message. (%s, %s)\n", call->callType,
2041                  call->callToken);
2042    switch(command->t)
2043    {
2044       case T_H245CommandMessage_endSessionCommand:
2045          OOTRACEINFO3("Received EndSession command (%s, %s)\n", 
2046                        call->callType, call->callToken);
2047          if(call->h245SessionState == OO_H245SESSION_ENDSENT)
2048          {
2049             /* Disable Session timer */
2050             for(i = 0; i<call->timerList.count; i++)
2051             {
2052                pNode = dListFindByIndex(&call->timerList, i);
2053                pTimer = (OOTimer*)pNode->data;
2054                if(((ooTimerCallback*)pTimer->cbData)->timerType & 
2055                                                             OO_SESSION_TIMER)
2056                {
2057                   ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2058                   ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2059                   OOTRACEDBGC3("Deleted Session Timer. (%s, %s)\n", 
2060                                 call->callType, call->callToken);
2061                   break;
2062                }
2063             }
2064             ooCloseH245Connection(call);
2065          }
2066          else{
2067
2068             call->h245SessionState = OO_H245SESSION_ENDRECVD;
2069 #if 0
2070             if(call->callState < OO_CALL_CLEAR)
2071                call->callState = OO_CALL_CLEAR;
2072 #else 
2073             if(call->logicalChans)
2074             {
2075                OOTRACEINFO3("In response to received EndSessionCommand - "
2076                             "Clearing all logical channels. (%s, %s)\n", 
2077                             call->callType, call->callToken);
2078                ooClearAllLogicalChannels(call);
2079             }
2080             ooSendEndSessionCommand(call);
2081 #endif
2082          }
2083             
2084             
2085          break;
2086       case T_H245CommandMessage_sendTerminalCapabilitySet:
2087          OOTRACEWARN3("Warning: Received command Send terminal capability set "
2088                       "- Not handled (%s, %s)\n", call->callType, 
2089                       call->callToken);
2090          break;
2091       case T_H245CommandMessage_flowControlCommand:
2092          OOTRACEWARN3("Warning: Flow control command received - Not handled "
2093                       "(%s, %s)\n", call->callType, call->callToken);
2094          break;
2095       default:
2096          OOTRACEWARN3("Warning: Unhandled H245 command message received "
2097                       "(%s, %s)\n", call->callType, call->callToken);
2098    }
2099    OOTRACEDBGC3("Handling H.245 command message done. (%s, %s)\n", 
2100                  call->callType, call->callToken);   
2101    return OO_OK;
2102 }
2103
2104
2105 int ooOnReceivedTerminalCapabilitySetAck(OOH323CallData* call)
2106 {
2107    call->localTermCapState = OO_LocalTermCapSetAckRecvd;
2108    if(call->remoteTermCapState != OO_RemoteTermCapSetAckSent)
2109       return OO_OK;
2110    
2111    if((call->masterSlaveState == OO_MasterSlave_Master ||
2112        call->masterSlaveState == OO_MasterSlave_Slave) &&
2113        (call->msAckStatus == OO_msAck_remoteReceived))
2114    {
2115       if(gH323ep.h323Callbacks.openLogicalChannels)
2116          gH323ep.h323Callbacks.openLogicalChannels(call);
2117       else{
2118          if(!ooGetTransmitLogicalChannel(call))
2119             ooOpenLogicalChannels(call);
2120       }
2121 #if 0
2122       if(!call->logicalChans){
2123          if(!gH323ep.h323Callbacks.openLogicalChannels)
2124             ooOpenLogicalChannels(call);
2125          else
2126             gH323ep.h323Callbacks.openLogicalChannels(call);
2127       }
2128 #endif
2129    }
2130       
2131    return OO_OK;
2132 }
2133
2134 int ooCloseAllLogicalChannels(OOH323CallData *call, char* dir)
2135 {
2136    ooLogicalChannel *temp;
2137
2138    temp = call->logicalChans;
2139    while(temp)
2140    {
2141       if(temp->state == OO_LOGICALCHAN_ESTABLISHED && 
2142         (dir == NULL || !strcmp(temp->dir,dir)))
2143       {
2144          /* Sending closelogicalchannel only for outgoing channels*/
2145          if(!strcmp(temp->dir, "transmit"))
2146          {
2147             ooSendCloseLogicalChannel(call, temp);
2148          }
2149          else{
2150             ooSendRequestCloseLogicalChannel(call, temp);
2151          }
2152       }
2153       temp = temp->next;
2154    }
2155    return OO_OK;
2156 }
2157
2158 int ooSendCloseLogicalChannel(OOH323CallData *call, ooLogicalChannel *logicalChan)
2159 {
2160    int ret = OO_OK, error=0;
2161    H245Message *ph245msg = NULL;
2162    OOCTXT *pctxt;
2163    H245RequestMessage *request;
2164    H245CloseLogicalChannel* clc;
2165    
2166    ret = ooCreateH245Message(call, &ph245msg, 
2167                              T_H245MultimediaSystemControlMessage_request);
2168    if(ret != OO_OK)
2169    {
2170       OOTRACEERR3("ERROR:Failed to create H245 message for closeLogicalChannel"
2171                   " message (%s, %s)\n", call->callType, call->callToken);
2172       return OO_FAILED;
2173    }
2174    ph245msg->msgType = OOCloseLogicalChannel;
2175    ph245msg->logicalChannelNo = logicalChan->channelNo;
2176    /* pctxt = &gH323ep.msgctxt; */
2177    pctxt = call->msgctxt;
2178    request = ph245msg->h245Msg.u.request;
2179
2180    request->t = T_H245RequestMessage_closeLogicalChannel;
2181    request->u.closeLogicalChannel = (H245CloseLogicalChannel*)ASN1MALLOC(pctxt,
2182                                      sizeof(H245CloseLogicalChannel));
2183    if(!request->u.closeLogicalChannel)
2184    {
2185       OOTRACEERR3("ERROR:Memory allocation for CloseLogicalChannel failed "
2186                   "(%s, %s)\n", call->callType, call->callToken);
2187       ooFreeH245Message(call, ph245msg);
2188       return OO_FAILED;
2189    }
2190    clc = request->u.closeLogicalChannel;
2191    memset(clc, 0, sizeof(H245CloseLogicalChannel));
2192
2193    clc->forwardLogicalChannelNumber = logicalChan->channelNo;
2194    clc->source.t = T_H245CloseLogicalChannel_source_lcse;
2195    clc->m.reasonPresent = 1;
2196    clc->reason.t = T_H245CloseLogicalChannel_reason_unknown;
2197
2198    OOTRACEDBGA4("Built close logical channel for %d (%s, %s)\n", 
2199                  logicalChan->channelNo, call->callType, call->callToken);
2200    ret = ooSendH245Msg(call, ph245msg);
2201    if(ret != OO_OK)
2202    {
2203      OOTRACEERR3("Error:Failed to enqueue CloseLogicalChannel to outbound queue.(%s, %s)\n", call->callType,
2204                  call->callToken);
2205      error++;
2206    }
2207    ooFreeH245Message(call, ph245msg);
2208    
2209    /* Stop the media transmission */
2210    OOTRACEINFO4("Closing logical channel %d (%s, %s)\n", 
2211                 clc->forwardLogicalChannelNumber, call->callType, 
2212                 call->callToken);
2213    ret = ooClearLogicalChannel(call, clc->forwardLogicalChannelNumber);
2214    if(ret != OO_OK)
2215    {
2216       OOTRACEERR4("ERROR:Failed to close logical channel %d (%s, %s)\n",
2217          clc->forwardLogicalChannelNumber, call->callType, call->callToken);
2218       return OO_FAILED;
2219    }
2220    if(error) return OO_FAILED;
2221    return ret;
2222 }
2223
2224 /*TODO: Need to pass reason as a parameter */
2225 int ooSendRequestCloseLogicalChannel(OOH323CallData *call, 
2226                                      ooLogicalChannel *logicalChan)
2227 {
2228    int ret = OO_OK;
2229    H245Message *ph245msg = NULL;
2230    OOCTXT *pctxt;
2231    H245RequestMessage *request;
2232    H245RequestChannelClose *rclc;
2233
2234    ret = ooCreateH245Message(call, &ph245msg, 
2235                              T_H245MultimediaSystemControlMessage_request);
2236    if(ret != OO_OK)
2237    {
2238       OOTRACEERR3("ERROR:Failed to create H245 message for "
2239                   "requestCloseLogicalChannel message (%s, %s)\n", 
2240                    call->callType, call->callToken);
2241       return OO_FAILED;
2242    }
2243    ph245msg->msgType = OORequestChannelClose;
2244    ph245msg->logicalChannelNo = logicalChan->channelNo;
2245    /* pctxt = &gH323ep.msgctxt; */
2246    pctxt = call->msgctxt;
2247    request = ph245msg->h245Msg.u.request;
2248
2249    request->t = T_H245RequestMessage_requestChannelClose;
2250    request->u.requestChannelClose = (H245RequestChannelClose*)ASN1MALLOC(pctxt,
2251                                      sizeof(H245RequestChannelClose));
2252    if(!request->u.requestChannelClose)
2253    {
2254       OOTRACEERR3("ERROR:Memory allocation for RequestCloseLogicalChannel "
2255                   " failed (%s, %s)\n", call->callType, call->callToken);
2256       ooFreeH245Message(call, ph245msg);
2257       return OO_FAILED;
2258    }
2259
2260    rclc = request->u.requestChannelClose;
2261    memset(rclc, 0, sizeof(H245RequestChannelClose));
2262    rclc->forwardLogicalChannelNumber = logicalChan->channelNo;
2263    
2264    rclc->m.reasonPresent = 1;
2265    rclc->reason.t = T_H245RequestChannelClose_reason_unknown;
2266
2267    OOTRACEDBGA4("Built RequestCloseChannel for %d (%s, %s)\n", 
2268                  logicalChan->channelNo, call->callType, call->callToken);
2269    ret = ooSendH245Msg(call, ph245msg);
2270    if(ret != OO_OK)
2271    {
2272      OOTRACEERR3("Error:Failed to enqueue the RequestCloseChannel to outbound"
2273                  " queue (%s, %s)\n", call->callType,
2274                  call->callToken);
2275    }
2276    ooFreeH245Message(call, ph245msg);
2277
2278    return ret;
2279 }
2280
2281 int ooSendRequestChannelCloseRelease(OOH323CallData *call, int channelNum)
2282 {
2283    int ret = OO_OK;
2284    H245Message *ph245msg = NULL;
2285    OOCTXT *pctxt;
2286    H245IndicationMessage *indication;
2287
2288    ret = ooCreateH245Message(call, &ph245msg, 
2289                              T_H245MultimediaSystemControlMessage_indication);
2290    if(ret != OO_OK)
2291    {
2292       OOTRACEERR3("ERROR:Failed to create H245 message for "
2293                   "RequestChannelCloseRelease message (%s, %s)\n", 
2294                    call->callType, call->callToken);
2295       return OO_FAILED;
2296    }
2297    ph245msg->msgType = OORequestChannelCloseRelease;
2298    ph245msg->logicalChannelNo = channelNum;
2299    /* pctxt = &gH323ep.msgctxt; */
2300    pctxt = call->msgctxt;
2301    indication = ph245msg->h245Msg.u.indication;
2302    indication->t = T_H245IndicationMessage_requestChannelCloseRelease;
2303    indication->u.requestChannelCloseRelease = (H245RequestChannelCloseRelease*)
2304                      ASN1MALLOC(pctxt, sizeof(H245RequestChannelCloseRelease));
2305    if(!indication->u.requestChannelCloseRelease)
2306    {
2307       OOTRACEERR3("Error:Failed to allocate memory for "
2308                   "RequestChannelCloseRelease message. (%s, %s)\n", 
2309                    call->callType, call->callToken);
2310       ooFreeH245Message(call, ph245msg);
2311    }
2312
2313    indication->u.requestChannelCloseRelease->forwardLogicalChannelNumber = 
2314                                                                 channelNum;
2315
2316    OOTRACEDBGA4("Built RequestChannelCloseRelease for %d (%s, %s)\n", 
2317                 channelNum, call->callType, call->callToken);
2318    ret = ooSendH245Msg(call, ph245msg);
2319    if(ret != OO_OK)
2320    {
2321      OOTRACEERR3("Error:Failed to enqueue the RequestChannelCloseRelease to "
2322                  "outbound queue (%s, %s)\n", call->callType, call->callToken);
2323    }
2324    ooFreeH245Message(call, ph245msg);
2325
2326    return ret;
2327 }
2328
2329
2330    
2331 int ooOnReceivedRequestChannelClose(OOH323CallData *call, 
2332                                     H245RequestChannelClose *rclc)
2333 {
2334    int ret=0, error=0;
2335    H245Message *ph245msg=NULL;
2336    H245ResponseMessage *response = NULL;
2337    OOCTXT *pctxt=NULL;
2338    H245RequestChannelCloseAck *rclcAck;
2339    ooLogicalChannel * lChannel=NULL;
2340    /* Send Ack: TODO: Need to send reject, if doesn't exist
2341    */
2342    lChannel = ooFindLogicalChannelByLogicalChannelNo(call, 
2343                                         rclc->forwardLogicalChannelNumber);
2344    if(!lChannel)
2345    {
2346       OOTRACEERR4("ERROR:Channel %d requested to be closed not found "
2347                   "(%s, %s)\n", rclc->forwardLogicalChannelNumber,
2348                   call->callType, call->callToken);
2349       return OO_FAILED;
2350    }
2351    else{
2352       if(strcmp(lChannel->dir, "transmit"))
2353       {
2354          OOTRACEERR4("ERROR:Channel %d requested to be closed, Not a forward "
2355                      "channel (%s, %s)\n", rclc->forwardLogicalChannelNumber,
2356                      call->callType, call->callToken);
2357          return OO_FAILED;
2358       }
2359    }
2360    ret = ooCreateH245Message(call, &ph245msg, 
2361                              T_H245MultimediaSystemControlMessage_response);
2362    if(ret != OO_OK)
2363    {
2364       OOTRACEERR3("ERROR:Memory allocation for RequestChannelCloseAck message "
2365                   "failed (%s, %s)\n", call->callType, call->callToken);
2366       return OO_FAILED;
2367    }
2368    /* pctxt = &gH323ep.msgctxt; */
2369    pctxt = call->msgctxt;
2370    ph245msg->msgType = OORequestChannelCloseAck;
2371    ph245msg->logicalChannelNo = rclc->forwardLogicalChannelNumber;
2372    response = ph245msg->h245Msg.u.response;
2373    response->t = T_H245ResponseMessage_requestChannelCloseAck;
2374    response->u.requestChannelCloseAck = (H245RequestChannelCloseAck*)ASN1MALLOC
2375                                    (pctxt, sizeof(H245RequestChannelCloseAck));
2376    if(!response->u.requestChannelCloseAck)
2377    {
2378       OOTRACEERR3("ERROR:Failed to allocate memory for RequestChannelCloseAck "
2379                   "message (%s, %s)\n", call->callType, call->callToken);
2380       return OO_FAILED;
2381    }
2382    rclcAck = response->u.requestChannelCloseAck;
2383    memset(rclcAck, 0, sizeof(H245RequestChannelCloseAck));
2384    rclcAck->forwardLogicalChannelNumber = rclc->forwardLogicalChannelNumber;
2385
2386    OOTRACEDBGA3("Built RequestCloseChannelAck message (%s, %s)\n", 
2387                  call->callType, call->callToken);
2388    ret = ooSendH245Msg(call, ph245msg);
2389    if(ret != OO_OK)
2390    {
2391       OOTRACEERR3("Error:Failed to enqueue RequestCloseChannelAck to outbound queue. (%s, %s)\n", call->callType,
2392                   call->callToken);
2393       error++;
2394    }
2395
2396    ooFreeH245Message(call, ph245msg);
2397    
2398    /* Send Close Logical Channel*/
2399    ret = ooSendCloseLogicalChannel(call, lChannel);
2400    if(ret != OO_OK)
2401    {
2402       OOTRACEERR3("ERROR:Failed to build CloseLgicalChannel message(%s, %s)\n",
2403                    call->callType, call->callToken);
2404       return OO_FAILED;
2405    }
2406
2407    if(error) return OO_FAILED;
2408
2409    return ret;
2410 }
2411
2412 int ooSendRoundTripDelayRequest(OOH323CallData *call)
2413 {
2414    int ret=0;
2415    H245Message *ph245msg=NULL;
2416    H245RequestMessage *request = NULL;
2417    OOCTXT *pctxt=NULL;
2418    H245RoundTripDelayRequest *rtdr;
2419    ooTimerCallback *cbData=NULL;
2420
2421    if (call->rtdrSend > call->rtdrRecv + call->rtdrCount) {
2422         if(call->callState < OO_CALL_CLEAR) {
2423                 call->callState = OO_CALL_CLEAR;
2424                 call->callEndReason = OO_REASON_UNKNOWN;
2425                 call->q931cause = Q931RecoveryOnTimerExpiry;
2426         }
2427         return OO_FAILED;
2428    }
2429    
2430    ret = ooCreateH245Message(call, &ph245msg, 
2431                              T_H245MultimediaSystemControlMessage_request);
2432    if(ret != OO_OK)
2433    {
2434       OOTRACEERR3("ERROR:Memory allocation for RoundTripDelayResponse message "
2435                   "failed (%s, %s)\n", call->callType, call->callToken);
2436       return OO_FAILED;
2437    }
2438
2439    pctxt = call->msgctxt;
2440    ph245msg->msgType = OORequestDelayRequest;
2441    request = ph245msg->h245Msg.u.request;
2442    request->t = T_H245RequestMessage_roundTripDelayRequest;
2443    request->u.roundTripDelayRequest = (H245RoundTripDelayRequest *)ASN1MALLOC
2444                                    (pctxt, sizeof(H245RoundTripDelayRequest));
2445    if(!request->u.roundTripDelayRequest)
2446    {
2447       OOTRACEERR3("ERROR:Failed to allocate memory for H245RoundTripDelayRequest "
2448                   "message (%s, %s)\n", call->callType, call->callToken);
2449       return OO_FAILED;
2450    }
2451    rtdr = request->u.roundTripDelayRequest;
2452    memset(rtdr, 0, sizeof(H245RoundTripDelayRequest));
2453    rtdr->sequenceNumber = ++call->rtdrSend;
2454
2455    OOTRACEDBGA3("Built RoundTripDelayRequest message (%s, %s)\n", 
2456                  call->callType, call->callToken);
2457    ret = ooSendH245Msg(call, ph245msg);
2458    if(ret != OO_OK)
2459    {
2460       OOTRACEERR3("Error:Failed to enqueue RoundTripDelayRequest to outbound queue. (%s, %s)\n",
2461         call->callType, call->callToken);
2462       return OO_FAILED;
2463    } else {
2464       cbData = (ooTimerCallback*) memAlloc(call->pctxt,
2465                                      sizeof(ooTimerCallback));
2466       if(!cbData)
2467       {
2468          OOTRACEERR3("Error:Unable to allocate memory for timer callback data."
2469                      "(%s, %s)\n", call->callType, call->callToken);
2470          return OO_FAILED;
2471       }
2472       cbData->call = call;
2473       cbData->timerType = OO_RTD_TIMER;
2474       if(!ooTimerCreate(call->pctxt, &call->timerList, &ooRTDTimerExpired,
2475                         call->rtdrInterval, cbData, FALSE))
2476       {
2477          OOTRACEERR3("Error:Unable to create RTDR timer. "
2478                      "(%s, %s)\n", call->callType, call->callToken);
2479          memFreePtr(call->pctxt, cbData);
2480          return OO_FAILED;
2481       }
2482
2483    }
2484
2485    ooFreeH245Message(call, ph245msg);
2486
2487    return ret;
2488 }
2489
2490 int ooOnReceivedRoundTripDelayRequest(OOH323CallData *call, 
2491                                      H245SequenceNumber sequenceNumber)
2492 {
2493    int ret=0;
2494    H245Message *ph245msg=NULL;
2495    H245ResponseMessage *response = NULL;
2496    OOCTXT *pctxt=NULL;
2497    H245RoundTripDelayResponse *rtdr;
2498
2499    ret = ooCreateH245Message(call, &ph245msg, 
2500                              T_H245MultimediaSystemControlMessage_response);
2501    if(ret != OO_OK)
2502    {
2503       OOTRACEERR3("ERROR:Memory allocation for RoundTripDelayResponse message "
2504                   "failed (%s, %s)\n", call->callType, call->callToken);
2505       return OO_FAILED;
2506    }
2507
2508    pctxt = call->msgctxt;
2509    ph245msg->msgType = OORequestDelayResponse;
2510    response = ph245msg->h245Msg.u.response;
2511    response->t = T_H245ResponseMessage_roundTripDelayResponse;
2512    response->u.roundTripDelayResponse = (H245RoundTripDelayResponse *)ASN1MALLOC
2513                                    (pctxt, sizeof(H245RoundTripDelayResponse));
2514    if(!response->u.roundTripDelayResponse)
2515    {
2516       OOTRACEERR3("ERROR:Failed to allocate memory for H245RoundTripDelayResponse "
2517                   "message (%s, %s)\n", call->callType, call->callToken);
2518       return OO_FAILED;
2519    }
2520    rtdr = response->u.roundTripDelayResponse;
2521    memset(rtdr, 0, sizeof(H245RoundTripDelayResponse));
2522    rtdr->sequenceNumber = sequenceNumber;
2523
2524    OOTRACEDBGA3("Built RoundTripDelayResponse message (%s, %s)\n", 
2525                  call->callType, call->callToken);
2526    ret = ooSendH245Msg(call, ph245msg);
2527    if(ret != OO_OK)
2528    {
2529       OOTRACEERR3("Error:Failed to enqueue RoundTripDelayResponse to outbound queue. (%s, %s)\n",
2530         call->callType, call->callToken);
2531    }
2532
2533    ooFreeH245Message(call, ph245msg);
2534    
2535    return ret;
2536 }
2537
2538 /*
2539   We clear channel here. Ideally the remote endpoint should send 
2540   CloseLogicalChannel and then the channel should be cleared. But there's no
2541   timer for this and if remote endpoint misbehaves, the call will keep waiting
2542   for CloseLogicalChannel and hence, wouldn't be cleared. In case when remote
2543   endpoint sends CloseLogicalChannel, we call ooClearLogicalChannel again,
2544   which simply returns OO_OK as channel was already cleared. Other option is
2545   to start a timer for call cleanup and if call is not cleaned up within 
2546   timeout, we clean call forcefully. Note, no such timer is defined in 
2547   standards.
2548 */
2549 int ooOnReceivedRequestChannelCloseAck
2550                        (OOH323CallData *call, H245RequestChannelCloseAck *rccAck)
2551 {
2552    int ret=OO_OK;
2553    /* Remote endpoint is ok to close channel. So let's do it */
2554    ret = ooClearLogicalChannel(call, rccAck->forwardLogicalChannelNumber);
2555    if(ret != OO_OK)
2556    {
2557       OOTRACEERR4("Error:Failed to clear logical channel %d. (%s, %s)\n", 
2558                    rccAck->forwardLogicalChannelNumber, call->callType, 
2559                    call->callToken);
2560    }
2561
2562    return ret;
2563 }
2564
2565 int ooOnReceivedRequestChannelCloseReject
2566    (OOH323CallData *call, H245RequestChannelCloseReject *rccReject)
2567 {
2568    int ret =0;
2569    switch(rccReject->cause.t)
2570    {
2571    case T_H245RequestChannelCloseReject_cause_unspecified:
2572       OOTRACEDBGA4("Remote endpoint has rejected request to close logical "
2573                    "channel %d - cause unspecified. (%s, %s)\n", 
2574                    rccReject->forwardLogicalChannelNumber, call->callType, 
2575                    call->callToken);
2576      break;
2577    case T_H245RequestChannelCloseReject_cause_extElem1:
2578       OOTRACEDBGA4("Remote endpoint has rejected request to close logical "
2579                    "channel %d - cause propriatory. (%s, %s)\n", 
2580                    rccReject->forwardLogicalChannelNumber, call->callType, 
2581                    call->callToken);   
2582       break;
2583    default:
2584       OOTRACEDBGA4("Remote endpoint has rejected request to close logical "
2585                    "channel %d - cause INVALID. (%s, %s)\n", 
2586                    rccReject->forwardLogicalChannelNumber, call->callType, 
2587                    call->callToken);
2588    }
2589    OOTRACEDBGA4("Clearing logical channel %d. (%s, %s)\n", 
2590                  rccReject->forwardLogicalChannelNumber, call->callType, 
2591                  call->callToken);
2592    ret = ooClearLogicalChannel(call, rccReject->forwardLogicalChannelNumber);
2593    if(ret != OO_OK)
2594    {
2595       OOTRACEERR4("Error: failed to clear logical channel %d.(%s, %s)\n", 
2596                    rccReject->forwardLogicalChannelNumber, call->callType, 
2597                    call->callToken);
2598    }
2599    return ret;
2600 }
2601
2602 /****/
2603 int ooOnReceivedCloseLogicalChannel(OOH323CallData *call, 
2604                                     H245CloseLogicalChannel* clc)
2605 {
2606    int ret=0;
2607    H245Message *ph245msg = NULL;
2608    OOCTXT *pctxt = NULL;
2609    H245CloseLogicalChannelAck * clcAck;
2610    H245ResponseMessage *response;
2611    
2612    OOTRACEINFO4("Closing logical channel number %d (%s, %s)\n",
2613       clc->forwardLogicalChannelNumber, call->callType, call->callToken);
2614    
2615    ret = ooClearLogicalChannel(call, clc->forwardLogicalChannelNumber);
2616    if(ret != OO_OK)
2617    {
2618       OOTRACEERR4("ERROR:Failed to close logical channel %d (%s, %s)\n",
2619          clc->forwardLogicalChannelNumber, call->callType, call->callToken);
2620       return OO_FAILED;
2621    }
2622
2623    ret = ooCreateH245Message(call, &ph245msg, 
2624                               T_H245MultimediaSystemControlMessage_response);
2625    if(ret != OO_OK)
2626    {
2627       OOTRACEERR3("ERROR:Failed to create H245 message for "
2628                   "closeLogicalChannelAck (%s, %s)\n", call->callType, 
2629                   call->callToken);
2630       return OO_FAILED;
2631    }
2632    /* pctxt = &gH323ep.msgctxt; */
2633    pctxt = call->msgctxt;
2634    ph245msg->msgType = OOCloseLogicalChannelAck;
2635    ph245msg->logicalChannelNo = clc->forwardLogicalChannelNumber;
2636    response = ph245msg->h245Msg.u.response;
2637    response->t = T_H245ResponseMessage_closeLogicalChannelAck;
2638    response->u.closeLogicalChannelAck = (H245CloseLogicalChannelAck*)
2639                          ASN1MALLOC(pctxt, sizeof(H245CloseLogicalChannelAck));
2640    clcAck = response->u.closeLogicalChannelAck;
2641    if(!clcAck)
2642    {
2643       OOTRACEERR3("ERROR:Failed to allocate memory for closeLogicalChannelAck "
2644                   "(%s, %s)\n", call->callType, call->callToken);
2645       return OO_OK;
2646    }
2647    memset(clcAck, 0, sizeof(H245CloseLogicalChannelAck));
2648    clcAck->forwardLogicalChannelNumber = clc->forwardLogicalChannelNumber;
2649
2650    OOTRACEDBGA3("Built CloseLogicalChannelAck message (%s, %s)\n",
2651                  call->callType, call->callToken);
2652    ret = ooSendH245Msg(call, ph245msg);
2653    if(ret != OO_OK)
2654    {
2655      OOTRACEERR3("Error:Failed to enqueue CloseLogicalChannelAck message to "
2656                  "outbound queue.(%s, %s)\n", call->callType, call->callToken);
2657    }
2658
2659    ooFreeH245Message(call, ph245msg);
2660    return ret;
2661 }
2662
2663 int ooOnReceivedCloseChannelAck(OOH323CallData* call, 
2664                                 H245CloseLogicalChannelAck* clcAck)
2665 {
2666    int ret = OO_OK;
2667    return ret;
2668 }
2669
2670 int ooHandleH245Message(OOH323CallData *call, H245Message * pmsg)
2671 {
2672    ASN1UINT i;
2673    DListNode *pNode = NULL;
2674    OOTimer *pTimer = NULL;
2675    H245Message *pH245 = (H245Message*)pmsg;
2676    /* There are four major types of H.245 messages that can be received.
2677       Request/Response/Command/Indication. Each one of them need to be 
2678       handled separately.
2679    */   
2680    H245RequestMessage *request = NULL;
2681    H245ResponseMessage *response = NULL;
2682    H245CommandMessage *command = NULL;
2683    H245IndicationMessage *indication = NULL;
2684    
2685    OOTRACEDBGC3("Handling H245 message. (%s, %s)\n", call->callType, 
2686                  call->callToken);
2687    
2688    switch(pH245->h245Msg.t)
2689    {
2690       /* H.245 Request message is received */
2691       case (T_H245MultimediaSystemControlMessage_request):
2692          request = pH245->h245Msg.u.request;
2693          switch(request->t)
2694          {
2695             case T_H245RequestMessage_terminalCapabilitySet:
2696                /* If session isn't marked active yet, do it. possible in case of 
2697                   tunneling */
2698                if(call->h245SessionState == OO_H245SESSION_IDLE)
2699                   call->h245SessionState = OO_H245SESSION_ACTIVE; 
2700
2701                ooOnReceivedTerminalCapabilitySet(call, pH245);
2702                if(call->localTermCapState == OO_LocalTermCapExchange_Idle)
2703                   ooSendTermCapMsg(call);
2704                break;
2705             case T_H245RequestMessage_masterSlaveDetermination:
2706                ooHandleMasterSlave(call, 
2707                                      request->u.masterSlaveDetermination, 
2708                                      OOMasterSlaveDetermination);
2709                break;
2710             case T_H245RequestMessage_openLogicalChannel:
2711                ooHandleOpenLogicalChannel(call, 
2712                                           request->u.openLogicalChannel);
2713                 if(!ooGetTransmitLogicalChannel(call))
2714                         ooOpenLogicalChannels(call);
2715                break;
2716             case T_H245RequestMessage_requestMode:
2717                 OOTRACEINFO4("Received request mode - %d (%s, %s)\n",
2718                 request->u.requestMode->sequenceNumber, call->callType, call->callToken);
2719                ooHandleRequestMode(call, 
2720                                         request->u.requestMode);
2721                 break;
2722             case T_H245RequestMessage_closeLogicalChannel:
2723                OOTRACEINFO4("Received close logical Channel - %d (%s, %s)\n",
2724                   request->u.closeLogicalChannel->forwardLogicalChannelNumber, 
2725                   call->callType, call->callToken);
2726                if (ooOnReceivedCloseLogicalChannel(call, 
2727                                                request->u.closeLogicalChannel) == OO_OK) {
2728                         ooCloseAllLogicalChannels(call, NULL);
2729                }
2730                break;
2731             case T_H245RequestMessage_requestChannelClose:
2732                OOTRACEINFO4("Received RequestChannelClose - %d (%s, %s)\n",
2733                   request->u.requestChannelClose->forwardLogicalChannelNumber, 
2734                   call->callType, call->callToken);
2735                ooOnReceivedRequestChannelClose(call, 
2736                                                request->u.requestChannelClose);
2737                break;
2738              case T_H245RequestMessage_roundTripDelayRequest:
2739                OOTRACEINFO4("Received roundTripDelayRequest - %d (%s, %s)\n",
2740                   request->u.roundTripDelayRequest->sequenceNumber,  call->callType, call->callToken);
2741                ooOnReceivedRoundTripDelayRequest(call, request->u.roundTripDelayRequest->sequenceNumber);
2742                break;
2743             default:
2744                ;
2745          } /* End of Request Message */
2746          break;
2747       /* H.245 Response message is received */ 
2748       case (T_H245MultimediaSystemControlMessage_response):
2749          response = pH245->h245Msg.u.response;
2750          switch(response->t)
2751          {
2752             case T_H245ResponseMessage_masterSlaveDeterminationAck:
2753                /* Disable MSD timer */
2754                for(i = 0; i<call->timerList.count; i++)
2755                {
2756                   pNode = dListFindByIndex(&call->timerList, i);
2757                   pTimer = (OOTimer*)pNode->data;
2758                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_MSD_TIMER)
2759                   {
2760                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2761                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2762                      OOTRACEDBGC3("Deleted MSD Timer. (%s, %s)\n", call->callType,
2763                    call->callToken);
2764                      break;
2765                   }
2766                }
2767
2768                ooHandleMasterSlave(call, 
2769                                    response->u.masterSlaveDeterminationAck, 
2770                                    OOMasterSlaveAck);
2771                break;
2772             case T_H245ResponseMessage_masterSlaveDeterminationReject:
2773                /* Disable MSD timer */
2774                for(i = 0; i<call->timerList.count; i++)
2775                {
2776                   pNode = dListFindByIndex(&call->timerList, i);
2777                   pTimer = (OOTimer*)pNode->data;
2778                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_MSD_TIMER)
2779                   {
2780                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2781                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2782                      OOTRACEDBGC3("Deleted MSD Timer. (%s, %s)\n", call->callType,
2783                    call->callToken);
2784                      break;
2785                   }
2786                }
2787                ooHandleMasterSlaveReject(call, 
2788                                   response->u.masterSlaveDeterminationReject);
2789                break;
2790             case T_H245ResponseMessage_terminalCapabilitySetAck:
2791                /* Disable TCS timer */
2792                for(i = 0; i<call->timerList.count; i++)
2793                {
2794                   pNode = dListFindByIndex(&call->timerList, i);
2795                   pTimer = (OOTimer*)pNode->data;
2796                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_TCS_TIMER)
2797                   {
2798                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2799                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2800                      OOTRACEDBGC3("Deleted TCS Timer. (%s, %s)\n", call->callType,
2801                         call->callToken);
2802                      break;
2803                   }
2804                }
2805                ooOnReceivedTerminalCapabilitySetAck(call);
2806                break;
2807             case T_H245ResponseMessage_terminalCapabilitySetReject:
2808                OOTRACEINFO3("TerminalCapabilitySetReject message received."
2809                             " (%s, %s)\n", call->callType, call->callToken);
2810                if(response->u.terminalCapabilitySetReject->sequenceNumber != 
2811                   call->localTermCapSeqNo)
2812                {
2813                   OOTRACEINFO5("Ignoring TCSReject with mismatched seqno %d "
2814                               "(local - %d). (%s, %s)\n", 
2815                           response->u.terminalCapabilitySetReject->sequenceNumber,
2816                         call->localTermCapSeqNo, call->callType, call->callToken);
2817                   break;
2818                }
2819                /* Disable TCS timer */
2820                for(i = 0; i<call->timerList.count; i++)
2821                {
2822                   pNode = dListFindByIndex(&call->timerList, i);
2823                   pTimer = (OOTimer*)pNode->data;
2824                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_TCS_TIMER)
2825                   {
2826                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2827                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2828                      OOTRACEDBGC3("Deleted TCS Timer. (%s, %s)\n", call->callType,
2829                         call->callToken);
2830                      break;
2831                   }
2832                }
2833                if(call->callState < OO_CALL_CLEAR)
2834                {
2835                   call->callState = OO_CALL_CLEAR;
2836                   call->callEndReason = OO_REASON_NOCOMMON_CAPABILITIES;
2837                }
2838                break;
2839             case T_H245ResponseMessage_requestModeAck:
2840                if (call->requestSequence == response->u.requestModeAck->sequenceNumber) {
2841                         /* response to our last request, process it */
2842                         ooOnReceivedRequestModeAck(call, response->u.requestModeAck);
2843                }
2844                break;
2845             case T_H245ResponseMessage_requestModeReject:
2846                 OOTRACEDBGC3("Received requestModeReject, clearing call (%s, %s)\n",
2847                                  call->callType, call->callToken);
2848                if(call->callState < OO_CALL_CLEAR)
2849                {
2850                   call->callState = OO_CALL_CLEAR;
2851                   call->callEndReason = OO_REASON_REMOTE_REJECTED;
2852                }
2853                break;
2854             case T_H245ResponseMessage_openLogicalChannelAck:
2855                for(i = 0; i<call->timerList.count; i++)
2856                {
2857                   pNode = dListFindByIndex(&call->timerList, i);
2858                   pTimer = (OOTimer*)pNode->data;
2859                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_OLC_TIMER)                                            && 
2860                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
2861                    response->u.openLogicalChannelAck->forwardLogicalChannelNumber)
2862                   {
2863
2864                      memFreePtr(call->pctxt, pTimer->cbData);
2865                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2866                      OOTRACEDBGC3("Deleted OpenLogicalChannel Timer. (%s, %s)\n", 
2867                                    call->callType, call->callToken);
2868                      break;
2869                   }
2870                }
2871                ooOnReceivedOpenLogicalChannelAck(call, 
2872                                               response->u.openLogicalChannelAck);
2873                break;
2874             case T_H245ResponseMessage_openLogicalChannelReject:
2875                OOTRACEINFO3("Open Logical Channel Reject received (%s, %s)\n",
2876                              call->callType, call->callToken);
2877                for(i = 0; i<call->timerList.count; i++)
2878                {
2879                   pNode = dListFindByIndex(&call->timerList, i);
2880                   pTimer = (OOTimer*)pNode->data;
2881                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_OLC_TIMER)                                            && 
2882                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
2883                    response->u.openLogicalChannelAck->forwardLogicalChannelNumber)
2884                   {
2885
2886                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2887                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2888                      OOTRACEDBGC3("Deleted OpenLogicalChannel Timer. (%s, %s)\n", 
2889                                    call->callType, call->callToken);
2890                      break;
2891                   }
2892                }
2893                ooOnReceivedOpenLogicalChannelRejected(call, 
2894                                         response->u.openLogicalChannelReject);
2895                break;
2896             case T_H245ResponseMessage_closeLogicalChannelAck:
2897                OOTRACEINFO4("CloseLogicalChannelAck received for %d (%s, %s)\n",
2898                   response->u.closeLogicalChannelAck->forwardLogicalChannelNumber,
2899                   call->callType, call->callToken);
2900                for(i = 0; i<call->timerList.count; i++)
2901                {
2902                   pNode = dListFindByIndex(&call->timerList, i);
2903                   pTimer = (OOTimer*)pNode->data;
2904                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_CLC_TIMER)                                            && 
2905                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
2906                   response->u.closeLogicalChannelAck->forwardLogicalChannelNumber)
2907                   {
2908
2909                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2910                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2911                      OOTRACEDBGC3("Deleted CloseLogicalChannel Timer. (%s, %s)\n",
2912                                    call->callType, call->callToken);
2913                      break;
2914                   }
2915                }
2916                ooOnReceivedCloseChannelAck(call, 
2917                                            response->u.closeLogicalChannelAck);
2918                 if(!ooGetTransmitLogicalChannel(call))
2919                         ooOpenLogicalChannels(call);
2920                break;
2921             case T_H245ResponseMessage_requestChannelCloseAck:
2922                 OOTRACEINFO4("RequestChannelCloseAck received - %d (%s, %s)\n",
2923                   response->u.requestChannelCloseAck->forwardLogicalChannelNumber,
2924                   call->callType, call->callToken);
2925                 for(i = 0; i<call->timerList.count; i++)
2926                 {
2927                   pNode = dListFindByIndex(&call->timerList, i);
2928                   pTimer = (OOTimer*)pNode->data;
2929                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_RCC_TIMER)                                            && 
2930                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
2931                   response->u.requestChannelCloseAck->forwardLogicalChannelNumber)
2932                   {
2933
2934                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2935                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2936                      OOTRACEDBGC3("Deleted RequestChannelClose Timer. (%s, %s)\n",
2937                                    call->callType, call->callToken);
2938                      break;
2939                   }
2940                 }
2941                 ooOnReceivedRequestChannelCloseAck(call, 
2942                                              response->u.requestChannelCloseAck);
2943                 break;
2944             case T_H245ResponseMessage_requestChannelCloseReject:
2945                OOTRACEINFO4("RequestChannelCloseReject received - %d (%s, %s)\n",
2946                response->u.requestChannelCloseReject->forwardLogicalChannelNumber,
2947                  call->callType, call->callToken);
2948                 for(i = 0; i<call->timerList.count; i++)
2949                 {
2950                   pNode = dListFindByIndex(&call->timerList, i);
2951                   pTimer = (OOTimer*)pNode->data;
2952                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_RCC_TIMER) && 
2953                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
2954                       response->u.requestChannelCloseReject->forwardLogicalChannelNumber)
2955                   {
2956
2957                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2958                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2959                      OOTRACEDBGC3("Deleted RequestChannelClose Timer. (%s, %s)\n",
2960                                    call->callType, call->callToken);
2961                      break;
2962                   }
2963                }
2964                ooOnReceivedRequestChannelCloseReject(call, 
2965                                            response->u.requestChannelCloseReject);
2966                break;
2967              case T_H245ResponseMessage_roundTripDelayResponse:
2968                OOTRACEINFO4("Received roundTripDelayResponse - %d (%s, %s)\n",
2969                   response->u.roundTripDelayResponse->sequenceNumber,  call->callType, call->callToken);
2970                call->rtdrRecv = response->u.roundTripDelayResponse->sequenceNumber;
2971                break;
2972             default:
2973                ;
2974          }
2975          break;
2976       /* H.245 command message is received */
2977       case (T_H245MultimediaSystemControlMessage_command):
2978          command = pH245->h245Msg.u.command;
2979          ooHandleH245Command(call, command);
2980          break;
2981       /* H.245 Indication message received */
2982       case (T_H245MultimediaSystemControlMessage_indication):
2983          indication = pH245->h245Msg.u.indication;
2984          switch(indication->t)
2985          {
2986             case T_H245IndicationMessage_userInput:
2987                ooOnReceivedUserInputIndication(call, indication->u.userInput);
2988                break;
2989             default:
2990                OOTRACEWARN3("Unhandled indication message received.(%s, %s)\n",
2991                              call->callType, call->callToken);
2992          }
2993          break;
2994       default:
2995         ;
2996    }
2997    OOTRACEDBGC3("Finished handling H245 message. (%s, %s)\n", 
2998                  call->callType, call->callToken);
2999    return OO_OK;
3000 }
3001
3002
3003 int ooOnReceivedUserInputIndication
3004    (OOH323CallData *call, H245UserInputIndication *indication)
3005 {
3006    if((indication->t == T_H245UserInputIndication_alphanumeric) && 
3007       (call->dtmfmode & OO_CAP_DTMF_H245_alphanumeric))
3008    {
3009       if(gH323ep.h323Callbacks.onReceivedDTMF)
3010          gH323ep.h323Callbacks.onReceivedDTMF(call,indication->u.alphanumeric);
3011    }
3012    else if((indication->t == T_H245UserInputIndication_signal) && 
3013            (call->dtmfmode & OO_CAP_DTMF_H245_signal)) {
3014       if(call->lastDTMF && indication->u.signal->signalType[0] == call->lastDTMF &&
3015          call->nextDTMFstamp && indication->u.signal->m.rtpPresent && 
3016          indication->u.signal->rtp.m.timestampPresent) {
3017           if(call->nextDTMFstamp > indication->u.signal->rtp.timestamp) {
3018             OOTRACEERR4("ERROR:Duplicate dtmf %c on ((%s, %s)\n", call->lastDTMF, call->callType, 
3019                         call->callToken);
3020             return OO_OK;
3021           }
3022       }
3023       if (indication->u.signal->m.rtpPresent && indication->u.signal->rtp.m.timestampPresent &&
3024           indication->u.signal->m.durationPresent) {
3025           call->nextDTMFstamp = indication->u.signal->rtp.timestamp +
3026                                 indication->u.signal->duration;
3027           call->lastDTMF = indication->u.signal->signalType[0];
3028       } else {
3029           call->nextDTMFstamp = 0;
3030           call->lastDTMF = 0;
3031       }
3032       if(gH323ep.h323Callbacks.onReceivedDTMF)
3033          gH323ep.h323Callbacks.onReceivedDTMF(call, 
3034                                              indication->u.signal->signalType);
3035    }
3036    else {
3037       OOTRACEINFO3("Unsupported userInput message type received - ignoring."
3038                    "(%s, %s)\n", call->callType, call->callToken);
3039    }
3040    return OO_OK;
3041 }
3042
3043 int ooOnReceivedTerminalCapabilitySet(OOH323CallData *call, H245Message *pmsg)
3044 {
3045    int ret = 0,k;
3046    H245TerminalCapabilitySet *tcs=NULL;
3047    DListNode *pNode=NULL;
3048    H245CapabilityTableEntry *capEntry = NULL;
3049
3050    tcs =  pmsg->h245Msg.u.request->u.terminalCapabilitySet;
3051    if(call->remoteTermCapSeqNo > tcs->sequenceNumber)
3052    {
3053       OOTRACEINFO4("Rejecting TermCapSet message with SeqNo %d, as already "
3054                    "acknowledged message with this SeqNo (%s, %s)\n", 
3055                    call->remoteTermCapSeqNo, call->callType, call->callToken);
3056       ooSendTerminalCapabilitySetReject(call, tcs->sequenceNumber, 
3057                          T_H245TerminalCapabilitySetReject_cause_unspecified);
3058       return OO_OK;
3059
3060     } else {
3061 /* 20090924 */
3062 /* bogus soft-switch can send more than one request with  cap set
3063    if it goto to next choice. Right swith don't send but not all are right ;(
3064    we can accept new capability set only. We must remember also that new join caps
3065    will be previously joined caps with new cap set.
3066  */
3067    if(call->remoteTermCapSeqNo == tcs->sequenceNumber)
3068     call->localTermCapState = OO_LocalTermCapExchange_Idle;
3069    }
3070   
3071    if(!tcs->m.capabilityTablePresent)
3072    {
3073       // OOTRACEWARN3("Warn:Ignoring TCS as no capability table present(%s, %s)\n",
3074       OOTRACEWARN3("Empty TCS found.  Pausing call...(%s, %s)\n",
3075                     call->callType, call->callToken);
3076       call->h245SessionState = OO_H245SESSION_PAUSED;
3077       //ooSendTerminalCapabilitySetReject(call, tcs->sequenceNumber, 
3078       //                   T_H245TerminalCapabilitySetReject_cause_unspecified);
3079       //return OO_OK;
3080    }
3081    call->remoteTermCapSeqNo = tcs->sequenceNumber;
3082
3083    if(tcs->m.capabilityTablePresent) {
3084       for(k=0; k<(int)tcs->capabilityTable.count; k++)
3085       {
3086          pNode = dListFindByIndex(&tcs->capabilityTable, k);
3087          if(pNode)
3088          {
3089             OOTRACEDBGC4("Processing CapabilityTable Entry %d (%s, %s)\n", 
3090                           k, call->callType, call->callToken);
3091             capEntry = (H245CapabilityTableEntry*) pNode->data;
3092             if(capEntry->m.capabilityPresent){
3093                ret =  ooAddRemoteCapability(call, &capEntry->capability);
3094                if(ret != OO_OK)
3095                {
3096                   OOTRACEERR4("Error:Failed to process remote capability in "
3097                               "capability table at index %d. (%s, %s)\n", 
3098                                k, call->callType, call->callToken);
3099                }
3100                ooCapabilityUpdateJointCapabilities(call, &capEntry->capability);
3101             }
3102          }
3103          pNode = NULL;
3104          capEntry=NULL;
3105       }
3106    }
3107
3108    if (call->t38sides == 3) /* both side support t.38 */
3109         OO_SETFLAG(call->flags, OO_M_T38SUPPORTED);
3110    else
3111         OO_CLRFLAG(call->flags, OO_M_T38SUPPORTED);
3112    
3113    /* Update remoteTermCapSetState */
3114    call->remoteTermCapState = OO_RemoteTermCapSetRecvd;
3115
3116    ooH245AcknowledgeTerminalCapabilitySet(call);   
3117
3118    /* If we haven't yet send TCS then send it now */
3119    if(call->localTermCapState == OO_LocalTermCapExchange_Idle)
3120    {
3121       ret = ooSendTermCapMsg(call);
3122       if(ret != OO_OK)
3123       {
3124          OOTRACEERR3("ERROR:Sending Terminal capability message (%s, %s)\n",
3125                       call->callType, call->callToken);
3126          return ret;
3127       }
3128    }
3129
3130    if(call->remoteTermCapState != OO_RemoteTermCapSetAckSent ||
3131       call->localTermCapState  != OO_LocalTermCapSetAckRecvd)
3132       return OO_OK;
3133
3134    /* Check MasterSlave procedure has finished */
3135    if(call->masterSlaveState != OO_MasterSlave_Master &&
3136       call->masterSlaveState != OO_MasterSlave_Slave)
3137       return OO_OK;
3138
3139    /* As both MasterSlave and TerminalCapabilitySet procedures have finished,
3140       OpenLogicalChannels */
3141  
3142    if(gH323ep.h323Callbacks.openLogicalChannels)
3143       gH323ep.h323Callbacks.openLogicalChannels(call);
3144    else{
3145       if(!ooGetTransmitLogicalChannel(call))
3146          ooOpenLogicalChannels(call);
3147    }
3148 #if 0
3149    if(!call->logicalChans){
3150       if(!gH323ep.h323Callbacks.openLogicalChannels)
3151          ret = ooOpenLogicalChannels(call);
3152       else
3153          gH323ep.h323Callbacks.openLogicalChannels(call);
3154    }
3155 #endif
3156    return OO_OK;
3157 }
3158
3159 int ooSendTerminalCapabilitySetReject
3160                         (OOH323CallData *call, int seqNo, ASN1UINT cause)
3161 {
3162    H245Message *ph245msg=NULL;
3163    H245ResponseMessage * response=NULL;
3164    OOCTXT *pctxt=NULL;
3165    int ret = ooCreateH245Message(call, &ph245msg, 
3166                       T_H245MultimediaSystemControlMessage_response);
3167    if(ret != OO_OK)
3168    {
3169       OOTRACEERR1("ERROR:H245 message creation failed for - "
3170                            "TerminalCapabilitySetReject\n");
3171       return OO_FAILED;
3172    }
3173    ph245msg->msgType = OOTerminalCapabilitySetReject;
3174    response = ph245msg->h245Msg.u.response;
3175    memset(response, 0, sizeof(H245ResponseMessage));
3176    /* pctxt = &gH323ep.msgctxt; */
3177    pctxt = call->msgctxt;
3178    response->t = T_H245ResponseMessage_terminalCapabilitySetReject;
3179    
3180    response->u.terminalCapabilitySetReject = (H245TerminalCapabilitySetReject*)
3181                    ASN1MALLOC(pctxt, sizeof(H245TerminalCapabilitySetReject));
3182
3183    memset(response->u.terminalCapabilitySetReject, 0, 
3184                                  sizeof(H245TerminalCapabilitySetReject));
3185    response->u.terminalCapabilitySetReject->sequenceNumber = seqNo;
3186    response->u.terminalCapabilitySetReject->cause.t = cause;
3187
3188    OOTRACEDBGA3("Built TerminalCapabilitySetReject (%s, %s)\n", 
3189                  call->callType, call->callToken);
3190  
3191    ret = ooSendH245Msg(call, ph245msg);
3192    if(ret != OO_OK)
3193    {
3194      OOTRACEERR3("Error:Failed to enqueue TCSReject to outbound queue. "
3195                  "(%s, %s)\n", call->callType, call->callToken);
3196    }
3197    else
3198       call->remoteTermCapState = OO_RemoteTermCapExchange_Idle;
3199
3200    ooFreeH245Message(call, ph245msg);
3201    return ret;
3202 }
3203
3204 int ooH245AcknowledgeTerminalCapabilitySet(OOH323CallData *call)
3205 {
3206    H245Message *ph245msg=NULL;
3207    H245ResponseMessage * response=NULL;
3208    OOCTXT *pctxt=NULL;
3209    int ret = ooCreateH245Message(call, &ph245msg, 
3210                       T_H245MultimediaSystemControlMessage_response);
3211    if(ret != OO_OK)
3212    {
3213       OOTRACEERR1("ERROR:H245 message creation failed for - "
3214                            "TerminalCapability Set Ack\n");
3215       return OO_FAILED;
3216    }
3217    ph245msg->msgType = OOTerminalCapabilitySetAck;
3218    response = ph245msg->h245Msg.u.response;
3219    memset(response, 0, sizeof(H245ResponseMessage));
3220    /* pctxt = &gH323ep.msgctxt; */
3221    pctxt = call->msgctxt;
3222    response->t = T_H245ResponseMessage_terminalCapabilitySetAck;
3223    
3224    response->u.terminalCapabilitySetAck = (H245TerminalCapabilitySetAck*)
3225                    ASN1MALLOC(pctxt, sizeof(H245TerminalCapabilitySetAck));
3226
3227    memset(response->u.terminalCapabilitySetAck, 0, 
3228                                  sizeof(H245TerminalCapabilitySetAck));
3229    response->u.terminalCapabilitySetAck->sequenceNumber = call->remoteTermCapSeqNo;
3230
3231    OOTRACEDBGA3("Built TerminalCapabilitySet Ack (%s, %s)\n", 
3232                  call->callType, call->callToken);
3233    ret = ooSendH245Msg(call, ph245msg);
3234
3235    if(ret != OO_OK)
3236    {
3237      OOTRACEERR3("Error:Failed to enqueue TCSAck to outbound queue. (%s, %s)\n", call->callType, call->callToken);
3238    }
3239    else
3240       call->remoteTermCapState = OO_RemoteTermCapSetAckSent;
3241
3242    ooFreeH245Message(call, ph245msg);
3243    return ret;
3244 }
3245
3246
3247 int ooSendTerminalCapabilitySetRelease(OOH323CallData * call)
3248 {
3249    int ret=0;
3250    H245IndicationMessage* indication=NULL;
3251    H245Message *ph245msg=NULL;
3252    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
3253    OOCTXT *pctxt=call->msgctxt;
3254
3255    ret = ooCreateH245Message
3256       (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication);
3257
3258    if (ret != OO_OK) {
3259       OOTRACEERR3("Error:H245 message creation failed for - Terminal"
3260                   "CapabilitySetRelease (%s, %s)\n",call->callType, 
3261                   call->callToken);
3262       return OO_FAILED;
3263    }
3264    ph245msg->msgType = OOTerminalCapabilitySetRelease;
3265    indication = ph245msg->h245Msg.u.indication;
3266
3267    indication->t = T_H245IndicationMessage_terminalCapabilitySetRelease;
3268
3269    indication->u.terminalCapabilitySetRelease = 
3270       (H245TerminalCapabilitySetRelease*)
3271       memAlloc (pctxt, sizeof(H245TerminalCapabilitySetRelease));
3272
3273    if(!indication->u.terminalCapabilitySetRelease)
3274    {
3275       OOTRACEERR3("Error: Failed to allocate memory for TCSRelease message."
3276                   " (%s, %s)\n", call->callType, call->callToken);
3277       ooFreeH245Message(call, ph245msg);
3278       return OO_FAILED;
3279    }
3280    OOTRACEDBGA3 ("Built TerminalCapabilitySetRelease (%s, %s)\n", 
3281                  call->callType, call->callToken);
3282
3283    ret = ooSendH245Msg (call, ph245msg);
3284
3285    if (ret != OO_OK) {
3286       OOTRACEERR3 
3287          ("Error:Failed to enqueue TerminalCapabilitySetRelease "
3288          "message to outbound queue.(%s, %s)\n", call->callType, 
3289          call->callToken);
3290    }
3291    
3292    ooFreeH245Message (call, ph245msg);
3293    return ret;
3294 }
3295
3296
3297 int ooSendH245UserInputIndication_alphanumeric
3298    (OOH323CallData *call, const char *data)
3299 {
3300    int ret=0;
3301    H245IndicationMessage* indication=NULL;
3302    H245Message *ph245msg=NULL;
3303    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
3304    OOCTXT *pctxt=call->msgctxt;
3305
3306    ret = ooCreateH245Message
3307       (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication);
3308
3309    if (ret != OO_OK) {
3310       OOTRACEERR3("Error:H245 message creation failed for - H245UserInput"
3311                   "Indication_alphanumeric (%s, %s)\n",call->callType, 
3312                   call->callToken);
3313       return OO_FAILED;
3314    }
3315    ph245msg->msgType = OOUserInputIndication;
3316    indication = ph245msg->h245Msg.u.indication;
3317
3318    indication->t = T_H245IndicationMessage_userInput;
3319    indication->u.userInput = 
3320       (H245UserInputIndication*)
3321       memAllocZ (pctxt, sizeof(H245UserInputIndication));
3322
3323    if(!indication->u.userInput)
3324    {
3325       OOTRACEERR3("Error: Memory - ooH245UserInputIndication_alphanumeric - "
3326                   " userInput (%s, %s)\n", call->callType, call->callToken);
3327       ooFreeH245Message(call, ph245msg);
3328       return OO_FAILED;
3329    }
3330    indication->u.userInput->t = T_H245UserInputIndication_alphanumeric;
3331    indication->u.userInput->u.alphanumeric = (ASN1GeneralString)
3332                                               memAlloc(pctxt, strlen(data)+1);
3333    if(!indication->u.userInput->u.alphanumeric)
3334    {
3335       OOTRACEERR3("Error: Memory - ooH245UserInputIndication-alphanumeric - "
3336                   "alphanumeric (%s, %s).\n", call->callType, call->callToken);
3337       ooFreeH245Message(call, ph245msg);
3338       return OO_FAILED;
3339    }
3340    strcpy(*(char**)&indication->u.userInput->u.alphanumeric, data);
3341    OOTRACEDBGA3 ("Built UserInputIndication_alphanumeric (%s, %s)\n", 
3342                  call->callType, call->callToken);
3343
3344    ret = ooSendH245Msg (call, ph245msg);
3345
3346    if (ret != OO_OK) {
3347       OOTRACEERR3 
3348          ("Error:Failed to enqueue UserInputIndication_alphanumeric "
3349           "message to outbound queue.(%s, %s)\n", call->callType, 
3350           call->callToken);
3351    }
3352    
3353    ooFreeH245Message (call, ph245msg);
3354    return ret;
3355 }
3356
3357 int ooSendH245UserInputIndication_signal
3358    (OOH323CallData *call, const char *data)
3359 {
3360    int ret=0;
3361    H245IndicationMessage* indication=NULL;
3362    H245Message *ph245msg=NULL;
3363    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
3364    OOCTXT *pctxt=call->msgctxt;
3365
3366    ret = ooCreateH245Message
3367       (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication);
3368
3369    if (ret != OO_OK) {
3370       OOTRACEERR3("Error:H245 message creation failed for - H245UserInput"
3371                   "Indication_signal (%s, %s)\n",call->callType, 
3372                   call->callToken);
3373       return OO_FAILED;
3374    }
3375    ph245msg->msgType = OOUserInputIndication;
3376    indication = ph245msg->h245Msg.u.indication;
3377
3378    indication->t = T_H245IndicationMessage_userInput;
3379    indication->u.userInput = 
3380       (H245UserInputIndication*)
3381       memAllocZ (pctxt, sizeof(H245UserInputIndication));
3382
3383    if(!indication->u.userInput)
3384    {
3385       OOTRACEERR3("Error: Memory - ooH245UserInputIndication_signal - "
3386                   " userInput (%s, %s)\n", call->callType, call->callToken);
3387       ooFreeH245Message(call, ph245msg);
3388       return OO_FAILED;
3389    }
3390    indication->u.userInput->t = T_H245UserInputIndication_signal;
3391    indication->u.userInput->u.signal = (H245UserInputIndication_signal*)
3392                       memAllocZ(pctxt, sizeof(H245UserInputIndication_signal));
3393    indication->u.userInput->u.signal->signalType = (ASN1IA5String)
3394                                               memAlloc(pctxt, strlen(data)+1);
3395    if(!indication->u.userInput->u.signal ||
3396       !indication->u.userInput->u.signal->signalType)
3397    {
3398       OOTRACEERR3("Error: Memory - ooH245UserInputIndication_signal - "
3399                   "signal (%s, %s).\n", call->callType, call->callToken);
3400       ooFreeH245Message(call, ph245msg);
3401       return OO_FAILED;
3402    }
3403    strcpy(*(char**)&indication->u.userInput->u.signal->signalType, data);
3404    OOTRACEDBGA3 ("Built UserInputIndication_signal (%s, %s)\n", 
3405                  call->callType, call->callToken);
3406
3407    ret = ooSendH245Msg (call, ph245msg);
3408
3409    if (ret != OO_OK) {
3410       OOTRACEERR3 
3411          ("Error:Failed to enqueue UserInputIndication_signal "
3412           "message to outbound queue.(%s, %s)\n", call->callType, 
3413           call->callToken);
3414    }
3415    
3416    ooFreeH245Message (call, ph245msg);
3417    return ret;
3418 }
3419
3420
3421 int ooOpenLogicalChannels(OOH323CallData *call)
3422 {
3423    int ret=0;
3424    OOTRACEINFO3("Opening logical channels (%s, %s)\n", call->callType, 
3425                  call->callToken); 
3426
3427    /* Audio channels */
3428    if(gH323ep.callMode == OO_CALLMODE_AUDIOCALL ||
3429       gH323ep.callMode == OO_CALLMODE_AUDIOTX)
3430    {
3431       if (OO_TESTFLAG (call->flags, OO_M_AUDIOSESSION)) {
3432          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_AUDIO);
3433       } else if (OO_TESTFLAG (call->flags, OO_M_DATASESSION)) {
3434          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_DATA);
3435       }
3436       if(ret != OO_OK) {
3437        OOTRACEERR3("ERROR:Failed to open audio/data channels. Clearing call."
3438                    "(%s, %s)\n", call->callType, call->callToken);
3439        if (call->callState < OO_CALL_CLEAR) {
3440         call->callEndReason = OO_REASON_LOCAL_CLEARED;
3441         call->callState = OO_CALL_CLEAR;
3442        }
3443        return ret;
3444       }
3445    }
3446    
3447    if(gH323ep.callMode == OO_CALLMODE_VIDEOCALL)
3448    {
3449      /*      if (!OO_TESTFLAG (call->flags, OO_M_AUDIOSESSION))
3450         {*/
3451          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_AUDIO);
3452          if(ret != OO_OK)
3453          {
3454             OOTRACEERR3("ERROR:Failed to open audio channel. Clearing call."
3455                         "(%s, %s)\n", call->callType, call->callToken);
3456             if(call->callState < OO_CALL_CLEAR)
3457             {
3458                call->callEndReason = OO_REASON_LOCAL_CLEARED;
3459                call->callState = OO_CALL_CLEAR;
3460             }
3461             return ret;
3462          }
3463       //}
3464       /*      if(!OO_TESTFLAG(call->flags, OO_M_VIDEOSESSION))
3465       {*/
3466          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_VIDEO);
3467          if(ret != OO_OK)
3468          {
3469             OOTRACEERR3("ERROR:Failed to open video channel. Clearing call."
3470                         "(%s, %s)\n", call->callType, call->callToken);
3471             if(call->callState < OO_CALL_CLEAR)
3472             {
3473                call->callEndReason = OO_REASON_LOCAL_CLEARED;
3474                call->callState = OO_CALL_CLEAR;
3475             }
3476             return ret;
3477          }
3478      //}
3479    }
3480    return OO_OK;
3481 }
3482
3483 /* CapType indicates whether to Open Audio or Video channel */
3484 int ooOpenLogicalChannel(OOH323CallData *call, enum OOCapType capType )
3485 {
3486    ooH323EpCapability *epCap=NULL;
3487    int k=0;
3488
3489    /* Check whether local endpoint has audio capability */
3490    if(gH323ep.myCaps == 0 && call->ourCaps == 0)
3491    {
3492       OOTRACEERR3("ERROR:Local endpoint does not have any audio capabilities"
3493                   " (%s, %s)\n", call->callType, call->callToken);
3494       return OO_FAILED;
3495    }
3496    
3497    /* Go through local endpoints capabilities sequentially, and find out the
3498       first one which has a match in the remote endpoints receive capabilities.
3499    */
3500    OOTRACEINFO3("Looking for matching capabilities. (%s, %s)\n", 
3501                  call->callType, call->callToken);
3502 /* May */
3503    if(call->masterSlaveState == OO_MasterSlave_Master)
3504    {
3505       for(k=0; k<call->capPrefs.index; k++)
3506       {
3507          /*Search for audio caps only */
3508          if(capType == OO_CAP_TYPE_AUDIO && 
3509             call->capPrefs.order[k] > OO_CAP_VIDEO_BASE)
3510             continue;
3511          /* Search for video caps only */
3512          if(capType == OO_CAP_TYPE_VIDEO && 
3513             call->capPrefs.order[k] <= OO_CAP_VIDEO_BASE)
3514             continue;
3515
3516          epCap = call->jointCaps;
3517
3518          while(epCap){
3519             if(epCap->cap == call->capPrefs.order[k] && (epCap->dir & OOTX))
3520                break;
3521             epCap = epCap->next;
3522          }
3523          if(!epCap)
3524          {
3525             OOTRACEDBGA4("Prefereed capability %d is not a local transmit "
3526                          "capability(%s, %s)\n", call->capPrefs.order[k],
3527                          call->callType, call->callToken);
3528             continue;
3529          }
3530          break;
3531       }
3532       if(!epCap)
3533       {
3534          OOTRACEERR4("ERROR:Incompatible capabilities - Can not open "
3535                   "%s channel (%s, %s)\n", 
3536                   (capType==OO_CAP_TYPE_AUDIO)?"audio":"video", call->callType,
3537                   call->callToken);
3538          return OO_FAILED;
3539       }
3540
3541    }
3542    else
3543    {
3544       epCap = call->jointCaps;
3545
3546       while(epCap){
3547          if(epCap->capType == capType && epCap->dir & OOTX) { break; }
3548          epCap = epCap->next;
3549       }
3550       if(!epCap)
3551       {
3552          OOTRACEERR4("ERROR:Incompatible audio capabilities - Can not open "
3553                   "%s channel (%s, %s)\n", 
3554                   (capType==OO_CAP_TYPE_AUDIO)?"audio":"video", call->callType,
3555                   call->callToken);
3556          return OO_FAILED;
3557       }
3558        
3559    }
3560
3561    switch(epCap->cap)
3562    {
3563    case OO_G711ALAW64K:
3564    case OO_G711ALAW56K:
3565    case OO_G711ULAW64K:
3566    case OO_G711ULAW56K:
3567    case OO_G726:
3568    case OO_G726AAL2:
3569    case OO_AMRNB:
3570    case OO_SPEEX:
3571    case OO_G728:
3572    case OO_G729:
3573    case OO_G729A:
3574    case OO_G729B:
3575    case OO_G7231:
3576    case OO_GSMFULLRATE:
3577    case OO_GSMHALFRATE:
3578    case OO_GSMENHANCEDFULLRATE:
3579    case OO_H263VIDEO:
3580    case OO_T38:
3581       ooOpenChannel(call, epCap);
3582       break;
3583
3584       
3585    default:
3586       OOTRACEERR3("ERROR:Unknown Audio Capability type (%s, %s)\n", 
3587                    call->callType, call->callToken);
3588    }
3589    return OO_OK;
3590 }
3591
3592 int ooOpenChannel(OOH323CallData* call, ooH323EpCapability *epCap)
3593 {
3594    int ret;
3595    H245Message *ph245msg = NULL;
3596    H245RequestMessage * request;
3597    OOCTXT *pctxt = NULL;
3598    H245OpenLogicalChannel_forwardLogicalChannelParameters *flcp = NULL;
3599    H245AudioCapability *audioCap = NULL;
3600    H245VideoCapability *videoCap = NULL;
3601    H245DataApplicationCapability *t38Cap = NULL;
3602    H245H2250LogicalChannelParameters *h2250lcp = NULL;
3603    H245UnicastAddress *unicastAddrs = NULL;
3604    H245UnicastAddress_iPAddress *iPAddress = NULL;
3605    unsigned session_id=0;
3606    ooLogicalChannel *pLogicalChannel = NULL;
3607    
3608    OOTRACEDBGC4("Doing Open Channel for %s. (%s, %s)\n", 
3609                  ooGetCapTypeText(epCap->cap), call->callType, 
3610                  call->callToken);
3611
3612    ret = ooCreateH245Message(call, &ph245msg, 
3613                       T_H245MultimediaSystemControlMessage_request);
3614    if(ret != OO_OK)
3615    {
3616       OOTRACEERR4("Error: H245 message creation failed for - Open %s"
3617                   "channel (%s, %s)\n", ooGetCapTypeText(epCap->cap), 
3618                   call->callType, call->callToken);
3619       return OO_FAILED;
3620    }
3621
3622    ph245msg->msgType = OOOpenLogicalChannel;
3623
3624    ph245msg->logicalChannelNo =  call->logicalChanNoCur++;
3625    if(call->logicalChanNoCur > call->logicalChanNoMax)
3626       call->logicalChanNoCur = call->logicalChanNoBase; 
3627
3628    request = ph245msg->h245Msg.u.request;
3629    /* pctxt = &gH323ep.msgctxt; */
3630    pctxt = call->msgctxt;
3631    memset(request, 0, sizeof(H245RequestMessage));
3632
3633    request->t = T_H245RequestMessage_openLogicalChannel;
3634    request->u.openLogicalChannel = (H245OpenLogicalChannel*)
3635                      memAlloc(pctxt, sizeof(H245OpenLogicalChannel));
3636    if(!request->u.openLogicalChannel)
3637    {
3638       OOTRACEERR3("Error:Memory - ooOpenChannel - openLogicalChannel."
3639                   "(%s, %s)\n", call->callType, call->callToken);
3640       return OO_FAILED;
3641
3642    }
3643    memset(request->u.openLogicalChannel, 0, 
3644                                      sizeof(H245OpenLogicalChannel));
3645    request->u.openLogicalChannel->forwardLogicalChannelNumber = 
3646                                                  ph245msg->logicalChannelNo;
3647
3648    
3649    session_id = ooCallGenerateSessionID(call, epCap->capType, "transmit");
3650
3651
3652    pLogicalChannel = ooAddNewLogicalChannel(call, 
3653                    request->u.openLogicalChannel->forwardLogicalChannelNumber,
3654                    session_id, "transmit", epCap);
3655    
3656    if(!pLogicalChannel)
3657    {
3658       OOTRACEERR3("ERROR:Failed to add new logical channel entry (%s, %s)\n",
3659                   call->callType, call->callToken);
3660       ooFreeH245Message(call, ph245msg);
3661       return OO_FAILED;
3662    }
3663    /* Populate H245OpenLogicalChannel_ForwardLogicalChannel Parameters*/
3664    flcp = &(request->u.openLogicalChannel->forwardLogicalChannelParameters);
3665    flcp->m.portNumberPresent = 0;
3666    flcp->m.forwardLogicalChannelDependencyPresent = 0;
3667    flcp->m.replacementForPresent = 0;
3668
3669    /* data type of channel */
3670    if(epCap->capType == OO_CAP_TYPE_AUDIO)
3671    {
3672       flcp->dataType.t = T_H245DataType_audioData;
3673       /* set audio capability for channel */
3674       audioCap = ooCapabilityCreateAudioCapability(epCap,pctxt, OOTX);
3675       if(!audioCap)
3676       {
3677          OOTRACEERR4("Error:Failed to create duplicate audio capability in "
3678                      "ooOpenChannel- %s (%s, %s)\n", 
3679                      ooGetCapTypeText(epCap->cap), call->callType, 
3680                      call->callToken);
3681          ooFreeH245Message(call, ph245msg);
3682          return OO_FAILED;
3683       }
3684    
3685       flcp->dataType.u.audioData = audioCap;
3686    }
3687    else if(epCap->capType == OO_CAP_TYPE_VIDEO)
3688    {
3689       flcp->dataType.t = T_H245DataType_videoData;      
3690       videoCap = ooCapabilityCreateVideoCapability(epCap, pctxt, OOTX);
3691       if(!videoCap)
3692       {
3693          OOTRACEERR4("Error:Failed to create duplicate video capability in "
3694                      "ooOpenChannel- %s (%s, %s)\n", 
3695                      ooGetCapTypeText(epCap->cap), call->callType, 
3696                      call->callToken);
3697          ooFreeH245Message(call, ph245msg);
3698          return OO_FAILED;
3699       }
3700    
3701       flcp->dataType.u.videoData = videoCap;
3702    }
3703    else if(epCap->capType == OO_CAP_TYPE_DATA)
3704    {
3705       flcp->dataType.t = T_H245DataType_data;
3706       /* set audio capability for channel */
3707       t38Cap = ooCapabilityCreateT38Capability(epCap,pctxt, OOTX);
3708       if(!t38Cap)
3709       {
3710          OOTRACEERR4("Error:Failed to create duplicate T38 capability in "
3711                      "ooOpenChannel- %s (%s, %s)\n", 
3712                      ooGetCapTypeText(epCap->cap), call->callType, 
3713                      call->callToken);
3714          ooFreeH245Message(call, ph245msg);
3715          return OO_FAILED;
3716       }
3717    
3718       flcp->dataType.u.data = t38Cap;
3719    }
3720    else{
3721       OOTRACEERR1("Error: Unhandled media type in ooOpenChannel\n");
3722       return OO_FAILED;
3723    }
3724
3725   
3726    flcp->multiplexParameters.t = 
3727       T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters;
3728    flcp->multiplexParameters.u.h2250LogicalChannelParameters = 
3729                          (H245H2250LogicalChannelParameters*)ASN1MALLOC(pctxt, 
3730                           sizeof(H245H2250LogicalChannelParameters));
3731
3732    h2250lcp = flcp->multiplexParameters.u.h2250LogicalChannelParameters;
3733    memset(h2250lcp, 0, sizeof(H245H2250LogicalChannelParameters));
3734
3735    h2250lcp->sessionID = session_id;
3736
3737    h2250lcp->mediaGuaranteedDelivery = 0;
3738    h2250lcp->silenceSuppression = 0;
3739    h2250lcp->m.mediaControlChannelPresent = 1;
3740    
3741    h2250lcp->mediaControlChannel.t = 
3742                                  T_H245TransportAddress_unicastAddress;
3743    h2250lcp->mediaControlChannel.u.unicastAddress =  (H245UnicastAddress*)
3744                          ASN1MALLOC(pctxt, sizeof(H245UnicastAddress));
3745
3746    unicastAddrs = h2250lcp->mediaControlChannel.u.unicastAddress;
3747    memset(unicastAddrs, 0, sizeof(H245UnicastAddress));
3748    unicastAddrs->t = T_H245UnicastAddress_iPAddress;
3749    unicastAddrs->u.iPAddress = (H245UnicastAddress_iPAddress*)
3750                ASN1MALLOC(pctxt, sizeof(H245UnicastAddress_iPAddress));
3751    iPAddress = unicastAddrs->u.iPAddress;
3752    memset(iPAddress, 0, sizeof(H245UnicastAddress_iPAddress));
3753
3754    ooSocketConvertIpToNwAddr(pLogicalChannel->localIP,iPAddress->network.data);
3755
3756    iPAddress->network.numocts = 4;
3757    iPAddress->tsapIdentifier = pLogicalChannel->localRtcpPort;
3758    pLogicalChannel->state = OO_LOGICALCHAN_PROPOSED; 
3759    OOTRACEDBGA4("Built OpenLogicalChannel-%s (%s, %s)\n", 
3760                  ooGetCapTypeText(epCap->cap), call->callType, 
3761                  call->callToken);
3762    ret = ooSendH245Msg(call, ph245msg);
3763    if(ret != OO_OK)
3764    {
3765       OOTRACEERR3("Error:Failed to enqueue OpenLogicalChannel to outbound "
3766                  "queue. (%s, %s)\n", call->callType,
3767                  call->callToken);
3768    }
3769    ooFreeH245Message(call, ph245msg);
3770   
3771    return ret;
3772 }
3773
3774
3775 /* Used to build  OLCs for fast connect. Keep in mind that forward and 
3776    reverse 
3777    are always with&nbs