adbe1842e7ec7243db4658ba9ff45a09f91779b9
[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          }
2064          else{
2065
2066             call->h245SessionState = OO_H245SESSION_ENDRECVD;
2067 #if 0
2068             if(call->callState < OO_CALL_CLEAR)
2069                call->callState = OO_CALL_CLEAR;
2070 #else 
2071             if(call->logicalChans)
2072             {
2073                OOTRACEINFO3("In response to received EndSessionCommand - "
2074                             "Clearing all logical channels. (%s, %s)\n", 
2075                             call->callType, call->callToken);
2076                ooClearAllLogicalChannels(call);
2077             }
2078             ooSendEndSessionCommand(call);
2079 #endif
2080          }
2081             
2082             
2083          break;
2084       case T_H245CommandMessage_sendTerminalCapabilitySet:
2085          OOTRACEWARN3("Warning: Received command Send terminal capability set "
2086                       "- Not handled (%s, %s)\n", call->callType, 
2087                       call->callToken);
2088          break;
2089       case T_H245CommandMessage_flowControlCommand:
2090          OOTRACEWARN3("Warning: Flow control command received - Not handled "
2091                       "(%s, %s)\n", call->callType, call->callToken);
2092          break;
2093       default:
2094          OOTRACEWARN3("Warning: Unhandled H245 command message received "
2095                       "(%s, %s)\n", call->callType, call->callToken);
2096    }
2097    OOTRACEDBGC3("Handling H.245 command message done. (%s, %s)\n", 
2098                  call->callType, call->callToken);   
2099    return OO_OK;
2100 }
2101
2102
2103 int ooOnReceivedTerminalCapabilitySetAck(OOH323CallData* call)
2104 {
2105    call->localTermCapState = OO_LocalTermCapSetAckRecvd;
2106    if(call->remoteTermCapState != OO_RemoteTermCapSetAckSent)
2107       return OO_OK;
2108    
2109    if((call->masterSlaveState == OO_MasterSlave_Master ||
2110        call->masterSlaveState == OO_MasterSlave_Slave) &&
2111        (call->msAckStatus == OO_msAck_remoteReceived))
2112    {
2113       if(gH323ep.h323Callbacks.openLogicalChannels)
2114          gH323ep.h323Callbacks.openLogicalChannels(call);
2115       if(!ooGetTransmitLogicalChannel(call))
2116          ooOpenLogicalChannels(call);
2117 #if 0
2118       if(!call->logicalChans){
2119          if(!gH323ep.h323Callbacks.openLogicalChannels)
2120             ooOpenLogicalChannels(call);
2121          else
2122             gH323ep.h323Callbacks.openLogicalChannels(call);
2123       }
2124 #endif
2125    }
2126       
2127    return OO_OK;
2128 }
2129
2130 int ooCloseAllLogicalChannels(OOH323CallData *call, char* dir)
2131 {
2132    ooLogicalChannel *temp;
2133
2134    temp = call->logicalChans;
2135    while(temp)
2136    {
2137       if(temp->state == OO_LOGICALCHAN_ESTABLISHED && 
2138         (dir == NULL || !strcmp(temp->dir,dir)))
2139       {
2140          /* Sending closelogicalchannel only for outgoing channels*/
2141          if(!strcmp(temp->dir, "transmit"))
2142          {
2143             ooSendCloseLogicalChannel(call, temp);
2144          }
2145          else{
2146             ooSendRequestCloseLogicalChannel(call, temp);
2147          }
2148       }
2149       temp = temp->next;
2150    }
2151    return OO_OK;
2152 }
2153
2154 int ooSendCloseLogicalChannel(OOH323CallData *call, ooLogicalChannel *logicalChan)
2155 {
2156    int ret = OO_OK, error=0;
2157    H245Message *ph245msg = NULL;
2158    OOCTXT *pctxt;
2159    H245RequestMessage *request;
2160    H245CloseLogicalChannel* clc;
2161    
2162    ret = ooCreateH245Message(call, &ph245msg, 
2163                              T_H245MultimediaSystemControlMessage_request);
2164    if(ret != OO_OK)
2165    {
2166       OOTRACEERR3("ERROR:Failed to create H245 message for closeLogicalChannel"
2167                   " message (%s, %s)\n", call->callType, call->callToken);
2168       return OO_FAILED;
2169    }
2170    ph245msg->msgType = OOCloseLogicalChannel;
2171    ph245msg->logicalChannelNo = logicalChan->channelNo;
2172    /* pctxt = &gH323ep.msgctxt; */
2173    pctxt = call->msgctxt;
2174    request = ph245msg->h245Msg.u.request;
2175
2176    request->t = T_H245RequestMessage_closeLogicalChannel;
2177    request->u.closeLogicalChannel = (H245CloseLogicalChannel*)ASN1MALLOC(pctxt,
2178                                      sizeof(H245CloseLogicalChannel));
2179    if(!request->u.closeLogicalChannel)
2180    {
2181       OOTRACEERR3("ERROR:Memory allocation for CloseLogicalChannel failed "
2182                   "(%s, %s)\n", call->callType, call->callToken);
2183       ooFreeH245Message(call, ph245msg);
2184       return OO_FAILED;
2185    }
2186    clc = request->u.closeLogicalChannel;
2187    memset(clc, 0, sizeof(H245CloseLogicalChannel));
2188
2189    clc->forwardLogicalChannelNumber = logicalChan->channelNo;
2190    clc->source.t = T_H245CloseLogicalChannel_source_lcse;
2191    clc->m.reasonPresent = 1;
2192    clc->reason.t = T_H245CloseLogicalChannel_reason_unknown;
2193
2194    OOTRACEDBGA4("Built close logical channel for %d (%s, %s)\n", 
2195                  logicalChan->channelNo, call->callType, call->callToken);
2196    ret = ooSendH245Msg(call, ph245msg);
2197    if(ret != OO_OK)
2198    {
2199      OOTRACEERR3("Error:Failed to enqueue CloseLogicalChannel to outbound queue.(%s, %s)\n", call->callType,
2200                  call->callToken);
2201      error++;
2202    }
2203    ooFreeH245Message(call, ph245msg);
2204    
2205    /* Stop the media transmission */
2206    OOTRACEINFO4("Closing logical channel %d (%s, %s)\n", 
2207                 clc->forwardLogicalChannelNumber, call->callType, 
2208                 call->callToken);
2209    ret = ooClearLogicalChannel(call, clc->forwardLogicalChannelNumber);
2210    if(ret != OO_OK)
2211    {
2212       OOTRACEERR4("ERROR:Failed to close logical channel %d (%s, %s)\n",
2213          clc->forwardLogicalChannelNumber, call->callType, call->callToken);
2214       return OO_FAILED;
2215    }
2216    if(error) return OO_FAILED;
2217    return ret;
2218 }
2219
2220 /*TODO: Need to pass reason as a parameter */
2221 int ooSendRequestCloseLogicalChannel(OOH323CallData *call, 
2222                                      ooLogicalChannel *logicalChan)
2223 {
2224    int ret = OO_OK;
2225    H245Message *ph245msg = NULL;
2226    OOCTXT *pctxt;
2227    H245RequestMessage *request;
2228    H245RequestChannelClose *rclc;
2229
2230    ret = ooCreateH245Message(call, &ph245msg, 
2231                              T_H245MultimediaSystemControlMessage_request);
2232    if(ret != OO_OK)
2233    {
2234       OOTRACEERR3("ERROR:Failed to create H245 message for "
2235                   "requestCloseLogicalChannel message (%s, %s)\n", 
2236                    call->callType, call->callToken);
2237       return OO_FAILED;
2238    }
2239    ph245msg->msgType = OORequestChannelClose;
2240    ph245msg->logicalChannelNo = logicalChan->channelNo;
2241    /* pctxt = &gH323ep.msgctxt; */
2242    pctxt = call->msgctxt;
2243    request = ph245msg->h245Msg.u.request;
2244
2245    request->t = T_H245RequestMessage_requestChannelClose;
2246    request->u.requestChannelClose = (H245RequestChannelClose*)ASN1MALLOC(pctxt,
2247                                      sizeof(H245RequestChannelClose));
2248    if(!request->u.requestChannelClose)
2249    {
2250       OOTRACEERR3("ERROR:Memory allocation for RequestCloseLogicalChannel "
2251                   " failed (%s, %s)\n", call->callType, call->callToken);
2252       ooFreeH245Message(call, ph245msg);
2253       return OO_FAILED;
2254    }
2255
2256    rclc = request->u.requestChannelClose;
2257    memset(rclc, 0, sizeof(H245RequestChannelClose));
2258    rclc->forwardLogicalChannelNumber = logicalChan->channelNo;
2259    
2260    rclc->m.reasonPresent = 1;
2261    rclc->reason.t = T_H245RequestChannelClose_reason_unknown;
2262
2263    OOTRACEDBGA4("Built RequestCloseChannel for %d (%s, %s)\n", 
2264                  logicalChan->channelNo, call->callType, call->callToken);
2265    ret = ooSendH245Msg(call, ph245msg);
2266    if(ret != OO_OK)
2267    {
2268      OOTRACEERR3("Error:Failed to enqueue the RequestCloseChannel to outbound"
2269                  " queue (%s, %s)\n", call->callType,
2270                  call->callToken);
2271    }
2272    ooFreeH245Message(call, ph245msg);
2273
2274    return ret;
2275 }
2276
2277 int ooSendRequestChannelCloseRelease(OOH323CallData *call, int channelNum)
2278 {
2279    int ret = OO_OK;
2280    H245Message *ph245msg = NULL;
2281    OOCTXT *pctxt;
2282    H245IndicationMessage *indication;
2283
2284    ret = ooCreateH245Message(call, &ph245msg, 
2285                              T_H245MultimediaSystemControlMessage_indication);
2286    if(ret != OO_OK)
2287    {
2288       OOTRACEERR3("ERROR:Failed to create H245 message for "
2289                   "RequestChannelCloseRelease message (%s, %s)\n", 
2290                    call->callType, call->callToken);
2291       return OO_FAILED;
2292    }
2293    ph245msg->msgType = OORequestChannelCloseRelease;
2294    ph245msg->logicalChannelNo = channelNum;
2295    /* pctxt = &gH323ep.msgctxt; */
2296    pctxt = call->msgctxt;
2297    indication = ph245msg->h245Msg.u.indication;
2298    indication->t = T_H245IndicationMessage_requestChannelCloseRelease;
2299    indication->u.requestChannelCloseRelease = (H245RequestChannelCloseRelease*)
2300                      ASN1MALLOC(pctxt, sizeof(H245RequestChannelCloseRelease));
2301    if(!indication->u.requestChannelCloseRelease)
2302    {
2303       OOTRACEERR3("Error:Failed to allocate memory for "
2304                   "RequestChannelCloseRelease message. (%s, %s)\n", 
2305                    call->callType, call->callToken);
2306       ooFreeH245Message(call, ph245msg);
2307    }
2308
2309    indication->u.requestChannelCloseRelease->forwardLogicalChannelNumber = 
2310                                                                 channelNum;
2311
2312    OOTRACEDBGA4("Built RequestChannelCloseRelease for %d (%s, %s)\n", 
2313                 channelNum, call->callType, call->callToken);
2314    ret = ooSendH245Msg(call, ph245msg);
2315    if(ret != OO_OK)
2316    {
2317      OOTRACEERR3("Error:Failed to enqueue the RequestChannelCloseRelease to "
2318                  "outbound queue (%s, %s)\n", call->callType, call->callToken);
2319    }
2320    ooFreeH245Message(call, ph245msg);
2321
2322    return ret;
2323 }
2324
2325
2326    
2327 int ooOnReceivedRequestChannelClose(OOH323CallData *call, 
2328                                     H245RequestChannelClose *rclc)
2329 {
2330    int ret=0, error=0;
2331    H245Message *ph245msg=NULL;
2332    H245ResponseMessage *response = NULL;
2333    OOCTXT *pctxt=NULL;
2334    H245RequestChannelCloseAck *rclcAck;
2335    ooLogicalChannel * lChannel=NULL;
2336    /* Send Ack: TODO: Need to send reject, if doesn't exist
2337    */
2338    lChannel = ooFindLogicalChannelByLogicalChannelNo(call, 
2339                                         rclc->forwardLogicalChannelNumber);
2340    if(!lChannel)
2341    {
2342       OOTRACEERR4("ERROR:Channel %d requested to be closed not found "
2343                   "(%s, %s)\n", rclc->forwardLogicalChannelNumber,
2344                   call->callType, call->callToken);
2345       return OO_FAILED;
2346    }
2347    else{
2348       if(strcmp(lChannel->dir, "transmit"))
2349       {
2350          OOTRACEERR4("ERROR:Channel %d requested to be closed, Not a forward "
2351                      "channel (%s, %s)\n", rclc->forwardLogicalChannelNumber,
2352                      call->callType, call->callToken);
2353          return OO_FAILED;
2354       }
2355    }
2356    ret = ooCreateH245Message(call, &ph245msg, 
2357                              T_H245MultimediaSystemControlMessage_response);
2358    if(ret != OO_OK)
2359    {
2360       OOTRACEERR3("ERROR:Memory allocation for RequestChannelCloseAck message "
2361                   "failed (%s, %s)\n", call->callType, call->callToken);
2362       return OO_FAILED;
2363    }
2364    /* pctxt = &gH323ep.msgctxt; */
2365    pctxt = call->msgctxt;
2366    ph245msg->msgType = OORequestChannelCloseAck;
2367    ph245msg->logicalChannelNo = rclc->forwardLogicalChannelNumber;
2368    response = ph245msg->h245Msg.u.response;
2369    response->t = T_H245ResponseMessage_requestChannelCloseAck;
2370    response->u.requestChannelCloseAck = (H245RequestChannelCloseAck*)ASN1MALLOC
2371                                    (pctxt, sizeof(H245RequestChannelCloseAck));
2372    if(!response->u.requestChannelCloseAck)
2373    {
2374       OOTRACEERR3("ERROR:Failed to allocate memory for RequestChannelCloseAck "
2375                   "message (%s, %s)\n", call->callType, call->callToken);
2376       return OO_FAILED;
2377    }
2378    rclcAck = response->u.requestChannelCloseAck;
2379    memset(rclcAck, 0, sizeof(H245RequestChannelCloseAck));
2380    rclcAck->forwardLogicalChannelNumber = rclc->forwardLogicalChannelNumber;
2381
2382    OOTRACEDBGA3("Built RequestCloseChannelAck message (%s, %s)\n", 
2383                  call->callType, call->callToken);
2384    ret = ooSendH245Msg(call, ph245msg);
2385    if(ret != OO_OK)
2386    {
2387       OOTRACEERR3("Error:Failed to enqueue RequestCloseChannelAck to outbound queue. (%s, %s)\n", call->callType,
2388                   call->callToken);
2389       error++;
2390    }
2391
2392    ooFreeH245Message(call, ph245msg);
2393    
2394    /* Send Close Logical Channel*/
2395    ret = ooSendCloseLogicalChannel(call, lChannel);
2396    if(ret != OO_OK)
2397    {
2398       OOTRACEERR3("ERROR:Failed to build CloseLgicalChannel message(%s, %s)\n",
2399                    call->callType, call->callToken);
2400       return OO_FAILED;
2401    }
2402
2403    if(error) return OO_FAILED;
2404
2405    return ret;
2406 }
2407
2408 int ooSendRoundTripDelayRequest(OOH323CallData *call)
2409 {
2410    int ret=0;
2411    H245Message *ph245msg=NULL;
2412    H245RequestMessage *request = NULL;
2413    OOCTXT *pctxt=NULL;
2414    H245RoundTripDelayRequest *rtdr;
2415    ooTimerCallback *cbData=NULL;
2416
2417    if (call->rtdrSend > call->rtdrRecv + call->rtdrCount) {
2418         if(call->callState < OO_CALL_CLEAR) {
2419                 call->callState = OO_CALL_CLEAR;
2420                 call->callEndReason = OO_REASON_UNKNOWN;
2421                 call->q931cause = Q931RecoveryOnTimerExpiry;
2422         }
2423         return OO_FAILED;
2424    }
2425    
2426    ret = ooCreateH245Message(call, &ph245msg, 
2427                              T_H245MultimediaSystemControlMessage_request);
2428    if(ret != OO_OK)
2429    {
2430       OOTRACEERR3("ERROR:Memory allocation for RoundTripDelayResponse message "
2431                   "failed (%s, %s)\n", call->callType, call->callToken);
2432       return OO_FAILED;
2433    }
2434
2435    pctxt = call->msgctxt;
2436    ph245msg->msgType = OORequestDelayRequest;
2437    request = ph245msg->h245Msg.u.request;
2438    request->t = T_H245RequestMessage_roundTripDelayRequest;
2439    request->u.roundTripDelayRequest = (H245RoundTripDelayRequest *)ASN1MALLOC
2440                                    (pctxt, sizeof(H245RoundTripDelayRequest));
2441    if(!request->u.roundTripDelayRequest)
2442    {
2443       OOTRACEERR3("ERROR:Failed to allocate memory for H245RoundTripDelayRequest "
2444                   "message (%s, %s)\n", call->callType, call->callToken);
2445       return OO_FAILED;
2446    }
2447    rtdr = request->u.roundTripDelayRequest;
2448    memset(rtdr, 0, sizeof(H245RoundTripDelayRequest));
2449    rtdr->sequenceNumber = ++call->rtdrSend;
2450
2451    OOTRACEDBGA3("Built RoundTripDelayRequest message (%s, %s)\n", 
2452                  call->callType, call->callToken);
2453    ret = ooSendH245Msg(call, ph245msg);
2454    if(ret != OO_OK)
2455    {
2456       OOTRACEERR3("Error:Failed to enqueue RoundTripDelayRequest to outbound queue. (%s, %s)\n",
2457         call->callType, call->callToken);
2458       return OO_FAILED;
2459    } else {
2460       cbData = (ooTimerCallback*) memAlloc(call->pctxt,
2461                                      sizeof(ooTimerCallback));
2462       if(!cbData)
2463       {
2464          OOTRACEERR3("Error:Unable to allocate memory for timer callback data."
2465                      "(%s, %s)\n", call->callType, call->callToken);
2466          return OO_FAILED;
2467       }
2468       cbData->call = call;
2469       cbData->timerType = OO_RTD_TIMER;
2470       if(!ooTimerCreate(call->pctxt, &call->timerList, &ooRTDTimerExpired,
2471                         call->rtdrInterval, cbData, FALSE))
2472       {
2473          OOTRACEERR3("Error:Unable to create RTDR timer. "
2474                      "(%s, %s)\n", call->callType, call->callToken);
2475          memFreePtr(call->pctxt, cbData);
2476          return OO_FAILED;
2477       }
2478
2479    }
2480
2481    ooFreeH245Message(call, ph245msg);
2482
2483    return ret;
2484 }
2485
2486 int ooOnReceivedRoundTripDelayRequest(OOH323CallData *call, 
2487                                      H245SequenceNumber sequenceNumber)
2488 {
2489    int ret=0;
2490    H245Message *ph245msg=NULL;
2491    H245ResponseMessage *response = NULL;
2492    OOCTXT *pctxt=NULL;
2493    H245RoundTripDelayResponse *rtdr;
2494
2495    ret = ooCreateH245Message(call, &ph245msg, 
2496                              T_H245MultimediaSystemControlMessage_response);
2497    if(ret != OO_OK)
2498    {
2499       OOTRACEERR3("ERROR:Memory allocation for RoundTripDelayResponse message "
2500                   "failed (%s, %s)\n", call->callType, call->callToken);
2501       return OO_FAILED;
2502    }
2503
2504    pctxt = call->msgctxt;
2505    ph245msg->msgType = OORequestDelayResponse;
2506    response = ph245msg->h245Msg.u.response;
2507    response->t = T_H245ResponseMessage_roundTripDelayResponse;
2508    response->u.roundTripDelayResponse = (H245RoundTripDelayResponse *)ASN1MALLOC
2509                                    (pctxt, sizeof(H245RoundTripDelayResponse));
2510    if(!response->u.roundTripDelayResponse)
2511    {
2512       OOTRACEERR3("ERROR:Failed to allocate memory for H245RoundTripDelayResponse "
2513                   "message (%s, %s)\n", call->callType, call->callToken);
2514       return OO_FAILED;
2515    }
2516    rtdr = response->u.roundTripDelayResponse;
2517    memset(rtdr, 0, sizeof(H245RoundTripDelayResponse));
2518    rtdr->sequenceNumber = sequenceNumber;
2519
2520    OOTRACEDBGA3("Built RoundTripDelayResponse message (%s, %s)\n", 
2521                  call->callType, call->callToken);
2522    ret = ooSendH245Msg(call, ph245msg);
2523    if(ret != OO_OK)
2524    {
2525       OOTRACEERR3("Error:Failed to enqueue RoundTripDelayResponse to outbound queue. (%s, %s)\n",
2526         call->callType, call->callToken);
2527    }
2528
2529    ooFreeH245Message(call, ph245msg);
2530    
2531    return ret;
2532 }
2533
2534 /*
2535   We clear channel here. Ideally the remote endpoint should send 
2536   CloseLogicalChannel and then the channel should be cleared. But there's no
2537   timer for this and if remote endpoint misbehaves, the call will keep waiting
2538   for CloseLogicalChannel and hence, wouldn't be cleared. In case when remote
2539   endpoint sends CloseLogicalChannel, we call ooClearLogicalChannel again,
2540   which simply returns OO_OK as channel was already cleared. Other option is
2541   to start a timer for call cleanup and if call is not cleaned up within 
2542   timeout, we clean call forcefully. Note, no such timer is defined in 
2543   standards.
2544 */
2545 int ooOnReceivedRequestChannelCloseAck
2546                        (OOH323CallData *call, H245RequestChannelCloseAck *rccAck)
2547 {
2548    int ret=OO_OK;
2549    /* Remote endpoint is ok to close channel. So let's do it */
2550    ret = ooClearLogicalChannel(call, rccAck->forwardLogicalChannelNumber);
2551    if(ret != OO_OK)
2552    {
2553       OOTRACEERR4("Error:Failed to clear logical channel %d. (%s, %s)\n", 
2554                    rccAck->forwardLogicalChannelNumber, call->callType, 
2555                    call->callToken);
2556    }
2557
2558    return ret;
2559 }
2560
2561 int ooOnReceivedRequestChannelCloseReject
2562    (OOH323CallData *call, H245RequestChannelCloseReject *rccReject)
2563 {
2564    int ret =0;
2565    switch(rccReject->cause.t)
2566    {
2567    case T_H245RequestChannelCloseReject_cause_unspecified:
2568       OOTRACEDBGA4("Remote endpoint has rejected request to close logical "
2569                    "channel %d - cause unspecified. (%s, %s)\n", 
2570                    rccReject->forwardLogicalChannelNumber, call->callType, 
2571                    call->callToken);
2572      break;
2573    case T_H245RequestChannelCloseReject_cause_extElem1:
2574       OOTRACEDBGA4("Remote endpoint has rejected request to close logical "
2575                    "channel %d - cause propriatory. (%s, %s)\n", 
2576                    rccReject->forwardLogicalChannelNumber, call->callType, 
2577                    call->callToken);   
2578       break;
2579    default:
2580       OOTRACEDBGA4("Remote endpoint has rejected request to close logical "
2581                    "channel %d - cause INVALID. (%s, %s)\n", 
2582                    rccReject->forwardLogicalChannelNumber, call->callType, 
2583                    call->callToken);
2584    }
2585    OOTRACEDBGA4("Clearing logical channel %d. (%s, %s)\n", 
2586                  rccReject->forwardLogicalChannelNumber, call->callType, 
2587                  call->callToken);
2588    ret = ooClearLogicalChannel(call, rccReject->forwardLogicalChannelNumber);
2589    if(ret != OO_OK)
2590    {
2591       OOTRACEERR4("Error: failed to clear logical channel %d.(%s, %s)\n", 
2592                    rccReject->forwardLogicalChannelNumber, call->callType, 
2593                    call->callToken);
2594    }
2595    return ret;
2596 }
2597
2598 /****/
2599 int ooOnReceivedCloseLogicalChannel(OOH323CallData *call, 
2600                                     H245CloseLogicalChannel* clc)
2601 {
2602    int ret=0;
2603    H245Message *ph245msg = NULL;
2604    OOCTXT *pctxt = NULL;
2605    H245CloseLogicalChannelAck * clcAck;
2606    H245ResponseMessage *response;
2607    
2608    OOTRACEINFO4("Closing logical channel number %d (%s, %s)\n",
2609       clc->forwardLogicalChannelNumber, call->callType, call->callToken);
2610    
2611    ret = ooClearLogicalChannel(call, clc->forwardLogicalChannelNumber);
2612    if(ret != OO_OK)
2613    {
2614       OOTRACEERR4("ERROR:Failed to close logical channel %d (%s, %s)\n",
2615          clc->forwardLogicalChannelNumber, call->callType, call->callToken);
2616       return OO_FAILED;
2617    }
2618
2619    ret = ooCreateH245Message(call, &ph245msg, 
2620                               T_H245MultimediaSystemControlMessage_response);
2621    if(ret != OO_OK)
2622    {
2623       OOTRACEERR3("ERROR:Failed to create H245 message for "
2624                   "closeLogicalChannelAck (%s, %s)\n", call->callType, 
2625                   call->callToken);
2626       return OO_FAILED;
2627    }
2628    /* pctxt = &gH323ep.msgctxt; */
2629    pctxt = call->msgctxt;
2630    ph245msg->msgType = OOCloseLogicalChannelAck;
2631    ph245msg->logicalChannelNo = clc->forwardLogicalChannelNumber;
2632    response = ph245msg->h245Msg.u.response;
2633    response->t = T_H245ResponseMessage_closeLogicalChannelAck;
2634    response->u.closeLogicalChannelAck = (H245CloseLogicalChannelAck*)
2635                          ASN1MALLOC(pctxt, sizeof(H245CloseLogicalChannelAck));
2636    clcAck = response->u.closeLogicalChannelAck;
2637    if(!clcAck)
2638    {
2639       OOTRACEERR3("ERROR:Failed to allocate memory for closeLogicalChannelAck "
2640                   "(%s, %s)\n", call->callType, call->callToken);
2641       return OO_OK;
2642    }
2643    memset(clcAck, 0, sizeof(H245CloseLogicalChannelAck));
2644    clcAck->forwardLogicalChannelNumber = clc->forwardLogicalChannelNumber;
2645
2646    OOTRACEDBGA3("Built CloseLogicalChannelAck message (%s, %s)\n",
2647                  call->callType, call->callToken);
2648    ret = ooSendH245Msg(call, ph245msg);
2649    if(ret != OO_OK)
2650    {
2651      OOTRACEERR3("Error:Failed to enqueue CloseLogicalChannelAck message to "
2652                  "outbound queue.(%s, %s)\n", call->callType, call->callToken);
2653    }
2654
2655    ooFreeH245Message(call, ph245msg);
2656    return ret;
2657 }
2658
2659 int ooOnReceivedCloseChannelAck(OOH323CallData* call, 
2660                                 H245CloseLogicalChannelAck* clcAck)
2661 {
2662    int ret = OO_OK;
2663    return ret;
2664 }
2665
2666 int ooHandleH245Message(OOH323CallData *call, H245Message * pmsg)
2667 {
2668    ASN1UINT i;
2669    DListNode *pNode = NULL;
2670    OOTimer *pTimer = NULL;
2671    H245Message *pH245 = (H245Message*)pmsg;
2672    /* There are four major types of H.245 messages that can be received.
2673       Request/Response/Command/Indication. Each one of them need to be 
2674       handled separately.
2675    */   
2676    H245RequestMessage *request = NULL;
2677    H245ResponseMessage *response = NULL;
2678    H245CommandMessage *command = NULL;
2679    H245IndicationMessage *indication = NULL;
2680    
2681    OOTRACEDBGC3("Handling H245 message. (%s, %s)\n", call->callType, 
2682                  call->callToken);
2683    
2684    switch(pH245->h245Msg.t)
2685    {
2686       /* H.245 Request message is received */
2687       case (T_H245MultimediaSystemControlMessage_request):
2688          request = pH245->h245Msg.u.request;
2689          switch(request->t)
2690          {
2691             case T_H245RequestMessage_terminalCapabilitySet:
2692                /* If session isn't marked active yet, do it. possible in case of 
2693                   tunneling */
2694                if(call->h245SessionState == OO_H245SESSION_IDLE)
2695                   call->h245SessionState = OO_H245SESSION_ACTIVE; 
2696
2697                ooOnReceivedTerminalCapabilitySet(call, pH245);
2698                if(call->localTermCapState == OO_LocalTermCapExchange_Idle)
2699                   ooSendTermCapMsg(call);
2700                break;
2701             case T_H245RequestMessage_masterSlaveDetermination:
2702                ooHandleMasterSlave(call, 
2703                                      request->u.masterSlaveDetermination, 
2704                                      OOMasterSlaveDetermination);
2705                break;
2706             case T_H245RequestMessage_openLogicalChannel:
2707                ooHandleOpenLogicalChannel(call, 
2708                                           request->u.openLogicalChannel);
2709                 if(!ooGetTransmitLogicalChannel(call))
2710                         ooOpenLogicalChannels(call);
2711                break;
2712             case T_H245RequestMessage_requestMode:
2713                 OOTRACEINFO4("Received request mode - %d (%s, %s)\n",
2714                 request->u.requestMode->sequenceNumber, call->callType, call->callToken);
2715                ooHandleRequestMode(call, 
2716                                         request->u.requestMode);
2717                 break;
2718             case T_H245RequestMessage_closeLogicalChannel:
2719                OOTRACEINFO4("Received close logical Channel - %d (%s, %s)\n",
2720                   request->u.closeLogicalChannel->forwardLogicalChannelNumber, 
2721                   call->callType, call->callToken);
2722                if (ooOnReceivedCloseLogicalChannel(call, 
2723                                                request->u.closeLogicalChannel) == OO_OK) {
2724                         ooCloseAllLogicalChannels(call, NULL);
2725                }
2726                break;
2727             case T_H245RequestMessage_requestChannelClose:
2728                OOTRACEINFO4("Received RequestChannelClose - %d (%s, %s)\n",
2729                   request->u.requestChannelClose->forwardLogicalChannelNumber, 
2730                   call->callType, call->callToken);
2731                ooOnReceivedRequestChannelClose(call, 
2732                                                request->u.requestChannelClose);
2733                break;
2734              case T_H245RequestMessage_roundTripDelayRequest:
2735                OOTRACEINFO4("Received roundTripDelayRequest - %d (%s, %s)\n",
2736                   request->u.roundTripDelayRequest->sequenceNumber,  call->callType, call->callToken);
2737                ooOnReceivedRoundTripDelayRequest(call, request->u.roundTripDelayRequest->sequenceNumber);
2738                break;
2739             default:
2740                ;
2741          } /* End of Request Message */
2742          break;
2743       /* H.245 Response message is received */ 
2744       case (T_H245MultimediaSystemControlMessage_response):
2745          response = pH245->h245Msg.u.response;
2746          switch(response->t)
2747          {
2748             case T_H245ResponseMessage_masterSlaveDeterminationAck:
2749                /* Disable MSD timer */
2750                for(i = 0; i<call->timerList.count; i++)
2751                {
2752                   pNode = dListFindByIndex(&call->timerList, i);
2753                   pTimer = (OOTimer*)pNode->data;
2754                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_MSD_TIMER)
2755                   {
2756                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2757                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2758                      OOTRACEDBGC3("Deleted MSD Timer. (%s, %s)\n", call->callType,
2759                    call->callToken);
2760                      break;
2761                   }
2762                }
2763
2764                ooHandleMasterSlave(call, 
2765                                    response->u.masterSlaveDeterminationAck, 
2766                                    OOMasterSlaveAck);
2767                break;
2768             case T_H245ResponseMessage_masterSlaveDeterminationReject:
2769                /* Disable MSD timer */
2770                for(i = 0; i<call->timerList.count; i++)
2771                {
2772                   pNode = dListFindByIndex(&call->timerList, i);
2773                   pTimer = (OOTimer*)pNode->data;
2774                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_MSD_TIMER)
2775                   {
2776                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2777                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2778                      OOTRACEDBGC3("Deleted MSD Timer. (%s, %s)\n", call->callType,
2779                    call->callToken);
2780                      break;
2781                   }
2782                }
2783                ooHandleMasterSlaveReject(call, 
2784                                   response->u.masterSlaveDeterminationReject);
2785                break;
2786             case T_H245ResponseMessage_terminalCapabilitySetAck:
2787                /* Disable TCS timer */
2788                for(i = 0; i<call->timerList.count; i++)
2789                {
2790                   pNode = dListFindByIndex(&call->timerList, i);
2791                   pTimer = (OOTimer*)pNode->data;
2792                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_TCS_TIMER)
2793                   {
2794                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2795                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2796                      OOTRACEDBGC3("Deleted TCS Timer. (%s, %s)\n", call->callType,
2797                         call->callToken);
2798                      break;
2799                   }
2800                }
2801                ooOnReceivedTerminalCapabilitySetAck(call);
2802                break;
2803             case T_H245ResponseMessage_terminalCapabilitySetReject:
2804                OOTRACEINFO3("TerminalCapabilitySetReject message received."
2805                             " (%s, %s)\n", call->callType, call->callToken);
2806                if(response->u.terminalCapabilitySetReject->sequenceNumber != 
2807                   call->localTermCapSeqNo)
2808                {
2809                   OOTRACEINFO5("Ignoring TCSReject with mismatched seqno %d "
2810                               "(local - %d). (%s, %s)\n", 
2811                           response->u.terminalCapabilitySetReject->sequenceNumber,
2812                         call->localTermCapSeqNo, call->callType, call->callToken);
2813                   break;
2814                }
2815                /* Disable TCS timer */
2816                for(i = 0; i<call->timerList.count; i++)
2817                {
2818                   pNode = dListFindByIndex(&call->timerList, i);
2819                   pTimer = (OOTimer*)pNode->data;
2820                   if(((ooTimerCallback*)pTimer->cbData)->timerType & OO_TCS_TIMER)
2821                   {
2822                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2823                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2824                      OOTRACEDBGC3("Deleted TCS Timer. (%s, %s)\n", call->callType,
2825                         call->callToken);
2826                      break;
2827                   }
2828                }
2829                if(call->callState < OO_CALL_CLEAR)
2830                {
2831                   call->callState = OO_CALL_CLEAR;
2832                   call->callEndReason = OO_REASON_NOCOMMON_CAPABILITIES;
2833                }
2834                break;
2835             case T_H245ResponseMessage_requestModeAck:
2836                if (call->requestSequence == response->u.requestModeAck->sequenceNumber) {
2837                         /* response to our last request, process it */
2838                         ooOnReceivedRequestModeAck(call, response->u.requestModeAck);
2839                }
2840                break;
2841             case T_H245ResponseMessage_requestModeReject:
2842                 OOTRACEDBGC3("Received requestModeReject, clearing call (%s, %s)\n",
2843                                  call->callType, call->callToken);
2844                if(call->callState < OO_CALL_CLEAR)
2845                {
2846                   call->callState = OO_CALL_CLEAR;
2847                   call->callEndReason = OO_REASON_REMOTE_REJECTED;
2848                }
2849                break;
2850             case T_H245ResponseMessage_openLogicalChannelAck:
2851                for(i = 0; i<call->timerList.count; i++)
2852                {
2853                   pNode = dListFindByIndex(&call->timerList, i);
2854                   pTimer = (OOTimer*)pNode->data;
2855                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_OLC_TIMER)                                            && 
2856                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
2857                    response->u.openLogicalChannelAck->forwardLogicalChannelNumber)
2858                   {
2859
2860                      memFreePtr(call->pctxt, pTimer->cbData);
2861                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2862                      OOTRACEDBGC3("Deleted OpenLogicalChannel Timer. (%s, %s)\n", 
2863                                    call->callType, call->callToken);
2864                      break;
2865                   }
2866                }
2867                ooOnReceivedOpenLogicalChannelAck(call, 
2868                                               response->u.openLogicalChannelAck);
2869                break;
2870             case T_H245ResponseMessage_openLogicalChannelReject:
2871                OOTRACEINFO3("Open Logical Channel Reject received (%s, %s)\n",
2872                              call->callType, call->callToken);
2873                for(i = 0; i<call->timerList.count; i++)
2874                {
2875                   pNode = dListFindByIndex(&call->timerList, i);
2876                   pTimer = (OOTimer*)pNode->data;
2877                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_OLC_TIMER)                                            && 
2878                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
2879                    response->u.openLogicalChannelAck->forwardLogicalChannelNumber)
2880                   {
2881
2882                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2883                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2884                      OOTRACEDBGC3("Deleted OpenLogicalChannel Timer. (%s, %s)\n", 
2885                                    call->callType, call->callToken);
2886                      break;
2887                   }
2888                }
2889                ooOnReceivedOpenLogicalChannelRejected(call, 
2890                                         response->u.openLogicalChannelReject);
2891                break;
2892             case T_H245ResponseMessage_closeLogicalChannelAck:
2893                OOTRACEINFO4("CloseLogicalChannelAck received for %d (%s, %s)\n",
2894                   response->u.closeLogicalChannelAck->forwardLogicalChannelNumber,
2895                   call->callType, call->callToken);
2896                for(i = 0; i<call->timerList.count; i++)
2897                {
2898                   pNode = dListFindByIndex(&call->timerList, i);
2899                   pTimer = (OOTimer*)pNode->data;
2900                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_CLC_TIMER)                                            && 
2901                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
2902                   response->u.closeLogicalChannelAck->forwardLogicalChannelNumber)
2903                   {
2904
2905                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2906                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2907                      OOTRACEDBGC3("Deleted CloseLogicalChannel Timer. (%s, %s)\n",
2908                                    call->callType, call->callToken);
2909                      break;
2910                   }
2911                }
2912                ooOnReceivedCloseChannelAck(call, 
2913                                            response->u.closeLogicalChannelAck);
2914                 if(!ooGetTransmitLogicalChannel(call))
2915                         ooOpenLogicalChannels(call);
2916                break;
2917             case T_H245ResponseMessage_requestChannelCloseAck:
2918                 OOTRACEINFO4("RequestChannelCloseAck received - %d (%s, %s)\n",
2919                   response->u.requestChannelCloseAck->forwardLogicalChannelNumber,
2920                   call->callType, call->callToken);
2921                 for(i = 0; i<call->timerList.count; i++)
2922                 {
2923                   pNode = dListFindByIndex(&call->timerList, i);
2924                   pTimer = (OOTimer*)pNode->data;
2925                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_RCC_TIMER)                                            && 
2926                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
2927                   response->u.requestChannelCloseAck->forwardLogicalChannelNumber)
2928                   {
2929
2930                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2931                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2932                      OOTRACEDBGC3("Deleted RequestChannelClose Timer. (%s, %s)\n",
2933                                    call->callType, call->callToken);
2934                      break;
2935                   }
2936                 }
2937                 ooOnReceivedRequestChannelCloseAck(call, 
2938                                              response->u.requestChannelCloseAck);
2939                 break;
2940             case T_H245ResponseMessage_requestChannelCloseReject:
2941                OOTRACEINFO4("RequestChannelCloseReject received - %d (%s, %s)\n",
2942                response->u.requestChannelCloseReject->forwardLogicalChannelNumber,
2943                  call->callType, call->callToken);
2944                 for(i = 0; i<call->timerList.count; i++)
2945                 {
2946                   pNode = dListFindByIndex(&call->timerList, i);
2947                   pTimer = (OOTimer*)pNode->data;
2948                   if((((ooTimerCallback*)pTimer->cbData)->timerType & OO_RCC_TIMER) && 
2949                       ((ooTimerCallback*)pTimer->cbData)->channelNumber == 
2950                       response->u.requestChannelCloseReject->forwardLogicalChannelNumber)
2951                   {
2952
2953                      ASN1MEMFREEPTR(call->pctxt, pTimer->cbData);
2954                      ooTimerDelete(call->pctxt, &call->timerList, pTimer);
2955                      OOTRACEDBGC3("Deleted RequestChannelClose Timer. (%s, %s)\n",
2956                                    call->callType, call->callToken);
2957                      break;
2958                   }
2959                }
2960                ooOnReceivedRequestChannelCloseReject(call, 
2961                                            response->u.requestChannelCloseReject);
2962                break;
2963              case T_H245ResponseMessage_roundTripDelayResponse:
2964                OOTRACEINFO4("Received roundTripDelayResponse - %d (%s, %s)\n",
2965                   response->u.roundTripDelayResponse->sequenceNumber,  call->callType, call->callToken);
2966                call->rtdrRecv = response->u.roundTripDelayResponse->sequenceNumber;
2967                break;
2968             default:
2969                ;
2970          }
2971          break;
2972       /* H.245 command message is received */
2973       case (T_H245MultimediaSystemControlMessage_command):
2974          command = pH245->h245Msg.u.command;
2975          ooHandleH245Command(call, command);
2976          break;
2977       /* H.245 Indication message received */
2978       case (T_H245MultimediaSystemControlMessage_indication):
2979          indication = pH245->h245Msg.u.indication;
2980          switch(indication->t)
2981          {
2982             case T_H245IndicationMessage_userInput:
2983                ooOnReceivedUserInputIndication(call, indication->u.userInput);
2984                break;
2985             default:
2986                OOTRACEWARN3("Unhandled indication message received.(%s, %s)\n",
2987                              call->callType, call->callToken);
2988          }
2989          break;
2990       default:
2991         ;
2992    }
2993    OOTRACEDBGC3("Finished handling H245 message. (%s, %s)\n", 
2994                  call->callType, call->callToken);
2995    return OO_OK;
2996 }
2997
2998
2999 int ooOnReceivedUserInputIndication
3000    (OOH323CallData *call, H245UserInputIndication *indication)
3001 {
3002    if((indication->t == T_H245UserInputIndication_alphanumeric) && 
3003       (call->dtmfmode & OO_CAP_DTMF_H245_alphanumeric))
3004    {
3005       if(gH323ep.h323Callbacks.onReceivedDTMF)
3006          gH323ep.h323Callbacks.onReceivedDTMF(call,indication->u.alphanumeric);
3007    }
3008    else if((indication->t == T_H245UserInputIndication_signal) && 
3009            (call->dtmfmode & OO_CAP_DTMF_H245_signal)) {
3010       if(call->lastDTMF && indication->u.signal->signalType[0] == call->lastDTMF &&
3011          call->nextDTMFstamp && indication->u.signal->m.rtpPresent && 
3012          indication->u.signal->rtp.m.timestampPresent) {
3013           if(call->nextDTMFstamp > indication->u.signal->rtp.timestamp) {
3014             OOTRACEERR4("ERROR:Duplicate dtmf %c on ((%s, %s)\n", call->lastDTMF, call->callType, 
3015                         call->callToken);
3016             return OO_OK;
3017           }
3018       }
3019       if (indication->u.signal->m.rtpPresent && indication->u.signal->rtp.m.timestampPresent &&
3020           indication->u.signal->m.durationPresent) {
3021           call->nextDTMFstamp = indication->u.signal->rtp.timestamp +
3022                                 indication->u.signal->duration;
3023           call->lastDTMF = indication->u.signal->signalType[0];
3024       } else {
3025           call->nextDTMFstamp = 0;
3026           call->lastDTMF = 0;
3027       }
3028       if(gH323ep.h323Callbacks.onReceivedDTMF)
3029          gH323ep.h323Callbacks.onReceivedDTMF(call, 
3030                                              indication->u.signal->signalType);
3031    }
3032    else {
3033       OOTRACEINFO3("Unsupported userInput message type received - ignoring."
3034                    "(%s, %s)\n", call->callType, call->callToken);
3035    }
3036    return OO_OK;
3037 }
3038
3039 int ooOnReceivedTerminalCapabilitySet(OOH323CallData *call, H245Message *pmsg)
3040 {
3041    int ret = 0,k;
3042    H245TerminalCapabilitySet *tcs=NULL;
3043    DListNode *pNode=NULL;
3044    H245CapabilityTableEntry *capEntry = NULL;
3045
3046    tcs =  pmsg->h245Msg.u.request->u.terminalCapabilitySet;
3047    if(call->remoteTermCapSeqNo > tcs->sequenceNumber)
3048    {
3049       OOTRACEINFO4("Rejecting TermCapSet message with SeqNo %d, as already "
3050                    "acknowledged message with this SeqNo (%s, %s)\n", 
3051                    call->remoteTermCapSeqNo, call->callType, call->callToken);
3052       ooSendTerminalCapabilitySetReject(call, tcs->sequenceNumber, 
3053                          T_H245TerminalCapabilitySetReject_cause_unspecified);
3054       return OO_OK;
3055
3056     } else {
3057 /* 20090924 */
3058 /* bogus soft-switch can send more than one request with  cap set
3059    if it goto to next choice. Right swith don't send but not all are right ;(
3060    we can accept new capability set only. We must remember also that new join caps
3061    will be previously joined caps with new cap set.
3062  */
3063    if(call->remoteTermCapSeqNo == tcs->sequenceNumber)
3064     call->localTermCapState = OO_LocalTermCapExchange_Idle;
3065    }
3066   
3067    if(!tcs->m.capabilityTablePresent)
3068    {
3069       // OOTRACEWARN3("Warn:Ignoring TCS as no capability table present(%s, %s)\n",
3070       OOTRACEWARN3("Empty TCS found.  Pausing call...(%s, %s)\n",
3071                     call->callType, call->callToken);
3072       call->h245SessionState = OO_H245SESSION_PAUSED;
3073       //ooSendTerminalCapabilitySetReject(call, tcs->sequenceNumber, 
3074       //                   T_H245TerminalCapabilitySetReject_cause_unspecified);
3075       //return OO_OK;
3076    }
3077    call->remoteTermCapSeqNo = tcs->sequenceNumber;
3078
3079    if(tcs->m.capabilityTablePresent) {
3080       for(k=0; k<(int)tcs->capabilityTable.count; k++)
3081       {
3082          pNode = dListFindByIndex(&tcs->capabilityTable, k);
3083          if(pNode)
3084          {
3085             OOTRACEDBGC4("Processing CapabilityTable Entry %d (%s, %s)\n", 
3086                           k, call->callType, call->callToken);
3087             capEntry = (H245CapabilityTableEntry*) pNode->data;
3088             if(capEntry->m.capabilityPresent){
3089                ret =  ooAddRemoteCapability(call, &capEntry->capability);
3090                if(ret != OO_OK)
3091                {
3092                   OOTRACEERR4("Error:Failed to process remote capability in "
3093                               "capability table at index %d. (%s, %s)\n", 
3094                                k, call->callType, call->callToken);
3095                }
3096                ooCapabilityUpdateJointCapabilities(call, &capEntry->capability);
3097             }
3098          }
3099          pNode = NULL;
3100          capEntry=NULL;
3101       }
3102    }
3103
3104    if (call->t38sides == 3) /* both side support t.38 */
3105         OO_SETFLAG(call->flags, OO_M_T38SUPPORTED);
3106    else
3107         OO_CLRFLAG(call->flags, OO_M_T38SUPPORTED);
3108    
3109    /* Update remoteTermCapSetState */
3110    call->remoteTermCapState = OO_RemoteTermCapSetRecvd;
3111
3112    ooH245AcknowledgeTerminalCapabilitySet(call);   
3113
3114    /* If we haven't yet send TCS then send it now */
3115    if(call->localTermCapState == OO_LocalTermCapExchange_Idle)
3116    {
3117       ret = ooSendTermCapMsg(call);
3118       if(ret != OO_OK)
3119       {
3120          OOTRACEERR3("ERROR:Sending Terminal capability message (%s, %s)\n",
3121                       call->callType, call->callToken);
3122          return ret;
3123       }
3124    }
3125
3126    if(call->remoteTermCapState != OO_RemoteTermCapSetAckSent ||
3127       call->localTermCapState  != OO_LocalTermCapSetAckRecvd)
3128       return OO_OK;
3129
3130    /* Check MasterSlave procedure has finished */
3131    if(call->masterSlaveState != OO_MasterSlave_Master &&
3132       call->masterSlaveState != OO_MasterSlave_Slave)
3133       return OO_OK;
3134
3135    /* As both MasterSlave and TerminalCapabilitySet procedures have finished,
3136       OpenLogicalChannels */
3137  
3138    if(gH323ep.h323Callbacks.openLogicalChannels)
3139       gH323ep.h323Callbacks.openLogicalChannels(call);
3140    if(!ooGetTransmitLogicalChannel(call))
3141       ooOpenLogicalChannels(call);
3142 #if 0
3143    if(!call->logicalChans){
3144       if(!gH323ep.h323Callbacks.openLogicalChannels)
3145          ret = ooOpenLogicalChannels(call);
3146       else
3147          gH323ep.h323Callbacks.openLogicalChannels(call);
3148    }
3149 #endif
3150    return OO_OK;
3151 }
3152
3153 int ooSendTerminalCapabilitySetReject
3154                         (OOH323CallData *call, int seqNo, ASN1UINT cause)
3155 {
3156    H245Message *ph245msg=NULL;
3157    H245ResponseMessage * response=NULL;
3158    OOCTXT *pctxt=NULL;
3159    int ret = ooCreateH245Message(call, &ph245msg, 
3160                       T_H245MultimediaSystemControlMessage_response);
3161    if(ret != OO_OK)
3162    {
3163       OOTRACEERR1("ERROR:H245 message creation failed for - "
3164                            "TerminalCapabilitySetReject\n");
3165       return OO_FAILED;
3166    }
3167    ph245msg->msgType = OOTerminalCapabilitySetReject;
3168    response = ph245msg->h245Msg.u.response;
3169    memset(response, 0, sizeof(H245ResponseMessage));
3170    /* pctxt = &gH323ep.msgctxt; */
3171    pctxt = call->msgctxt;
3172    response->t = T_H245ResponseMessage_terminalCapabilitySetReject;
3173    
3174    response->u.terminalCapabilitySetReject = (H245TerminalCapabilitySetReject*)
3175                    ASN1MALLOC(pctxt, sizeof(H245TerminalCapabilitySetReject));
3176
3177    memset(response->u.terminalCapabilitySetReject, 0, 
3178                                  sizeof(H245TerminalCapabilitySetReject));
3179    response->u.terminalCapabilitySetReject->sequenceNumber = seqNo;
3180    response->u.terminalCapabilitySetReject->cause.t = cause;
3181
3182    OOTRACEDBGA3("Built TerminalCapabilitySetReject (%s, %s)\n", 
3183                  call->callType, call->callToken);
3184  
3185    ret = ooSendH245Msg(call, ph245msg);
3186    if(ret != OO_OK)
3187    {
3188      OOTRACEERR3("Error:Failed to enqueue TCSReject to outbound queue. "
3189                  "(%s, %s)\n", call->callType, call->callToken);
3190    }
3191    else
3192       call->remoteTermCapState = OO_RemoteTermCapExchange_Idle;
3193
3194    ooFreeH245Message(call, ph245msg);
3195    return ret;
3196 }
3197
3198 int ooH245AcknowledgeTerminalCapabilitySet(OOH323CallData *call)
3199 {
3200    H245Message *ph245msg=NULL;
3201    H245ResponseMessage * response=NULL;
3202    OOCTXT *pctxt=NULL;
3203    int ret = ooCreateH245Message(call, &ph245msg, 
3204                       T_H245MultimediaSystemControlMessage_response);
3205    if(ret != OO_OK)
3206    {
3207       OOTRACEERR1("ERROR:H245 message creation failed for - "
3208                            "TerminalCapability Set Ack\n");
3209       return OO_FAILED;
3210    }
3211    ph245msg->msgType = OOTerminalCapabilitySetAck;
3212    response = ph245msg->h245Msg.u.response;
3213    memset(response, 0, sizeof(H245ResponseMessage));
3214    /* pctxt = &gH323ep.msgctxt; */
3215    pctxt = call->msgctxt;
3216    response->t = T_H245ResponseMessage_terminalCapabilitySetAck;
3217    
3218    response->u.terminalCapabilitySetAck = (H245TerminalCapabilitySetAck*)
3219                    ASN1MALLOC(pctxt, sizeof(H245TerminalCapabilitySetAck));
3220
3221    memset(response->u.terminalCapabilitySetAck, 0, 
3222                                  sizeof(H245TerminalCapabilitySetAck));
3223    response->u.terminalCapabilitySetAck->sequenceNumber = call->remoteTermCapSeqNo;
3224
3225    OOTRACEDBGA3("Built TerminalCapabilitySet Ack (%s, %s)\n", 
3226                  call->callType, call->callToken);
3227    ret = ooSendH245Msg(call, ph245msg);
3228
3229    if(ret != OO_OK)
3230    {
3231      OOTRACEERR3("Error:Failed to enqueue TCSAck to outbound queue. (%s, %s)\n", call->callType, call->callToken);
3232    }
3233    else
3234       call->remoteTermCapState = OO_RemoteTermCapSetAckSent;
3235
3236    ooFreeH245Message(call, ph245msg);
3237    return ret;
3238 }
3239
3240
3241 int ooSendTerminalCapabilitySetRelease(OOH323CallData * call)
3242 {
3243    int ret=0;
3244    H245IndicationMessage* indication=NULL;
3245    H245Message *ph245msg=NULL;
3246    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
3247    OOCTXT *pctxt=call->msgctxt;
3248
3249    ret = ooCreateH245Message
3250       (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication);
3251
3252    if (ret != OO_OK) {
3253       OOTRACEERR3("Error:H245 message creation failed for - Terminal"
3254                   "CapabilitySetRelease (%s, %s)\n",call->callType, 
3255                   call->callToken);
3256       return OO_FAILED;
3257    }
3258    ph245msg->msgType = OOTerminalCapabilitySetRelease;
3259    indication = ph245msg->h245Msg.u.indication;
3260
3261    indication->t = T_H245IndicationMessage_terminalCapabilitySetRelease;
3262
3263    indication->u.terminalCapabilitySetRelease = 
3264       (H245TerminalCapabilitySetRelease*)
3265       memAlloc (pctxt, sizeof(H245TerminalCapabilitySetRelease));
3266
3267    if(!indication->u.terminalCapabilitySetRelease)
3268    {
3269       OOTRACEERR3("Error: Failed to allocate memory for TCSRelease message."
3270                   " (%s, %s)\n", call->callType, call->callToken);
3271       ooFreeH245Message(call, ph245msg);
3272       return OO_FAILED;
3273    }
3274    OOTRACEDBGA3 ("Built TerminalCapabilitySetRelease (%s, %s)\n", 
3275                  call->callType, call->callToken);
3276
3277    ret = ooSendH245Msg (call, ph245msg);
3278
3279    if (ret != OO_OK) {
3280       OOTRACEERR3 
3281          ("Error:Failed to enqueue TerminalCapabilitySetRelease "
3282          "message to outbound queue.(%s, %s)\n", call->callType, 
3283          call->callToken);
3284    }
3285    
3286    ooFreeH245Message (call, ph245msg);
3287    return ret;
3288 }
3289
3290
3291 int ooSendH245UserInputIndication_alphanumeric
3292    (OOH323CallData *call, const char *data)
3293 {
3294    int ret=0;
3295    H245IndicationMessage* indication=NULL;
3296    H245Message *ph245msg=NULL;
3297    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
3298    OOCTXT *pctxt=call->msgctxt;
3299
3300    ret = ooCreateH245Message
3301       (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication);
3302
3303    if (ret != OO_OK) {
3304       OOTRACEERR3("Error:H245 message creation failed for - H245UserInput"
3305                   "Indication_alphanumeric (%s, %s)\n",call->callType, 
3306                   call->callToken);
3307       return OO_FAILED;
3308    }
3309    ph245msg->msgType = OOUserInputIndication;
3310    indication = ph245msg->h245Msg.u.indication;
3311
3312    indication->t = T_H245IndicationMessage_userInput;
3313    indication->u.userInput = 
3314       (H245UserInputIndication*)
3315       memAllocZ (pctxt, sizeof(H245UserInputIndication));
3316
3317    if(!indication->u.userInput)
3318    {
3319       OOTRACEERR3("Error: Memory - ooH245UserInputIndication_alphanumeric - "
3320                   " userInput (%s, %s)\n", call->callType, call->callToken);
3321       ooFreeH245Message(call, ph245msg);
3322       return OO_FAILED;
3323    }
3324    indication->u.userInput->t = T_H245UserInputIndication_alphanumeric;
3325    indication->u.userInput->u.alphanumeric = (ASN1GeneralString)
3326                                               memAlloc(pctxt, strlen(data)+1);
3327    if(!indication->u.userInput->u.alphanumeric)
3328    {
3329       OOTRACEERR3("Error: Memory - ooH245UserInputIndication-alphanumeric - "
3330                   "alphanumeric (%s, %s).\n", call->callType, call->callToken);
3331       ooFreeH245Message(call, ph245msg);
3332       return OO_FAILED;
3333    }
3334    strcpy(*(char**)&indication->u.userInput->u.alphanumeric, data);
3335    OOTRACEDBGA3 ("Built UserInputIndication_alphanumeric (%s, %s)\n", 
3336                  call->callType, call->callToken);
3337
3338    ret = ooSendH245Msg (call, ph245msg);
3339
3340    if (ret != OO_OK) {
3341       OOTRACEERR3 
3342          ("Error:Failed to enqueue UserInputIndication_alphanumeric "
3343           "message to outbound queue.(%s, %s)\n", call->callType, 
3344           call->callToken);
3345    }
3346    
3347    ooFreeH245Message (call, ph245msg);
3348    return ret;
3349 }
3350
3351 int ooSendH245UserInputIndication_signal
3352    (OOH323CallData *call, const char *data)
3353 {
3354    int ret=0;
3355    H245IndicationMessage* indication=NULL;
3356    H245Message *ph245msg=NULL;
3357    /* OOCTXT *pctxt=&gH323ep.msgctxt; */
3358    OOCTXT *pctxt=call->msgctxt;
3359
3360    ret = ooCreateH245Message
3361       (call, &ph245msg, T_H245MultimediaSystemControlMessage_indication);
3362
3363    if (ret != OO_OK) {
3364       OOTRACEERR3("Error:H245 message creation failed for - H245UserInput"
3365                   "Indication_signal (%s, %s)\n",call->callType, 
3366                   call->callToken);
3367       return OO_FAILED;
3368    }
3369    ph245msg->msgType = OOUserInputIndication;
3370    indication = ph245msg->h245Msg.u.indication;
3371
3372    indication->t = T_H245IndicationMessage_userInput;
3373    indication->u.userInput = 
3374       (H245UserInputIndication*)
3375       memAllocZ (pctxt, sizeof(H245UserInputIndication));
3376
3377    if(!indication->u.userInput)
3378    {
3379       OOTRACEERR3("Error: Memory - ooH245UserInputIndication_signal - "
3380                   " userInput (%s, %s)\n", call->callType, call->callToken);
3381       ooFreeH245Message(call, ph245msg);
3382       return OO_FAILED;
3383    }
3384    indication->u.userInput->t = T_H245UserInputIndication_signal;
3385    indication->u.userInput->u.signal = (H245UserInputIndication_signal*)
3386                       memAllocZ(pctxt, sizeof(H245UserInputIndication_signal));
3387    indication->u.userInput->u.signal->signalType = (ASN1IA5String)
3388                                               memAlloc(pctxt, strlen(data)+1);
3389    if(!indication->u.userInput->u.signal ||
3390       !indication->u.userInput->u.signal->signalType)
3391    {
3392       OOTRACEERR3("Error: Memory - ooH245UserInputIndication_signal - "
3393                   "signal (%s, %s).\n", call->callType, call->callToken);
3394       ooFreeH245Message(call, ph245msg);
3395       return OO_FAILED;
3396    }
3397    strcpy(*(char**)&indication->u.userInput->u.signal->signalType, data);
3398    OOTRACEDBGA3 ("Built UserInputIndication_signal (%s, %s)\n", 
3399                  call->callType, call->callToken);
3400
3401    ret = ooSendH245Msg (call, ph245msg);
3402
3403    if (ret != OO_OK) {
3404       OOTRACEERR3 
3405          ("Error:Failed to enqueue UserInputIndication_signal "
3406           "message to outbound queue.(%s, %s)\n", call->callType, 
3407           call->callToken);
3408    }
3409    
3410    ooFreeH245Message (call, ph245msg);
3411    return ret;
3412 }
3413
3414
3415 int ooOpenLogicalChannels(OOH323CallData *call)
3416 {
3417    int ret=0;
3418    OOTRACEINFO3("Opening logical channels (%s, %s)\n", call->callType, 
3419                  call->callToken); 
3420
3421    /* Audio channels */
3422    if(gH323ep.callMode == OO_CALLMODE_AUDIOCALL ||
3423       gH323ep.callMode == OO_CALLMODE_AUDIOTX)
3424    {
3425       if (OO_TESTFLAG (call->flags, OO_M_AUDIOSESSION)) {
3426          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_AUDIO);
3427       } else if (OO_TESTFLAG (call->flags, OO_M_DATASESSION)) {
3428          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_DATA);
3429       }
3430       if(ret != OO_OK) {
3431        OOTRACEERR3("ERROR:Failed to open audio/data channels. Clearing call."
3432                    "(%s, %s)\n", call->callType, call->callToken);
3433        if (call->callState < OO_CALL_CLEAR) {
3434         call->callEndReason = OO_REASON_LOCAL_CLEARED;
3435         call->callState = OO_CALL_CLEAR;
3436        }
3437        return ret;
3438       }
3439    }
3440    
3441    if(gH323ep.callMode == OO_CALLMODE_VIDEOCALL)
3442    {
3443      /*      if (!OO_TESTFLAG (call->flags, OO_M_AUDIOSESSION))
3444         {*/
3445          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_AUDIO);
3446          if(ret != OO_OK)
3447          {
3448             OOTRACEERR3("ERROR:Failed to open audio channel. Clearing call."
3449                         "(%s, %s)\n", call->callType, call->callToken);
3450             if(call->callState < OO_CALL_CLEAR)
3451             {
3452                call->callEndReason = OO_REASON_LOCAL_CLEARED;
3453                call->callState = OO_CALL_CLEAR;
3454             }
3455             return ret;
3456          }
3457       //}
3458       /*      if(!OO_TESTFLAG(call->flags, OO_M_VIDEOSESSION))
3459       {*/
3460          ret = ooOpenLogicalChannel(call, OO_CAP_TYPE_VIDEO);
3461          if(ret != OO_OK)
3462          {
3463             OOTRACEERR3("ERROR:Failed to open video channel. Clearing call."
3464                         "(%s, %s)\n", call->callType, call->callToken);
3465             if(call->callState < OO_CALL_CLEAR)
3466             {
3467                call->callEndReason = OO_REASON_LOCAL_CLEARED;
3468                call->callState = OO_CALL_CLEAR;
3469             }
3470             return ret;
3471          }
3472      //}
3473    }
3474    return OO_OK;
3475 }
3476
3477 /* CapType indicates whether to Open Audio or Video channel */
3478 int ooOpenLogicalChannel(OOH323CallData *call, enum OOCapType capType )
3479 {
3480    ooH323EpCapability *epCap=NULL;
3481    int k=0;
3482
3483    /* Check whether local endpoint has audio capability */
3484    if(gH323ep.myCaps == 0 && call->ourCaps == 0)
3485    {
3486       OOTRACEERR3("ERROR:Local endpoint does not have any audio capabilities"
3487                   " (%s, %s)\n", call->callType, call->callToken);
3488       return OO_FAILED;
3489    }
3490    
3491    /* Go through local endpoints capabilities sequentially, and find out the
3492       first one which has a match in the remote endpoints receive capabilities.
3493    */
3494    OOTRACEINFO3("Looking for matching capabilities. (%s, %s)\n", 
3495                  call->callType, call->callToken);
3496 /* May */
3497    if(call->masterSlaveState == OO_MasterSlave_Master)
3498    {
3499       for(k=0; k<call->capPrefs.index; k++)
3500       {
3501          /*Search for audio caps only */
3502          if(capType == OO_CAP_TYPE_AUDIO && 
3503             call->capPrefs.order[k] > OO_CAP_VIDEO_BASE)
3504             continue;
3505          /* Search for video caps only */
3506          if(capType == OO_CAP_TYPE_VIDEO && 
3507             call->capPrefs.order[k] <= OO_CAP_VIDEO_BASE)
3508             continue;
3509
3510          epCap = call->jointCaps;
3511
3512          while(epCap){
3513             if(epCap->cap == call->capPrefs.order[k] && (epCap->dir & OOTX))
3514                break;
3515             epCap = epCap->next;
3516          }
3517          if(!epCap)
3518          {
3519             OOTRACEDBGA4("Prefereed capability %d is not a local transmit "
3520                          "capability(%s, %s)\n", call->capPrefs.order[k],
3521                          call->callType, call->callToken);
3522             continue;
3523          }
3524          break;
3525       }
3526       if(!epCap)
3527       {
3528          OOTRACEERR4("ERROR:Incompatible capabilities - Can not open "
3529                   "%s channel (%s, %s)\n", 
3530                   (capType==OO_CAP_TYPE_AUDIO)?"audio":"video", call->callType,
3531                   call->callToken);
3532          return OO_FAILED;
3533       }
3534
3535    }
3536    else
3537    {
3538       epCap = call->jointCaps;
3539
3540       while(epCap){
3541          if(epCap->capType == capType && epCap->dir & OOTX) { break; }
3542          epCap = epCap->next;
3543       }
3544       if(!epCap)
3545       {
3546          OOTRACEERR4("ERROR:Incompatible audio capabilities - Can not open "
3547                   "%s channel (%s, %s)\n", 
3548                   (capType==OO_CAP_TYPE_AUDIO)?"audio":"video", call->callType,
3549                   call->callToken);
3550          return OO_FAILED;
3551       }
3552        
3553    }
3554
3555    switch(epCap->cap)
3556    {
3557    case OO_G711ALAW64K:
3558    case OO_G711ALAW56K:
3559    case OO_G711ULAW64K:
3560    case OO_G711ULAW56K:
3561    case OO_G726:
3562    case OO_G726AAL2:
3563    case OO_AMRNB:
3564    case OO_SPEEX:
3565    case OO_G728:
3566    case OO_G729:
3567    case OO_G729A:
3568    case OO_G729B:
3569    case OO_G7231:
3570    case OO_GSMFULLRATE:
3571    case OO_GSMHALFRATE:
3572    case OO_GSMENHANCEDFULLRATE:
3573    case OO_H263VIDEO:
3574    case OO_T38:
3575       ooOpenChannel(call, epCap);
3576       break;
3577
3578       
3579    default:
3580       OOTRACEERR3("ERROR:Unknown Audio Capability type (%s, %s)\n", 
3581                    call->callType, call->callToken);
3582    }
3583    return OO_OK;
3584 }
3585
3586 int ooOpenChannel(OOH323CallData* call, ooH323EpCapability *epCap)
3587 {
3588    int ret;
3589    H245Message *ph245msg = NULL;
3590    H245RequestMessage * request;
3591    OOCTXT *pctxt = NULL;
3592    H245OpenLogicalChannel_forwardLogicalChannelParameters *flcp = NULL;
3593    H245AudioCapability *audioCap = NULL;
3594    H245VideoCapability *videoCap = NULL;
3595    H245DataApplicationCapability *t38Cap = NULL;
3596    H245H2250LogicalChannelParameters *h2250lcp = NULL;
3597    H245UnicastAddress *unicastAddrs = NULL;
3598    H245UnicastAddress_iPAddress *iPAddress = NULL;
3599    unsigned session_id=0;
3600    ooLogicalChannel *pLogicalChannel = NULL;
3601    
3602    OOTRACEDBGC4("Doing Open Channel for %s. (%s, %s)\n", 
3603                  ooGetCapTypeText(epCap->cap), call->callType, 
3604                  call->callToken);
3605
3606    ret = ooCreateH245Message(call, &ph245msg, 
3607                       T_H245MultimediaSystemControlMessage_request);
3608    if(ret != OO_OK)
3609    {
3610       OOTRACEERR4("Error: H245 message creation failed for - Open %s"
3611                   "channel (%s, %s)\n", ooGetCapTypeText(epCap->cap), 
3612                   call->callType, call->callToken);
3613       return OO_FAILED;
3614    }
3615
3616    ph245msg->msgType = OOOpenLogicalChannel;
3617
3618    ph245msg->logicalChannelNo =  call->logicalChanNoCur++;
3619    if(call->logicalChanNoCur > call->logicalChanNoMax)
3620       call->logicalChanNoCur = call->logicalChanNoBase; 
3621
3622    request = ph245msg->h245Msg.u.request;
3623    /* pctxt = &gH323ep.msgctxt; */
3624    pctxt = call->msgctxt;
3625    memset(request, 0, sizeof(H245RequestMessage));
3626
3627    request->t = T_H245RequestMessage_openLogicalChannel;
3628    request->u.openLogicalChannel = (H245OpenLogicalChannel*)
3629                      memAlloc(pctxt, sizeof(H245OpenLogicalChannel));
3630    if(!request->u.openLogicalChannel)
3631    {
3632       OOTRACEERR3("Error:Memory - ooOpenChannel - openLogicalChannel."
3633                   "(%s, %s)\n", call->callType, call->callToken);
3634       return OO_FAILED;
3635
3636    }
3637    memset(request->u.openLogicalChannel, 0, 
3638                                      sizeof(H245OpenLogicalChannel));
3639    request->u.openLogicalChannel->forwardLogicalChannelNumber = 
3640                                                  ph245msg->logicalChannelNo;
3641
3642    
3643    session_id = ooCallGenerateSessionID(call, epCap->capType, "transmit");
3644
3645
3646    pLogicalChannel = ooAddNewLogicalChannel(call, 
3647                    request->u.openLogicalChannel->forwardLogicalChannelNumber,
3648                    session_id, "transmit", epCap);
3649    
3650    if(!pLogicalChannel)
3651    {
3652       OOTRACEERR3("ERROR:Failed to add new logical channel entry (%s, %s)\n",
3653                   call->callType, call->callToken);
3654       ooFreeH245Message(call, ph245msg);
3655       return OO_FAILED;
3656    }
3657    /* Populate H245OpenLogicalChannel_ForwardLogicalChannel Parameters*/
3658    flcp = &(request->u.openLogicalChannel->forwardLogicalChannelParameters);
3659    flcp->m.portNumberPresent = 0;
3660    flcp->m.forwardLogicalChannelDependencyPresent = 0;
3661    flcp->m.replacementForPresent = 0;
3662
3663    /* data type of channel */
3664    if(epCap->capType == OO_CAP_TYPE_AUDIO)
3665    {
3666       flcp->dataType.t = T_H245DataType_audioData;
3667       /* set audio capability for channel */
3668       audioCap = ooCapabilityCreateAudioCapability(epCap,pctxt, OOTX);
3669       if(!audioCap)
3670       {
3671          OOTRACEERR4("Error:Failed to create duplicate audio capability in "
3672                      "ooOpenChannel- %s (%s, %s)\n", 
3673                      ooGetCapTypeText(epCap->cap), call->callType, 
3674                      call->callToken);
3675          ooFreeH245Message(call, ph245msg);
3676          return OO_FAILED;
3677       }
3678    
3679       flcp->dataType.u.audioData = audioCap;
3680    }
3681    else if(epCap->capType == OO_CAP_TYPE_VIDEO)
3682    {
3683       flcp->dataType.t = T_H245DataType_videoData;      
3684       videoCap = ooCapabilityCreateVideoCapability(epCap, pctxt, OOTX);
3685       if(!videoCap)
3686       {
3687          OOTRACEERR4("Error:Failed to create duplicate video capability in "
3688                      "ooOpenChannel- %s (%s, %s)\n", 
3689                      ooGetCapTypeText(epCap->cap), call->callType, 
3690                      call->callToken);
3691          ooFreeH245Message(call, ph245msg);
3692          return OO_FAILED;
3693       }
3694    
3695       flcp->dataType.u.videoData = videoCap;
3696    }
3697    else if(epCap->capType == OO_CAP_TYPE_DATA)
3698    {
3699       flcp->dataType.t = T_H245DataType_data;
3700       /* set audio capability for channel */
3701       t38Cap = ooCapabilityCreateT38Capability(epCap,pctxt, OOTX);
3702       if(!t38Cap)
3703       {
3704          OOTRACEERR4("Error:Failed to create duplicate T38 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.data = t38Cap;
3713    }
3714    else{
3715       OOTRACEERR1("Error: Unhandled media type in ooOpenChannel\n");
3716       return OO_FAILED;
3717    }
3718
3719   
3720    flcp->multiplexParameters.t = 
3721       T_H245OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters;
3722    flcp->multiplexParameters.u.h2250LogicalChannelParameters = 
3723                          (H245H2250LogicalChannelParameters*)ASN1MALLOC(pctxt, 
3724                           sizeof(H245H2250LogicalChannelParameters));
3725
3726    h2250lcp = flcp->multiplexParameters.u.h2250LogicalChannelParameters;
3727    memset(h2250lcp, 0, sizeof(H245H2250LogicalChannelParameters));
3728
3729    h2250lcp->sessionID = session_id;
3730
3731    h2250lcp->mediaGuaranteedDelivery = 0;
3732    h2250lcp->silenceSuppression = 0;
3733    h2250lcp->m.mediaControlChannelPresent = 1;
3734    
3735    h2250lcp->mediaControlChannel.t = 
3736                                  T_H245TransportAddress_unicastAddress;
3737    h2250lcp->mediaControlChannel.u.unicastAddress =  (H245UnicastAddress*)
3738                          ASN1MALLOC(pctxt, sizeof(H245UnicastAddress));
3739
3740    unicastAddrs = h2250lcp->mediaControlChannel.u.unicastAddress;
3741    memset(unicastAddrs, 0, sizeof(H245UnicastAddress));
3742    unicastAddrs->t = T_H245UnicastAddress_iPAddress;
3743    unicastAddrs->u.iPAddress = (H245UnicastAddress_iPAddress*)
3744                ASN1MALLOC(pctxt, sizeof(H245UnicastAddress_iPAddress));
3745    iPAddress = unicastAddrs->u.iPAddress;
3746    memset(iPAddress, 0, sizeof(H245UnicastAddress_iPAddress));
3747
3748    ooSocketConvertIpToNwAddr(pLogicalChannel->localIP,iPAddress->network.data);
3749
3750    iPAddress->network.numocts = 4;
3751    iPAddress->tsapIdentifier = pLogicalChannel->localRtcpPort;
3752    pLogicalChannel->state = OO_LOGICALCHAN_PROPOSED; 
3753    OOTRACEDBGA4("Built OpenLogicalChannel-%s (%s, %s)\n", 
3754                  ooGetCapTypeText(epCap->cap), call->callType, 
3755                  call->callToken);
3756    ret = ooSendH245Msg(call, ph245msg);
3757    if(ret != OO_OK)
3758    {
3759       OOTRACEERR3("Error:Failed to enqueue OpenLogicalChannel to outbound "
3760                  "queue. (%s, %s)\n", call->callType,
3761                  call->callToken);
3762    }
3763    ooFreeH245Message(call, ph245msg);
3764   
3765    return ret;
3766 }
3767
3768
3769 /* Used to build  OLCs for fast connect. Keep in mind that forward and 
3770    reverse 
3771    are always with respect to the endpoint which proposes channels 
3772    TODO: Need to clean logical channel in case of failure.    */
3773 int ooBuildFastStartOLC
3774    (OOH323CallData *call, H245OpenLogicalChannel *olc, 
3775     ooH323EpCapability *epCap, OOCTXT*pctxt, int dir)
3776 {