687e07eb53f71cccb7d0558458554f7194f177e5
[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             if(!ooGetTransmitLogicalChannel(call))
961                ooOpenLogicalChannels(call);
962 #if 0
963             if(!call->logicalChans){
964                if(!gH323ep.h323Callbacks.openLogicalChannels)
965                   ooOpenLogicalChannels(call);
966                else
967                   gH323ep.h323Callbacks.openLogicalChannels(call);
968             }
969 #endif
970          }
971          else
972             OOTRACEDBGC1("Not opening logical channels as Cap exchange "
973                          "remaining\n");
974          break;
975        default:
976           OOTRACEWARN3("Warn:Unhandled Master Slave message received - %s - "
977                        "%s\n", call->callType, call->callToken);
978    }
979    return OO_OK;      
980 }
981
982 int ooSendMasterSlaveDetermination(OOH323CallData *call)
983 {
984    int ret;
985    H245Message* ph245msg=NULL;
986    H245RequestMessage *request;
987    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
988    OOCTXT *pctxt=call->msgctxt;
989    H245MasterSlaveDetermination* pMasterSlave;
990
991    /* Check whether Master Slave Determination already in progress */
992    if(call->masterSlaveState != OO_MasterSlave_Idle)
993    {
994       OOTRACEINFO3("MasterSlave determination already in progress (%s, %s)\n",
995                    call->callType, call->callToken);
996       return OO_OK;
997    }
998
999    ret = ooCreateH245Message(call, &ph245msg,
1000                    T_H245MultimediaSystemControlMessage_request);
1001    if(ret != OO_OK)
1002    {
1003       OOTRACEERR3("Error: creating H245 message - MasterSlave Determination "
1004                   "(%s, %s)\n", call->callType, call->callToken);
1005       return OO_FAILED;
1006    }
1007    ph245msg->msgType = OOMasterSlaveDetermination;
1008    request = ph245msg->h245Msg.u.request;
1009    request->t = T_H245RequestMessage_masterSlaveDetermination;
1010    request->u.masterSlaveDetermination = (H245MasterSlaveDetermination*)
1011             ASN1MALLOC(pctxt, sizeof(H245MasterSlaveDetermination));
1012
1013    
1014    pMasterSlave = request->u.masterSlaveDetermination;
1015    memset(pMasterSlave, 0, sizeof(H245MasterSlaveDetermination));   
1016    pMasterSlave->terminalType = gH323ep.termType; 
1017    pMasterSlave->statusDeterminationNumber = 
1018                        ooGenerateStatusDeterminationNumber();
1019    call->statusDeterminationNumber = pMasterSlave->statusDeterminationNumber;
1020
1021    OOTRACEDBGA3("Built MasterSlave Determination (%s, %s)\n", call->callType,
1022                  call->callToken); 
1023    ret = ooSendH245Msg(call, ph245msg);
1024
1025    if(ret != OO_OK)
1026    {
1027       OOTRACEERR3("Error:Failed to enqueue MasterSlaveDetermination message to"
1028                   " outbound queue. (%s, %s)\n", call->callType, 
1029                   call->callToken);
1030    }
1031    else
1032       call->masterSlaveState = OO_MasterSlave_DetermineSent;
1033    
1034    ooFreeH245Message(call, ph245msg);
1035
1036    return ret;
1037 }
1038
1039 int ooSendMasterSlaveDeterminationAck(OOH323CallData* call,
1040                                       char * status)
1041 {
1042    int ret=0;
1043    H245ResponseMessage * response=NULL;
1044    H245Message *ph245msg=NULL;
1045    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
1046    OOCTXT *pctxt=call->msgctxt;
1047
1048    ret = ooCreateH245Message(call, &ph245msg, 
1049                       T_H245MultimediaSystemControlMessage_response);
1050    if(ret != OO_OK)
1051    {
1052       OOTRACEERR3("Error:H245 message creation failed for - MasterSlave "
1053                   "Determination Ack (%s, %s)\n",call->callType, 
1054                   call->callToken);
1055       return OO_FAILED;
1056    }
1057    ph245msg->msgType = OOMasterSlaveAck;
1058    response = ph245msg->h245Msg.u.response;
1059    memset(response, 0, sizeof(H245ResponseMessage));
1060    response->t = T_H245ResponseMessage_masterSlaveDeterminationAck;
1061    response->u.masterSlaveDeterminationAck = (H245MasterSlaveDeterminationAck*)
1062                    ASN1MALLOC(pctxt, sizeof(H245MasterSlaveDeterminationAck));
1063    memset(response->u.masterSlaveDeterminationAck, 0, 
1064                              sizeof(H245MasterSlaveDeterminationAck));
1065    if(!strcmp("master", status))
1066       response->u.masterSlaveDeterminationAck->decision.t = 
1067                          T_H245MasterSlaveDeterminationAck_decision_master;
1068    else
1069       response->u.masterSlaveDeterminationAck->decision.t = 
1070                          T_H245MasterSlaveDeterminationAck_decision_slave;
1071    
1072    OOTRACEDBGA3("Built MasterSlave determination Ack (%s, %s)\n", 
1073                 call->callType, call->callToken);
1074    ret = ooSendH245Msg(call, ph245msg);
1075    if(ret != OO_OK)
1076    {
1077       OOTRACEERR3("Error:Failed to enqueue MasterSlaveDeterminationAck message"
1078                   " to outbound queue. (%s, %s)\n", call->callType, 
1079                   call->callToken);
1080    }
1081    
1082    ooFreeH245Message(call, ph245msg);
1083    call->msAckStatus = OO_msAck_localSent;
1084    return ret;
1085 }
1086
1087 int ooSendMasterSlaveDeterminationReject (OOH323CallData* call)
1088 {
1089    int ret=0;
1090    H245ResponseMessage* response=NULL;
1091    H245Message *ph245msg=NULL;
1092    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
1093    OOCTXT *pctxt=call->msgctxt;
1094
1095    ret = ooCreateH245Message
1096       (call, &ph245msg, T_H245MultimediaSystemControlMessage_response);
1097
1098    if (ret != OO_OK) {
1099       OOTRACEERR3("Error:H245 message creation failed for - MasterSlave "
1100                   "Determination Reject (%s, %s)\n",call->callType, 
1101                   call->callToken);
1102       return OO_FAILED;
1103    }
1104    ph245msg->msgType = OOMasterSlaveReject;
1105    response = ph245msg->h245Msg.u.response;
1106
1107    response->t = T_H245ResponseMessage_masterSlaveDeterminationReject;
1108
1109    response->u.masterSlaveDeterminationReject = 
1110       (H245MasterSlaveDeterminationReject*)
1111       memAlloc (pctxt, sizeof(H245MasterSlaveDeterminationReject));
1112
1113    response->u.masterSlaveDeterminationReject->cause.t =
1114       T_H245MasterSlaveDeterminationReject_cause_identicalNumbers;
1115
1116    OOTRACEDBGA3 ("Built MasterSlave determination reject (%s, %s)\n", 
1117                  call->callType, call->callToken);
1118
1119    ret = ooSendH245Msg (call, ph245msg);
1120
1121    if (ret != OO_OK) {
1122       OOTRACEERR3 
1123          ("Error:Failed to enqueue MasterSlaveDeterminationReject "
1124           "message to outbound queue.(%s, %s)\n", call->callType, 
1125           call->callToken);
1126    }
1127    
1128    ooFreeH245Message (call, ph245msg);
1129
1130    return ret;
1131 }
1132
1133 int ooSendMasterSlaveDeterminationRelease(OOH323CallData * call)
1134 {
1135    int ret=0;
1136    H245IndicationMessage* indication=NULL;
1137    H245Message *ph245msg=NULL;
1138    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
1139    OOCTXT *pctxt=call->msgctxt;
1140
1141    ret = ooCreateH245Message
1142       (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication);
1143
1144    if (ret != OO_OK) {
1145       OOTRACEERR3("Error:H245 message creation failed for - MasterSlave "
1146                   "Determination Release (%s, %s)\n",call->callType, 
1147                   call->callToken);
1148       return OO_FAILED;
1149    }
1150    ph245msg->msgType = OOMasterSlaveRelease;
1151    indication = ph245msg->h245Msg.u.indication;
1152
1153    indication->t = T_H245IndicationMessage_masterSlaveDeterminationRelease;
1154
1155    indication->u.masterSlaveDeterminationRelease = 
1156       (H245MasterSlaveDeterminationRelease*)
1157       memAlloc (pctxt, sizeof(H245MasterSlaveDeterminationRelease));
1158
1159    if(!indication->u.masterSlaveDeterminationRelease)
1160    {
1161       OOTRACEERR3("Error: Failed to allocate memory for MSDRelease message."
1162                   " (%s, %s)\n", call->callType, call->callToken);
1163       ooFreeH245Message(call, ph245msg);
1164       return OO_FAILED;
1165    }
1166    OOTRACEDBGA3 ("Built MasterSlave determination Release (%s, %s)\n", 
1167                  call->callType, call->callToken);
1168
1169    ret = ooSendH245Msg (call, ph245msg);
1170
1171    if (ret != OO_OK) {
1172       OOTRACEERR3 
1173         ("Error:Failed to enqueue MasterSlaveDeterminationRelease "
1174         "message to outbound queue.(%s, %s)\n", call->callType, 
1175         call->callToken);
1176    }
1177    
1178    ooFreeH245Message (call, ph245msg);
1179    return ret;
1180 }
1181
1182 int ooHandleMasterSlaveReject
1183    (OOH323CallData *call, H245MasterSlaveDeterminationReject* reject)
1184 {
1185    if(call->msdRetries < DEFAULT_MAX_RETRIES)
1186    {
1187       call->msdRetries++;
1188       OOTRACEDBGA3("Retrying MasterSlaveDetermination. (%s, %s)\n", 
1189                     call->callType, call->callToken);
1190       call->masterSlaveState = OO_MasterSlave_Idle;
1191       ooSendMasterSlaveDetermination(call);
1192       return OO_OK;
1193    }
1194    OOTRACEERR3("Error:Failed to complete MasterSlaveDetermination - "
1195                "Ending call. (%s, %s)\n", call->callType, call->callToken);
1196    if(call->callState < OO_CALL_CLEAR)
1197    {
1198       call->callEndReason = OO_REASON_LOCAL_CLEARED;
1199       call->callState = OO_CALL_CLEAR;
1200    }
1201    return OO_OK;
1202 }
1203
1204 /* handling requestmode routines */
1205
1206 int ooSendRequestModeAck(OOH323CallData* call,
1207                                       H245SequenceNumber sequenceNumber)
1208 {
1209    int ret=0;
1210    H245ResponseMessage* response=NULL;
1211    H245Message *ph245msg=NULL;
1212    OOCTXT *pctxt=call->msgctxt;
1213
1214    ret = ooCreateH245Message(call, &ph245msg, 
1215                       T_H245MultimediaSystemControlMessage_response);
1216    if(ret != OO_OK)
1217    {
1218       OOTRACEERR3("Error:H245 message creation failed for - RequestMode "
1219                   "Ack (%s, %s)\n",call->callType, 
1220                   call->callToken);
1221       return OO_FAILED;
1222    }
1223    ph245msg->msgType = OORequestModeAck;
1224    response = ph245msg->h245Msg.u.response;
1225    memset(response, 0, sizeof(H245ResponseMessage));
1226    response->t = T_H245ResponseMessage_requestModeAck;
1227    response->u.requestModeAck = (H245RequestModeAck *)
1228                    ASN1MALLOC(pctxt, sizeof(H245RequestModeAck));
1229    memset(response->u.requestModeAck, 0, 
1230                              sizeof(H245RequestModeAck));
1231
1232    response->u.requestModeAck->sequenceNumber = sequenceNumber;
1233    response->u.requestModeAck->response.t = 
1234         T_H245RequestModeAck_response_willTransmitMostPreferredMode;
1235
1236    OOTRACEDBGA3("Built RequestModeAck (%s, %s)\n", 
1237                 call->callType, call->callToken);
1238    ret = ooSendH245Msg(call, ph245msg);
1239    if(ret != OO_OK)
1240    {
1241       OOTRACEERR3("Error:Failed to enqueue RequestModeAck message"
1242                   " to outbound queue. (%s, %s)\n", call->callType, 
1243                   call->callToken);
1244    }
1245    
1246    ooFreeH245Message(call, ph245msg);
1247    return ret;
1248 }
1249
1250 int ooSendRequestModeReject(OOH323CallData* call,
1251                                       H245SequenceNumber sequenceNumber)
1252 {
1253    int ret=0;
1254    H245ResponseMessage* response=NULL;
1255    H245Message *ph245msg=NULL;
1256    OOCTXT *pctxt=call->msgctxt;
1257
1258    ret = ooCreateH245Message(call, &ph245msg, 
1259                       T_H245MultimediaSystemControlMessage_response);
1260    if(ret != OO_OK)
1261    {
1262       OOTRACEERR3("Error:H245 message creation failed for - RequstMode "
1263                   "Reject (%s, %s)\n",call->callType, 
1264                   call->callToken);
1265       return OO_FAILED;
1266    }
1267    ph245msg->msgType = OORequestModeReject;
1268    response = ph245msg->h245Msg.u.response;
1269    memset(response, 0, sizeof(H245ResponseMessage));
1270    response->t = T_H245ResponseMessage_requestModeReject;
1271    response->u.requestModeReject = (H245RequestModeReject *)
1272                    ASN1MALLOC(pctxt, sizeof(H245RequestModeReject));
1273    memset(response->u.requestModeReject, 0, 
1274                              sizeof(H245RequestModeReject));
1275
1276    response->u.requestModeReject->sequenceNumber = sequenceNumber;
1277    response->u.requestModeReject->cause.t = 
1278                 T_H245RequestModeReject_cause_modeUnavailable;
1279
1280    OOTRACEDBGA3("Built RequestModeReject (%s, %s)\n", 
1281                 call->callType, call->callToken);
1282    ret = ooSendH245Msg(call, ph245msg);
1283    if(ret != OO_OK)
1284    {
1285       OOTRACEERR3("Error:Failed to enqueue RequestModeReject message"
1286                   " to outbound queue. (%s, %s)\n", call->callType, 
1287                   call->callToken);
1288    }
1289    
1290    ooFreeH245Message(call, ph245msg);
1291    return ret;
1292 }
1293
1294 int ooSendRequestMode(OOH323CallData* call,
1295                                       int isT38Mode)
1296 {
1297    int ret=0;
1298    H245RequestMessage *request;
1299    H245Message *ph245msg=NULL;
1300    OOCTXT *pctxt=call->msgctxt;
1301
1302
1303    H245ModeDescription pModeDesc;
1304    H245ModeElement pModeElem;
1305
1306    if (isT38Mode && !OO_TESTFLAG(call->flags, OO_M_T38SUPPORTED)) /* t38 req but we dont support */
1307         return OO_OK;
1308
1309    ret = ooCreateH245Message(call, &ph245msg, 
1310                       T_H245MultimediaSystemControlMessage_request);
1311    if(ret != OO_OK)
1312    {
1313       OOTRACEERR3("Error:H245 message creation failed for - RequstMode "
1314                   "(%s, %s)\n",call->callType, 
1315                   call->callToken);
1316       return OO_FAILED;
1317    }
1318    ph245msg->msgType = OORequestMode;
1319    request = ph245msg->h245Msg.u.request;
1320    memset(request, 0, sizeof(H245RequestMessage));
1321    request->t = T_H245RequestMessage_requestMode;
1322
1323    request->u.requestMode = (H245RequestMode *)
1324                    ASN1MALLOC(pctxt, sizeof(H245RequestMode));
1325    memset(request->u.requestMode, 0, 
1326                              sizeof(H245RequestMode));
1327
1328    call->requestSequence++;
1329    call->reqFlags = (isT38Mode) ? OO_M_DATASESSION : OO_M_AUDIOSESSION;
1330
1331    request->u.requestMode->sequenceNumber = call->requestSequence;
1332    memset(&pModeElem, 0, sizeof(pModeElem));
1333    memset(&pModeDesc, 0, sizeof(pModeDesc));
1334    dListInit(&(request->u.requestMode->requestedModes));
1335    dListInit(&pModeDesc);
1336
1337    if (isT38Mode) {
1338
1339         pModeElem.type.t = T_H245ModeElementType_dataMode;
1340         pModeElem.type.u.dataMode = (H245DataMode *) memAllocZ(pctxt, sizeof(H245DataMode));
1341         pModeElem.type.u.dataMode->bitRate = 144;
1342         if (!ooCreateT38ApplicationData(pctxt,&(pModeElem.type.u.dataMode->application))) {
1343                 OOTRACEERR3("Error:Memory - ooCapabilityCreateT38Capability - (%s, %s)\n",
1344                                                 call->callType, 
1345                                                 call->callToken);
1346         }
1347    } else {
1348         pModeElem.type.t = T_H245ModeElementType_audioMode;
1349         pModeElem.type.u.audioMode = (H245AudioMode *) memAllocZ(pctxt, sizeof(H245AudioMode));
1350         pModeElem.type.u.audioMode->t = T_H245AudioMode_genericAudioMode;
1351         pModeElem.type.u.audioMode->u.genericAudioMode = (H245GenericCapability *)
1352                                         memAllocZ(pctxt, sizeof(H245GenericCapability));
1353         pModeElem.type.u.audioMode->u.genericAudioMode->capabilityIdentifier.t =
1354                                          T_H245CapabilityIdentifier_domainBased;
1355         pModeElem.type.u.audioMode->u.genericAudioMode->capabilityIdentifier.u.domainBased =
1356                                          "H.323";
1357         pModeElem.type.u.audioMode->u.genericAudioMode->m.maxBitRatePresent = TRUE;
1358         pModeElem.type.u.audioMode->u.genericAudioMode->maxBitRate = 144;
1359    }
1360
1361    dListAppend(pctxt, &pModeDesc, &pModeElem);
1362    dListAppend(pctxt, &(request->u.requestMode->requestedModes), &pModeDesc);
1363
1364    ret = ooSendH245Msg(call, ph245msg);
1365    if(ret != OO_OK)
1366    {
1367       OOTRACEERR3("Error:Failed to enqueue RequestMode message"
1368                   " to outbound queue. (%s, %s)\n", call->callType, 
1369                   call->callToken);
1370    }
1371    
1372    ooFreeH245Message(call, ph245msg);
1373    return ret;
1374 }
1375
1376 void ooOnReceivedRequestModeAck(OOH323CallData* call, H245RequestModeAck * requestModeAck)
1377 {
1378         int t38mode;
1379
1380         if (!call->reqFlags) return;
1381
1382         if (OO_TESTFLAG(call->reqFlags, OO_M_AUDIOSESSION)) {
1383                 OO_SETFLAG(call->flags, OO_M_AUDIOSESSION);
1384                 OO_CLRFLAG(call->flags, OO_M_DATASESSION);
1385                 t38mode = 0;
1386         } else {
1387                 OO_CLRFLAG(call->flags, OO_M_AUDIOSESSION);
1388                 OO_SETFLAG(call->flags, OO_M_DATASESSION);
1389                 t38mode = 1;
1390         }
1391
1392         call->reqFlags = 0; /* don't handle duplicate ack packet */
1393
1394         ooCloseAllLogicalChannels(call, "transmit");
1395         if(gH323ep.h323Callbacks.onModeChanged) {
1396                 OOTRACEDBGA3("Handle RequestModeAck: (%s, %s), calling "
1397                         "callback onModeChanged\n", call->callType, call->callToken);
1398                 gH323ep.h323Callbacks.onModeChanged(call, t38mode);
1399         }
1400 }
1401
1402 int ooHandleRequestMode(OOH323CallData* call,
1403                                 H245RequestMode *requestMode)
1404 {
1405   
1406   H245ModeDescription** pModeRef;
1407   H245ModeElement** pModeElem;
1408   H245ModeElementType* pMode;
1409
1410   pModeRef = (H245ModeDescription**)dListFindByIndex(&requestMode->requestedModes, 0);
1411   pModeElem = (H245ModeElement **) dListFindByIndex(*pModeRef, 0);
1412   pMode = &((*pModeElem)->type);
1413   OOTRACEDBGA5("Handle RequestMode: "
1414                   " modetype: %d/%d for (%s, %s)\n", pMode->t, pMode->u.dataMode->application.t,
1415                   call->callType, 
1416                   call->callToken);
1417   switch (pMode->t) {
1418         case T_H245ModeElementType_dataMode:
1419                 if (pMode->u.dataMode->application.t == T_H245DataMode_application_t38fax &&
1420                     OO_TESTFLAG(call->flags, OO_M_T38SUPPORTED)) {
1421                         if (ooSendRequestModeAck(call, requestMode->sequenceNumber) == OO_OK &&
1422                                 OO_TESTFLAG(call->flags, OO_M_AUDIOSESSION)) {
1423
1424                                 OO_CLRFLAG(call->flags, OO_M_AUDIOSESSION);
1425                                 OO_SETFLAG(call->flags, OO_M_DATASESSION);
1426                                 if(gH323ep.h323Callbacks.onModeChanged) {
1427                                         OOTRACEDBGA3("Handle RequestMode: (%s, %s), calling "
1428                                         "callback onModeChanged\n", call->callType, call->callToken);
1429                                         gH323ep.h323Callbacks.onModeChanged(call, 1);
1430                                 }
1431                         }
1432                 } else {
1433                         ooSendRequestModeReject(call, requestMode->sequenceNumber);
1434                 }
1435                 break;
1436         case T_H245ModeElementType_audioMode:
1437                 if (ooSendRequestModeAck(call, requestMode->sequenceNumber) == OO_OK && 
1438                         OO_TESTFLAG(call->flags, OO_M_DATASESSION)) {
1439
1440                         OO_CLRFLAG(call->flags, OO_M_DATASESSION);
1441                         OO_SETFLAG(call->flags, OO_M_AUDIOSESSION);
1442                         if(gH323ep.h323Callbacks.onModeChanged) {
1443                                 OOTRACEDBGA3("Handle RequestMode: (%s, %s), calling "
1444                                 "callback onModeChanged\n", call->callType, call->callToken);
1445                                 gH323ep.h323Callbacks.onModeChanged(call, 0);
1446                         }
1447                 }
1448                 break;
1449         default:
1450                 ;
1451   }
1452   return OO_OK;
1453   
1454 }
1455
1456 int ooHandleOpenLogicalChannel(OOH323CallData* call, 
1457                                  H245OpenLogicalChannel *olc)
1458 {
1459
1460    H245OpenLogicalChannel_forwardLogicalChannelParameters *flcp =
1461     &(olc->forwardLogicalChannelParameters);
1462    
1463 #if 0
1464    if(!call->logicalChans)
1465       ooOpenLogicalChannels(call);
1466 #endif
1467
1468    /* Check whether channel type is supported. Only supported channel 
1469       type for now is g711ulaw audio channel.
1470    */
1471    switch(flcp->dataType.t)
1472    {
1473    case T_H245DataType_nonStandard:
1474       OOTRACEWARN3("Warn:Media channel data type "
1475                    "'T_H245DataType_nonStandard' not supported (%s, %s)\n",
1476                    call->callType, call->callToken);
1477       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1478              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1479       break;
1480    case T_H245DataType_nullData:
1481       OOTRACEWARN3("Warn:Media channel data type "
1482                    "'T_H245DataType_nullData' not supported (%s, %s)\n",
1483                    call->callType, call->callToken);
1484       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1485              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1486       break;
1487    case T_H245DataType_videoData:
1488    case T_H245DataType_audioData:
1489    case T_H245DataType_data:
1490       ooHandleOpenLogicalChannel_helper(call, olc);
1491       break;
1492    case T_H245DataType_encryptionData:
1493       OOTRACEWARN3("Warn:Media channel data type "
1494                    "'T_H245DataType_encryptionData' not supported (%s, %s)\n",
1495                    call->callType, call->callToken);
1496       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1497              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1498       break;
1499    case T_H245DataType_h235Control:
1500       OOTRACEWARN3("Warn:Media channel data type "
1501                    "'T_H245DataType_h235Control' not supported (%s, %s)\n",
1502                    call->callType, call->callToken);
1503       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1504              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1505       break;
1506    case T_H245DataType_h235Media:
1507       OOTRACEWARN3("Warn:Media channel data type "
1508                    "'T_H245DataType_h235Media' not supported (%s, %s)\n",
1509                    call->callType, call->callToken);
1510       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1511              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1512       break;
1513    case T_H245DataType_multiplexedStream:
1514       OOTRACEWARN3("Warn:Media channel data type "
1515                   "'T_H245DataType_multiplexedStream' not supported(%s, %s)\n",
1516                    call->callType, call->callToken);
1517       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1518              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1519       break;
1520    case T_H245DataType_redundancyEncoding:
1521       OOTRACEWARN3("Warn:Media channel data type "
1522                 "'T_H245DataType_redundancyEncoding' not supported (%s, %s)\n",
1523                   call->callType, call->callToken);
1524       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1525              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1526       break;
1527    case T_H245DataType_multiplePayloadStream:
1528       OOTRACEWARN3("Warn:Media channel data type "
1529              "'T_H245DataType_multiplePayloadStream' not supported (%s, %s)\n",
1530                    call->callType, call->callToken);
1531       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1532              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1533       break;
1534    case T_H245DataType_fec:
1535       OOTRACEWARN3("Warn:Media channel data type 'T_H245DataType_fec' not "
1536                    "supported (%s, %s)\n", call->callType, call->callToken);
1537       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1538              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1539       break;
1540    default:
1541       OOTRACEERR3("ERROR:Unknown media channel data type (%s, %s)\n", 
1542                    call->callType, call->callToken);
1543       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1544              T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1545    }
1546    
1547    return OO_OK;
1548 }       
1549
1550 /*TODO: Need to clean logical channel in case of failure after creating one */
1551 int ooHandleOpenLogicalChannel_helper(OOH323CallData *call, 
1552                                     H245OpenLogicalChannel*olc)
1553 {
1554    int ret=0;
1555    H245Message *ph245msg=NULL;
1556    H245ResponseMessage *response;
1557    H245OpenLogicalChannelAck *olcAck;
1558    ooH323EpCapability *epCap=NULL;
1559    H245H2250LogicalChannelAckParameters *h2250lcap=NULL;
1560    OOCTXT *pctxt;
1561    H245UnicastAddress *unicastAddrs, *unicastAddrs1;
1562    H245UnicastAddress_iPAddress *iPAddress, *iPAddress1;
1563    ooLogicalChannel *pLogicalChannel = NULL;
1564    H245H2250LogicalChannelParameters *h2250lcp=NULL;
1565    H245OpenLogicalChannel_forwardLogicalChannelParameters *flcp =
1566     &(olc->forwardLogicalChannelParameters);
1567
1568    if(!flcp || flcp->multiplexParameters.t != T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
1569    {
1570       OOTRACEERR3("Error:ooHandleOpenLogicalChannel_helper - invalid forward "
1571                  "logical channel parameters. (%s, %s)\n", call->callType, 
1572                  call->callToken);
1573       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1574           T_H245OpenLogicalChannelReject_cause_unspecified);
1575       return OO_FAILED;
1576    }
1577
1578    h2250lcp = flcp->multiplexParameters.u.h2250LogicalChannelParameters;
1579
1580    if(!(epCap=ooIsDataTypeSupported(call, &flcp->dataType, OORX)))
1581    {
1582       OOTRACEERR3("ERROR:HandleOpenLogicalChannel_helper - capability not "
1583                   "supported (%s, %s)\n", call->callType, call->callToken);
1584       ooSendOpenLogicalChannelReject(call, olc->forwardLogicalChannelNumber,
1585           T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported);
1586       return OO_FAILED;
1587    }
1588    /* Generate an Ack for the open channel request */
1589    ret = ooCreateH245Message(call, &ph245msg,
1590                              T_H245MultimediaSystemControlMessage_response);
1591    if(ret != OO_OK)
1592    {
1593       OOTRACEERR3("Error: H245 message creation failed for - "
1594                   "OpenLogicalChannel Ack (%s, %s)\n", call->callType, 
1595                   call->callToken);
1596       memFreePtr(call->pctxt, epCap);
1597       epCap = NULL;
1598       return OO_FAILED;
1599    }
1600
1601    ph245msg->msgType = OOOpenLogicalChannelAck;
1602    ph245msg->logicalChannelNo = olc->forwardLogicalChannelNumber;
1603    response = ph245msg->h245Msg.u.response;
1604    /* pctxt = &gH323ep.msgctxt; */
1605    pctxt = call->msgctxt;
1606    memset(response, 0, sizeof(H245ResponseMessage));
1607    response->t = T_H245ResponseMessage_openLogicalChannelAck;
1608    response->u.openLogicalChannelAck = (H245OpenLogicalChannelAck*)
1609                    memAlloc(pctxt, sizeof(H245OpenLogicalChannelAck));   
1610    olcAck = response->u.openLogicalChannelAck;
1611    memset(olcAck, 0, sizeof(H245OpenLogicalChannelAck));
1612    olcAck->forwardLogicalChannelNumber = olc->forwardLogicalChannelNumber;
1613
1614    olcAck->m.forwardMultiplexAckParametersPresent = 1;
1615    olcAck->forwardMultiplexAckParameters.t = 
1616      T_H245OpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters;
1617    olcAck->forwardMultiplexAckParameters.u.h2250LogicalChannelAckParameters = 
1618                       (H245H2250LogicalChannelAckParameters*)ASN1MALLOC(pctxt, 
1619                       sizeof(H245H2250LogicalChannelAckParameters));
1620    h2250lcap = 
1621       olcAck->forwardMultiplexAckParameters.u.h2250LogicalChannelAckParameters;
1622    memset(h2250lcap, 0, sizeof(H245H2250LogicalChannelAckParameters));
1623
1624    h2250lcap->m.mediaChannelPresent = 1;
1625    h2250lcap->m.mediaControlChannelPresent = 1;
1626    h2250lcap->m.sessionIDPresent = 1;
1627
1628    if(h2250lcp->sessionID == 0)
1629       h2250lcap->sessionID = ooCallGenerateSessionID(call, epCap->capType, "receive");
1630    else
1631       h2250lcap->sessionID = h2250lcp->sessionID;
1632    
1633    h2250lcap->mediaChannel.t = 
1634                          T_H245TransportAddress_unicastAddress;
1635    h2250lcap->mediaChannel.u.unicastAddress =  (H245UnicastAddress*)
1636                          ASN1MALLOC(pctxt, sizeof(H245UnicastAddress));
1637
1638    unicastAddrs = h2250lcap->mediaChannel.u.unicastAddress;
1639    memset(unicastAddrs, 0, sizeof(H245UnicastAddress));
1640    unicastAddrs->t = T_H245UnicastAddress_iPAddress;
1641    unicastAddrs->u.iPAddress = (H245UnicastAddress_iPAddress*)
1642                memAlloc(pctxt, sizeof(H245UnicastAddress_iPAddress));
1643    iPAddress = unicastAddrs->u.iPAddress;
1644    memset(iPAddress, 0, sizeof(H245UnicastAddress_iPAddress));
1645
1646    pLogicalChannel = ooAddNewLogicalChannel(call, 
1647                         olc->forwardLogicalChannelNumber, h2250lcap->sessionID,
1648                         "receive", epCap);
1649    if(!pLogicalChannel)
1650    {
1651       OOTRACEERR3("ERROR:Failed to add new logical channel entry to call " 
1652                   "(%s, %s)\n", call->callType, call->callToken);
1653       return OO_FAILED;
1654    }
1655    ooSocketConvertIpToNwAddr(call->localIP, iPAddress->network.data);
1656
1657    iPAddress->network.numocts = 4;
1658    iPAddress->tsapIdentifier = pLogicalChannel->localRtpPort;
1659
1660    /* media contrcol channel */
1661    h2250lcap->mediaControlChannel.t = 
1662                                  T_H245TransportAddress_unicastAddress;
1663    h2250lcap->mediaControlChannel.u.unicastAddress =  (H245UnicastAddress*)
1664                          ASN1MALLOC(pctxt, sizeof(H245UnicastAddress));
1665
1666    unicastAddrs1 = h2250lcap->mediaControlChannel.u.unicastAddress;
1667    memset(unicastAddrs1, 0, sizeof(H245UnicastAddress));
1668    unicastAddrs1->t = T_H245UnicastAddress_iPAddress;
1669    unicastAddrs1->u.iPAddress = (H245UnicastAddress_iPAddress*)
1670                memAlloc(pctxt, sizeof(H245UnicastAddress_iPAddress));
1671    iPAddress1 = unicastAddrs1->u.iPAddress;
1672    memset(iPAddress1, 0, sizeof(H245UnicastAddress_iPAddress));
1673
1674    ooSocketConvertIpToNwAddr(call->localIP, iPAddress1->network.data);
1675
1676    iPAddress1->network.numocts = 4;
1677    iPAddress1->tsapIdentifier = pLogicalChannel->localRtcpPort;
1678
1679    OOTRACEDBGA3("Built OpenLogicalChannelAck (%s, %s)\n", call->callType, 
1680                  call->callToken);
1681    ret = ooSendH245Msg(call, ph245msg);
1682    if(ret != OO_OK)
1683    {
1684       OOTRACEERR3("Error:Failed to enqueue OpenLogicalChannelAck message to "
1685                   "outbound queue. (%s, %s)\n", call->callType, 
1686                   call->callToken);
1687    }
1688    ooFreeH245Message(call, ph245msg);
1689
1690
1691    if(epCap->startReceiveChannel)
1692    {
1693       epCap->startReceiveChannel(call, pLogicalChannel);      
1694       OOTRACEINFO6("Receive channel of type %s started at %s:%d(%s, %s)\n", 
1695                     ooGetCapTypeText(epCap->cap), call->localIP, 
1696                     pLogicalChannel->localRtpPort, call->callType, 
1697                     call->callToken);
1698    }
1699    else{
1700       OOTRACEERR3("ERROR:No callback registered to start receive audio "
1701                   "channel (%s, %s)\n", call->callType, call->callToken);
1702       return OO_FAILED;
1703    }
1704    pLogicalChannel->state = OO_LOGICALCHAN_ESTABLISHED;
1705    return ret;
1706 }
1707
1708 int ooSendOpenLogicalChannelReject
1709    (OOH323CallData *call, ASN1UINT channelNum, ASN1UINT cause)
1710 {
1711    int ret=0;
1712    H245ResponseMessage* response=NULL;
1713    H245Message *ph245msg=NULL;
1714    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
1715    OOCTXT *pctxt=call->msgctxt;
1716
1717    ret = ooCreateH245Message
1718       (call, &ph245msg, T_H245MultimediaSystemControlMessage_response);
1719
1720    if (ret != OO_OK) {
1721       OOTRACEERR3("Error:H245 message creation failed for - OpenLogicalChannel"
1722                   "Reject (%s, %s)\n",call->callType, 
1723                   call->callToken);
1724       return OO_FAILED;
1725    }
1726    ph245msg->msgType = OOOpenLogicalChannelReject;
1727    response = ph245msg->h245Msg.u.response;
1728
1729    response->t = T_H245ResponseMessage_openLogicalChannelReject;
1730
1731    response->u.openLogicalChannelReject = 
1732       (H245OpenLogicalChannelReject*)
1733       memAlloc (pctxt, sizeof(H245OpenLogicalChannelReject));
1734
1735    if(!response->u.openLogicalChannelReject)
1736    {
1737       OOTRACEERR3("Error: Failed to allocate memory for OpenLogicalChannel"
1738                   "Reject message. (%s, %s)\n", call->callType, 
1739                   call->callToken);
1740       ooFreeH245Message(call, ph245msg);
1741       return OO_FAILED;
1742    }
1743    response->u.openLogicalChannelReject->forwardLogicalChannelNumber = 
1744                                                                  channelNum;
1745    response->u.openLogicalChannelReject->cause.t = cause;
1746
1747    OOTRACEDBGA3 ("Built OpenLogicalChannelReject (%s, %s)\n", 
1748                  call->callType, call->callToken);
1749
1750    ret = ooSendH245Msg (call, ph245msg);
1751
1752    if (ret != OO_OK) {
1753       OOTRACEERR3 
1754          ("Error:Failed to enqueue OpenLogicalChannelReject "
1755          "message to outbound queue.(%s, %s)\n", call->callType, 
1756          call->callToken);
1757    }
1758    
1759    ooFreeH245Message (call, ph245msg);
1760
1761    return ret;
1762 }
1763
1764
1765 int ooOnReceivedOpenLogicalChannelAck(OOH323CallData *call,
1766                                       H245OpenLogicalChannelAck *olcAck)
1767 {
1768    char remoteip[20];
1769    regmatch_t pmatch[1];
1770    ooLogicalChannel *pLogicalChannel;
1771    H245H2250LogicalChannelAckParameters *h2250lcap;
1772    H245UnicastAddress *unicastAddr;
1773    H245UnicastAddress_iPAddress *iPAddress;
1774    H245UnicastAddress *unicastAddr1;
1775    H245UnicastAddress_iPAddress *iPAddress1 = NULL;
1776
1777    if(!((olcAck->m.forwardMultiplexAckParametersPresent == 1) &&
1778         (olcAck->forwardMultiplexAckParameters.t == 
1779          T_H245OpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters)))
1780    {
1781       OOTRACEERR3("Error: Processing open logical channel ack - LogicalChannel"
1782                   "Ack parameters absent (%s, %s)\n", call->callType, 
1783                   call->callToken);
1784       return OO_OK;  /* should send CloseLogicalChannel request */
1785    }
1786
1787    h2250lcap = 
1788       olcAck->forwardMultiplexAckParameters.u.h2250LogicalChannelAckParameters;
1789    /* Extract media channel address */
1790    if(h2250lcap->m.mediaChannelPresent != 1)
1791    { 
1792       OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media channel "
1793                   "absent (%s, %s)\n", call->callType, call->callToken);
1794       return OO_FAILED;
1795    }
1796    if(h2250lcap->mediaChannel.t != T_H245TransportAddress_unicastAddress)
1797    {
1798       OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media channel "
1799                   "address type is not unicast (%s, %s)\n", call->callType, 
1800                   call->callToken);
1801       return OO_FAILED;
1802    }
1803    
1804    unicastAddr = h2250lcap->mediaChannel.u.unicastAddress;
1805    if(unicastAddr->t != T_H245UnicastAddress_iPAddress)
1806    {
1807       OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media channel "
1808                   "address type is not IP (%s, %s)\n", call->callType, 
1809                    call->callToken);
1810       return OO_FAILED;
1811    }
1812    iPAddress = unicastAddr->u.iPAddress;
1813    
1814    sprintf(remoteip,"%d.%d.%d.%d", iPAddress->network.data[0],
1815                                   iPAddress->network.data[1], 
1816                                   iPAddress->network.data[2], 
1817                                   iPAddress->network.data[3]);
1818    
1819    /* Extract media control channel address */
1820    if(h2250lcap->m.mediaControlChannelPresent == 1) {
1821         if(h2250lcap->mediaControlChannel.t != 
1822                                      T_H245TransportAddress_unicastAddress)
1823         {
1824          OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media control "
1825                   "channel addres type is not unicast (%s, %s)\n", 
1826                    call->callType, call->callToken);
1827          return OO_FAILED;
1828         }
1829    
1830         unicastAddr1 = h2250lcap->mediaControlChannel.u.unicastAddress;
1831         if(unicastAddr1->t != T_H245UnicastAddress_iPAddress) {
1832                 OOTRACEERR3("Error: Processing OpenLogicalChannelAck - media control "
1833                   "channel address type is not IP (%s, %s)\n", call->callType, 
1834                    call->callToken);
1835         return OO_FAILED;
1836         }
1837
1838         iPAddress1 = unicastAddr1->u.iPAddress;
1839    } else {
1840       OOTRACEDBGA3("Warning: Processing OpenLogicalChannelAck - Missing media "
1841                 "control channel (%s, %s)\n", call->callType, call->callToken);
1842    }
1843
1844    /* Set remote destination address for rtp session */
1845    //   strcpy(call->remoteIP, remoteip);
1846    
1847    /* Start channel here */
1848    pLogicalChannel = ooFindLogicalChannelByLogicalChannelNo(call,olcAck->forwardLogicalChannelNumber);
1849    if(!pLogicalChannel)
1850    {
1851       OOTRACEERR4("ERROR:Logical channel %d not found in the channel list for "
1852                   "call (%s, %s)\n", olcAck->forwardLogicalChannelNumber, 
1853                   call->callType, call->callToken);
1854       return OO_FAILED;
1855    }
1856
1857    /* Update session id if we were waiting for remote to assign one and remote 
1858       did assign one. */
1859    if(pLogicalChannel->sessionID == 0 && h2250lcap->m.sessionIDPresent)
1860       pLogicalChannel->sessionID = h2250lcap->sessionID;   
1861
1862    /* Populate ports &ip  for channel */
1863
1864    if (call->rtpMaskStr[0]) {
1865      if (regexec(&call->rtpMask->regex, remoteip, 1, pmatch, 0)) {
1866                 OOTRACEERR5("ERROR:H245 Address is not matched with filter %s/%s"
1867                         "(%s, %s)\n", remoteip, call->rtpMaskStr, call->callType, call->callToken);
1868          return OO_FAILED;
1869         }
1870    }
1871
1872    strcpy(pLogicalChannel->remoteIP, remoteip);   
1873    pLogicalChannel->remoteMediaPort = iPAddress->tsapIdentifier;
1874    if (iPAddress1)
1875         pLogicalChannel->remoteMediaControlPort = iPAddress1->tsapIdentifier;
1876
1877    if(pLogicalChannel->chanCap->startTransmitChannel)
1878    {
1879       pLogicalChannel->chanCap->startTransmitChannel(call, pLogicalChannel);
1880       OOTRACEINFO4("TransmitLogical Channel of type %s started (%s, %s)\n", 
1881                    ooGetCapTypeText(pLogicalChannel->chanCap->cap),
1882                    call->callType, call->callToken);
1883    }
1884    else{
1885       OOTRACEERR3("ERROR:No callback registered for starting transmit channel "
1886                   "(%s, %s)\n", call->callType, call->callToken);
1887       return OO_FAILED;
1888    }
1889    pLogicalChannel->state = OO_LOGICALCHAN_ESTABLISHED;
1890    return OO_OK;
1891 }
1892
1893 int ooOnReceivedOpenLogicalChannelRejected(OOH323CallData *call, 
1894                                      H245OpenLogicalChannelReject *olcReject)
1895 {
1896    switch(olcReject->cause.t)
1897    {
1898    case T_H245OpenLogicalChannelReject_cause_unspecified:
1899       OOTRACEINFO4("Open logical channel %d rejected - unspecified (%s, %s)\n",
1900                    olcReject->forwardLogicalChannelNumber, call->callType, 
1901                    call->callToken);
1902       break;
1903    case T_H245OpenLogicalChannelReject_cause_unsuitableReverseParameters:
1904       OOTRACEINFO4("Open logical channel %d rejected - "
1905                    "unsuitableReverseParameters (%s, %s)\n", 
1906                    olcReject->forwardLogicalChannelNumber, call->callType, 
1907                    call->callToken);
1908       break;
1909    case T_H245OpenLogicalChannelReject_cause_dataTypeNotSupported:
1910       OOTRACEINFO4("Open logical channel %d rejected - dataTypeNotSupported"
1911                    "(%s, %s)\n", olcReject->forwardLogicalChannelNumber, 
1912                    call->callType, call->callToken);
1913       break;
1914    case T_H245OpenLogicalChannelReject_cause_dataTypeNotAvailable:
1915       OOTRACEINFO4("Open logical channel %d rejected - dataTypeNotAvailable"
1916                    "(%s, %s)\n", olcReject->forwardLogicalChannelNumber, 
1917                    call->callType, call->callToken);
1918       break;
1919    case T_H245OpenLogicalChannelReject_cause_unknownDataType:
1920       OOTRACEINFO4("Open logical channel %d rejected - unknownDataType"
1921                    "(%s, %s)\n", olcReject->forwardLogicalChannelNumber, 
1922                    call->callType, call->callToken);
1923       break;
1924    case T_H245OpenLogicalChannelReject_cause_dataTypeALCombinationNotSupported:
1925       OOTRACEINFO4("Open logical channel %d rejected - "
1926                    "dataTypeALCombinationNotSupported(%s, %s)\n", 
1927                    olcReject->forwardLogicalChannelNumber, 
1928                    call->callType, call->callToken);
1929       break;
1930    case T_H245OpenLogicalChannelReject_cause_multicastChannelNotAllowed:
1931        OOTRACEINFO4("Open logical channel %d rejected - "
1932                     "multicastChannelNotAllowed (%s, %s)\n", 
1933                     olcReject->forwardLogicalChannelNumber, 
1934                     call->callType, call->callToken);
1935       break;
1936    case T_H245OpenLogicalChannelReject_cause_insufficientBandwidth:
1937       OOTRACEINFO4("Open logical channel %d rejected - insufficientBandwidth"
1938                    "(%s, %s)\n", olcReject->forwardLogicalChannelNumber, 
1939                    call->callType, call->callToken);
1940       break;
1941    case T_H245OpenLogicalChannelReject_cause_separateStackEstablishmentFailed:
1942       OOTRACEINFO4("Open logical channel %d rejected - "
1943                     "separateStackEstablishmentFailed (%s, %s)\n", 
1944                     olcReject->forwardLogicalChannelNumber, 
1945                     call->callType, call->callToken);
1946       break;
1947    case T_H245OpenLogicalChannelReject_cause_invalidSessionID:
1948       OOTRACEINFO4("Open logical channel %d rejected - "
1949                     "invalidSessionID (%s, %s)\n", 
1950                     olcReject->forwardLogicalChannelNumber, 
1951                     call->callType, call->callToken);
1952       break;
1953    case T_H245OpenLogicalChannelReject_cause_masterSlaveConflict:
1954       OOTRACEINFO4("Open logical channel %d rejected - "
1955                     "invalidSessionID (%s, %s)\n", 
1956                     olcReject->forwardLogicalChannelNumber, 
1957                     call->callType, call->callToken);
1958       break;
1959    case T_H245OpenLogicalChannelReject_cause_waitForCommunicationMode:
1960       OOTRACEINFO4("Open logical channel %d rejected - "
1961                     "waitForCommunicationMode (%s, %s)\n", 
1962                     olcReject->forwardLogicalChannelNumber, 
1963                     call->callType, call->callToken);
1964       break;
1965    case T_H245OpenLogicalChannelReject_cause_invalidDependentChannel:
1966       OOTRACEINFO4("Open logical channel %d rejected - "
1967                     "invalidDependentChannel (%s, %s)\n", 
1968                     olcReject->forwardLogicalChannelNumber, 
1969                     call->callType, call->callToken);
1970       break;
1971    case T_H245OpenLogicalChannelReject_cause_replacementForRejected:
1972       OOTRACEINFO4("Open logical channel %d rejected - "
1973                     "replacementForRejected (%s, %s)\n", 
1974                     olcReject->forwardLogicalChannelNumber, 
1975                     call->callType, call->callToken);
1976       break;
1977    default:
1978       OOTRACEERR4("Error: OpenLogicalChannel %d rejected - "
1979                   "invalid cause(%s, %s)\n",
1980                    olcReject->forwardLogicalChannelNumber, 
1981                     call->callType, call->callToken);
1982    }
1983    if(call->callState < OO_CALL_CLEAR)
1984    {
1985       call->callState = OO_CALL_CLEAR;
1986       call->callEndReason = OO_REASON_LOCAL_CLEARED;
1987    }
1988    return OO_OK;
1989 }
1990
1991 /**
1992  * Currently only disconnect end session command is supported.
1993  **/
1994 int ooSendEndSessionCommand(OOH323CallData *call)
1995 {
1996    int ret;
1997    H245CommandMessage * command;
1998    OOCTXT *pctxt;
1999    H245Message *ph245msg=NULL;
2000    ret = ooCreateH245Message(call, &ph245msg, 
2001                       T_H245MultimediaSystemControlMessage_command);
2002    if(ret != OO_OK)
2003    {
2004       OOTRACEERR3("Error: H245 message creation failed for - End Session "
2005                   "Command (%s, %s)\n", call->callType, call->callToken);
2006       return OO_FAILED;
2007    }
2008    ph245msg->msgType = OOEndSessionCommand;
2009
2010    command = ph245msg->h245Msg.u.command;
2011    /* pctxt = &gH323ep.msgctxt; */
2012    pctxt = call->msgctxt;
2013    memset(command, 0, sizeof(H245CommandMessage));
2014    command->t = T_H245CommandMessage_endSessionCommand;
2015    command->u.endSessionCommand = (H245EndSessionCommand*) ASN1MALLOC(pctxt,
2016                                   sizeof(H245EndSessionCommand));
2017    memset(command->u.endSessionCommand, 0, sizeof(H245EndSessionCommand));
2018    command->u.endSessionCommand->t = T_H245EndSessionCommand_disconnect;
2019    OOTRACEDBGA3("Built EndSession Command (%s, %s)\n", call->callType,
2020                 call->callToken);
2021    ret = ooSendH245Msg(call, ph245msg);
2022    if(ret != OO_OK)
2023    {
2024       OOTRACEERR3("Error:Failed to enqueue EndSession message to outbound "
2025                   "queue.(%s, %s)\n", call->callType, call->callToken);
2026    }
2027    ooFreeH245Message(call, ph245msg);
2028    return ret;
2029 }
2030
2031
2032 int ooHandleH245Command(OOH323CallData *call, 
2033                         H245CommandMessage *command)
2034 {
2035    ASN1UINT i;
2036    DListNode *pNode = NULL;
2037    OOTimer *pTimer = NULL;
2038    OOTRACEDBGC3("Handling H.245 command message. (%s, %s)\n", call->callType,
2039                  call->callToken);
2040    switch(command->t)
2041    {
2042       case T_H245CommandMessage_endSessionCommand:
2043          OOTRACEINFO3("Received EndSession command (%s, %s)\n", 
2044                        call->callType, call->callToken);
2045          if(call->h245SessionState == OO_H245SESSION_ENDSENT)
2046          {
2047             /* Disable Session timer */
2048             for(i = 0; i<call->timerList.count; i++)
2049             {
2050                pNode = dListFindByIndex(&call->timerList, i);
2051                pTimer = (OOTimer*)pNode->data;
2052                if(((ooTimerCallback*)pTimer->cbData)->timerType & 
2053                                                             OO_SESSION_TIMER)
2054                {
2055                   ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2056                   ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2057                   OOTRACEDBGC3("Deleted Session Timer. (%s, %s)\n", 
2058                                 call->callType, call->callToken);
2059                   break;
2060                }
2061             }
2062             ooCloseH245Connection(call);
2063             if (call->callState < OO_CALL_CLEAR)
2064                 call->callState = OO_CALL_CLEAR;
2065          }
2066          else{
2067
2068             call->h245SessionState = OO_H245SESSION_ENDRECVD;
2069             if(call->logicalChans)
2070             {
2071                OOTRACEINFO3("In response to received EndSessionCommand - "
2072                             "Clearing all logical channels. (%s, %s)\n", 
2073                             call->callType, call->callToken);
2074                ooClearAllLogicalChannels(call);
2075             }
2076             ooSendEndSessionCommand(call);
2077          }
2078             
2079             
2080          break;
2081       case T_H245CommandMessage_sendTerminalCapabilitySet:
2082          OOTRACEWARN3("Warning: Received command Send terminal capability set "
2083                       "- Not handled (%s, %s)\n", call->callType, 
2084                       call->callToken);
2085          break;
2086       case T_H245CommandMessage_flowControlCommand:
2087          OOTRACEWARN3("Warning: Flow control command received - Not handled "
2088                       "(%s, %s)\n", call->callType, call->callToken);
2089          break;
2090       default:
2091          OOTRACEWARN3("Warning: Unhandled H245 command message received "
2092                       "(%s, %s)\n", call->callType, call->callToken);
2093    }
2094    OOTRACEDBGC3("Handling H.245 command message done. (%s, %s)\n", 
2095                  call->callType, call->callToken);   
2096    return OO_OK;
2097 }
2098
2099
2100 int ooOnReceivedTerminalCapabilitySetAck(OOH323CallData* call)
2101 {
2102    int ret = OO_OK;
2103    call->localTermCapState = OO_LocalTermCapSetAckRecvd;
2104    if(call->remoteTermCapState != OO_RemoteTermCapSetAckSent)
2105       return OO_OK;
2106    
2107    if(call->masterSlaveState == OO_MasterSlave_Idle) {
2108       ret = ooSendMasterSlaveDetermination(call);
2109       if(ret != OO_OK) {
2110                 OOTRACEERR3("ERROR:Sending Master-slave determination message "
2111                             "(%s, %s)\n", call->callType, call->callToken);
2112                 return ret;
2113       }
2114    } 
2115
2116    if((call->masterSlaveState == OO_MasterSlave_Master ||
2117        call->masterSlaveState == OO_MasterSlave_Slave) &&
2118        (call->msAckStatus == OO_msAck_remoteReceived))
2119    {
2120       if(gH323ep.h323Callbacks.openLogicalChannels)
2121          gH323ep.h323Callbacks.openLogicalChannels(call);
2122       if(!ooGetTransmitLogicalChannel(call))
2123          ooOpenLogicalChannels(call);
2124 #if 0
2125       if(!call->logicalChans){
2126          if(!gH323ep.h323Callbacks.openLogicalChannels)
2127             ooOpenLogicalChannels(call);
2128          else
2129             gH323ep.h323Callbacks.openLogicalChannels(call);
2130       }
2131 #endif
2132    }
2133       
2134    return OO_OK;
2135 }
2136
2137 int ooCloseAllLogicalChannels(OOH323CallData *call, char* dir)
2138 {
2139    ooLogicalChannel *temp;
2140
2141    temp = call->logicalChans;
2142    while(temp)
2143    {
2144       if(temp->state == OO_LOGICALCHAN_ESTABLISHED && 
2145         (dir == NULL || !strcmp(temp->dir,dir)))
2146       {
2147          /* Sending closelogicalchannel only for outgoing channels*/
2148          if(!strcmp(temp->dir, "transmit"))
2149          {
2150             ooSendCloseLogicalChannel(call, temp);
2151          }
2152          else{
2153             ooSendRequestCloseLogicalChannel(call, temp);
2154          }
2155       }
2156       temp = temp->next;
2157    }
2158    return OO_OK;
2159 }
2160
2161 int ooSendCloseLogicalChannel(OOH323CallData *call, ooLogicalChannel *logicalChan)
2162 {
2163    int ret = OO_OK, error=0;
2164    H245Message *ph245msg = NULL;
2165    OOCTXT *pctxt;
2166    H245RequestMessage *request;
2167    H245CloseLogicalChannel* clc;
2168    
2169    ret = ooCreateH245Message(call, &ph245msg, 
2170                              T_H245MultimediaSystemControlMessage_request);
2171    if(ret != OO_OK)
2172    {
2173       OOTRACEERR3("ERROR:Failed to create H245 message for closeLogicalChannel"
2174                   " message (%s, %s)\n", call->callType, call->callToken);
2175       return OO_FAILED;
2176    }
2177    ph245msg->msgType = OOCloseLogicalChannel;
2178    ph245msg->logicalChannelNo = logicalChan->channelNo;
2179    /* pctxt = &gH323ep.msgctxt; */
2180    pctxt = call->msgctxt;
2181    request = ph245msg->h245Msg.u.request;
2182
2183    request->t = T_H245RequestMessage_closeLogicalChannel;
2184    request->u.closeLogicalChannel = (H245CloseLogicalChannel*)ASN1MALLOC(pctxt,
2185                                      sizeof(H245CloseLogicalChannel));
2186    if(!request->u.closeLogicalChannel)
2187    {
2188       OOTRACEERR3("ERROR:Memory allocation for CloseLogicalChannel failed "
2189                   "(%s, %s)\n", call->callType, call->callToken);
2190       ooFreeH245Message(call, ph245msg);
2191       return OO_FAILED;
2192    }
2193    clc = request->u.closeLogicalChannel;
2194    memset(clc, 0, sizeof(H245CloseLogicalChannel));
2195
2196    clc->forwardLogicalChannelNumber = logicalChan->channelNo;
2197    clc->source.t = T_H245CloseLogicalChannel_source_lcse;
2198    clc->m.reasonPresent = 1;
2199    clc->reason.t = T_H245CloseLogicalChannel_reason_unknown;
2200
2201    OOTRACEDBGA4("Built close logical channel for %d (%s, %s)\n", 
2202                  logicalChan->channelNo, call->callType, call->callToken);
2203    ret = ooSendH245Msg(call, ph245msg);
2204    if(ret != OO_OK)
2205    {
2206      OOTRACEERR3("Error:Failed to enqueue CloseLogicalChannel to outbound queue.(%s, %s)\n", call->callType,
2207                  call->callToken);
2208      error++;
2209    }
2210    ooFreeH245Message(call, ph245msg);
2211    
2212    /* Stop the media transmission */
2213    OOTRACEINFO4("Closing logical channel %d (%s, %s)\n", 
2214                 clc->forwardLogicalChannelNumber, call->callType, 
2215                 call->callToken);
2216    ret = ooClearLogicalChannel(call, clc->forwardLogicalChannelNumber);
2217    if(ret != OO_OK)
2218    {
2219       OOTRACEERR4("ERROR:Failed to close logical channel %d (%s, %s)\n",
2220          clc->forwardLogicalChannelNumber, call->callType, call->callToken);
2221       return OO_FAILED;
2222    }
2223    if(error) return OO_FAILED;
2224    return ret;
2225 }
2226
2227 /*TODO: Need to pass reason as a parameter */
2228 int ooSendRequestCloseLogicalChannel(OOH323CallData *call, 
2229                                      ooLogicalChannel *logicalChan)
2230 {
2231    int ret = OO_OK;
2232    H245Message *ph245msg = NULL;
2233    OOCTXT *pctxt;
2234    H245RequestMessage *request;
2235    H245RequestChannelClose *rclc;
2236
2237    ret = ooCreateH245Message(call, &ph245msg, 
2238                              T_H245MultimediaSystemControlMessage_request);
2239    if(ret != OO_OK)
2240    {
2241       OOTRACEERR3("ERROR:Failed to create H245 message for "
2242                   "requestCloseLogicalChannel message (%s, %s)\n", 
2243                    call->callType, call->callToken);
2244       return OO_FAILED;
2245    }
2246    ph245msg->msgType = OORequestChannelClose;
2247    ph245msg->logicalChannelNo = logicalChan->channelNo;
2248    /* pctxt = &gH323ep.msgctxt; */
2249    pctxt = call->msgctxt;
2250    request = ph245msg->h245Msg.u.request;
2251
2252    request->t = T_H245RequestMessage_requestChannelClose;
2253    request->u.requestChannelClose = (H245RequestChannelClose*)ASN1MALLOC(pctxt,
2254                                      sizeof(H245RequestChannelClose));
2255    if(!request->u.requestChannelClose)
2256    {
2257       OOTRACEERR3("ERROR:Memory allocation for RequestCloseLogicalChannel "
2258                   " failed (%s, %s)\n", call->callType, call->callToken);
2259       ooFreeH245Message(call, ph245msg);
2260       return OO_FAILED;
2261    }
2262
2263    rclc = request->u.requestChannelClose;
2264    memset(rclc, 0, sizeof(H245RequestChannelClose));
2265    rclc->forwardLogicalChannelNumber = logicalChan->channelNo;
2266    
2267    rclc->m.reasonPresent = 1;
2268    rclc->reason.t = T_H245RequestChannelClose_reason_unknown;
2269
2270    OOTRACEDBGA4("Built RequestCloseChannel for %d (%s, %s)\n", 
2271                  logicalChan->channelNo, call->callType, call->callToken);
2272    ret = ooSendH245Msg(call, ph245msg);
2273    if(ret != OO_OK)
2274    {
2275      OOTRACEERR3("Error:Failed to enqueue the RequestCloseChannel to outbound"
2276                  " queue (%s, %s)\n", call->callType,
2277                  call->callToken);
2278    }
2279    ooFreeH245Message(call, ph245msg);
2280
2281    return ret;
2282 }
2283
2284 int ooSendRequestChannelCloseRelease(OOH323CallData *call, int channelNum)
2285 {
2286    int ret = OO_OK;
2287    H245Message *ph245msg = NULL;
2288    OOCTXT *pctxt;
2289    H245IndicationMessage *indication;
2290
2291    ret = ooCreateH245Message(call, &ph245msg, 
2292                              T_H245MultimediaSystemControlMessage_indication);
2293    if(ret != OO_OK)
2294    {
2295       OOTRACEERR3("ERROR:Failed to create H245 message for "
2296                   "RequestChannelCloseRelease message (%s, %s)\n", 
2297                    call->callType, call->callToken);
2298       return OO_FAILED;
2299    }
2300    ph245msg->msgType = OORequestChannelCloseRelease;
2301    ph245msg->logicalChannelNo = channelNum;
2302    /* pctxt = &gH323ep.msgctxt; */
2303    pctxt = call->msgctxt;
2304    indication = ph245msg->h245Msg.u.indication;
2305    indication->t = T_H245IndicationMessage_requestChannelCloseRelease;
2306    indication->u.requestChannelCloseRelease = (H245RequestChannelCloseRelease*)
2307                      ASN1MALLOC(pctxt, sizeof(H245RequestChannelCloseRelease));
2308    if(!indication->u.requestChannelCloseRelease)
2309    {
2310       OOTRACEERR3("Error:Failed to allocate memory for "
2311                   "RequestChannelCloseRelease message. (%s, %s)\n", 
2312                    call->callType, call->callToken);
2313       ooFreeH245Message(call, ph245msg);
2314    }
2315
2316    indication->u.requestChannelCloseRelease->forwardLogicalChannelNumber = 
2317                                                                 channelNum;
2318
2319    OOTRACEDBGA4("Built RequestChannelCloseRelease for %d (%s, %s)\n", 
2320                 channelNum, call->callType, call->callToken);
2321    ret = ooSendH245Msg(call, ph245msg);
2322    if(ret != OO_OK)
2323    {
2324      OOTRACEERR3("Error:Failed to enqueue the RequestChannelCloseRelease to "
2325                  "outbound queue (%s, %s)\n", call->callType, call->callToken);
2326    }
2327    ooFreeH245Message(call, ph245msg);
2328
2329    return ret;
2330 }
2331
2332
2333    
2334 int ooOnReceivedRequestChannelClose(OOH323CallData *call, 
2335                                     H245RequestChannelClose *rclc)
2336 {
2337    int ret=0, error=0;
2338    H245Message *ph245msg=NULL;
2339    H245ResponseMessage *response = NULL;
2340    OOCTXT *pctxt=NULL;
2341    H245RequestChannelCloseAck *rclcAck;
2342    ooLogicalChannel * lChannel=NULL;
2343    /* Send Ack: TODO: Need to send reject, if doesn't exist
2344    */
2345    lChannel = ooFindLogicalChannelByLogicalChannelNo(call, 
2346                                         rclc->forwardLogicalChannelNumber);
2347    if(!lChannel)
2348    {
2349       OOTRACEERR4("ERROR:Channel %d requested to be closed not found "
2350                   "(%s, %s)\n", rclc->forwardLogicalChannelNumber,
2351                   call->callType, call->callToken);
2352       return OO_FAILED;
2353    }
2354    else{
2355       if(strcmp(lChannel->dir, "transmit"))
2356       {
2357          OOTRACEERR4("ERROR:Channel %d requested to be closed, Not a forward "
2358                      "channel (%s, %s)\n", rclc->forwardLogicalChannelNumber,
2359                      call->callType, call->callToken);
2360          return OO_FAILED;
2361       }
2362    }
2363    ret = ooCreateH245Message(call, &ph245msg, 
2364                              T_H245MultimediaSystemControlMessage_response);
2365    if(ret != OO_OK)
2366    {
2367       OOTRACEERR3("ERROR:Memory allocation for RequestChannelCloseAck message "
2368                   "failed (%s, %s)\n", call->callType, call->callToken);
2369       return OO_FAILED;
2370    }
2371    /* pctxt = &gH323ep.msgctxt; */
2372    pctxt = call->msgctxt;
2373    ph245msg->msgType = OORequestChannelCloseAck;
2374    ph245msg->logicalChannelNo = rclc->forwardLogicalChannelNumber;
2375    response = ph245msg->h245Msg.u.response;
2376    response->t = T_H245ResponseMessage_requestChannelCloseAck;
2377    response->u.requestChannelCloseAck = (H245RequestChannelCloseAck*)ASN1MALLOC
2378                                    (pctxt, sizeof(H245RequestChannelCloseAck));
2379    if(!response->u.requestChannelCloseAck)
2380    {
2381       OOTRACEERR3("ERROR:Failed to allocate memory for RequestChannelCloseAck "
2382                   "message (%s, %s)\n", call->callType, call->callToken);
2383       return OO_FAILED;
2384    }
2385    rclcAck = response->u.requestChannelCloseAck;
2386    memset(rclcAck, 0, sizeof(H245RequestChannelCloseAck));
2387    rclcAck->forwardLogicalChannelNumber = rclc->forwardLogicalChannelNumber;
2388
2389    OOTRACEDBGA3("Built RequestCloseChannelAck message (%s, %s)\n", 
2390                  call->callType, call->callToken);
2391    ret = ooSendH245Msg(call, ph245msg);
2392    if(ret != OO_OK)
2393    {
2394       OOTRACEERR3("Error:Failed to enqueue RequestCloseChannelAck to outbound queue. (%s, %s)\n", call->callType,
2395                   call->callToken);
2396       error++;
2397    }
2398
2399    ooFreeH245Message(call, ph245msg);
2400    
2401    /* Send Close Logical Channel*/
2402    ret = ooSendCloseLogicalChannel(call, lChannel);
2403    if(ret != OO_OK)
2404    {
2405       OOTRACEERR3("ERROR:Failed to build CloseLgicalChannel message(%s, %s)\n",
2406                    call->callType, call->callToken);
2407       return OO_FAILED;
2408    }
2409
2410    if(error) return OO_FAILED;
2411
2412    return ret;
2413 }
2414
2415 int ooSendRoundTripDelayRequest(OOH323CallData *call)
2416 {
2417    int ret=0;
2418    H245Message *ph245msg=NULL;
2419    H245RequestMessage *request = NULL;
2420    OOCTXT *pctxt=NULL;
2421    H245RoundTripDelayRequest *rtdr;
2422    ooTimerCallback *cbData=NULL;
2423
2424    if (call->rtdrSend > call->rtdrRecv + call->rtdrCount) {
2425         if(call->callState < OO_CALL_CLEAR) {
2426                 call->callState = OO_CALL_CLEAR;
2427                 call->callEndReason = OO_REASON_UNKNOWN;
2428                 call->q931cause = Q931RecoveryOnTimerExpiry;
2429         }
2430         return OO_FAILED;
2431    }
2432    
2433    ret = ooCreateH245Message(call, &ph245msg, 
2434                              T_H245MultimediaSystemControlMessage_request);
2435    if(ret != OO_OK)
2436    {
2437       OOTRACEERR3("ERROR:Memory allocation for RoundTripDelayResponse message "
2438                   "failed (%s, %s)\n", call->callType, call->callToken);
2439       return OO_FAILED;
2440    }
2441
2442    pctxt = call->msgctxt;
2443    ph245msg->msgType = OORequestDelayRequest;
2444    request = ph245msg->h245Msg.u.request;
2445    request->t = T_H245RequestMessage_roundTripDelayRequest;
2446    request->u.roundTripDelayRequest = (H245RoundTripDelayRequest *)ASN1MALLOC
2447                                    (pctxt, sizeof(H245RoundTripDelayRequest));
2448    if(!request->u.roundTripDelayRequest)
2449    {
2450       OOTRACEERR3("ERROR:Failed to allocate memory for H245RoundTripDelayRequest "
2451                   "message (%s, %s)\n", call->callType, call->callToken);
2452       return OO_FAILED;
2453    }
2454    rtdr = request->u.roundTripDelayRequest;
2455    memset(rtdr, 0, sizeof(H245RoundTripDelayRequest));
2456    rtdr->sequenceNumber = ++call->rtdrSend;
2457
2458    OOTRACEDBGA3("Built RoundTripDelayRequest message (%s, %s)\n", 
2459                  call->callType, call->callToken);
2460    ret = ooSendH245Msg(call, ph245msg);
2461    if(ret != OO_OK)
2462    {
2463       OOTRACEERR3("Error:Failed to enqueue RoundTripDelayRequest to outbound queue. (%s, %s)\n",
2464         call->callType, call->callToken);
2465       return OO_FAILED;
2466    } else {
2467       cbData = (ooTimerCallback*) memAlloc(call->pctxt,
2468                                      sizeof(ooTimerCallback));
2469       if(!cbData)
2470       {
2471          OOTRACEERR3("Error:Unable to allocate memory for timer callback data."
2472                      "(%s, %s)\n", call->callType, call->callToken);
2473          return OO_FAILED;
2474       }
2475       cbData->call = call;
2476       cbData->timerType = OO_RTD_TIMER;
2477       if(!ooTimerCreate(call->pctxt, &call->timerList, &ooRTDTimerExpired,
2478                         call->rtdrInterval, cbData, FALSE))
2479       {
2480          OOTRACEERR3("Error:Unable to create RTDR timer. "
2481                      "(%s, %s)\n", call->callType, call->callToken);
2482          memFreePtr(call->pctxt, cbData);
2483          return OO_FAILED;
2484       }
2485
2486    }
2487
2488    ooFreeH245Message(call, ph245msg);
2489
2490    return ret;
2491 }
2492
2493 int ooOnReceivedRoundTripDelayRequest(OOH323CallData *call, 
2494                                      H245SequenceNumber sequenceNumber)
2495 {
2496    int ret=0;
2497    H245Message *ph245msg=NULL;
2498    H245ResponseMessage *response = NULL;
2499    OOCTXT *pctxt=NULL;
2500    H245RoundTripDelayResponse *rtdr;
2501
2502    ret = ooCreateH245Message(call, &ph245msg, 
2503                              T_H245MultimediaSystemControlMessage_response);
2504    if(ret != OO_OK)
2505    {
2506       OOTRACEERR3("ERROR:Memory allocation for RoundTripDelayResponse message "
2507                   "failed (%s, %s)\n", call->callType, call->callToken);
2508       return OO_FAILED;
2509    }
2510
2511    pctxt = call->msgctxt;
2512    ph245msg->msgType = OORequestDelayResponse;
2513    response = ph245msg->h245Msg.u.response;
2514    response->t = T_H245ResponseMessage_roundTripDelayResponse;
2515    response->u.roundTripDelayResponse = (H245RoundTripDelayResponse *)ASN1MALLOC
2516                                    (pctxt, sizeof(H245RoundTripDelayResponse));
2517    if(!response->u.roundTripDelayResponse)
2518    {
2519       OOTRACEERR3("ERROR:Failed to allocate memory for H245RoundTripDelayResponse "
2520                   "message (%s, %s)\n", call->callType, call->callToken);
2521       return OO_FAILED;
2522    }
2523    rtdr = response->u.roundTripDelayResponse;
2524    memset(rtdr, 0, sizeof(H245RoundTripDelayResponse));
2525    rtdr->sequenceNumber = sequenceNumber;
2526
2527    OOTRACEDBGA3("Built RoundTripDelayResponse message (%s, %s)\n", 
2528                  call->callType, call->callToken);
2529    ret = ooSendH245Msg(call, ph245msg);
2530    if(ret != OO_OK)
2531    {
2532       OOTRACEERR3("Error:Failed to enqueue RoundTripDelayResponse to outbound queue. (%s, %s)\n",
2533         call->callType, call->callToken);
2534    }
2535
2536    ooFreeH245Message(call, ph245msg);
2537    
2538    return ret;
2539 }
2540
2541 /*
2542   We clear channel here. Ideally the remote endpoint should send 
2543   CloseLogicalChannel and then the channel should be cleared. But there's no
2544   timer for this and if remote endpoint misbehaves, the call will keep waiting
2545   for CloseLogicalChannel and hence, wouldn't be cleared. In case when remote
2546   endpoint sends CloseLogicalChannel, we call ooClearLogicalChannel again,
2547   which simply returns OO_OK as channel was already cleared. Other option is
2548   to start a timer for call cleanup and if call is not cleaned up within 
2549   timeout, we clean call forcefully. Note, no such timer is defined in 
2550   standards.
2551 */
2552 int ooOnReceivedRequestChannelCloseAck
2553                        (OOH323CallData *call, H245RequestChannelCloseAck *rccAck)
2554 {
2555    int ret=OO_OK;
2556    /* Remote endpoint is ok to close channel. So let's do it */
2557    ret = ooClearLogicalChannel(call, rccAck->forwardLogicalChannelNumber);
2558    if(ret != OO_OK)
2559    {
2560       OOTRACEERR4("Error:Failed to clear logical channel %d. (%s, %s)\n", 
2561                    rccAck->forwardLogicalChannelNumber, call->callType, 
2562                    call->callToken);
2563    }
2564
2565    return ret;
2566 }
2567
2568 int ooOnReceivedRequestChannelCloseReject
2569    (OOH323CallData *call, H245RequestChannelCloseReject *rccReject)
2570 {
2571    int ret =0;
2572    switch(rccReject->cause.t)
2573    {
2574    case T_H245RequestChannelCloseReject_cause_unspecified:
2575       OOTRACEDBGA4("Remote endpoint has rejected request to close logical "
2576                    "channel %d - cause unspecified. (%s, %s)\n", 
2577                    rccReject->forwardLogicalChannelNumber, call->callType, 
2578                    call->callToken);
2579      break;
2580    case T_H245RequestChannelCloseReject_cause_extElem1:
2581       OOTRACEDBGA4("Remote endpoint has rejected request to close logical "
2582                    "channel %d - cause propriatory. (%s, %s)\n", 
2583                    rccReject->forwardLogicalChannelNumber, call->callType, 
2584                    call->callToken);   
2585       break;
2586    default:
2587       OOTRACEDBGA4("Remote endpoint has rejected request to close logical "
2588                    "channel %d - cause INVALID. (%s, %s)\n", 
2589                    rccReject->forwardLogicalChannelNumber, call->callType, 
2590                    call->callToken);
2591    }
2592    OOTRACEDBGA4("Clearing logical channel %d. (%s, %s)\n", 
2593                  rccReject->forwardLogicalChannelNumber, call->callType, 
2594                  call->callToken);
2595    ret = ooClearLogicalChannel(call, rccReject->forwardLogicalChannelNumber);
2596    if(ret != OO_OK)
2597    {
2598       OOTRACEERR4("Error: failed to clear logical channel %d.(%s, %s)\n", 
2599                    rccReject->forwardLogicalChannelNumber, call->callType, 
2600                    call->callToken);
2601    }
2602    return ret;
2603 }
2604
2605 /****/
2606 int ooOnReceivedCloseLogicalChannel(OOH323CallData *call, 
2607                                     H245CloseLogicalChannel* clc)
2608 {
2609    int ret=0;
2610    H245Message *ph245msg = NULL;
2611    OOCTXT *pctxt = NULL;
2612    H245CloseLogicalChannelAck * clcAck;
2613    H245ResponseMessage *response;
2614    
2615    OOTRACEINFO4("Closing logical channel number %d (%s, %s)\n",
2616       clc->forwardLogicalChannelNumber, call->callType, call->callToken);
2617    
2618    ret = ooClearLogicalChannel(call, clc->forwardLogicalChannelNumber);
2619    if(ret != OO_OK)
2620    {
2621       OOTRACEERR4("ERROR:Failed to close logical channel %d (%s, %s)\n",
2622          clc->forwardLogicalChannelNumber, call->callType, call->callToken);
2623       return OO_FAILED;
2624    }
2625
2626    ret = ooCreateH245Message(call, &ph245msg, 
2627                               T_H245MultimediaSystemControlMessage_response);
2628    if(ret != OO_OK)
2629    {
2630       OOTRACEERR3("ERROR:Failed to create H245 message for "
2631                   "closeLogicalChannelAck (%s, %s)\n", call->callType, 
2632                   call->callToken);
2633       return OO_FAILED;
2634    }
2635    /* pctxt = &gH323ep.msgctxt; */
2636    pctxt = call->msgctxt;
2637    ph245msg->msgType = OOCloseLogicalChannelAck;
2638    ph245msg->logicalChannelNo = clc->forwardLogicalChannelNumber;
2639    response = ph245msg->h245Msg.u.response;
2640    response->t = T_H245ResponseMessage_closeLogicalChannelAck;
2641    response->u.closeLogicalChannelAck = (H245CloseLogicalChannelAck*)
2642                          ASN1MALLOC(pctxt, sizeof(H245CloseLogicalChannelAck));
2643    clcAck = response->u.closeLogicalChannelAck;
2644    if(!clcAck)
2645    {
2646       OOTRACEERR3("ERROR:Failed to allocate memory for closeLogicalChannelAck "
2647                   "(%s, %s)\n", call->callType, call->callToken);
2648       return OO_OK;
2649    }
2650    memset(clcAck, 0, sizeof(H245CloseLogicalChannelAck));
2651    clcAck->forwardLogicalChannelNumber = clc->forwardLogicalChannelNumber;
2652
2653    OOTRACEDBGA3("Built CloseLogicalChannelAck message (%s, %s)\n",
2654                  call->callType, call->callToken);
2655    ret = ooSendH245Msg(call, ph245msg);
2656    if(ret != OO_OK)
2657    {
2658      OOTRACEERR3("Error:Failed to enqueue CloseLogicalChannelAck message to "
2659                  "outbound queue.(%s, %s)\n", call->callType, call->callToken);
2660    }
2661
2662    ooFreeH245Message(call, ph245msg);
2663    return ret;
2664 }
2665
2666 int ooOnReceivedCloseChannelAck(OOH323CallData* call, 
2667                                 H245CloseLogicalChannelAck* clcAck)
2668 {
2669    int ret = OO_OK;
2670    return ret;
2671 }
2672
2673 int ooHandleH245Message(OOH323CallData *call, H245Message * pmsg)
2674 {
2675    ASN1UINT i;
2676    DListNode *pNode = NULL;
2677    OOTimer *pTimer = NULL;
2678    H245Message *pH245 = (H245Message*)pmsg;
2679    /* There are four major types of H.245 messages that can be received.
2680       Request/Response/Command/Indication. Each one of them need to be 
2681       handled separately.
2682    */   
2683    H245RequestMessage *request = NULL;
2684    H245ResponseMessage *response = NULL;
2685    H245CommandMessage *command = NULL;
2686    H245IndicationMessage *indication = NULL;
2687    
2688    OOTRACEDBGC3("Handling H245 message. (%s, %s)\n", call->callType, 
2689                  call->callToken);
2690    
2691    switch(pH245->h245Msg.t)
2692    {
2693       /* H.245 Request message is received */
2694       case (T_H245MultimediaSystemControlMessage_request):
2695          request = pH245->h245Msg.u.request;
2696          switch(request->t)
2697          {
2698             case T_H245RequestMessage_terminalCapabilitySet:
2699                /* If session isn't marked active yet, do it. possible in case of 
2700                   tunneling */
2701                if(call->h245SessionState == OO_H245SESSION_IDLE)
2702                   call->h245SessionState = OO_H245SESSION_ACTIVE; 
2703
2704                ooOnReceivedTerminalCapabilitySet(call, pH245);
2705                if(call->localTermCapState == OO_LocalTermCapExchange_Idle)
2706                   ooSendTermCapMsg(call);
2707                break;
2708             case T_H245RequestMessage_masterSlaveDetermination:
2709                ooHandleMasterSlave(call, 
2710                                      request->u.masterSlaveDetermination, 
2711                                      OOMasterSlaveDetermination);
2712                break;
2713             case T_H245RequestMessage_openLogicalChannel:
2714                ooHandleOpenLogicalChannel(call, 
2715                                           request->u.openLogicalChannel);
2716                 if(!ooGetTransmitLogicalChannel(call))
2717                         ooOpenLogicalChannels(call);
2718                break;
2719             case T_H245RequestMessage_requestMode:
2720                 OOTRACEINFO4("Received request mode - %d (%s, %s)\n",
2721                 request->u.requestMode->sequenceNumber, call->callType, call->callToken);
2722                ooHandleRequestMode(call, 
2723                                         request->u.requestMode);
2724                 break;
2725             case T_H245RequestMessage_closeLogicalChannel:
2726                OOTRACEINFO4("Received close logical Channel - %d (%s, %s)\n",
2727                   request->u.closeLogicalChannel->forwardLogicalChannelNumber, 
2728                   call->callType, call->callToken);
2729                if (ooOnReceivedCloseLogicalChannel(call, 
2730                                                request->u.closeLogicalChannel) == OO_OK) {
2731                         ooCloseAllLogicalChannels(call, NULL);
2732                }
2733                break;
2734             case T_H245RequestMessage_requestChannelClose:
2735                OOTRACEINFO4("Received RequestChannelClose - %d (%s, %s)\n",
2736                   request->u.requestChannelClose->forwardLogicalChannelNumber, 
2737                   call->callType, call->callToken);
2738                ooOnReceivedRequestChannelClose(call, 
2739                                                request->u.requestChannelClose);
2740                break;
2741              case T_H245RequestMessage_roundTripDelayRequest:
2742                OOTRACEINFO4("Received roundTripDelayRequest - %d (%s, %s)\n",
2743                   request->u.roundTripDelayRequest->sequenceNumber,  call->callType, call->callToken);
2744                ooOnReceivedRoundTripDelayRequest(call, request->u.roundTripDelayRequest->sequenceNumber);
2745                break;
2746             default:
2747                ;
2748          } /* End of Request Message */
2749          break;
2750       /* H.245 Response message is received */ 
2751       case (T_H245MultimediaSystemControlMessage_response):
2752          response = pH245->h245Msg.u.response;
2753          switch(response->t)
2754          {
2755             case T_H245ResponseMessage_masterSlaveDeterminationAck:
2756                /* Disable MSD timer */
2757                for(i = 0; i<call->timerList.count; i++)
2758                {
2759                   pNode = dListFindByIndex(&call->timerList, i);
2760                   pTimer = (OOTimer*)pNode->data;
2761                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_MSD_TIMER)
2762                   {
2763                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2764                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2765                      OOTRACEDBGC3("Deleted MSD Timer. (%s, %s)\n", call->callType,
2766                    call->callToken);
2767                      break;
2768                   }
2769                }
2770
2771                ooHandleMasterSlave(call, 
2772                                    response->u.masterSlaveDeterminationAck, 
2773                                    OOMasterSlaveAck);
2774                break;
2775             case T_H245ResponseMessage_masterSlaveDeterminationReject:
2776                /* Disable MSD timer */
2777                for(i = 0; i<call->timerList.count; i++)
2778                {
2779                   pNode = dListFindByIndex(&call->timerList, i);
2780                   pTimer = (OOTimer*)pNode->data;
2781                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_MSD_TIMER)
2782                   {
2783                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2784                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2785                      OOTRACEDBGC3("Deleted MSD Timer. (%s, %s)\n", call->callType,
2786                    call->callToken);
2787                      break;
2788                   }
2789                }
2790                ooHandleMasterSlaveReject(call, 
2791                                   response->u.masterSlaveDeterminationReject);
2792                break;
2793             case T_H245ResponseMessage_terminalCapabilitySetAck:
2794                /* Disable TCS timer */
2795                for(i = 0; i<call->timerList.count; i++)
2796                {
2797                   pNode = dListFindByIndex(&call->timerList, i);
2798                   pTimer = (OOTimer*)pNode->data;
2799                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_TCS_TIMER)
2800                   {
2801                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2802                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2803                      OOTRACEDBGC3("Deleted TCS Timer. (%s, %s)\n", call->callType,
2804                         call->callToken);
2805                      break;
2806                   }
2807                }
2808                ooOnReceivedTerminalCapabilitySetAck(call);
2809                break;
2810             case T_H245ResponseMessage_terminalCapabilitySetReject:
2811                OOTRACEINFO3("TerminalCapabilitySetReject message received."
2812                             " (%s, %s)\n", call->callType, call->callToken);
2813                if(response->u.terminalCapabilitySetReject->sequenceNumber != 
2814                   call->localTermCapSeqNo)
2815                {
2816                   OOTRACEINFO5("Ignoring TCSReject with mismatched seqno %d "
2817                               "(local - %d). (%s, %s)\n", 
2818                           response->u.terminalCapabilitySetReject->sequenceNumber,
2819                         call->localTermCapSeqNo, call->callType, call->callToken);
2820                   break;
2821                }
2822                /* Disable TCS timer */
2823                for(i = 0; i<call->timerList.count; i++)
2824                {
2825                   pNode = dListFindByIndex(&call->timerList, i);
2826                   pTimer = (OOTimer*)pNode->data;
2827                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_TCS_TIMER)
2828                   {
2829                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2830                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2831                      OOTRACEDBGC3("Deleted TCS Timer. (%s, %s)\n", call->callType,
2832                         call->callToken);
2833                      break;
2834                   }
2835                }
2836                if(call->callState < OO_CALL_CLEAR)
2837                {
2838                   call->callState = OO_CALL_CLEAR;
2839                   call->callEndReason = OO_REASON_NOCOMMON_CAPABILITIES;
2840                }
2841                break;
2842             case T_H245ResponseMessage_requestModeAck:
2843                if (call->requestSequence == response->u.requestModeAck->sequenceNumber) {
2844                         /* response to our last request, process it */
2845                         ooOnReceivedRequestModeAck(call, response->u.requestModeAck);
2846                }
2847                break;
2848             case T_H245ResponseMessage_requestModeReject:
2849                 OOTRACEDBGC3("Received requestModeReject, clearing call (%s, %s)\n",
2850                                  call->callType, call->callToken);
2851                if(call->callState < OO_CALL_CLEAR)
2852                {
2853                   call->callState = OO_CALL_CLEAR;
2854                   call->callEndReason = OO_REASON_REMOTE_REJECTED;
2855                }
2856                break;
2857             case T_H245ResponseMessage_openLogicalChannelAck:
2858                for(i = 0; i<call->timerList.count; i++)
2859                {
2860                   pNode = dListFindByIndex(&call->timerList, i);
2861                   pTimer = (OOTimer*)pNode->data;
2862                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_OLC_TIMER)                                            && 
2863                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
2864                    response->u.openLogicalChannelAck->forwardLogicalChannelNumber)
2865                   {
2866
2867                      memFreePtr(call->pctxt, pTimer->cbData);
2868                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2869                      OOTRACEDBGC3("Deleted OpenLogicalChannel Timer. (%s, %s)\n", 
2870                                    call->callType, call->callToken);
2871                      break;
2872                   }
2873                }
2874                ooOnReceivedOpenLogicalChannelAck(call, 
2875                                               response->u.openLogicalChannelAck);
2876                break;
2877             case T_H245ResponseMessage_openLogicalChannelReject:
2878                OOTRACEINFO3("Open Logical Channel Reject received (%s, %s)\n",
2879                              call->callType, call->callToken);
2880                for(i = 0; i<call->timerList.count; i++)
2881                {
2882                   pNode = dListFindByIndex(&call->timerList, i);
2883                   pTimer = (OOTimer*)pNode->data;
2884                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_OLC_TIMER)                                            && 
2885                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
2886                    response->u.openLogicalChannelAck->forwardLogicalChannelNumber)
2887                   {
2888
2889                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2890                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2891                      OOTRACEDBGC3("Deleted OpenLogicalChannel Timer. (%s, %s)\n", 
2892                                    call->callType, call->callToken);
2893                      break;
2894                   }
2895                }
2896                ooOnReceivedOpenLogicalChannelRejected(call, 
2897                                         response->u.openLogicalChannelReject);
2898                break;
2899             case T_H245ResponseMessage_closeLogicalChannelAck:
2900                OOTRACEINFO4("CloseLogicalChannelAck received for %d (%s, %s)\n",
2901                   response->u.closeLogicalChannelAck->forwardLogicalChannelNumber,
2902                   call->callType, call->callToken);
2903                for(i = 0; i<call->timerList.count; i++)
2904                {
2905                   pNode = dListFindByIndex(&call->timerList, i);
2906                   pTimer = (OOTimer*)pNode->data;
2907                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_CLC_TIMER)                                            && 
2908                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
2909                   response->u.closeLogicalChannelAck->forwardLogicalChannelNumber)
2910                   {
2911
2912                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2913                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2914                      OOTRACEDBGC3("Deleted CloseLogicalChannel Timer. (%s, %s)\n",
2915                                    call->callType, call->callToken);
2916                      break;
2917                   }
2918                }
2919                ooOnReceivedCloseChannelAck(call, 
2920                                            response->u.closeLogicalChannelAck);
2921                 if(!ooGetTransmitLogicalChannel(call))
2922                         ooOpenLogicalChannels(call);
2923                break;
2924             case T_H245ResponseMessage_requestChannelCloseAck:
2925                 OOTRACEINFO4("RequestChannelCloseAck received - %d (%s, %s)\n",
2926                   response->u.requestChannelCloseAck->forwardLogicalChannelNumber,
2927                   call->callType, call->callToken);
2928                 for(i = 0; i<call->timerList.count; i++)
2929                 {
2930                   pNode = dListFindByIndex(&call->timerList, i);
2931                   pTimer = (OOTimer*)pNode->data;
2932                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_RCC_TIMER)                                            && 
2933                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
2934                   response->u.requestChannelCloseAck->forwardLogicalChannelNumber)
2935                   {
2936
2937                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2938                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2939                      OOTRACEDBGC3("Deleted RequestChannelClose Timer. (%s, %s)\n",
2940                                    call->callType, call->callToken);
2941                      break;
2942                   }
2943                 }
2944                 ooOnReceivedRequestChannelCloseAck(call, 
2945                                              response->u.requestChannelCloseAck);
2946                 break;
2947             case T_H245ResponseMessage_requestChannelCloseReject:
2948                OOTRACEINFO4("RequestChannelCloseReject received - %d (%s, %s)\n",
2949                response->u.requestChannelCloseReject->forwardLogicalChannelNumber,
2950                  call->callType, call->callToken);
2951                 for(i = 0; i<call->timerList.count; i++)
2952                 {
2953                   pNode = dListFindByIndex(&call->timerList, i);
2954                   pTimer = (OOTimer*)pNode->data;
2955                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_RCC_TIMER) && 
2956                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
2957                       response->u.requestChannelCloseReject->forwardLogicalChannelNumber)
2958                   {
2959
2960                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2961                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2962                      OOTRACEDBGC3("Deleted RequestChannelClose Timer. (%s, %s)\n",
2963                                    call->callType, call->callToken);
2964                      break;
2965                   }
2966                }
2967                ooOnReceivedRequestChannelCloseReject(call, 
2968                                            response->u.requestChannelCloseReject);
2969                break;
2970              case T_H245ResponseMessage_roundTripDelayResponse:
2971                OOTRACEINFO4("Received roundTripDelayResponse - %d (%s, %s)\n",
2972                   response->u.roundTripDelayResponse->sequenceNumber,  call->callType, call->callToken);
2973                call->rtdrRecv = response->u.roundTripDelayResponse->sequenceNumber;
2974                break;
2975             default:
2976                ;
2977          }
2978          break;
2979       /* H.245 command message is received */
2980       case (T_H245MultimediaSystemControlMessage_command):
2981          command = pH245->h245Msg.u.command;
2982          ooHandleH245Command(call, command);
2983          break;
2984       /* H.245 Indication message received */
2985       case (T_H245MultimediaSystemControlMessage_indication):
2986          indication = pH245->h245Msg.u.indication;
2987          switch(indication->t)
2988          {
2989             case T_H245IndicationMessage_userInput:
2990                ooOnReceivedUserInputIndication(call, indication->u.userInput);
2991                break;
2992             default:
2993                OOTRACEWARN3("Unhandled indication message received.(%s, %s)\n",
2994                              call->callType, call->callToken);
2995          }
2996          break;
2997       default:
2998         ;
2999    }
3000    OOTRACEDBGC3("Finished handling H245 message. (%s, %s)\n", 
3001                  call->callType, call->callToken);
3002    return OO_OK;
3003 }
3004
3005
3006 int ooOnReceivedUserInputIndication
3007    (OOH323CallData *call, H245UserInputIndication *indication)
3008 {
3009    if((indication->t == T_H245UserInputIndication_alphanumeric) && 
3010       (call->dtmfmode & OO_CAP_DTMF_H245_alphanumeric))
3011    {
3012       if(gH323ep.h323Callbacks.onReceivedDTMF)
3013          gH323ep.h323Callbacks.onReceivedDTMF(call,indication->u.alphanumeric);
3014    }
3015    else if((indication->t == T_H245UserInputIndication_signal) && 
3016            (call->dtmfmode & OO_CAP_DTMF_H245_signal)) {
3017       if(call->lastDTMF && indication->u.signal->signalType[0] == call->lastDTMF &&
3018          call->nextDTMFstamp && indication->u.signal->m.rtpPresent && 
3019          indication->u.signal->rtp.m.timestampPresent) {
3020           if(call->nextDTMFstamp > indication->u.signal->rtp.timestamp) {
3021             OOTRACEERR4("ERROR:Duplicate dtmf %c on ((%s, %s)\n", call->lastDTMF, call->callType, 
3022                         call->callToken);
3023             return OO_OK;
3024           }
3025       }
3026       if (indication->u.signal->m.rtpPresent && indication->u.signal->rtp.m.timestampPresent &&
3027           indication->u.signal->m.durationPresent) {
3028           call->nextDTMFstamp = indication->u.signal->rtp.timestamp +
3029                                 indication->u.signal->duration;
3030           call->lastDTMF = indication->u.signal->signalType[0];
3031       } else {
3032           call->nextDTMFstamp = 0;
3033           call->lastDTMF = 0;
3034       }
3035       if(gH323ep.h323Callbacks.onReceivedDTMF)
3036          gH323ep.h323Callbacks.onReceivedDTMF(call, 
3037                                              indication->u.signal->signalType);
3038    }
3039    else {
3040       OOTRACEINFO3("Unsupported userInput message type received - ignoring."
3041                    "(%s, %s)\n", call->callType, call->callToken);
3042    }
3043    return OO_OK;
3044 }
3045
3046 int ooOnReceivedTerminalCapabilitySet(OOH323CallData *call, H245Message *pmsg)
3047 {
3048    int ret = 0,k;
3049    H245TerminalCapabilitySet *tcs=NULL;
3050    DListNode *pNode=NULL;
3051    H245CapabilityTableEntry *capEntry = NULL;
3052
3053    tcs =  pmsg->h245Msg.u.request->u.terminalCapabilitySet;
3054    if(call->remoteTermCapSeqNo > tcs->sequenceNumber)
3055    {
3056       OOTRACEINFO4("Rejecting TermCapSet message with SeqNo %d, as already "
3057                    "acknowledged message with this SeqNo (%s, %s)\n", 
3058                    call->remoteTermCapSeqNo, call->callType, call->callToken);
3059       ooSendTerminalCapabilitySetReject(call, tcs->sequenceNumber, 
3060                          T_H245TerminalCapabilitySetReject_cause_unspecified);
3061       return OO_OK;
3062
3063     } else {
3064 /* 20090924 */
3065 /* bogus soft-switch can send more than one request with  cap set
3066    if it goto to next choice. Right swith don't send but not all are right ;(
3067    we can accept new capability set only. We must remember also that new join caps
3068    will be previously joined caps with new cap set.
3069  */
3070    if(call->remoteTermCapSeqNo == tcs->sequenceNumber)
3071     call->localTermCapState = OO_LocalTermCapExchange_Idle;
3072    }
3073   
3074    if(!tcs->m.capabilityTablePresent)
3075    {
3076       // OOTRACEWARN3("Warn:Ignoring TCS as no capability table present(%s, %s)\n",
3077       OOTRACEWARN3("Empty TCS found.  Pausing call...(%s, %s)\n",
3078                     call->callType, call->callToken);
3079       call->h245SessionState = OO_H245SESSION_PAUSED;
3080       //ooSendTerminalCapabilitySetReject(call, tcs->sequenceNumber, 
3081       //                   T_H245TerminalCapabilitySetReject_cause_unspecified);
3082       //return OO_OK;
3083    }
3084    call->remoteTermCapSeqNo = tcs->sequenceNumber;
3085
3086    if(tcs->m.capabilityTablePresent) {
3087       for(k=0; k<(int)tcs->capabilityTable.count; k++)
3088       {
3089          pNode = dListFindByIndex(&tcs->capabilityTable, k);
3090          if(pNode)
3091          {
3092             OOTRACEDBGC4("Processing CapabilityTable Entry %d (%s, %s)\n", 
3093                           k, call->callType, call->callToken);
3094             capEntry = (H245CapabilityTableEntry*) pNode->data;
3095             if(capEntry->m.capabilityPresent){
3096                ret =  ooAddRemoteCapability(call, &capEntry->capability);
3097                if(ret != OO_OK)
3098                {
3099                   OOTRACEERR4("Error:Failed to process remote capability in "
3100                               "capability table at index %d. (%s, %s)\n", 
3101                                k, call->callType, call->callToken);
3102                }
3103                ooCapabilityUpdateJointCapabilities(call, &capEntry->capability);
3104             }
3105          }
3106          pNode = NULL;
3107          capEntry=NULL;
3108       }
3109    }
3110
3111    if (call->t38sides == 3) /* both side support t.38 */
3112         OO_SETFLAG(call->flags, OO_M_T38SUPPORTED);
3113    else
3114         OO_CLRFLAG(call->flags, OO_M_T38SUPPORTED);
3115    
3116    /* Update remoteTermCapSetState */
3117    call->remoteTermCapState = OO_RemoteTermCapSetRecvd;
3118
3119    ooH245AcknowledgeTerminalCapabilitySet(call);   
3120
3121    /* If we haven't yet send TCS then send it now */
3122    if(call->localTermCapState == OO_LocalTermCapExchange_Idle)
3123    {
3124       ret = ooSendTermCapMsg(call);
3125       if(ret != OO_OK)
3126       {
3127          OOTRACEERR3("ERROR:Sending Terminal capability message (%s, %s)\n",
3128                       call->callType, call->callToken);
3129          return ret;
3130       }
3131    }
3132
3133    if(call->remoteTermCapState != OO_RemoteTermCapSetAckSent ||
3134       call->localTermCapState  != OO_LocalTermCapSetAckRecvd)
3135       return OO_OK;
3136
3137    if(call->masterSlaveState == OO_MasterSlave_Idle) {
3138       ret = ooSendMasterSlaveDetermination(call);
3139       if(ret != OO_OK) {
3140                 OOTRACEERR3("ERROR:Sending Master-slave determination message "
3141                             "(%s, %s)\n", call->callType, call->callToken);
3142                 return ret;
3143       }
3144    } 
3145
3146
3147    /* Check MasterSlave procedure has finished */
3148    if(call->masterSlaveState != OO_MasterSlave_Master &&
3149       call->masterSlaveState != OO_MasterSlave_Slave)
3150       return OO_OK;
3151
3152    /* As both MasterSlave and TerminalCapabilitySet procedures have finished,
3153       OpenLogicalChannels */
3154  
3155    if(gH323ep.h323Callbacks.openLogicalChannels)
3156       gH323ep.h323Callbacks.openLogicalChannels(call);
3157    if(!ooGetTransmitLogicalChannel(call))
3158       ooOpenLogicalChannels(call);
3159 #if 0
3160    if(!call->logicalChans){
3161       if(!gH323ep.h323Callbacks.openLogicalChannels)
3162          ret = ooOpenLogicalChannels(call);
3163       else
3164          gH323ep.h323Callbacks.openLogicalChannels(call);
3165    }
3166 #endif
3167    return OO_OK;
3168 }
3169
3170 int ooSendTerminalCapabilitySetReject
3171                         (OOH323CallData *call, int seqNo, ASN1UINT cause)
3172 {
3173    H245Message *ph245msg=NULL;
3174    H245ResponseMessage * response=NULL;
3175    OOCTXT *pctxt=NULL;
3176    int ret = ooCreateH245Message(call, &ph245msg, 
3177                       T_H245MultimediaSystemControlMessage_response);
3178    if(ret != OO_OK)
3179    {
3180       OOTRACEERR1("ERROR:H245 message creation failed for - "
3181                            "TerminalCapabilitySetReject\n");
3182       return OO_FAILED;
3183    }
3184    ph245msg->msgType = OOTerminalCapabilitySetReject;
3185    response = ph245msg->h245Msg.u.response;
3186    memset(response, 0, sizeof(H245ResponseMessage));
3187    /* pctxt = &gH323ep.msgctxt; */
3188    pctxt = call->msgctxt;
3189    response->t = T_H245ResponseMessage_terminalCapabilitySetReject;
3190    
3191    response->u.terminalCapabilitySetReject = (H245TerminalCapabilitySetReject*)
3192                    ASN1MALLOC(pctxt, sizeof(H245TerminalCapabilitySetReject));
3193
3194    memset(response->u.terminalCapabilitySetReject, 0, 
3195                                  sizeof(H245TerminalCapabilitySetReject));
3196    response->u.terminalCapabilitySetReject->sequenceNumber = seqNo;
3197    response->u.terminalCapabilitySetReject->cause.t = cause;
3198
3199    OOTRACEDBGA3("Built TerminalCapabilitySetReject (%s, %s)\n", 
3200                  call->callType, call->callToken);
3201  
3202    ret = ooSendH245Msg(call, ph245msg);
3203    if(ret != OO_OK)
3204    {
3205      OOTRACEERR3("Error:Failed to enqueue TCSReject to outbound queue. "
3206                  "(%s, %s)\n", call->callType, call->callToken);
3207    }
3208    else
3209       call->remoteTermCapState = OO_RemoteTermCapExchange_Idle;
3210
3211    ooFreeH245Message(call, ph245msg);
3212    return ret;
3213 }
3214
3215 int ooH245AcknowledgeTerminalCapabilitySet(OOH323CallData *call)
3216 {
3217    H245Message *ph245msg=NULL;
3218    H245ResponseMessage * response=NULL;
3219    OOCTXT *pctxt=NULL;
3220    int ret = ooCreateH245Message(call, &ph245msg, 
3221                       T_H245MultimediaSystemControlMessage_response);
3222    if(ret != OO_OK)
3223    {
3224       OOTRACEERR1("ERROR:H245 message creation failed for - "
3225                            "TerminalCapability Set Ack\n");
3226       return OO_FAILED;
3227    }
3228    ph245msg->msgType = OOTerminalCapabilitySetAck;
3229    response = ph245msg->h245Msg.u.response;
3230    memset(response, 0, sizeof(H245ResponseMessage));
3231    /* pctxt = &gH323ep.msgctxt; */
3232    pctxt = call->msgctxt;
3233    response->t = T_H245ResponseMessage_terminalCapabilitySetAck;
3234    
3235    response->u.terminalCapabilitySetAck = (H245TerminalCapabilitySetAck*)
3236                    ASN1MALLOC(pctxt, sizeof(H245TerminalCapabilitySetAck));
3237
3238    memset(response->u.terminalCapabilitySetAck, 0, 
3239                                  sizeof(H245TerminalCapabilitySetAck));
3240    response->u.terminalCapabilitySetAck->sequenceNumber = call->remoteTermCapSeqNo;
3241
3242    OOTRACEDBGA3("Built TerminalCapabilitySet Ack (%s, %s)\n", 
3243                  call->callType, call->callToken);
3244    ret = ooSendH245Msg(call, ph245msg);
3245
3246    if(ret != OO_OK)
3247    {
3248      OOTRACEERR3("Error:Failed to enqueue TCSAck to outbound queue. (%s, %s)\n", call->callType, call->callToken);
3249    }
3250    else
3251       call->remoteTermCapState = OO_RemoteTermCapSetAckSent;
3252
3253    ooFreeH245Message(call, ph245msg);
3254    return ret;
3255 }
3256
3257
3258 int ooSendTerminalCapabilitySetRelease(OOH323CallData * call)
3259 {
3260    int ret=0;
3261    H245IndicationMessage* indication=NULL;
3262    H245Message *ph245msg=NULL;
3263    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
3264    OOCTXT *pctxt=call->msgctxt;
3265
3266    ret = ooCreateH245Message
3267       (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication);
3268
3269    if (ret != OO_OK) {
3270       OOTRACEERR3("Error:H245 message creation failed for - Terminal"
3271                   "CapabilitySetRelease (%s, %s)\n",call->callType, 
3272                   call->callToken);
3273       return OO_FAILED;
3274    }
3275    ph245msg->msgType = OOTerminalCapabilitySetRelease;
3276    indication = ph245msg->h245Msg.u.indication;
3277
3278    indication->t = T_H245IndicationMessage_terminalCapabilitySetRelease;
3279
3280    indication->u.terminalCapabilitySetRelease = 
3281       (H245TerminalCapabilitySetRelease*)
3282       memAlloc (pctxt, sizeof(H245TerminalCapabilitySetRelease));
3283
3284    if(!indication->u.terminalCapabilitySetRelease)
3285    {
3286       OOTRACEERR3("Error: Failed to allocate memory for TCSRelease message."
3287                   " (%s, %s)\n", call->callType, call->callToken);
3288       ooFreeH245Message(call, ph245msg);
3289       return OO_FAILED;
3290    }
3291    OOTRACEDBGA3 ("Built TerminalCapabilitySetRelease (%s, %s)\n", 
3292                  call->callType, call->callToken);
3293
3294    ret = ooSendH245Msg (call, ph245msg);
3295
3296    if (ret != OO_OK) {
3297       OOTRACEERR3 
3298          ("Error:Failed to enqueue TerminalCapabilitySetRelease "
3299          "message to outbound queue.(%s, %s)\n", call->callType, 
3300          call->callToken);
3301    }
3302    
3303    ooFreeH245Message (call, ph245msg);
3304    return ret;
3305 }
3306
3307
3308 int ooSendH245UserInputIndication_alphanumeric
3309    (OOH323CallData *call, const char *data)
3310 {
3311    int ret=0;
3312    H245IndicationMessage* indication=NULL;
3313    H245Message *ph245msg=NULL;
3314    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
3315    OOCTXT *pctxt=call->msgctxt;
3316
3317    ret = ooCreateH245Message
3318       (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication);
3319
3320    if (ret != OO_OK) {
3321       OOTRACEERR3("Error:H245 message creation failed for - H245UserInput"
3322                   "Indication_alphanumeric (%s, %s)\n",call->callType, 
3323                   call->callToken);
3324       return OO_FAILED;
3325    }
3326    ph245msg->msgType = OOUserInputIndication;
3327    indication = ph245msg->h245Msg.u.indication;
3328
3329    indication->t = T_H245IndicationMessage_userInput;
3330    indication->u.userInput = 
3331       (H245UserInputIndication*)
3332       memAllocZ (pctxt, sizeof(H245UserInputIndication));
3333
3334    if(!indication->u.userInput)
3335    {
3336       OOTRACEERR3("Error: Memory - ooH245UserInputIndication_alphanumeric - "
3337                   " userInput (%s, %s)\n", call->callType, call->callToken);
3338       ooFreeH245Message(call, ph245msg);
3339       return OO_FAILED;
3340    }
3341    indication->u.userInput->t = T_H245UserInputIndication_alphanumeric;
3342    indication->u.userInput->u.alphanumeric = (ASN1GeneralString)
3343                                               memAlloc(pctxt, strlen(data)+1);
3344    if(!indication->u.userInput->u.alphanumeric)
3345    {
3346       OOTRACEERR3("Error: Memory - ooH245UserInputIndication-alphanumeric - "
3347                   "alphanumeric (%s, %s).\n", call->callType, call->callToken);
3348       ooFreeH245Message(call, ph245msg);
3349       return OO_FAILED;
3350    }
3351    strcpy(*(char**)&indication->u.userInput->u.alphanumeric, data);
3352    OOTRACEDBGA3 ("Built UserInputIndication_alphanumeric (%s, %s)\n", 
3353                  call->callType, call->callToken);
3354
3355    ret = ooSendH245Msg (call, ph245msg);
3356
3357    if (ret != OO_OK) {
3358       OOTRACEERR3 
3359          ("Error:Failed to enqueue UserInputIndication_alphanumeric "
3360           "message to outbound queue.(%s, %s)\n", call->callType, 
3361           call->callToken);
3362    }
3363    
3364    ooFreeH245Message (call, ph245msg);
3365    return ret;
3366 }
3367
3368 int ooSendH245UserInputIndication_signal
3369    (OOH323CallData *call, const char *data)
3370 {
3371    int ret=0;
3372    H245IndicationMessage* indication=NULL;
3373    H245Message *ph245msg=NULL;
3374    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
3375    OOCTXT *pctxt=call->msgctxt;
3376
3377    ret = ooCreateH245Message
3378       (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication);
3379
3380    if (ret != OO_OK) {
3381       OOTRACEERR3("Error:H245 message creation failed for - H245UserInput"
3382                   "Indication_signal (%s, %s)\n",call->callType, 
3383                   call->callToken);
3384       return OO_FAILED;
3385    }
3386    ph245msg->msgType = OOUserInputIndication;
3387    indication = ph245msg->h245Msg.u.indication;
3388
3389    indication->t = T_H245IndicationMessage_userInput;
3390    indication->u.userInput = 
3391       (H245UserInputIndication*)
3392       memAllocZ (pctxt, sizeof(H245UserInputIndication));
3393
3394    if(!indication->u.userInput)
3395    {
3396       OOTRACEERR3("Error: Memory - ooH245UserInputIndication_signal - "
3397                   " userInput (%s, %s)\n", call->callType, call->callToken);
3398       ooFreeH245Message(call, ph245msg);
3399       return OO_FAILED;
3400    }
3401    indication->u.userInput->t = T_H245UserInputIndication_signal;
3402    indication->u.userInput->u.signal = (H245UserInputIndication_signal*)
3403                       memAllocZ(pctxt, sizeof(H245UserInputIndication_signal));
3404    indication->u.userInput->u.signal->signalType = (ASN1IA5String)
3405                                               memAlloc(pctxt, strlen(data)+1);
3406    if(!indication->u.userInput->u.signal ||
3407       !indication->u.userInput->u.signal->signalType)
3408    {
3409       OOTRACEERR3("Error: Memory - ooH245UserInputIndication_signal - "
3410                   "signal (%s, %s).\n", call->callType, call->callToken);
3411       ooFreeH245Message(call, ph245msg);
3412       return OO_FAILED;
3413    }
3414    strcpy(*(char**)&indication->u.userInput->u.signal->signalType, data);
3415    OOTRACEDBGA3 ("Built UserInputIndication_signal (%s, %s)\n", 
3416                  call->callType, call->callToken);
3417
3418    ret = ooSendH245Msg (call, ph245msg);
3419
3420    if (ret != OO_OK) {
3421       OOTRACEERR3 
3422          ("Error:Failed to enqueue UserInputIndication_signal "
3423           "message to outbound queue.(%s, %s)\n", call->callType, 
3424           call->callToken);
3425    }
3426    
3427    ooFreeH245Message (call, ph245msg);
3428    return ret;
3429 }
3430
3431
3432 int ooOpenLogicalChannels(OOH323CallData *call)
3433 {
3434    int ret=0;
3435    OOTRACEINFO3("Opening logical channels (%s, %s)\n", call->callType, 
3436                  call->callToken); 
3437
3438    /* Audio channels */
3439    if(gH323ep.callMode == OO_CALLMODE_AUDIOCALL ||
3440       gH323ep.callMode == OO_CALLMODE_AUDIOTX)
3441    {
3442       if (OO_TESTFLAG (call->flags, OO_M_AUDIOSESSION)) {
3443          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_AUDIO);
3444       } else if (OO_TESTFLAG (call->flags, OO_M_DATASESSION)) {
3445          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_DATA);
3446       }
3447       if(ret != OO_OK) {
3448        OOTRACEERR3("ERROR:Failed to open audio/data channels. Clearing call."
3449                    "(%s, %s)\n", call->callType, call->callToken);
3450        if (call->callState < OO_CALL_CLEAR) {
3451         call->callEndReason = OO_REASON_LOCAL_CLEARED;
3452         call->callState = OO_CALL_CLEAR;
3453        }
3454        return ret;
3455       }
3456    }
3457    
3458    if(gH323ep.callMode == OO_CALLMODE_VIDEOCALL)
3459    {
3460      /*      if (!OO_TESTFLAG (call->flags, OO_M_AUDIOSESSION))
3461         {*/
3462          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_AUDIO);
3463          if(ret != OO_OK)
3464          {
3465             OOTRACEERR3("ERROR:Failed to open audio channel. Clearing call."
3466                         "(%s, %s)\n", call->callType, call->callToken);
3467             if(call->callState < OO_CALL_CLEAR)
3468             {
3469                call->callEndReason = OO_REASON_LOCAL_CLEARED;
3470                call->callState = OO_CALL_CLEAR;
3471             }
3472             return ret;
3473          }
3474       //}
3475       /*      if(!OO_TESTFLAG(call->flags, OO_M_VIDEOSESSION))
3476       {*/
3477          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_VIDEO);
3478          if(ret != OO_OK)
3479          {
3480             OOTRACEERR3("ERROR:Failed to open video channel. Clearing call."
3481                         "(%s, %s)\n", call->callType, call->callToken);
3482             if(call->callState < OO_CALL_CLEAR)
3483             {
3484                call->callEndReason = OO_REASON_LOCAL_CLEARED;
3485                call->callState = OO_CALL_CLEAR;
3486             }
3487             return ret;
3488          }
3489      //}
3490    }
3491    return OO_OK;
3492 }
3493
3494 /* CapType indicates whether to Open Audio or Video channel */
3495 int ooOpenLogicalChannel(OOH323CallData *call, enum OOCapType capType )
3496 {
3497    ooH323EpCapability *epCap=NULL;
3498    int k=0;
3499
3500    /* Check whether local endpoint has audio capability */
3501    if(gH323ep.myCaps == 0 && call->ourCaps == 0)
3502    {
3503       OOTRACEERR3("ERROR:Local endpoint does not have any audio capabilities"
3504                   " (%s, %s)\n", call->callType, call->callToken);
3505       return OO_FAILED;
3506    }
3507    
3508    /* Go through local endpoints capabilities sequentially, and find out the
3509       first one which has a match in the remote endpoints receive capabilities.
3510    */
3511    OOTRACEINFO3("Looking for matching capabilities. (%s, %s)\n", 
3512                  call->callType, call->callToken);
3513 /* May */
3514    if(call->masterSlaveState == OO_MasterSlave_Master)
3515    {
3516       for(k=0; k<call->capPrefs.index; k++)
3517       {
3518          /*Search for audio caps only */
3519          if(capType == OO_CAP_TYPE_AUDIO && 
3520             call->capPrefs.order[k] > OO_CAP_VIDEO_BASE)
3521             continue;
3522          /* Search for video caps only */
3523          if(capType == OO_CAP_TYPE_VIDEO && 
3524             call->capPrefs.order[k] <= OO_CAP_VIDEO_BASE)
3525             continue;
3526
3527          epCap = call->jointCaps;
3528
3529          while(epCap){
3530             if(epCap->cap == call->capPrefs.order[k] && (epCap->dir & OOTX))
3531                break;
3532             epCap = epCap->next;
3533          }
3534          if(!epCap)
3535          {
3536             OOTRACEDBGA4("Prefereed capability %d is not a local transmit "
3537                          "capability(%s, %s)\n", call->capPrefs.order[k],
3538                          call->callType, call->callToken);
3539             continue;
3540          }
3541          break;
3542       }
3543       if(!epCap)
3544       {
3545          OOTRACEERR4("ERROR:Incompatible capabilities - Can not open "
3546                   "%s channel (%s, %s)\n", 
3547                   (capType==OO_CAP_TYPE_AUDIO)?"audio":"video", call->callType,
3548                   call->callToken);
3549          return OO_FAILED;
3550       }
3551
3552    }
3553    else
3554    {
3555       epCap = call->jointCaps;
3556
3557       while(epCap){
3558          if(epCap->capType == capType && epCap->dir & OOTX) { break; }
3559          epCap = epCap->next;
3560       }
3561       if(!epCap)
3562       {
3563          OOTRACEERR4("ERROR:Incompatible audio capabilities - Can not open "
3564                   "%s channel (%s, %s)\n", 
3565                   (capType==OO_CAP_TYPE_AUDIO)?"audio":"video", call->callType,
3566                   call->callToken);
3567          return OO_FAILED;
3568       }
3569        
3570    }
3571
3572    switch(epCap->cap)
3573    {
3574    case OO_G711ALAW64K:
3575    case OO_G711ALAW56K:
3576    case OO_G711ULAW64K:
3577    case OO_G711ULAW56K:
3578    case OO_G726:
3579    case OO_G726AAL2:
3580    case OO_AMRNB:
3581    case OO_SPEEX:
3582    case OO_G728:
3583    case OO_G729:
3584    case OO_G729A:
3585    case OO_G729B:
3586    case OO_G7231:
3587    case OO_GSMFULLRATE:
3588    case OO_GSMHALFRATE:
3589    case OO_GSMENHANCEDFULLRATE:
3590    case OO_H263VIDEO:
3591    case OO_T38:
3592       ooOpenChannel(call, epCap);
3593       break;
3594
3595       
3596    default:
3597       OOTRACEERR3("ERROR:Unknown Audio Capability type (%s, %s)\n", 
3598                    call->callType, call->callToken);
3599    }
3600    return OO_OK;
3601 }
3602
3603 int ooOpenChannel(OOH323CallData* call, ooH323EpCapability *epCap)
3604 {
3605    int ret;
3606    H245Message *ph245msg = NULL;
3607    H245RequestMessage * request;
3608    OOCTXT *pctxt = NULL;
3609    H245OpenLogicalChannel_forwardLogicalChannelParameters *flcp = NULL;
3610    H245AudioCapability *audioCap = NULL;
3611    H245VideoCapability *videoCap = NULL;
3612    H245DataApplicationCapability *t38Cap = NULL;
3613    H245H2250LogicalChannelParameters *h2250lcp = NULL;
3614    H245UnicastAddress *unicastAddrs = NULL;
3615    H245UnicastAddress_iPAddress *iPAddress = NULL;
3616    unsigned session_id=0;
3617    ooLogicalChannel *pLogicalChannel = NULL;
3618    
3619    OOTRACEDBGC4("Doing Open Channel for %s. (%s, %s)\n", 
3620                  ooGetCapTypeText(epCap->cap), call->callType, 
3621                  call->callToken);
3622
3623    ret = ooCreateH245Message(call, &ph245msg, 
3624                       T_H245MultimediaSystemControlMessage_request);
3625    if(ret != OO_OK)
3626    {
3627       OOTRACEERR4("Error: H245 message creation failed for - Open %s"
3628                   "channel (%s, %s)\n", ooGetCapTypeText(epCap->cap), 
3629                   call->callType, call->callToken);
3630       return OO_FAILED;
3631    }
3632
3633    ph245msg->msgType = OOOpenLogicalChannel;
3634
3635    ph245msg->logicalChannelNo =  call->logicalChanNoCur++;
3636    if(call->logicalChanNoCur > call->logicalChanNoMax)
3637       call->logicalChanNoCur = call->logicalChanNoBase; 
3638
3639    request = ph245msg->h245Msg.u.request;
3640    /* pctxt = &gH323ep.msgctxt; */
3641    pctxt = call->msgctxt;
3642    memset(request, 0, sizeof(H245RequestMessage));
3643
3644    request->t = T_H245RequestMessage_openLogicalChannel;
3645    request->u.openLogicalChannel = (H245OpenLogicalChannel*)
3646                      memAlloc(pctxt, sizeof(H245OpenLogicalChannel));
3647    if(!request->u.openLogicalChannel)
3648    {
3649       OOTRACEERR3("Error:Memory - ooOpenChannel - openLogicalChannel."
3650                   "(%s, %s)\n", call->callType, call->callToken);
3651       return OO_FAILED;
3652
3653    }
3654    memset(request->u.openLogicalChannel, 0, 
3655                                      sizeof(H245OpenLogicalChannel));
3656    request->u.openLogicalChannel->forwardLogicalChannelNumber = 
3657                                                  ph245msg->logicalChannelNo;
3658
3659    
3660    session_id = ooCallGenerateSessionID(call, epCap->capType, "transmit");
3661
3662
3663    pLogicalChannel = ooAddNewLogicalChannel(call, 
3664                    request->u.openLogicalChannel->forwardLogicalChannelNumber,
3665                    session_id, "transmit", epCap);
3666    
3667    if(!pLogicalChannel)
3668    {
3669       OOTRACEERR3("ERROR:Failed to add new logical channel entry (%s, %s)\n",
3670                   call->callType, call->callToken);
3671       ooFreeH245Message(call, ph245msg);
3672       return OO_FAILED;
3673    }
3674    /* Populate H245OpenLogicalChannel_ForwardLogicalChannel Parameters*/
3675    flcp = &(request->u.openLogicalChannel->forwardLogicalChannelParameters);
3676    flcp->m.portNumberPresent = 0;
3677    flcp->m.forwardLogicalChannelDependencyPresent = 0;
3678    flcp->m.replacementForPresent = 0;
3679
3680    /* data type of channel */
3681    if(epCap->capType == OO_CAP_TYPE_AUDIO)
3682    {
3683       flcp->dataType.t = T_H245DataType_audioData;
3684       /* set audio capability for channel */
3685       audioCap = ooCapabilityCreateAudioCapability(epCap,pctxt, OOTX);
3686       if(!audioCap)
3687       {
3688          OOTRACEERR4("Error:Failed to create duplicate audio capability in "
3689                      "ooOpenChannel- %s (%s, %s)\n", 
3690                      ooGetCapTypeText(epCap->cap), call->callType, 
3691                      call->callToken);
3692          ooFreeH245Message(call, ph245msg);
3693          return OO_FAILED;
3694       }
3695    
3696       flcp->dataType.u.audioData = audioCap;
3697    }
3698    else if(epCap->capType == OO_CAP_TYPE_VIDEO)
3699    {
3700       flcp->dataType.t = T_H245DataType_videoData;      
3701       videoCap = ooCapabilityCreateVideoCapability(epCap, pctxt, OOTX);
3702       if(!videoCap)
3703       {
3704          OOTRACEERR4("Error:Failed to create duplicate video capability in "
3705                      "ooOpenChannel- %s (%s, %s)\n", 
3706                      ooGetCapTypeText(epCap->cap), call->callType, 
3707                      call->callToken);
3708          ooFreeH245Message(call, ph245msg);
3709          return OO_FAILED;
3710       }
3711    
3712       flcp->dataType.u.videoData = videoCap;
3713    }
3714    else if(epCap->capType == OO_CAP_TYPE_DATA)
3715    {
3716       flcp->dataType.t = T_H245DataType_data;
3717       /* set audio capability for channel */
3718       t38Cap = ooCapabilityCreateT38Capability(epCap,pctxt, OOTX);
3719       if(!t38Cap)
3720       {
3721          OOTRACEERR4("Error:Failed to create duplicate T38 capability in "
3722                      "ooOpenChannel- %s (%s, %s)\n", 
3723                      ooGetCapTypeText(epCap->cap), call->callType, 
3724                      call->callToken);
3725          ooFreeH245Message(call, ph245msg);
3726          return OO_FAILED;
3727       }
3728    
3729       flcp->dataType.u.data = t38Cap;
3730    }
3731    else{
3732       OOTRACEERR1("Error: Unhandled media type in ooOpenChannel\n");
3733       return OO_FAILED;
3734    }
3735
3736   
3737    flcp->multiplexParameters.t = 
3738       T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters;
3739    flcp->multiplexParameters.u.h2250LogicalChannelParameters = 
3740                          (H245H2250LogicalChannelParameters*)ASN1MALLOC(pctxt, 
3741                           sizeof(H245H2250LogicalChannelParameters));
3742
3743    h2250lcp = flcp->multiplexParameters.u.h2250LogicalChannelParameters;
3744    memset(h2250lcp, 0, sizeof(H245H2250LogicalChannelParameters));
3745
3746    h2250lcp->sessionID = session_id;
3747
3748    h2250lcp->mediaGuaranteedDelivery = 0;
3749    h2250lcp->silenceSuppression = 0;
3750    h2250lcp->m.mediaControlChannelPresent = 1;
3751    
3752    h2250lcp->mediaControlChannel.t = 
3753                                  T_H245TransportAddress_unicastAddress;
3754    h2250lcp->mediaControlChannel.u.unicastAddress =  (H245UnicastAddress*)
3755                          ASN1MALLOC(pctxt, sizeof(H245UnicastAddress));
3756
3757    unicastAddrs = h2250lcp->mediaControlChannel.u.unicastAddress;
3758    memset(unicastAddrs, 0, sizeof(H245UnicastAddress));
3759    unicastAddrs->t = T_H245UnicastAddress_iPAddress;
3760    unicastAddrs->u.iPAddress = (H245UnicastAddress_iPAddress*)
3761                ASN1MALLOC(pctxt, sizeof(H245UnicastAddress_iPAddress));
3762    iPAddress = unicastAddrs->u.iPAddress;
3763    memset(iPAddress, 0, sizeof(H245UnicastAddress_iPAddress));
3764
3765    ooSocketConvertIpToNwAddr(pLogicalChannel->localIP,iPAddress->network.data);
3766
3767    iPAddress->network.numocts = 4;
3768    iPAddress->tsapIdentifier = pLogicalChannel->localRtcpPort;
3769    pLogicalChannel->state = OO_LOGICALCHAN_PROPOSED; 
3770    OOTRACEDBGA4("Built OpenLogicalChannel-%s (%s, %s)\n", 
3771                  ooGetCapTypeText(epCap->cap), call->callType, 
3772                  call->callToken);
3773    ret = ooSendH245Msg(call, ph245msg);
3774    if(ret != OO_OK