small correction for verbose print h.323 packets
[asterisk/asterisk.git] / addons / ooh323c / src / oochannels.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 "asterisk/poll-compat.h"
19
20 #include "ooports.h" 
21 #include "oochannels.h"
22 #include "ootrace.h"
23 #include "ooq931.h"
24 #include "ooh245.h"
25 #include "ooh323.h"
26 #include "ooCalls.h"
27 #include "printHandler.h"
28 #include "ooGkClient.h"
29 #include "stdio.h"
30 #include "ooTimer.h"
31 #include "ooh323ep.h"
32 #include "ooStackCmds.h"
33 #include "ooCmdChannel.h"
34 #include "ootypes.h"
35
36
37 /** Global endpoint structure */
38 extern OOH323EndPoint gH323ep;
39 extern ast_mutex_t callListLock;
40 extern ast_mutex_t monitorLock;
41
42 extern DList g_TimerList;
43
44 static OOBOOL gMonitor = FALSE;
45
46 int ooSetCmdFDSETs(struct pollfd *pfds, int *nfds);
47 int ooProcessCmdFDSETsAndTimers
48    (struct pollfd *pfds, int nfds, struct timeval *pToMin);
49 int ooSetFDSETs(struct pollfd *pfds, int *nfds);
50 int ooProcessFDSETsAndTimers
51    (struct pollfd* pfds, int nfds, struct timeval *pToMin);
52 int ooProcessCallFDSETsAndTimers
53    (OOH323CallData *call, struct pollfd* pfds, int nfds, struct timeval *pToMin);
54 int ooSetCallFDSETs(OOH323CallData* call, struct pollfd* pfds, int *nfds);
55
56
57
58 int ooCreateH245Listener(OOH323CallData *call)
59 {
60    int ret=0;
61    OOSOCKET channelSocket=0;
62    OOTRACEINFO1("Creating H245 listener\n");
63    if((ret=ooSocketCreate (&channelSocket))!=ASN_OK)
64    {
65       OOTRACEERR3("ERROR: Failed to create socket for H245 listener "
66                   "(%s, %s)\n", call->callType, call->callToken);
67       return OO_FAILED;
68    }
69    ret = ooBindPort (OOTCP, channelSocket, call->localIP); 
70    if(ret == OO_FAILED)
71    {
72       OOTRACEERR3("Error:Unable to bind to a TCP port - H245 listener creation"
73                   " (%s, %s)\n", call->callType, call->callToken);
74       return OO_FAILED;
75    }
76    call->h245listenport = (int*) memAlloc(call->pctxt, sizeof(int));
77    *(call->h245listenport) = ret;
78    call->h245listener = (OOSOCKET*)memAlloc(call->pctxt, sizeof(OOSOCKET));
79    *(call->h245listener) = channelSocket;
80    ret = ooSocketListen(*(call->h245listener), 4096);
81    if(ret != ASN_OK)
82    {
83       OOTRACEERR3("Error:Unable to listen on H.245 socket (%s, %s)\n", 
84                    call->callType, call->callToken);
85       return OO_FAILED;
86    }
87    
88    OOTRACEINFO4("H245 listener creation - successful(port %d) (%s, %s)\n", 
89                 *(call->h245listenport),call->callType, call->callToken);
90    return OO_OK;
91 }
92
93 int ooCreateH245Connection(OOH323CallData *call)
94 {
95    int ret=0;
96    OOSOCKET channelSocket=0;
97    ooTimerCallback *cbData=NULL;
98
99    OOTRACEINFO1("Creating H245 Connection\n");
100    if((ret=ooSocketCreate (&channelSocket))!=ASN_OK)
101    {
102       OOTRACEERR3("ERROR:Failed to create socket for H245 connection "
103                   "(%s, %s)\n", call->callType, call->callToken);
104       return OO_FAILED;
105    }
106    else
107    {
108       if (0 == call->pH245Channel) {
109          call->pH245Channel = 
110             (OOH323Channel*) memAllocZ (call->pctxt, sizeof(OOH323Channel));
111       }
112
113       /*
114          bind socket to a port before connecting. Thus avoiding
115          implicit bind done by a connect call.
116       */
117       ret = ooBindPort(OOTCP, channelSocket, call->localIP); 
118       if(ret == OO_FAILED)
119       {
120          OOTRACEERR3("Error:Unable to bind to a TCP port - h245 connection "
121                      "(%s, %s)\n", call->callType, call->callToken);
122          return OO_FAILED;
123       }
124       call->pH245Channel->port = ret;
125       OOTRACEDBGC4("Local H.245 port is %d (%s, %s)\n", 
126                    call->pH245Channel->port,
127                    call->callType, call->callToken);
128       OOTRACEINFO5("Trying to connect to remote endpoint to setup H245 "
129                    "connection %s:%d(%s, %s)\n", call->remoteIP, 
130                     call->remoteH245Port, call->callType, call->callToken);
131               
132       if((ret=ooSocketConnect(channelSocket, call->remoteIP,
133                               call->remoteH245Port))==ASN_OK)
134       {
135          call->pH245Channel->sock = channelSocket;
136          call->h245SessionState = OO_H245SESSION_ACTIVE;
137
138          OOTRACEINFO3("H245 connection creation successful (%s, %s)\n",
139                       call->callType, call->callToken);
140
141          /*Start terminal capability exchange and master slave determination */
142          ret = ooSendTermCapMsg(call);
143          if(ret != OO_OK)
144          {
145             OOTRACEERR3("ERROR:Sending Terminal capability message (%s, %s)\n",
146                          call->callType, call->callToken);
147             return ret;
148          }
149          ret = ooSendMasterSlaveDetermination(call);
150          if(ret != OO_OK)
151          {
152             OOTRACEERR3("ERROR:Sending Master-slave determination message "
153                         "(%s, %s)\n", call->callType, call->callToken);
154             return ret;
155          }
156       }
157       else
158       {
159          if(call->h245ConnectionAttempts >= 3)
160          {
161             OOTRACEERR3("Error:Failed to setup an H245 connection with remote "
162                         "destination. (%s, %s)\n", call->callType, 
163                          call->callToken);
164             if(call->callState < OO_CALL_CLEAR)
165             {
166                call->callEndReason = OO_REASON_TRANSPORTFAILURE;
167                call->callState = OO_CALL_CLEAR;
168             }
169             return OO_FAILED;
170          }
171          else{
172             OOTRACEWARN4("Warn:Failed to connect to remote destination for "
173                          "H245 connection - will retry after %d seconds"
174                          "(%s, %s)\n", DEFAULT_H245CONNECTION_RETRYTIMEOUT,
175                          call->callType, call->callToken);
176
177             cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
178                                                      sizeof(ooTimerCallback));
179             if(!cbData)
180             {
181                OOTRACEERR3("Error:Unable to allocate memory for timer "
182                            "callback.(%s, %s)\n", call->callType, 
183                             call->callToken);
184                return OO_FAILED;
185             }
186             cbData->call = call;
187             cbData->timerType = OO_H245CONNECT_TIMER;
188             if(!ooTimerCreate(call->pctxt, &call->timerList, 
189                               &ooCallH245ConnectionRetryTimerExpired, 
190                               DEFAULT_H245CONNECTION_RETRYTIMEOUT, cbData, 
191                               FALSE))
192             {
193                OOTRACEERR3("Error:Unable to create H245 connection retry timer"
194                            "(%s, %s)\n", call->callType, call->callToken);
195                memFreePtr(call->pctxt, cbData);
196                return OO_FAILED;
197             }
198             return OO_OK;
199          }
200       }
201    }
202    return OO_OK;
203 }
204
205 int ooSendH225Msg(OOH323CallData *call, Q931Message *msg)
206 {
207    int iRet=0;
208    ASN1OCTET * encodebuf;
209    if(!call)
210       return OO_FAILED;
211
212    encodebuf = (ASN1OCTET*) memAlloc (call->pctxt, MAXMSGLEN);
213    if(!encodebuf)
214    {
215       OOTRACEERR3("Error:Failed to allocate memory for encoding H225 "
216                   "message(%s, %s)\n", call->callType, call->callToken);
217       return OO_FAILED;
218    }
219    iRet = ooEncodeH225Message(call, msg, (char *)encodebuf, MAXMSGLEN);
220    if(iRet != OO_OK)
221    {
222       OOTRACEERR3("Error:Failed to encode H225 message. (%s, %s)\n", 
223                   call->callType, call->callToken);
224       memFreePtr (call->pctxt, encodebuf);
225       return OO_FAILED;
226    }
227
228    /* If high priority messages, send immediately.*/
229    if(encodebuf[0] == OOReleaseComplete || 
230       (encodebuf[0]==OOFacility && encodebuf[1]==OOEndSessionCommand))
231    {
232       dListFreeAll(call->pctxt, &call->pH225Channel->outQueue);
233       dListAppend (call->pctxt, &call->pH225Channel->outQueue, encodebuf);
234       // ooSendMsg(call, OOQ931MSG);
235    }
236    else{
237       dListAppend (call->pctxt, &call->pH225Channel->outQueue, encodebuf);
238  
239       OOTRACEDBGC4("Queued H225 messages %d. (%s, %s)\n", 
240                                      call->pH225Channel->outQueue.count, 
241                                      call->callType, call->callToken);  
242    }
243    return OO_OK;
244 }
245
246 int ooCreateH225Connection(OOH323CallData *call)
247 {
248    int ret=0, i;
249    OOSOCKET channelSocket=0;
250    for (i=0;i<3;i++) {
251    if((ret=ooSocketCreate (&channelSocket))!=ASN_OK)
252    {
253       OOTRACEERR3("Failed to create socket for transmit H2250 channel (%s, %s)"
254                   "\n", call->callType, call->callToken);
255       if(call->callState < OO_CALL_CLEAR)
256       {
257          call->callState = OO_CALL_CLEAR;
258          call->callEndReason = OO_REASON_TRANSPORTFAILURE;
259       }
260       return OO_FAILED;
261    }
262    else
263    {
264       /*
265          bind socket to a port before connecting. Thus avoiding
266          implicit bind done by a connect call. Avoided on windows as 
267          windows sockets have problem in reusing the addresses even after
268          setting SO_REUSEADDR, hence in windows we just allow os to bind
269          to any random port.
270       */
271 #ifndef _WIN32
272       ret = ooBindPort(OOTCP,channelSocket, call->localIP); 
273 #else
274       ret = ooBindOSAllocatedPort(channelSocket, call->localIP);
275 #endif
276       
277       if(ret == OO_FAILED)
278       {
279          OOTRACEERR3("Error:Unable to bind to a TCP port (%s, %s)\n", 
280          call->callType, call->callToken);
281          if(call->callState < OO_CALL_CLEAR)
282          {
283             call->callState = OO_CALL_CLEAR;
284             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
285          }
286          return OO_FAILED;
287       }
288
289       if (0 == call->pH225Channel) {
290          call->pH225Channel = 
291             (OOH323Channel*) memAllocZ (call->pctxt, sizeof(OOH323Channel));
292       }
293       call->pH225Channel->port = ret;
294
295       OOTRACEINFO5("Trying to connect to remote endpoint(%s:%d) to setup "
296                    "H2250 channel (%s, %s)\n", call->remoteIP, 
297                    call->remotePort, call->callType, call->callToken);
298
299       if((ret=ooSocketConnect(channelSocket, call->remoteIP,
300                               call->remotePort))==ASN_OK)
301       {
302          call->pH225Channel->sock = channelSocket;
303
304          OOTRACEINFO3("H2250 transmiter channel creation - successful "
305                       "(%s, %s)\n", call->callType, call->callToken);
306
307          /* If multihomed, get ip from socket */
308          if(!strcmp(call->localIP, "0.0.0.0"))
309          {
310             OOTRACEDBGA3("Determining IP address for outgoing call in "
311                          "multihomed mode. (%s, %s)\n", call->callType, 
312                           call->callToken);
313             ret = ooSocketGetIpAndPort(channelSocket, call->localIP, 20, 
314                                        &call->pH225Channel->port);
315             if(ret != ASN_OK)
316             {
317                OOTRACEERR3("ERROR:Failed to retrieve local ip and port from "
318                            "socket for multihomed mode.(%s, %s)\n", 
319                             call->callType, call->callToken);
320                if(call->callState < OO_CALL_CLEAR)
321                {  /* transport failure */
322                   call->callState = OO_CALL_CLEAR;
323                   call->callEndReason = OO_REASON_TRANSPORTFAILURE;
324                }
325                return OO_FAILED;
326             }
327             OOTRACEDBGA4("Using local ip %s for outgoing call(multihomedMode)."
328                          " (%s, %s)\n", call->localIP, call->callType, 
329                          call->callToken);
330          }
331          return OO_OK;
332       }
333       else
334       {
335          OOTRACEERR5("ERROR:Failed to connect to remote destination for "
336                     "transmit H2250 channel(%s, %s, %d, %s)\n",call->callType,
337                      call->callToken, channelSocket, call->localIP);
338          close(channelSocket);
339
340          if(call->callState < OO_CALL_CLEAR)
341          {  /* No one is listening at remote end */
342             call->callState = OO_CALL_CLEAR;
343             call->callEndReason = OO_REASON_NOUSER;
344          }
345          if (i>=2) return OO_FAILED; else continue;
346       }
347
348       return OO_FAILED;
349     }
350   }
351   return OO_FAILED;
352 }
353
354 int ooCloseH225Connection (OOH323CallData *call)
355 {
356    if (0 != call->pH225Channel)
357    {
358       if(call->pH225Channel->sock != 0)
359          ooSocketClose (call->pH225Channel->sock);
360       if (call->pH225Channel->outQueue.count > 0)
361       {
362          dListFreeAll (call->pctxt, &(call->pH225Channel->outQueue));
363       }
364       memFreePtr (call->pctxt, call->pH225Channel);
365       call->pH225Channel = NULL;
366    }
367    return OO_OK;
368 }
369
370 int ooCreateH323Listener()
371 {
372    int ret=0;
373    OOSOCKET channelSocket=0;
374    OOIPADDR ipaddrs;
375
376     /* Create socket */
377    if((ret=ooSocketCreate (&channelSocket))!=ASN_OK)
378    {
379       OOTRACEERR1("Failed to create socket for H323 Listener\n");
380       return OO_FAILED;
381    }
382    ret= ooSocketStrToAddr (gH323ep.signallingIP, &ipaddrs);
383    if((ret=ooSocketBind (channelSocket, ipaddrs, 
384                          gH323ep.listenPort))==ASN_OK) 
385    {
386       gH323ep.listener = (OOSOCKET*)memAlloc(&gH323ep.ctxt,sizeof(OOSOCKET));
387       *(gH323ep.listener) = channelSocket;
388           
389       ooSocketListen(channelSocket,2048); /*listen on socket*/
390       OOTRACEINFO1("H323 listener creation - successful\n");
391       return OO_OK;
392    }
393    else
394    {
395       OOTRACEERR1("ERROR:Failed to create H323 listener\n");
396       return OO_FAILED;
397    }
398 }
399
400
401
402 int ooAcceptH225Connection()    
403 {
404    OOH323CallData * call;
405    int ret;
406    char callToken[20];
407    OOSOCKET h225Channel=0;
408    ret = ooSocketAccept (*(gH323ep.listener), &h225Channel, 
409                          NULL, NULL);
410    if(ret != ASN_OK)
411    {
412       OOTRACEERR1("Error:Accepting h225 connection\n");
413       return OO_FAILED;
414    }
415    ooGenerateCallToken(callToken, sizeof(callToken));
416
417    call = ooCreateCall("incoming", callToken);
418    if(!call)
419    {
420       OOTRACEERR1("ERROR:Failed to create an incoming call\n");
421       return OO_FAILED;
422    }
423
424    ast_mutex_lock(&call->Lock);
425    call->pH225Channel = (OOH323Channel*) 
426       memAllocZ (call->pctxt, sizeof(OOH323Channel));
427
428    call->pH225Channel->sock = h225Channel;
429
430    /* If multihomed, get ip from socket */
431    if(!strcmp(call->localIP, "0.0.0.0"))
432    {
433       OOTRACEDBGA3("Determining IP address for incoming call in multihomed "
434                    "mode (%s, %s)\n", call->callType, call->callToken);
435
436       ret = ooSocketGetIpAndPort(h225Channel, call->localIP, 20, 
437                                        &call->pH225Channel->port);
438       if(ret != ASN_OK)
439       {
440          OOTRACEERR3("Error:Failed to retrieve local ip and port from "
441                      "socket for multihomed mode.(%s, %s)\n", 
442                       call->callType, call->callToken);
443          if(call->callState < OO_CALL_CLEAR)
444          {  /* transport failure */
445             call->callState = OO_CALL_CLEAR;
446             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
447          }
448          ast_mutex_unlock(&call->Lock);
449          return OO_FAILED;
450       }
451       OOTRACEDBGA4("Using Local IP address %s for incoming call in multihomed "
452                    "mode. (%s, %s)\n", call->localIP, call->callType, 
453                     call->callToken);
454    }
455    
456    ast_mutex_unlock(&call->Lock);
457    return OO_OK;
458 }
459
460 int ooAcceptH245Connection(OOH323CallData *call)
461 {
462    int ret;
463    OOSOCKET h245Channel=0;
464    ret = ooSocketAccept (*(call->h245listener), &h245Channel, 
465                          NULL, NULL);
466    if(ret != ASN_OK)
467    {
468       OOTRACEERR1("Error:Accepting h245 connection\n");
469       return OO_FAILED;
470    }
471
472    if (0 == call->pH245Channel) {
473       call->pH245Channel = 
474          (OOH323Channel*) memAllocZ (call->pctxt, sizeof(OOH323Channel));
475    }
476    call->pH245Channel->sock = h245Channel; 
477    call->h245SessionState = OO_H245SESSION_ACTIVE;
478
479
480    OOTRACEINFO3("H.245 connection established (%s, %s)\n", 
481                 call->callType, call->callToken);
482
483
484    /* Start terminal capability exchange and master slave determination */
485    ret = ooSendTermCapMsg(call);
486    if(ret != OO_OK)
487    {
488       OOTRACEERR3("ERROR:Sending Terminal capability message (%s, %s)\n",
489                    call->callType, call->callToken);
490       return ret;
491    }
492    ret = ooSendMasterSlaveDetermination(call);
493    if(ret != OO_OK)
494    {
495       OOTRACEERR3("ERROR:Sending Master-slave determination message "
496                   "(%s, %s)\n", call->callType, call->callToken);
497       return ret;
498    }   
499    return OO_OK;
500 }
501
502
503 int ooSetCmdFDSETs(struct pollfd *pfds, int *nfds)
504 {
505    if(gH323ep.cmdSock)
506    {
507       pfds[*nfds].fd = gH323ep.cmdSock;
508       pfds[*nfds].events = POLLIN;
509       (*nfds)++;
510    }
511
512    return OO_OK;
513
514 }
515
516 int ooProcessCmdFDSETsAndTimers
517    (struct pollfd *pfds, int nfds, struct timeval *pToMin)
518 {
519    if(gH323ep.cmdSock) {
520       if(ooPDRead(pfds, nfds, gH323ep.cmdSock)) {
521          if(ooReadAndProcessStackCommand() != OO_OK) {
522                          /* ooReadAndProcessStackCommand prints an error message */
523                          return OO_FAILED;
524                  }
525       }
526    }
527
528    return OO_OK;
529
530 }
531
532
533 int ooSetFDSETs(struct pollfd *pfds, int *nfds)
534 {
535    if(gH323ep.gkClient && gH323ep.gkClient->rasSocket != 0)
536    {
537       pfds[*nfds].fd = gH323ep.gkClient->rasSocket;
538       pfds[*nfds].events = POLLIN;
539       (*nfds)++;
540    }
541    if(gH323ep.listener)
542    {
543       pfds[*nfds].fd = *gH323ep.listener;
544       pfds[*nfds].events = POLLIN;
545       (*nfds)++;
546    }
547
548    return OO_OK;
549
550 }
551
552 int ooSetCallFDSETs(OOH323CallData* call, struct pollfd* pfds, int *nfds)
553 {
554
555    if(call) {
556
557     if(call->cmdSock && call->callState < OO_CALL_CLEAR) {
558       pfds[*nfds].fd = call->cmdSock;
559       pfds[*nfds].events = POLLIN;
560       (*nfds)++;
561     }
562
563     if (0 != call->pH225Channel && 0 != call->pH225Channel->sock) {
564       pfds[*nfds].fd = call->pH225Channel->sock;
565       pfds[*nfds].events = POLLIN;
566
567       if (call->pH225Channel->outQueue.count > 0 ||
568        (OO_TESTFLAG (call->flags, OO_M_TUNNELING) && 
569          0 != call->pH245Channel && 
570          call->pH245Channel->outQueue.count>0))
571        pfds[*nfds].events |= POLLOUT;
572       (*nfds)++;
573
574     }
575            
576     if (0 != call->pH245Channel &&  call->pH245Channel->sock != 0) {
577        pfds[*nfds].fd = call->pH245Channel->sock;
578        pfds[*nfds].events = POLLIN;
579        if (call->pH245Channel->outQueue.count>0)
580         pfds[*nfds].events |= POLLOUT;
581        (*nfds)++;
582       }
583       else if(call->h245listener) {
584        OOTRACEINFO3("H.245 Listerner socket being monitored "
585         "(%s, %s)\n", call->callType, call->callToken);
586        pfds[*nfds].fd = *(call->h245listener);
587        pfds[*nfds].events = POLLIN;
588        (*nfds)++;
589       }
590
591
592    }
593
594    return OO_OK;
595 }
596    
597 int ooProcessFDSETsAndTimers
598    (struct pollfd* pfds, int nfds, struct timeval *pToMin)
599 {
600    struct timeval toNext;
601
602    /* Process gatekeeper client timers */
603    if(gH323ep.gkClient)
604    {   
605       ooTimerFireExpired(&gH323ep.gkClient->ctxt, 
606                          &gH323ep.gkClient->timerList);
607       if(ooTimerNextTimeout(&gH323ep.gkClient->timerList, &toNext))
608       {
609          if(ooCompareTimeouts(pToMin, &toNext)>0)
610          {
611             pToMin->tv_sec = toNext.tv_sec;
612             pToMin->tv_usec = toNext.tv_usec;
613          }
614       }
615       if(gH323ep.gkClient->state == GkClientFailed ||
616          gH323ep.gkClient->state == GkClientGkErr)
617       {
618          if(ooGkClientHandleClientOrGkFailure(gH323ep.gkClient)!=OO_OK)
619          {
620             //ooStopMonitorCalls(); //Function calling ooProcessFDSETsAndTimers is responsible for this.
621             return OO_FAILED;
622          }
623       }
624    }
625
626    /* Manage ready descriptors after select */
627
628    if(0 != gH323ep.gkClient && 0 != gH323ep.gkClient->rasSocket)
629    {
630       if(ooPDRead(pfds, nfds, gH323ep.gkClient->rasSocket) )
631       {
632          ooGkClientReceive(gH323ep.gkClient);
633          if(gH323ep.gkClient->state == GkClientFailed ||
634             gH323ep.gkClient->state == GkClientGkErr) {
635             ooGkClientHandleClientOrGkFailure(gH323ep.gkClient);
636          }
637       }
638    }
639
640    if(gH323ep.listener)
641    {
642       if(ooPDRead(pfds, nfds, *(gH323ep.listener)))
643       {
644          OOTRACEDBGA1("New connection at H225 receiver\n");
645          ooAcceptH225Connection();
646       }      
647    }
648       
649  
650    return OO_OK;
651
652 }
653 int ooProcessCallFDSETsAndTimers
654    (OOH323CallData *call, struct pollfd* pfds, int nfds, struct timeval *pToMin)
655 {
656    struct timeval toNext;
657
658    if(call)
659    {
660
661     if(call->cmdSock) {
662       if(ooPDRead(pfds, nfds, call->cmdSock)) {
663          ast_mutex_lock(&call->Lock);
664          if(ooReadAndProcessCallStackCommand(call) != OO_OK) {
665                          /* ooReadAndProcessStackCommand prints an error message */
666                          ast_mutex_unlock(&call->Lock);
667                          return OO_FAILED;
668                  }
669          ast_mutex_unlock(&call->Lock);
670       }
671     }
672
673     ooTimerFireExpired(call->pctxt, &call->timerList);
674     if (0 != call->pH225Channel && 0 != call->pH225Channel->sock)
675     {
676      if(ooPDRead(pfds, nfds, call->pH225Channel->sock))
677      {
678       if(ooH2250Receive(call) != OO_OK)
679       {
680        OOTRACEERR3("ERROR:Failed ooH2250Receive - Clearing call "
681         "(%s, %s)\n", call->callType, call->callToken);
682        if(call->callState < OO_CALL_CLEAR)
683        {
684         call->callEndReason = OO_REASON_INVALIDMESSAGE;
685         call->callState = OO_CALL_CLEAR;
686        }
687       }
688      }
689     }
690
691     if (0 != call->pH245Channel && 0 != call->pH245Channel->sock)
692      if(ooPDRead(pfds, nfds, call->pH245Channel->sock))
693       ooH245Receive(call);
694
695     if (0 != call->pH245Channel && 0 != call->pH245Channel->sock)
696     {
697      if(call->pH245Channel->outQueue.count>0)
698      {                           
699       if(ooPDWrite(pfds, nfds, call->pH245Channel->sock))
700        ooSendMsg(call, OOH245MSG);
701      }
702     }
703     else if(call->h245listener)
704     {
705      if(ooPDRead(pfds, nfds, *(call->h245listener)))
706      {
707       OOTRACEDBGC3("Incoming H.245 connection (%s, %s)\n",
708                     call->callType, call->callToken);
709       ooAcceptH245Connection(call);
710      }                           
711     }
712
713     if (0 != call->pH225Channel && 0 != call->pH225Channel->sock)
714     {
715      if(ooPDWrite(pfds, nfds, call->pH225Channel->sock))
716      {
717       if(call->pH225Channel->outQueue.count>0)
718       {
719        OOTRACEDBGC3("Sending H225 message (%s, %s)\n", 
720                         call->callType, call->callToken);
721        ooSendMsg(call, OOQ931MSG);
722       }
723       if(call->pH245Channel && 
724          call->pH245Channel->outQueue.count>0 && 
725         OO_TESTFLAG (call->flags, OO_M_TUNNELING))
726       {
727         OOTRACEDBGC3("H245 message needs to be tunneled. "
728                           "(%s, %s)\n", call->callType, 
729                                call->callToken);
730         ooSendMsg(call, OOH245MSG);
731       }
732      }                                
733     }
734
735      if(ooTimerNextTimeout(&call->timerList, &toNext))
736      {
737       if(ooCompareTimeouts(pToMin, &toNext) > 0)
738       {
739        pToMin->tv_sec = toNext.tv_sec;
740        pToMin->tv_usec = toNext.tv_usec;
741       }
742      }
743
744      if(call->callState >= OO_CALL_CLEAR && call->callState < OO_CALL_CLEARED) {
745             ast_mutex_lock(&call->Lock);
746             ooEndCall(call);
747             ast_mutex_unlock(&call->Lock);
748      } else if(call->callState == OO_CALL_CLEARED) {
749             ast_mutex_lock(&call->Lock);
750             ooEndCall(call);
751             ast_mutex_unlock(&call->Lock);
752      }
753      if(call->callState >= OO_CALL_CLEARED)
754                 ooStopMonitorCallChannels(call);
755    }
756
757    return OO_OK;
758
759 }
760    
761 int ooMonitorCmdChannels()
762 {
763    int ret=0, nfds=0;
764    struct timeval toMin;
765    struct pollfd pfds[1];
766
767    gMonitor = TRUE;
768
769    toMin.tv_sec = 3;
770    toMin.tv_usec = 0;
771    
772    while(1)
773    {
774       nfds = 0;
775       ooSetCmdFDSETs(pfds, &nfds);
776
777       if(!gMonitor) {
778          OOTRACEINFO1("Ending Monitor thread\n");
779          break;
780       }
781
782       
783       if(nfds == 0)
784 #ifdef _WIN32
785          Sleep(10);
786 #else
787       {
788          toMin.tv_sec = 0;
789          toMin.tv_usec = 10000;
790          ooSocketPoll(pfds, nfds, toMin.tv_usec / 1000);
791       }
792 #endif
793       else
794          ret = ooSocketPoll(pfds, nfds, toMin.tv_sec * 1000 + toMin.tv_usec / 1000);
795       
796       if(ret == -1)
797       {
798          
799          OOTRACEERR1("Error in poll ...exiting\n");
800          exit(-1); 
801          continue;
802       }
803
804       toMin.tv_sec = 2;  /* 2 sec */
805       toMin.tv_usec = 100000; /* 100ms*/
806
807       ast_mutex_lock(&monitorLock);
808       if(ooProcessCmdFDSETsAndTimers(pfds, nfds, &toMin) != OO_OK)
809       {
810          /* ooStopMonitorCalls(); */
811          ast_mutex_unlock(&monitorLock);
812          continue;
813       }
814       ast_mutex_unlock(&monitorLock);
815
816    }/* while(1)*/
817    return OO_OK;
818 }
819
820 int ooMonitorChannels()
821 {
822    int ret=0, nfds=0;
823    struct timeval toMin, toNext;
824    struct pollfd pfds[2];
825
826    gMonitor = TRUE;
827
828    toMin.tv_sec = 3;
829    toMin.tv_usec = 0;
830    ooH323EpPrintConfig();
831    
832    if(gH323ep.gkClient) {
833       ooGkClientPrintConfig(gH323ep.gkClient);
834       if(OO_OK != ooGkClientStart(gH323ep.gkClient))
835       {
836          OOTRACEERR1("Error:Failed to start Gatekeeper client\n");
837          ooGkClientDestroy();
838       }
839    }
840    
841    while(1)
842    {
843       nfds = 0;
844       ooSetFDSETs(pfds, &nfds);
845
846       if(!gMonitor) {
847          OOTRACEINFO1("Ending Monitor thread\n");
848          break;
849       }
850
851       
852       if(nfds == 0)
853 #ifdef _WIN32
854          Sleep(10);
855 #else
856       {
857          toMin.tv_sec = 0;
858          toMin.tv_usec = 10000;
859          ooSocketPoll(pfds, nfds, toMin.tv_usec / 1000);
860       }
861 #endif
862       else
863          ret = ooSocketPoll(pfds, nfds, toMin.tv_sec * 1000 + toMin.tv_usec / 1000);
864       
865       if(ret == -1)
866       {
867          
868          OOTRACEERR1("Error in poll ...exiting\n");
869          exit(-1);
870       }
871
872       toMin.tv_sec = 2; /* 2 sec */
873       toMin.tv_usec = 100000; /* 100ms*/
874       /*This is for test application. Not part of actual stack */
875   
876       ast_mutex_lock(&monitorLock);
877       ooTimerFireExpired(&gH323ep.ctxt, &g_TimerList);
878       if(ooTimerNextTimeout(&g_TimerList, &toNext))
879       {
880          if(ooCompareTimeouts(&toMin, &toNext)>0)
881          {
882             toMin.tv_sec = toNext.tv_sec;
883             toMin.tv_usec = toNext.tv_usec;
884          }
885       }
886
887       if(ooProcessFDSETsAndTimers(pfds, nfds, &toMin) != OO_OK)
888       {
889          ast_mutex_unlock(&monitorLock);
890          ooStopMonitorCalls();
891          continue;
892       }
893
894       ast_mutex_unlock(&monitorLock);
895    }/* while(1)*/
896    return OO_OK;
897 }
898 int ooMonitorCallChannels(OOH323CallData *call)
899 {
900    int ret=0, nfds=0, zeroloops = 0;
901 #define MAX_ZERO_LOOP 1020
902    struct timeval toMin;
903    struct pollfd pfds[5];
904
905    OOCTXT* pctxt;
906
907    call->Monitor = TRUE;
908
909    toMin.tv_sec = 3;
910    toMin.tv_usec = 0;
911    
912    while(1)
913    {
914       if(!call->Monitor) {
915          OOTRACEINFO1("Ending Call Monitor thread\n");
916          break;
917       }
918
919       nfds = 0;
920       ooSetCallFDSETs(call, pfds, &nfds);
921
922       
923       if(nfds == 0)
924 #ifdef _WIN32
925          Sleep(10);
926 #else
927       {
928          if (zeroloops++ > MAX_ZERO_LOOP) {
929                 ooCleanCall(call);
930                 ooStopMonitorCallChannels(call);
931                 break;
932          }
933          toMin.tv_sec = 0;
934          toMin.tv_usec = 10000;
935          ooSocketPoll(pfds, nfds, toMin.tv_usec / 1000);
936       }
937 #endif
938       else
939          ret = ooSocketPoll(pfds, nfds, toMin.tv_sec * 1000 + toMin.tv_usec / 1000);
940       
941       if(ret == -1)
942       {
943          
944         OOTRACEERR2("Error in poll %d ...exiting\n", errno);
945         call->callEndReason = OO_REASON_INVALIDMESSAGE;
946         call->callState = OO_CALL_CLEARED;
947         ooCleanCall(call);
948         ooStopMonitorCallChannels(call);
949         break;
950
951       }
952
953       toMin.tv_sec = 2; /* 2 sec */
954       toMin.tv_usec = 100000; /* 100ms*/
955       /*This is for test application. Not part of actual stack */
956   
957       if(ooProcessCallFDSETsAndTimers(call, pfds, nfds, &toMin) != OO_OK)
958       {
959          ooStopMonitorCallChannels(call);
960          continue;
961       }
962
963    }/* while(1)*/
964
965    if (call->cmdSock)
966     ooCloseCallCmdConnection(call);
967
968    ast_mutex_lock(&call->Lock);
969    ast_mutex_unlock(&call->Lock);
970    ast_mutex_destroy(&call->Lock);
971    ast_cond_destroy(&call->gkWait);
972    pctxt = call->pctxt;
973    freeContext(pctxt);
974    free(pctxt);
975
976    return OO_OK;
977 }
978
979 int ooH2250Receive(OOH323CallData *call)
980 {
981    int  recvLen=0, total=0, ret=0;
982    ASN1OCTET message[MAXMSGLEN], message1[MAXMSGLEN];
983    int len;
984    Q931Message *pmsg;
985    OOCTXT *pctxt = call->msgctxt;
986    
987    struct timeval timeout;
988
989    
990    pmsg = (Q931Message*)memAlloc(pctxt, sizeof(Q931Message));
991    if(!pmsg)
992    {
993       OOTRACEERR3("ERROR:Failed to allocate memory for incoming H.2250 message"
994                   " (%s, %s)\n", call->callType, call->callToken);
995       /* memReset(&gH323ep.msgctxt); */
996       memReset(call->pctxt);
997       return OO_FAILED;
998    }
999    memset(pmsg, 0, sizeof(Q931Message));
1000    /* First read just TPKT header which is four bytes */
1001    recvLen = ooSocketRecv (call->pH225Channel->sock, message, 4);
1002    if(recvLen <= 0)
1003    {
1004       if(recvLen == 0)
1005          OOTRACEWARN3("Warn:RemoteEndpoint closed connection (%s, %s)\n",
1006                       call->callType, call->callToken);
1007       else
1008          OOTRACEERR3("Error:Transport failure while reading Q931 "
1009                      "message (%s, %s)\n", call->callType, call->callToken);
1010
1011       ooCloseH225Connection(call);
1012       if(call->callState < OO_CALL_CLEARED)
1013       {
1014          if(call->callState < OO_CALL_CLEAR)
1015             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1016          call->callState = OO_CALL_CLEARED;
1017          
1018       }
1019       ooFreeQ931Message(pctxt, pmsg);
1020       return OO_OK;
1021    }
1022    OOTRACEDBGC3("Receiving H.2250 message (%s, %s)\n",
1023                 call->callType, call->callToken);   
1024    /* Since we are working with TCP, need to determine the
1025       message boundary. Has to be done at channel level, as channels
1026       know the message formats and can determine boundaries
1027    */
1028    if(recvLen != 4)
1029    {
1030       OOTRACEERR4("Error: Reading TPKT header for H225 message "
1031                   "recvLen= %d (%s, %s)\n", recvLen, call->callType, 
1032                   call->callToken);
1033       ooFreeQ931Message(pctxt, pmsg);
1034       if(call->callState < OO_CALL_CLEAR)
1035       {
1036          call->callEndReason = OO_REASON_INVALIDMESSAGE;
1037          call->callState = OO_CALL_CLEAR;
1038       }
1039       return OO_FAILED;
1040    }
1041
1042    
1043    len = message[2];
1044    len = len<<8;
1045    len = len | message[3];
1046    /* Remaining message length is length - tpkt length */
1047    len = len - 4;
1048
1049    if(len > MAXMSGLEN - 4)
1050    {
1051       OOTRACEERR4("Error: Invalid TPKT header for H225 message "
1052                   "Len = %d (%s, %s)\n", len, call->callType, 
1053                   call->callToken);
1054       ooCloseH225Connection(call);
1055       ooFreeQ931Message(pctxt, pmsg);
1056       if(call->callState < OO_CALL_CLEAR)
1057       {
1058          call->callEndReason = OO_REASON_INVALIDMESSAGE;
1059          call->callState = OO_CALL_CLEAR;
1060       }
1061       return OO_FAILED;
1062    }
1063
1064    /* Now read actual Q931 message body. We should make sure that we
1065       receive complete message as indicated by len. If we don't then there 
1066       is something wrong. The loop below receives message, then checks whether
1067       complete message is received. If not received, then uses select to peek
1068       for remaining bytes of the message. If message is not received in 3
1069       seconds, then we have a problem. Report an error and exit.
1070    */
1071    while(total < len)
1072    {
1073       struct pollfd pfds;
1074       recvLen = ooSocketRecv (call->pH225Channel->sock, message1, len-total);
1075       memcpy(message+total, message1, recvLen);
1076       total = total + recvLen;
1077
1078       if(total == len) break; /* Complete message is received */
1079       
1080       pfds.fd = call->pH225Channel->sock;
1081       pfds.events = POLLIN;
1082       timeout.tv_sec = 3;
1083       timeout.tv_usec = 0;
1084       ret = ooSocketPoll(&pfds, 1,  timeout.tv_sec * 1000);
1085       if(ret == -1)
1086       {
1087          OOTRACEERR3("Error in select while receiving H.2250 message - "
1088                      "clearing call (%s, %s)\n", call->callType, 
1089                      call->callToken);
1090          ooFreeQ931Message(pctxt, pmsg);
1091          if(call->callState < OO_CALL_CLEAR)
1092          {
1093             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1094             call->callState = OO_CALL_CLEAR;
1095          }
1096          return OO_FAILED;
1097       }
1098       /* If remaining part of the message is not received in 3 seconds 
1099          exit */
1100       if(!ooPDRead(&pfds, 1, call->pH225Channel->sock))
1101       {
1102          OOTRACEERR3("Error: Incomplete H.2250 message received - clearing "
1103                      "call (%s, %s)\n", call->callType, call->callToken);
1104          ooFreeQ931Message(pctxt, pmsg);
1105          if(call->callState < OO_CALL_CLEAR)
1106          {
1107             call->callEndReason = OO_REASON_INVALIDMESSAGE; 
1108             call->callState = OO_CALL_CLEAR;
1109          }
1110          return OO_FAILED;
1111       }
1112    }
1113
1114    OOTRACEDBGC3("Received Q.931 message: (%s, %s)\n", 
1115                 call->callType, call->callToken);
1116
1117    initializePrintHandler(&printHandler, "Received H.2250 Message");
1118    setEventHandler (pctxt, &printHandler);
1119    setPERBuffer (pctxt, message, len, TRUE);
1120    ret = ooQ931Decode (call, pmsg, len, message, 1);
1121    if(ret != OO_OK) {
1122       OOTRACEERR3("Error:Failed to decode received H.2250 message. (%s, %s)\n",
1123                    call->callType, call->callToken);
1124    }
1125    OOTRACEDBGC3("Decoded Q931 message (%s, %s)\n", call->callType, 
1126                 call->callToken);
1127    finishPrint();
1128    removeEventHandler(pctxt);
1129    if(ret == OO_OK) {
1130       ret = ooHandleH2250Message(call, pmsg);
1131    }
1132    return ret;
1133 }
1134
1135
1136
1137 int ooH245Receive(OOH323CallData *call)
1138 {
1139    int  recvLen, ret, len, total=0;
1140    ASN1OCTET message[MAXMSGLEN], message1[MAXMSGLEN];
1141    ASN1BOOL aligned = TRUE;
1142    H245Message *pmsg;
1143    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
1144    OOCTXT *pctxt = call->pctxt;
1145    struct timeval timeout;
1146    
1147    pmsg = (H245Message*)memAlloc(pctxt, sizeof(H245Message));
1148
1149    /* First read just TPKT header which is four bytes */
1150    recvLen = ooSocketRecv (call->pH245Channel->sock, message, 4);
1151    /* Since we are working with TCP, need to determine the
1152       message boundary. Has to be done at channel level, as channels
1153       know the message formats and can determine boundaries
1154    */
1155    if(recvLen<=0 && call->h245SessionState != OO_H245SESSION_PAUSED)
1156    {
1157       if(recvLen == 0)
1158          OOTRACEINFO3("Closing H.245 channels as remote end point closed H.245"
1159                     " connection (%s, %s)\n", call->callType, call->callToken);
1160       else
1161          OOTRACEERR3("Error: Transport failure while trying to receive H245"
1162                      " message (%s, %s)\n", call->callType, call->callToken);
1163
1164       ooCloseH245Connection(call);
1165       ooFreeH245Message(call, pmsg);
1166       if(call->callState < OO_CALL_CLEAR)
1167       {
1168          call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1169          call->callState = OO_CALL_CLEAR;
1170       }
1171       return OO_FAILED;
1172    }
1173    if(call->h245SessionState == OO_H245SESSION_PAUSED) 
1174    {
1175       ooLogicalChannel *temp;
1176
1177       OOTRACEINFO3("Call Paused, closing logical channels"
1178                     " (%s, %s)\n", call->callType, call->callToken);
1179
1180       temp = call->logicalChans;
1181       while(temp)
1182       {
1183          if(temp->state == OO_LOGICALCHAN_ESTABLISHED)
1184          {
1185             /* Sending closelogicalchannel only for outgoing channels*/
1186             if(!strcmp(temp->dir, "transmit"))
1187             {
1188                ooSendCloseLogicalChannel(call, temp);
1189             }
1190          }
1191          temp = temp->next;
1192       }
1193       call->masterSlaveState = OO_MasterSlave_Idle;
1194       call->callState = OO_CALL_PAUSED;
1195       call->localTermCapState = OO_LocalTermCapExchange_Idle;
1196       call->remoteTermCapState = OO_RemoteTermCapExchange_Idle;
1197       call->h245SessionState = OO_H245SESSION_IDLE;
1198       call->logicalChans = NULL;
1199    }
1200    OOTRACEDBGC1("Receiving H245 message\n");
1201    if(recvLen != 4)
1202    {
1203       OOTRACEERR3("Error: Reading TPKT header for H245 message (%s, %s)\n",
1204                   call->callType, call->callToken);
1205       ooFreeH245Message(call, pmsg);
1206       if(call->callState < OO_CALL_CLEAR)
1207       {
1208          call->callEndReason = OO_REASON_INVALIDMESSAGE;
1209          call->callState = OO_CALL_CLEAR;
1210       }
1211       return OO_FAILED;
1212    }
1213
1214    len = message[2];
1215    len = len<<8;
1216    len = (len | message[3]);
1217    /* Remaining message length is length - tpkt length */
1218    len = len - 4;
1219    /* Now read actual H245 message body. We should make sure that we
1220       receive complete message as indicated by len. If we don't then there 
1221       is something wrong. The loop below receives message, then checks whether
1222       complete message is received. If not received, then uses select to peek
1223       for remaining bytes of the message. If message is not received in 3
1224       seconds, then we have a problem. Report an error and exit.
1225    */
1226
1227    if(len > MAXMSGLEN - 4)
1228    {
1229       OOTRACEERR4("Error: Invalid TPKT header length %d for H245 message (%s, %s)\n",
1230                   len, call->callType, call->callToken);
1231       ooFreeH245Message(call, pmsg);
1232       if(call->callState < OO_CALL_CLEAR)
1233       {
1234          call->callEndReason = OO_REASON_INVALIDMESSAGE;
1235          call->callState = OO_CALL_CLEAR;
1236       }
1237       return OO_FAILED;
1238    }
1239
1240    while(total < len)
1241    {
1242       struct pollfd pfds;
1243       recvLen = ooSocketRecv (call->pH245Channel->sock, message1, len-total);
1244       memcpy(message+total, message1, recvLen);
1245       total = total + recvLen;
1246       if(total == len) break; /* Complete message is received */
1247
1248       pfds.fd = call->pH245Channel->sock;
1249       pfds.events = POLLIN;
1250       timeout.tv_sec = 3;
1251       timeout.tv_usec = 0;
1252       ret = ooSocketPoll(&pfds, 1,  timeout.tv_sec * 1000);
1253       if(ret == -1)
1254       {
1255          OOTRACEERR3("Error in select...H245 Receive-Clearing call (%s, %s)\n",
1256                      call->callType, call->callToken);
1257          ooFreeH245Message(call, pmsg);
1258          if(call->callState < OO_CALL_CLEAR)
1259          {
1260             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1261             call->callState = OO_CALL_CLEAR;
1262          }
1263          return OO_FAILED;
1264       }
1265       /* If remaining part of the message is not received in 3 seconds 
1266          exit */
1267       if(!ooPDRead(&pfds, 1, call->pH245Channel->sock))
1268       {
1269          OOTRACEERR3("Error: Incomplete h245 message received (%s, %s)\n",
1270                      call->callType, call->callToken);
1271          ooFreeH245Message(call, pmsg);
1272          if(call->callState < OO_CALL_CLEAR)
1273          {
1274             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1275             call->callState = OO_CALL_CLEAR;
1276          }
1277          return OO_FAILED;
1278       }
1279    }
1280
1281    OOTRACEDBGC3("Complete H245 message received (%s, %s)\n", 
1282                  call->callType, call->callToken);
1283    setPERBuffer(pctxt, message, recvLen, aligned);
1284    initializePrintHandler(&printHandler, "Received H.245 Message");
1285
1286    /* Set event handler */
1287    setEventHandler (pctxt, &printHandler);
1288
1289    ret = asn1PD_H245MultimediaSystemControlMessage(pctxt, &(pmsg->h245Msg));
1290    if(ret != ASN_OK)
1291    {
1292       OOTRACEERR3("Error decoding H245 message (%s, %s)\n", 
1293                   call->callType, call->callToken);
1294       ooFreeH245Message(call, pmsg);
1295       return OO_FAILED;
1296    }
1297    finishPrint();
1298    removeEventHandler(pctxt); 
1299    ooHandleH245Message(call, pmsg);
1300    return OO_OK;
1301 }
1302
1303 /* Generic Send Message functionality. Based on type of message to be sent,
1304    it calls the corresponding function to retrieve the message buffer and 
1305    then transmits on the associated channel
1306    Interpreting msgptr:
1307       Q931 messages except facility
1308                              1st octet - msgType, next 4 octets - tpkt header,
1309                              followed by encoded msg
1310       Q931 message facility
1311                              1st octect - OOFacility, 2nd octet - tunneled msg 
1312                              type(in case no tunneled msg - OOFacility), 
1313                              3rd and 4th octet - associated logical channel 
1314                              of the tunneled msg(0 when no channel is 
1315                              associated. ex. in case of MSD, TCS), next 
1316                              4 octets - tpkt header, followed by encoded 
1317                              message.
1318
1319       H.245 messages no tunneling
1320                              1st octet - msg type, next two octets - logical 
1321                              channel number(0, when no channel is associated),
1322                              next two octets - total length of the message
1323                             (including tpkt header)
1324
1325       H.245 messages - tunneling.
1326                              1st octet - msg type, next two octets - logical 
1327                              channel number(0, when no channel is associated),
1328                              next two octets - total length of the message. 
1329                              Note, no tpkt header is present in this case.
1330                             
1331 */
1332 int ooSendMsg(OOH323CallData *call, int type)
1333 {
1334
1335    int len=0, ret=0, msgType=0, tunneledMsgType=0, logicalChannelNo = 0;
1336    DListNode * p_msgNode=NULL;
1337    ASN1OCTET *msgptr, *msgToSend=NULL;
1338    
1339
1340
1341    if(call->callState == OO_CALL_CLEARED)
1342    {
1343       OOTRACEDBGA3("Warning:Call marked for cleanup. Can not send message."
1344                    "(%s, %s)\n", call->callType, call->callToken);
1345       return OO_OK;
1346    }
1347
1348    if(type == OOQ931MSG)
1349    {
1350       if(call->pH225Channel->outQueue.count == 0)
1351       {
1352          OOTRACEWARN3("WARN:No H.2250 message to send. (%s, %s)\n", 
1353                       call->callType, call->callToken);
1354          return OO_FAILED;
1355       }
1356
1357       OOTRACEDBGA3("Sending Q931 message (%s, %s)\n", call->callType, 
1358                                                       call->callToken);
1359       p_msgNode = call->pH225Channel->outQueue.head;
1360       msgptr = (ASN1OCTET*) p_msgNode->data;
1361       msgType = msgptr[0];
1362
1363       if(msgType == OOFacility)
1364       {
1365          tunneledMsgType = msgptr[1];
1366          logicalChannelNo = msgptr[2];
1367          logicalChannelNo = logicalChannelNo << 8;
1368          logicalChannelNo = (logicalChannelNo | msgptr[3]);
1369          len = msgptr[6];
1370          len = len<<8;
1371          len = (len | msgptr[7]);
1372          msgToSend = msgptr+4;
1373       }
1374       else {
1375          len = msgptr[3];
1376          len = len<<8;
1377          len = (len | msgptr[4]);
1378          msgToSend = msgptr+1;
1379       }
1380
1381       /* Remove the message from rtdlist pH225Channel->outQueue */
1382       dListRemove(&(call->pH225Channel->outQueue), p_msgNode);
1383       if(p_msgNode)
1384          memFreePtr(call->pctxt, p_msgNode);
1385       
1386       /*TODO: This is not required ideally. We will see for some time and if
1387          we don't face any problems we will delete this code */
1388 #if 0 
1389       /* Check whether connection with remote is alright */
1390       if(!ooChannelsIsConnectionOK(call, call->pH225Channel->sock))
1391       {
1392          OOTRACEERR3("Error:Transport failure for signalling channel. "
1393                      "Abandoning message send and marking call for cleanup.(%s"
1394                      "'%s)\n", call->callType, call->callToken);
1395          if(call->callState < OO_CALL_CLEAR)
1396             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1397          call->callState = OO_CALL_CLEARED;
1398          return OO_OK;
1399       }
1400 #endif     
1401       /* Send message out via TCP */      
1402       ret = ooSocketSend(call->pH225Channel->sock, msgToSend, len);
1403       if(ret == ASN_OK)
1404       {
1405          memFreePtr (call->pctxt, msgptr);
1406          OOTRACEDBGC3("H2250/Q931 Message sent successfully (%s, %s)\n", 
1407                       call->callType, call->callToken);
1408          ooOnSendMsg(call, msgType, tunneledMsgType, logicalChannelNo);
1409          return OO_OK;
1410       }
1411       else{
1412          OOTRACEERR3("H2250Q931 Message send failed (%s, %s)\n", 
1413                      call->callType, call->callToken);
1414          memFreePtr (call->pctxt, msgptr);
1415          if(call->callState < OO_CALL_CLEAR)
1416          {
1417             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1418             call->callState = OO_CALL_CLEAR;
1419          }
1420          return OO_FAILED;
1421       }
1422    }/* end of type==OOQ931MSG */
1423    if(type == OOH245MSG)
1424    {
1425       if(call->pH245Channel->outQueue.count == 0)
1426       {
1427          OOTRACEWARN3("WARN:No H.245 message to send. (%s, %s)\n", 
1428                                  call->callType, call->callToken);
1429          return OO_FAILED;
1430       }
1431       OOTRACEDBGA3("Sending H245 message (%s, %s)\n", call->callType, 
1432                                                       call->callToken);
1433       p_msgNode = call->pH245Channel->outQueue.head;
1434       msgptr = (ASN1OCTET*) p_msgNode->data;
1435       msgType = msgptr[0];
1436
1437       logicalChannelNo = msgptr[1];
1438       logicalChannelNo = logicalChannelNo << 8;
1439       logicalChannelNo = (logicalChannelNo | msgptr[2]);
1440
1441       len = msgptr[3];
1442       len = len<<8;
1443       len = (len | msgptr[4]);
1444       /* Remove the message from queue */
1445       dListRemove(&(call->pH245Channel->outQueue), p_msgNode);
1446       if(p_msgNode)
1447          memFreePtr(call->pctxt, p_msgNode);
1448
1449       /* Send message out */
1450       if (0 == call->pH245Channel && !OO_TESTFLAG(call->flags, OO_M_TUNNELING))
1451       {
1452          OOTRACEWARN3("Neither H.245 channel nor tunneling active "
1453                      "(%s, %s)\n", call->callType, call->callToken);
1454          memFreePtr (call->pctxt, msgptr);
1455          /*ooCloseH245Session(call);*/
1456          if(call->callState < OO_CALL_CLEAR)
1457          {
1458             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1459             call->callState = OO_CALL_CLEAR;
1460          }
1461          return OO_OK;
1462       }
1463       
1464       if (0 != call->pH245Channel && 0 != call->pH245Channel->sock)
1465       {
1466          OOTRACEDBGC4("Sending %s H245 message over H.245 channel. "
1467                       "(%s, %s)\n", ooGetMsgTypeText(msgType), 
1468                       call->callType, call->callToken);
1469
1470          ret = ooSocketSend(call->pH245Channel->sock, msgptr+5, len);
1471          if(ret == ASN_OK)
1472          {
1473             memFreePtr (call->pctxt, msgptr);
1474             OOTRACEDBGA3("H245 Message sent successfully (%s, %s)\n", 
1475                           call->callType, call->callToken);
1476             ooOnSendMsg(call, msgType, tunneledMsgType, logicalChannelNo);
1477             return OO_OK;
1478          }
1479          else{
1480             memFreePtr (call->pctxt, msgptr);
1481             OOTRACEERR3("ERROR:H245 Message send failed (%s, %s)\n", 
1482                         call->callType, call->callToken);
1483             if(call->callState < OO_CALL_CLEAR)
1484             {
1485                call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1486                call->callState = OO_CALL_CLEAR;
1487             }
1488             return OO_FAILED;
1489          }
1490       }
1491       else if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) {
1492          OOTRACEDBGC4("Sending %s H245 message as a tunneled message."
1493                       "(%s, %s)\n", ooGetMsgTypeText(msgType), 
1494                       call->callType, call->callToken);
1495
1496          ret = ooSendAsTunneledMessage
1497                   (call, msgptr+5,len,msgType, logicalChannelNo);
1498
1499          if(ret != OO_OK)
1500          {
1501             memFreePtr (call->pctxt, msgptr);
1502             OOTRACEERR3("ERROR:Failed to tunnel H.245 message (%s, %s)\n",
1503                          call->callType, call->callToken);
1504             if(call->callState < OO_CALL_CLEAR)
1505             {
1506                call->callEndReason = OO_REASON_INVALIDMESSAGE;
1507                call->callState = OO_CALL_CLEAR;
1508             }
1509             return OO_FAILED;
1510          }
1511          memFreePtr (call->pctxt, msgptr);
1512          return OO_OK;
1513       }
1514    }
1515    /* Need to add support for other messages such as T38 etc */
1516    OOTRACEWARN3("ERROR:Unknown message type - message not Sent (%s, %s)\n",
1517                 call->callType, call->callToken);
1518    return OO_FAILED;
1519 }       
1520
1521 int ooCloseH245Connection(OOH323CallData *call)
1522 {
1523    OOTRACEINFO3("Closing H.245 connection (%s, %s)\n", call->callType, 
1524                 call->callToken);
1525
1526    if (0 != call->pH245Channel)
1527    {
1528       if(0 != call->pH245Channel->sock)
1529          ooSocketClose (call->pH245Channel->sock);
1530       if (call->pH245Channel->outQueue.count > 0)
1531          dListFreeAll(call->pctxt, &(call->pH245Channel->outQueue));
1532       memFreePtr (call->pctxt, call->pH245Channel);
1533       call->pH245Channel = NULL;
1534       OOTRACEDBGC3("Closed H245 connection. (%s, %s)\n", call->callType, 
1535                                                        call->callToken);
1536    }
1537    call->h245SessionState = OO_H245SESSION_CLOSED;
1538
1539    return OO_OK;
1540 }
1541
1542 int ooCloseH245Listener(OOH323CallData *call)
1543 {
1544    OOTRACEINFO3("Closing H.245 Listener (%s, %s)\n", call->callType, 
1545                 call->callToken);
1546    if(call->h245listener)
1547    {
1548       ooSocketClose(*(call->h245listener));
1549       memFreePtr(call->pctxt, call->h245listener);
1550       call->h245listener = NULL;
1551    }
1552    return OO_OK;
1553 }
1554
1555 int ooOnSendMsg
1556    (OOH323CallData *call, int msgType, int tunneledMsgType, int associatedChan)
1557 {
1558    ooTimerCallback *cbData=NULL;
1559    switch(msgType)
1560    {
1561    case OOSetup:
1562       OOTRACEINFO3("Sent Message - Setup (%s, %s)\n", call->callType, 
1563                     call->callToken);
1564       /* Start call establishment timer */
1565       cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1566                                                      sizeof(ooTimerCallback));
1567       if(!cbData)
1568       {
1569          OOTRACEERR3("Error:Unable to allocate memory for timer callback."
1570                      "(%s, %s)\n", call->callType, call->callToken);
1571          return OO_FAILED;
1572       }
1573       cbData->call = call;
1574       cbData->timerType = OO_CALLESTB_TIMER;
1575       if(!ooTimerCreate(call->pctxt, &call->timerList, &ooCallEstbTimerExpired,
1576                         gH323ep.callEstablishmentTimeout, cbData, FALSE))
1577       {
1578          OOTRACEERR3("Error:Unable to create call establishment timer. "
1579                      "(%s, %s)\n", call->callType, call->callToken);
1580          memFreePtr(call->pctxt, cbData);
1581          return OO_FAILED;
1582       }
1583
1584       /* if(gH323ep.h323Callbacks.onOutgoingCall)
1585          gH323ep.h323Callbacks.onOutgoingCall(call); */
1586       break;
1587    case OOCallProceeding:
1588       OOTRACEINFO3("Sent Message - CallProceeding (%s, %s)\n", call->callType,
1589                     call->callToken);
1590       break;
1591    case OOAlert:
1592       OOTRACEINFO3("Sent Message - Alerting (%s, %s) \n", call->callType,
1593                     call->callToken);
1594       /* if(gH323ep.h323Callbacks.onAlerting && call->callState < OO_CALL_CLEAR)
1595          gH323ep.h323Callbacks.onAlerting(call); */
1596       break;
1597    case OOConnect:
1598       OOTRACEINFO3("Sent Message - Connect (%s, %s)\n", call->callType,
1599                     call->callToken);
1600       if(gH323ep.h323Callbacks.onCallEstablished)
1601          gH323ep.h323Callbacks.onCallEstablished(call);
1602       break;
1603    case OOReleaseComplete:
1604       OOTRACEINFO3("Sent Message - ReleaseComplete (%s, %s)\n", call->callType,
1605                     call->callToken);
1606
1607       if(call->callState == OO_CALL_CLEAR_RELEASERECVD)
1608          call->callState = OO_CALL_CLEARED;
1609       else{
1610          call->callState = OO_CALL_CLEAR_RELEASESENT;
1611          if(gH323ep.gkClient && !OO_TESTFLAG(call->flags, OO_M_DISABLEGK) && 
1612             gH323ep.gkClient->state == GkClientRegistered){
1613             OOTRACEDBGA3("Sending DRQ after sending ReleaseComplete."
1614                          "(%s, %s)\n",   call->callType, call->callToken);
1615
1616             call->endTime = (H235TimeStamp) time(NULL);
1617             ooGkClientSendDisengageRequest(gH323ep.gkClient, call);
1618          }
1619       }
1620
1621       if(call->callState == OO_CALL_CLEAR_RELEASESENT && 
1622          call->h245SessionState == OO_H245SESSION_IDLE)
1623       {
1624          cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1625                                                   sizeof(ooTimerCallback));
1626          if(!cbData)
1627          {
1628             OOTRACEERR3("Error:Unable to allocate memory for timer callback "
1629                         "data.(%s, %s)\n", call->callType, call->callToken);
1630             return OO_FAILED;
1631          }
1632          cbData->call = call;
1633          cbData->timerType = OO_SESSION_TIMER;
1634          cbData->channelNumber = 0;
1635          if(!ooTimerCreate(call->pctxt, &call->timerList, 
1636              &ooSessionTimerExpired, gH323ep.sessionTimeout, cbData, FALSE))
1637          {
1638             OOTRACEERR3("Error:Unable to create EndSession timer- "
1639                         "ReleaseComplete.(%s, %s)\n", call->callType, 
1640                         call->callToken);
1641             memFreePtr(call->pctxt, cbData);
1642             return OO_FAILED;
1643          }
1644       }
1645
1646       if(call->h245SessionState == OO_H245SESSION_CLOSED)
1647       {
1648          call->callState = OO_CALL_CLEARED;
1649       }
1650       break;
1651
1652    case OOFacility:
1653       if(tunneledMsgType == OOFacility)
1654       {
1655          OOTRACEINFO3("Sent Message - Facility. (%s, %s)\n", 
1656                       call->callType, call->callToken);
1657       }
1658       else{
1659          OOTRACEINFO4("Sent Message - Facility(%s) (%s, %s)\n", 
1660                       ooGetMsgTypeText(tunneledMsgType), 
1661                       call->callType, call->callToken);
1662
1663          ooOnSendMsg(call, tunneledMsgType, 0, associatedChan);
1664       }
1665       break;
1666
1667    case OOMasterSlaveDetermination:
1668      if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1669         OOTRACEINFO3("Tunneled Message - MasterSlaveDetermination (%s, %s)\n", 
1670                       call->callType, call->callToken);
1671       else
1672          OOTRACEINFO3("Sent Message - MasterSlaveDetermination (%s, %s)\n", 
1673                        call->callType, call->callToken);
1674        /* Start MSD timer */
1675       cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1676                                                      sizeof(ooTimerCallback));
1677       if(!cbData)
1678       {
1679          OOTRACEERR3("Error:Unable to allocate memory for timer callback data."
1680                      "(%s, %s)\n", call->callType, call->callToken);
1681          return OO_FAILED;
1682       }
1683       cbData->call = call;
1684       cbData->timerType = OO_MSD_TIMER;
1685       if(!ooTimerCreate(call->pctxt, &call->timerList, &ooMSDTimerExpired,
1686                         gH323ep.msdTimeout, cbData, FALSE))
1687       {
1688          OOTRACEERR3("Error:Unable to create MSD timer. "
1689                      "(%s, %s)\n", call->callType, call->callToken);
1690          memFreePtr(call->pctxt, cbData);
1691          return OO_FAILED;
1692       }
1693
1694       break;
1695    case OOMasterSlaveAck:
1696      if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1697          OOTRACEINFO3("Tunneled Message - MasterSlaveDeterminationAck (%s, %s)"
1698                       "\n",  call->callType, call->callToken);
1699      else
1700         OOTRACEINFO3("Sent Message - MasterSlaveDeterminationAck (%s, %s)\n", 
1701                     call->callType, call->callToken);
1702       break;
1703    case OOMasterSlaveReject:
1704      if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1705         OOTRACEINFO3("Tunneled Message - MasterSlaveDeterminationReject "
1706                      "(%s, %s)\n", call->callType, call->callToken);
1707      else
1708         OOTRACEINFO3("Sent Message - MasterSlaveDeterminationReject(%s, %s)\n",
1709                     call->callType, call->callToken);
1710       break;
1711    case OOMasterSlaveRelease:
1712       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1713          OOTRACEINFO3("Tunneled Message - MasterSlaveDeterminationRelease "
1714                       "(%s, %s)\n", call->callType, call->callToken);
1715       else
1716          OOTRACEINFO3("Sent Message - MasterSlaveDeterminationRelease "
1717                       "(%s, %s)\n", call->callType, call->callToken);
1718       break;
1719    case OOTerminalCapabilitySet:
1720       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) {
1721          /* If session isn't marked active yet, do it. possible in case of 
1722             tunneling */
1723          if(call->h245SessionState == OO_H245SESSION_IDLE ||
1724             call->h245SessionState == OO_H245SESSION_PAUSED) {
1725             call->h245SessionState = OO_H245SESSION_ACTIVE;
1726          }
1727          OOTRACEINFO3("Tunneled Message - TerminalCapabilitySet (%s, %s)\n", 
1728                        call->callType, call->callToken);
1729       }
1730       else {
1731          OOTRACEINFO3("Sent Message - TerminalCapabilitySet (%s, %s)\n", 
1732                        call->callType, call->callToken);
1733       }
1734       /* Start TCS timer */
1735       cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1736                                                      sizeof(ooTimerCallback));
1737       if(!cbData)
1738       {
1739          OOTRACEERR3("Error:Unable to allocate memory for timer callback data."
1740                      "(%s, %s)\n", call->callType, call->callToken);
1741          return OO_FAILED;
1742       }
1743       cbData->call = call;
1744       cbData->timerType = OO_TCS_TIMER;
1745       if(!ooTimerCreate(call->pctxt, &call->timerList, &ooTCSTimerExpired,
1746                         gH323ep.tcsTimeout, cbData, FALSE))
1747       {
1748          OOTRACEERR3("Error:Unable to create TCS timer. "
1749                      "(%s, %s)\n", call->callType, call->callToken);
1750          memFreePtr(call->pctxt, cbData);
1751          return OO_FAILED;
1752       }
1753       break;
1754
1755
1756    case OOTerminalCapabilitySetAck:
1757       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1758          OOTRACEINFO3("Tunneled Message - TerminalCapabilitySetAck (%s, %s)\n",
1759                        call->callType, call->callToken);
1760       else
1761          OOTRACEINFO3("Sent Message - TerminalCapabilitySetAck (%s, %s)\n", 
1762                        call->callType, call->callToken);
1763       break;
1764    case OOTerminalCapabilitySetReject:
1765       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1766          OOTRACEINFO3("Tunneled Message - TerminalCapabilitySetReject "
1767                       "(%s, %s)\n",  call->callType, call->callToken);
1768       else
1769          OOTRACEINFO3("Sent Message - TerminalCapabilitySetReject (%s, %s)\n", 
1770                        call->callType, call->callToken);
1771       break;
1772    case OOOpenLogicalChannel:
1773       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1774          OOTRACEINFO4("Tunneled Message - OpenLogicalChannel(%d). (%s, %s)\n", 
1775                        associatedChan, call->callType, call->callToken);
1776       else
1777          OOTRACEINFO4("Sent Message - OpenLogicalChannel(%d). (%s, %s)\n", 
1778                        associatedChan, call->callType, call->callToken);
1779       /* Start LogicalChannel timer */
1780       cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1781                                                      sizeof(ooTimerCallback));
1782       if(!cbData)
1783       {
1784          OOTRACEERR3("Error:Unable to allocate memory for timer callback data."
1785                      "(%s, %s)\n", call->callType, call->callToken);
1786          return OO_FAILED;
1787       }
1788       cbData->call = call;
1789       cbData->timerType = OO_OLC_TIMER;
1790       cbData->channelNumber = associatedChan;
1791       if(!ooTimerCreate(call->pctxt, &call->timerList, 
1792           &ooOpenLogicalChannelTimerExpired, gH323ep.logicalChannelTimeout, 
1793           cbData, FALSE))
1794       {
1795          OOTRACEERR3("Error:Unable to create OpenLogicalChannel timer. "
1796                      "(%s, %s)\n", call->callType, call->callToken);
1797          memFreePtr(call->pctxt, cbData);
1798          return OO_FAILED;
1799       }
1800       
1801       break;
1802    case OOOpenLogicalChannelAck:
1803       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1804          OOTRACEINFO4("Tunneled Message - OpenLogicalChannelAck(%d) (%s,%s)\n",
1805                        associatedChan, call->callType, call->callToken);
1806       else
1807          OOTRACEINFO4("Sent Message - OpenLogicalChannelAck(%d) (%s, %s)\n", 
1808                        associatedChan, call->callType, call->callToken);
1809       break;
1810    case OOOpenLogicalChannelReject:
1811       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1812          OOTRACEINFO4("Tunneled Message - OpenLogicalChannelReject(%d)"
1813                       "(%s, %s)\n", associatedChan, call->callType, 
1814                       call->callToken);
1815       else
1816          OOTRACEINFO4("Sent Message - OpenLogicalChannelReject(%d) (%s, %s)\n",
1817                        associatedChan, call->callType, call->callToken);
1818       break;
1819    case OOEndSessionCommand:
1820       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1821          OOTRACEINFO3("Tunneled Message - EndSessionCommand(%s, %s)\n", 
1822                                              call->callType, call->callToken);
1823       else
1824          OOTRACEINFO3("Sent Message - EndSessionCommand (%s, %s)\n", 
1825                                            call->callType, call->callToken);
1826       if((call->h245SessionState == OO_H245SESSION_ACTIVE))
1827       { 
1828          /* Start EndSession timer */
1829          call->h245SessionState = OO_H245SESSION_ENDSENT;
1830          cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1831                                                   sizeof(ooTimerCallback));
1832          if(!cbData)
1833          {
1834             OOTRACEERR3("Error:Unable to allocate memory for timer callback "
1835                         "data.(%s, %s)\n", call->callType, call->callToken);
1836             return OO_FAILED;
1837          }
1838          cbData->call = call;
1839          cbData->timerType = OO_SESSION_TIMER;
1840          cbData->channelNumber = 0;
1841          if(!ooTimerCreate(call->pctxt, &call->timerList, 
1842              &ooSessionTimerExpired, gH323ep.sessionTimeout, cbData, FALSE))
1843          {
1844             OOTRACEERR3("Error:Unable to create EndSession timer. "
1845                         "(%s, %s)\n", call->callType, call->callToken);
1846             memFreePtr(call->pctxt, cbData);
1847             return OO_FAILED;
1848          }
1849       }
1850       else{
1851          ooCloseH245Connection(call);
1852       }
1853       break;
1854    case OOCloseLogicalChannel:
1855       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1856          OOTRACEINFO3("Tunneled Message - CloseLogicalChannel (%s, %s)\n", 
1857                        call->callType, call->callToken);
1858       else
1859          OOTRACEINFO3("Sent Message - CloseLogicalChannel (%s, %s)\n", 
1860                        call->callType, call->callToken);
1861       /* Start LogicalChannel timer */
1862       cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1863                                                      sizeof(ooTimerCallback));
1864       if(!cbData)
1865       {
1866          OOTRACEERR3("Error:Unable to allocate memory for timer callback data."
1867                      "(%s, %s)\n", call->callType, call->callToken);
1868          return OO_FAILED;
1869       }
1870       cbData->call = call;
1871       cbData->timerType = OO_CLC_TIMER;
1872       cbData->channelNumber = associatedChan;
1873       if(!ooTimerCreate(call->pctxt, &call->timerList, 
1874           &ooCloseLogicalChannelTimerExpired, gH323ep.logicalChannelTimeout, 
1875           cbData, FALSE))
1876       {
1877          OOTRACEERR3("Error:Unable to create CloseLogicalChannel timer. "
1878                      "(%s, %s)\n", call->callType, call->callToken);
1879          memFreePtr(call->pctxt, cbData);
1880          return OO_FAILED;
1881       }
1882       
1883       break;
1884    case OOCloseLogicalChannelAck:
1885       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1886          OOTRACEINFO3("Tunneled Message - CloseLogicalChannelAck (%s, %s)\n", 
1887                        call->callType, call->callToken);
1888       else
1889          OOTRACEINFO3("Sent Message - CloseLogicalChannelAck (%s, %s)\n", 
1890                        call->callType, call->callToken);
1891       break;
1892    case OORequestChannelClose:
1893       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1894          OOTRACEINFO3("Tunneled Message - RequestChannelClose (%s, %s)\n", 
1895                        call->callType, call->callToken);
1896       else
1897          OOTRACEINFO3("Sent Message - RequestChannelClose (%s, %s)\n", 
1898                        call->callType, call->callToken);
1899       /* Start RequestChannelClose timer */
1900       cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1901                                                      sizeof(ooTimerCallback));
1902       if(!cbData)
1903       {
1904          OOTRACEERR3("Error:Unable to allocate memory for timer callback data."
1905                      "(%s, %s)\n", call->callType, call->callToken);
1906          return OO_FAILED;
1907       }
1908       cbData->call = call;
1909       cbData->timerType = OO_RCC_TIMER;
1910       cbData->channelNumber = associatedChan;
1911       if(!ooTimerCreate(call->pctxt, &call->timerList, 
1912           &ooRequestChannelCloseTimerExpired, gH323ep.logicalChannelTimeout, 
1913           cbData, FALSE))
1914       {
1915          OOTRACEERR3("Error:Unable to create RequestChannelClose timer. "
1916                      "(%s, %s)\n", call->callType, call->callToken);
1917          memFreePtr(call->pctxt, cbData);
1918          return OO_FAILED;
1919       }
1920       break;
1921    case OORequestChannelCloseAck:
1922       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1923          OOTRACEINFO3("Tunneled Message - RequestChannelCloseAck (%s, %s)\n", 
1924                        call->callType, call->callToken);
1925       else
1926          OOTRACEINFO3("Sent Message - RequestChannelCloseAck (%s, %s)\n", 
1927                        call->callType, call->callToken);
1928       break;
1929    
1930    default:
1931      ;
1932    }
1933    return OO_OK;
1934 }
1935
1936 void ooStopMonitorCallChannels(OOH323CallData * call) {
1937         if (call->Monitor)
1938          call->Monitor = FALSE;
1939         /* if (call->cmdSock)
1940          ooCloseCallCmdConnection(call); */
1941 }
1942
1943 int ooStopMonitorCalls()
1944 {
1945    OOH323CallData * call;
1946    if(gMonitor)
1947    {
1948       OOTRACEINFO1("Doing ooStopMonitorCalls\n");
1949       if(gH323ep.cmdSock)
1950       {
1951          ooCloseCmdConnection();
1952       }
1953
1954       if(gH323ep.callList)
1955       {
1956          OOTRACEWARN1("Warn:Abruptly ending calls as stack going down\n");
1957          call = gH323ep.callList;
1958          while(call)
1959          {
1960             OOTRACEWARN3("Clearing call (%s, %s)\n", call->callType, 
1961                           call->callToken);
1962             call->callEndReason = OO_REASON_LOCAL_CLEARED;
1963             ooCleanCall(call);
1964             call = NULL;
1965             call = gH323ep.callList;
1966          }
1967          gH323ep.callList = NULL;
1968       }
1969       OOTRACEINFO1("Stopping listener for incoming calls\n");   
1970       if(gH323ep.listener)
1971       {
1972          ooSocketClose(*(gH323ep.listener));
1973          memFreePtr(&gH323ep.ctxt, gH323ep.listener);
1974          gH323ep.listener = NULL;
1975       }
1976
1977       gMonitor = FALSE;
1978       OOTRACEINFO1("Done ooStopMonitorCalls\n");
1979    }
1980    return OO_OK;
1981 }
1982
1983 OOBOOL ooChannelsIsConnectionOK(OOH323CallData *call, OOSOCKET sock)
1984 {
1985    struct timeval to = { .tv_usec = 500 };
1986    struct pollfd pfds = { .fd = sock, .events = POLLIN };
1987    int ret = 0;
1988
1989    ret = ast_poll2(&pfds, 1, &to);
1990
1991    if(ret == -1)
1992    {
1993       OOTRACEERR3("Error in select ...broken pipe check(%s, %s)\n",
1994                    call->callType, call->callToken );
1995       return FALSE;
1996    }
1997
1998    if (pfds.events & POLLIN) {
1999       char buf[2];
2000       if(ooSocketRecvPeek(sock, (ASN1OCTET*) buf, 2) == 0)
2001       {
2002          OOTRACEWARN3("Broken pipe detected. (%s, %s)", call->callType, 
2003                        call->callToken);
2004          if(call->callState < OO_CALL_CLEAR)
2005             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
2006          call->callState = OO_CALL_CLEARED;
2007          return FALSE;
2008       }
2009    }
2010    return TRUE;
2011 }