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