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