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