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