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