fd6cbb3768319a75acd8107fb25c0832c86cba98
[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             ooStopMonitorCallChannels(call);
752      }
753    }
754
755    return OO_OK;
756
757 }
758    
759 int ooMonitorCmdChannels()
760 {
761    int ret=0, nfds=0;
762    struct timeval toMin;
763    struct pollfd pfds[1];
764
765    gMonitor = TRUE;
766
767    toMin.tv_sec = 3;
768    toMin.tv_usec = 0;
769    
770    while(1)
771    {
772       nfds = 0;
773       ooSetCmdFDSETs(pfds, &nfds);
774
775       if(!gMonitor) {
776          OOTRACEINFO1("Ending Monitor thread\n");
777          break;
778       }
779
780       
781       if(nfds == 0)
782 #ifdef _WIN32
783          Sleep(10);
784 #else
785       {
786          toMin.tv_sec = 0;
787          toMin.tv_usec = 10000;
788          ooSocketPoll(pfds, nfds, toMin.tv_usec / 1000);
789       }
790 #endif
791       else
792          ret = ooSocketPoll(pfds, nfds, toMin.tv_sec * 1000 + toMin.tv_usec / 1000);
793       
794       if(ret == -1)
795       {
796          
797          OOTRACEERR1("Error in poll ...exiting\n");
798          exit(-1); 
799          continue;
800       }
801
802       toMin.tv_sec = 2;  /* 2 sec */
803       toMin.tv_usec = 100000; /* 100ms*/
804
805       ast_mutex_lock(&monitorLock);
806       if(ooProcessCmdFDSETsAndTimers(pfds, nfds, &toMin) != OO_OK)
807       {
808          /* ooStopMonitorCalls(); */
809          ast_mutex_unlock(&monitorLock);
810          continue;
811       }
812       ast_mutex_unlock(&monitorLock);
813
814    }/* while(1)*/
815    return OO_OK;
816 }
817
818 int ooMonitorChannels()
819 {
820    int ret=0, nfds=0;
821    struct timeval toMin, toNext;
822    struct pollfd pfds[2];
823
824    gMonitor = TRUE;
825
826    toMin.tv_sec = 3;
827    toMin.tv_usec = 0;
828    ooH323EpPrintConfig();
829    
830    if(gH323ep.gkClient) {
831       ooGkClientPrintConfig(gH323ep.gkClient);
832       if(OO_OK != ooGkClientStart(gH323ep.gkClient))
833       {
834          OOTRACEERR1("Error:Failed to start Gatekeeper client\n");
835          ooGkClientDestroy();
836       }
837    }
838    
839    while(1)
840    {
841       nfds = 0;
842       ooSetFDSETs(pfds, &nfds);
843
844       if(!gMonitor) {
845          OOTRACEINFO1("Ending Monitor thread\n");
846          break;
847       }
848
849       
850       if(nfds == 0)
851 #ifdef _WIN32
852          Sleep(10);
853 #else
854       {
855          toMin.tv_sec = 0;
856          toMin.tv_usec = 10000;
857          ooSocketPoll(pfds, nfds, toMin.tv_usec / 1000);
858       }
859 #endif
860       else
861          ret = ooSocketPoll(pfds, nfds, toMin.tv_sec * 1000 + toMin.tv_usec / 1000);
862       
863       if(ret == -1)
864       {
865          
866          OOTRACEERR1("Error in poll ...exiting\n");
867          exit(-1);
868       }
869
870       toMin.tv_sec = 2; /* 2 sec */
871       toMin.tv_usec = 100000; /* 100ms*/
872       /*This is for test application. Not part of actual stack */
873   
874       ast_mutex_lock(&monitorLock);
875       ooTimerFireExpired(&gH323ep.ctxt, &g_TimerList);
876       if(ooTimerNextTimeout(&g_TimerList, &toNext))
877       {
878          if(ooCompareTimeouts(&toMin, &toNext)>0)
879          {
880             toMin.tv_sec = toNext.tv_sec;
881             toMin.tv_usec = toNext.tv_usec;
882          }
883       }
884
885       if(ooProcessFDSETsAndTimers(pfds, nfds, &toMin) != OO_OK)
886       {
887          ast_mutex_unlock(&monitorLock);
888          ooStopMonitorCalls();
889          continue;
890       }
891
892       ast_mutex_unlock(&monitorLock);
893    }/* while(1)*/
894    return OO_OK;
895 }
896 int ooMonitorCallChannels(OOH323CallData *call)
897 {
898    int ret=0, nfds=0, zeroloops = 0;
899 #define MAX_ZERO_LOOP 1020
900    struct timeval toMin;
901    struct pollfd pfds[5];
902
903    OOCTXT* pctxt;
904
905    call->Monitor = TRUE;
906
907    toMin.tv_sec = 3;
908    toMin.tv_usec = 0;
909    
910    while(1)
911    {
912       if(!call->Monitor) {
913          OOTRACEINFO1("Ending Call Monitor thread\n");
914          break;
915       }
916
917       nfds = 0;
918       ooSetCallFDSETs(call, pfds, &nfds);
919
920       
921       if(nfds == 0)
922 #ifdef _WIN32
923          Sleep(10);
924 #else
925       {
926          if (zeroloops++ > MAX_ZERO_LOOP) {
927                 ooCleanCall(call);
928                 ooStopMonitorCallChannels(call);
929                 break;
930          }
931          toMin.tv_sec = 0;
932          toMin.tv_usec = 10000;
933          ooSocketPoll(pfds, nfds, toMin.tv_usec / 1000);
934       }
935 #endif
936       else
937          ret = ooSocketPoll(pfds, nfds, toMin.tv_sec * 1000 + toMin.tv_usec / 1000);
938       
939       if(ret == -1)
940       {
941          
942         OOTRACEERR2("Error in poll %d ...exiting\n", errno);
943         call->callEndReason = OO_REASON_INVALIDMESSAGE;
944         call->callState = OO_CALL_CLEARED;
945         ooCleanCall(call);
946         ooStopMonitorCallChannels(call);
947         break;
948
949       }
950
951       toMin.tv_sec = 2; /* 2 sec */
952       toMin.tv_usec = 100000; /* 100ms*/
953       /*This is for test application. Not part of actual stack */
954   
955       if(ooProcessCallFDSETsAndTimers(call, pfds, nfds, &toMin) != OO_OK)
956       {
957          ooStopMonitorCallChannels(call);
958          continue;
959       }
960
961    }/* while(1)*/
962
963    if (call->cmdSock)
964     ooCloseCallCmdConnection(call);
965
966    ast_mutex_lock(&call->Lock);
967    ast_mutex_unlock(&call->Lock);
968    ast_mutex_destroy(&call->Lock);
969    ast_cond_destroy(&call->gkWait);
970    pctxt = call->pctxt;
971    freeContext(pctxt);
972    free(pctxt);
973
974    return OO_OK;
975 }
976
977 int ooH2250Receive(OOH323CallData *call)
978 {
979    int  recvLen=0, total=0, ret=0;
980    ASN1OCTET message[MAXMSGLEN], message1[MAXMSGLEN];
981    int len;
982    Q931Message *pmsg;
983    OOCTXT *pctxt = call->pctxt;
984    
985    struct timeval timeout;
986
987    
988    pmsg = (Q931Message*)memAlloc(pctxt, sizeof(Q931Message));
989    if(!pmsg)
990    {
991       OOTRACEERR3("ERROR:Failed to allocate memory for incoming H.2250 message"
992                   " (%s, %s)\n", call->callType, call->callToken);
993       /* memReset(&gH323ep.msgctxt); */
994       memReset(call->pctxt);
995       return OO_FAILED;
996    }
997    memset(pmsg, 0, sizeof(Q931Message));
998    /* First read just TPKT header which is four bytes */
999    recvLen = ooSocketRecv (call->pH225Channel->sock, message, 4);
1000    if(recvLen <= 0)
1001    {
1002       if(recvLen == 0)
1003          OOTRACEWARN3("Warn:RemoteEndpoint closed connection (%s, %s)\n",
1004                       call->callType, call->callToken);
1005       else
1006          OOTRACEERR3("Error:Transport failure while reading Q931 "
1007                      "message (%s, %s)\n", call->callType, call->callToken);
1008
1009       ooCloseH225Connection(call);
1010       if(call->callState < OO_CALL_CLEARED)
1011       {
1012          if(call->callState < OO_CALL_CLEAR)
1013             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1014          call->callState = OO_CALL_CLEARED;
1015          
1016       }
1017       ooFreeQ931Message(pctxt, pmsg);
1018       return OO_OK;
1019    }
1020    OOTRACEDBGC3("Receiving H.2250 message (%s, %s)\n",
1021                 call->callType, call->callToken);   
1022    /* Since we are working with TCP, need to determine the
1023       message boundary. Has to be done at channel level, as channels
1024       know the message formats and can determine boundaries
1025    */
1026    if(recvLen != 4)
1027    {
1028       OOTRACEERR4("Error: Reading TPKT header for H225 message "
1029                   "recvLen= %d (%s, %s)\n", recvLen, call->callType, 
1030                   call->callToken);
1031       ooFreeQ931Message(pctxt, pmsg);
1032       if(call->callState < OO_CALL_CLEAR)
1033       {
1034          call->callEndReason = OO_REASON_INVALIDMESSAGE;
1035          call->callState = OO_CALL_CLEAR;
1036       }
1037       return OO_FAILED;
1038    }
1039
1040    
1041    len = message[2];
1042    len = len<<8;
1043    len = len | message[3];
1044    /* Remaining message length is length - tpkt length */
1045    len = len - 4;
1046
1047    if(len > MAXMSGLEN - 4)
1048    {
1049       OOTRACEERR4("Error: Invalid TPKT header for H225 message "
1050                   "Len = %d (%s, %s)\n", len, call->callType, 
1051                   call->callToken);
1052       ooCloseH225Connection(call);
1053       ooFreeQ931Message(pctxt, pmsg);
1054       if(call->callState < OO_CALL_CLEAR)
1055       {
1056          call->callEndReason = OO_REASON_INVALIDMESSAGE;
1057          call->callState = OO_CALL_CLEAR;
1058       }
1059       return OO_FAILED;
1060    }
1061
1062    /* Now read actual Q931 message body. We should make sure that we
1063       receive complete message as indicated by len. If we don't then there 
1064       is something wrong. The loop below receives message, then checks whether
1065       complete message is received. If not received, then uses select to peek
1066       for remaining bytes of the message. If message is not received in 3
1067       seconds, then we have a problem. Report an error and exit.
1068    */
1069    while(total < len)
1070    {
1071       struct pollfd pfds;
1072       recvLen = ooSocketRecv (call->pH225Channel->sock, message1, len-total);
1073       memcpy(message+total, message1, recvLen);
1074       total = total + recvLen;
1075
1076       if(total == len) break; /* Complete message is received */
1077       
1078       pfds.fd = call->pH225Channel->sock;
1079       pfds.events = POLLIN;
1080       timeout.tv_sec = 3;
1081       timeout.tv_usec = 0;
1082       ret = ooSocketPoll(&pfds, 1,  timeout.tv_sec * 1000);
1083       if(ret == -1)
1084       {
1085          OOTRACEERR3("Error in select while receiving H.2250 message - "
1086                      "clearing call (%s, %s)\n", call->callType, 
1087                      call->callToken);
1088          ooFreeQ931Message(pctxt, pmsg);
1089          if(call->callState < OO_CALL_CLEAR)
1090          {
1091             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1092             call->callState = OO_CALL_CLEAR;
1093          }
1094          return OO_FAILED;
1095       }
1096       /* If remaining part of the message is not received in 3 seconds 
1097          exit */
1098       if(!ooPDRead(&pfds, 1, call->pH225Channel->sock))
1099       {
1100          OOTRACEERR3("Error: Incomplete H.2250 message received - clearing "
1101                      "call (%s, %s)\n", call->callType, call->callToken);
1102          ooFreeQ931Message(pctxt, pmsg);
1103          if(call->callState < OO_CALL_CLEAR)
1104          {
1105             call->callEndReason = OO_REASON_INVALIDMESSAGE; 
1106             call->callState = OO_CALL_CLEAR;
1107          }
1108          return OO_FAILED;
1109       }
1110    }
1111
1112    OOTRACEDBGC3("Received Q.931 message: (%s, %s)\n", 
1113                 call->callType, call->callToken);
1114
1115    initializePrintHandler(&printHandler, "Received H.2250 Message");
1116    setEventHandler (pctxt, &printHandler);
1117    ret = ooQ931Decode (call, pmsg, len, message, 1);
1118    if(ret != OO_OK) {
1119       OOTRACEERR3("Error:Failed to decode received H.2250 message. (%s, %s)\n",
1120                    call->callType, call->callToken);
1121    }
1122    OOTRACEDBGC3("Decoded Q931 message (%s, %s)\n", call->callType, 
1123                 call->callToken);
1124    finishPrint();
1125    removeEventHandler(pctxt);
1126    if(ret == OO_OK) {
1127       ooHandleH2250Message(call, pmsg);
1128    }
1129    return ret;
1130 }
1131
1132
1133
1134 int ooH245Receive(OOH323CallData *call)
1135 {
1136    int  recvLen, ret, len, total=0;
1137    ASN1OCTET message[MAXMSGLEN], message1[MAXMSGLEN];
1138    ASN1BOOL aligned = TRUE;
1139    H245Message *pmsg;
1140    /* OOCTXT *pctxt = &gH323ep.msgctxt; */
1141    OOCTXT *pctxt = call->pctxt;
1142    struct timeval timeout;
1143    
1144    pmsg = (H245Message*)memAlloc(pctxt, sizeof(H245Message));
1145
1146    /* First read just TPKT header which is four bytes */
1147    recvLen = ooSocketRecv (call->pH245Channel->sock, message, 4);
1148    /* Since we are working with TCP, need to determine the
1149       message boundary. Has to be done at channel level, as channels
1150       know the message formats and can determine boundaries
1151    */
1152    if(recvLen<=0 && call->h245SessionState != OO_H245SESSION_PAUSED)
1153    {
1154       if(recvLen == 0)
1155          OOTRACEINFO3("Closing H.245 channels as remote end point closed H.245"
1156                     " connection (%s, %s)\n", call->callType, call->callToken);
1157       else
1158          OOTRACEERR3("Error: Transport failure while trying to receive H245"
1159                      " message (%s, %s)\n", call->callType, call->callToken);
1160
1161       ooCloseH245Connection(call);
1162       ooFreeH245Message(call, pmsg);
1163       if(call->callState < OO_CALL_CLEAR)
1164       {
1165          call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1166          call->callState = OO_CALL_CLEAR;
1167       }
1168       return OO_FAILED;
1169    }
1170    if(call->h245SessionState == OO_H245SESSION_PAUSED) 
1171    {
1172       ooLogicalChannel *temp;
1173
1174       OOTRACEINFO3("Call Paused, closing logical channels"
1175                     " (%s, %s)\n", call->callType, call->callToken);
1176
1177       temp = call->logicalChans;
1178       while(temp)
1179       {
1180          if(temp->state == OO_LOGICALCHAN_ESTABLISHED)
1181          {
1182             /* Sending closelogicalchannel only for outgoing channels*/
1183             if(!strcmp(temp->dir, "transmit"))
1184             {
1185                ooSendCloseLogicalChannel(call, temp);
1186             }
1187          }
1188          temp = temp->next;
1189       }
1190       call->masterSlaveState = OO_MasterSlave_Idle;
1191       call->callState = OO_CALL_PAUSED;
1192       call->localTermCapState = OO_LocalTermCapExchange_Idle;
1193       call->remoteTermCapState = OO_RemoteTermCapExchange_Idle;
1194       call->h245SessionState = OO_H245SESSION_IDLE;
1195       call->logicalChans = NULL;
1196    }
1197    OOTRACEDBGC1("Receiving H245 message\n");
1198    if(recvLen != 4)
1199    {
1200       OOTRACEERR3("Error: Reading TPKT header for H245 message (%s, %s)\n",
1201                   call->callType, call->callToken);
1202       ooFreeH245Message(call, pmsg);
1203       if(call->callState < OO_CALL_CLEAR)
1204       {
1205          call->callEndReason = OO_REASON_INVALIDMESSAGE;
1206          call->callState = OO_CALL_CLEAR;
1207       }
1208       return OO_FAILED;
1209    }
1210
1211    len = message[2];
1212    len = len<<8;
1213    len = (len | message[3]);
1214    /* Remaining message length is length - tpkt length */
1215    len = len - 4;
1216    /* Now read actual H245 message body. We should make sure that we
1217       receive complete message as indicated by len. If we don't then there 
1218       is something wrong. The loop below receives message, then checks whether
1219       complete message is received. If not received, then uses select to peek
1220       for remaining bytes of the message. If message is not received in 3
1221       seconds, then we have a problem. Report an error and exit.
1222    */
1223
1224    if(len > MAXMSGLEN - 4)
1225    {
1226       OOTRACEERR4("Error: Invalid TPKT header length %d for H245 message (%s, %s)\n",
1227                   len, call->callType, call->callToken);
1228       ooFreeH245Message(call, pmsg);
1229       if(call->callState < OO_CALL_CLEAR)
1230       {
1231          call->callEndReason = OO_REASON_INVALIDMESSAGE;
1232          call->callState = OO_CALL_CLEAR;
1233       }
1234       return OO_FAILED;
1235    }
1236
1237    while(total < len)
1238    {
1239       struct pollfd pfds;
1240       recvLen = ooSocketRecv (call->pH245Channel->sock, message1, len-total);
1241       memcpy(message+total, message1, recvLen);
1242       total = total + recvLen;
1243       if(total == len) break; /* Complete message is received */
1244
1245       pfds.fd = call->pH245Channel->sock;
1246       pfds.events = POLLIN;
1247       timeout.tv_sec = 3;
1248       timeout.tv_usec = 0;
1249       ret = ooSocketPoll(&pfds, 1,  timeout.tv_sec * 1000);
1250       if(ret == -1)
1251       {
1252          OOTRACEERR3("Error in select...H245 Receive-Clearing call (%s, %s)\n",
1253                      call->callType, call->callToken);
1254          ooFreeH245Message(call, pmsg);
1255          if(call->callState < OO_CALL_CLEAR)
1256          {
1257             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1258             call->callState = OO_CALL_CLEAR;
1259          }
1260          return OO_FAILED;
1261       }
1262       /* If remaining part of the message is not received in 3 seconds 
1263          exit */
1264       if(!ooPDRead(&pfds, 1, call->pH245Channel->sock))
1265       {
1266          OOTRACEERR3("Error: Incomplete h245 message received (%s, %s)\n",
1267                      call->callType, call->callToken);
1268          ooFreeH245Message(call, pmsg);
1269          if(call->callState < OO_CALL_CLEAR)
1270          {
1271             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1272             call->callState = OO_CALL_CLEAR;
1273          }
1274          return OO_FAILED;
1275       }
1276    }
1277
1278    OOTRACEDBGC3("Complete H245 message received (%s, %s)\n", 
1279                  call->callType, call->callToken);
1280    setPERBuffer(pctxt, message, recvLen, aligned);
1281    initializePrintHandler(&printHandler, "Received H.245 Message");
1282
1283    /* Set event handler */
1284    setEventHandler (pctxt, &printHandler);
1285
1286    ret = asn1PD_H245MultimediaSystemControlMessage(pctxt, &(pmsg->h245Msg));
1287    if(ret != ASN_OK)
1288    {
1289       OOTRACEERR3("Error decoding H245 message (%s, %s)\n", 
1290                   call->callType, call->callToken);
1291       ooFreeH245Message(call, pmsg);
1292       return OO_FAILED;
1293    }
1294    finishPrint();
1295    removeEventHandler(pctxt); 
1296    ooHandleH245Message(call, pmsg);
1297    return OO_OK;
1298 }
1299
1300 /* Generic Send Message functionality. Based on type of message to be sent,
1301    it calls the corresponding function to retrieve the message buffer and 
1302    then transmits on the associated channel
1303    Interpreting msgptr:
1304       Q931 messages except facility
1305                              1st octet - msgType, next 4 octets - tpkt header,
1306                              followed by encoded msg
1307       Q931 message facility
1308                              1st octect - OOFacility, 2nd octet - tunneled msg 
1309                              type(in case no tunneled msg - OOFacility), 
1310                              3rd and 4th octet - associated logical channel 
1311                              of the tunneled msg(0 when no channel is 
1312                              associated. ex. in case of MSD, TCS), next 
1313                              4 octets - tpkt header, followed by encoded 
1314                              message.
1315
1316       H.245 messages no tunneling
1317                              1st octet - msg type, next two octets - logical 
1318                              channel number(0, when no channel is associated),
1319                              next two octets - total length of the message
1320                             (including tpkt header)
1321
1322       H.245 messages - tunneling.
1323                              1st octet - msg type, next two octets - logical 
1324                              channel number(0, when no channel is associated),
1325                              next two octets - total length of the message. 
1326                              Note, no tpkt header is present in this case.
1327                             
1328 */
1329 int ooSendMsg(OOH323CallData *call, int type)
1330 {
1331
1332    int len=0, ret=0, msgType=0, tunneledMsgType=0, logicalChannelNo = 0;
1333    DListNode * p_msgNode=NULL;
1334    ASN1OCTET *msgptr, *msgToSend=NULL;
1335    
1336
1337
1338    if(call->callState == OO_CALL_CLEARED)
1339    {
1340       OOTRACEDBGA3("Warning:Call marked for cleanup. Can not send message."
1341                    "(%s, %s)\n", call->callType, call->callToken);
1342       return OO_OK;
1343    }
1344
1345    if(type == OOQ931MSG)
1346    {
1347       if(call->pH225Channel->outQueue.count == 0)
1348       {
1349          OOTRACEWARN3("WARN:No H.2250 message to send. (%s, %s)\n", 
1350                       call->callType, call->callToken);
1351          return OO_FAILED;
1352       }
1353
1354       OOTRACEDBGA3("Sending Q931 message (%s, %s)\n", call->callType, 
1355                                                       call->callToken);
1356       p_msgNode = call->pH225Channel->outQueue.head;
1357       msgptr = (ASN1OCTET*) p_msgNode->data;
1358       msgType = msgptr[0];
1359
1360       if(msgType == OOFacility)
1361       {
1362          tunneledMsgType = msgptr[1];
1363          logicalChannelNo = msgptr[2];
1364          logicalChannelNo = logicalChannelNo << 8;
1365          logicalChannelNo = (logicalChannelNo | msgptr[3]);
1366          len = msgptr[6];
1367          len = len<<8;
1368          len = (len | msgptr[7]);
1369          msgToSend = msgptr+4;
1370       }
1371       else {
1372          len = msgptr[3];
1373          len = len<<8;
1374          len = (len | msgptr[4]);
1375          msgToSend = msgptr+1;
1376       }
1377
1378       /* Remove the message from rtdlist pH225Channel->outQueue */
1379       dListRemove(&(call->pH225Channel->outQueue), p_msgNode);
1380       if(p_msgNode)
1381          memFreePtr(call->pctxt, p_msgNode);
1382       
1383       /*TODO: This is not required ideally. We will see for some time and if
1384          we don't face any problems we will delete this code */
1385 #if 0 
1386       /* Check whether connection with remote is alright */
1387       if(!ooChannelsIsConnectionOK(call, call->pH225Channel->sock))
1388       {
1389          OOTRACEERR3("Error:Transport failure for signalling channel. "
1390                      "Abandoning message send and marking call for cleanup.(%s"
1391                      "'%s)\n", call->callType, call->callToken);
1392          if(call->callState < OO_CALL_CLEAR)
1393             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1394          call->callState = OO_CALL_CLEARED;
1395          return OO_OK;
1396       }
1397 #endif     
1398       /* Send message out via TCP */      
1399       ret = ooSocketSend(call->pH225Channel->sock, msgToSend, len);
1400       if(ret == ASN_OK)
1401       {
1402          memFreePtr (call->pctxt, msgptr);
1403          OOTRACEDBGC3("H2250/Q931 Message sent successfully (%s, %s)\n", 
1404                       call->callType, call->callToken);
1405          ooOnSendMsg(call, msgType, tunneledMsgType, logicalChannelNo);
1406          return OO_OK;
1407       }
1408       else{
1409          OOTRACEERR3("H2250Q931 Message send failed (%s, %s)\n", 
1410                      call->callType, call->callToken);
1411          memFreePtr (call->pctxt, msgptr);
1412          if(call->callState < OO_CALL_CLEAR)
1413          {
1414             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1415             call->callState = OO_CALL_CLEAR;
1416          }
1417          return OO_FAILED;
1418       }
1419    }/* end of type==OOQ931MSG */
1420    if(type == OOH245MSG)
1421    {
1422       if(call->pH245Channel->outQueue.count == 0)
1423       {
1424          OOTRACEWARN3("WARN:No H.245 message to send. (%s, %s)\n", 
1425                                  call->callType, call->callToken);
1426          return OO_FAILED;
1427       }
1428       OOTRACEDBGA3("Sending H245 message (%s, %s)\n", call->callType, 
1429                                                       call->callToken);
1430       p_msgNode = call->pH245Channel->outQueue.head;
1431       msgptr = (ASN1OCTET*) p_msgNode->data;
1432       msgType = msgptr[0];
1433
1434       logicalChannelNo = msgptr[1];
1435       logicalChannelNo = logicalChannelNo << 8;
1436       logicalChannelNo = (logicalChannelNo | msgptr[2]);
1437
1438       len = msgptr[3];
1439       len = len<<8;
1440       len = (len | msgptr[4]);
1441       /* Remove the message from queue */
1442       dListRemove(&(call->pH245Channel->outQueue), p_msgNode);
1443       if(p_msgNode)
1444          memFreePtr(call->pctxt, p_msgNode);
1445
1446       /* Send message out */
1447       if (0 == call->pH245Channel && !OO_TESTFLAG(call->flags, OO_M_TUNNELING))
1448       {
1449          OOTRACEWARN3("Neither H.245 channel nor tunneling active "
1450                      "(%s, %s)\n", call->callType, call->callToken);
1451          memFreePtr (call->pctxt, msgptr);
1452          /*ooCloseH245Session(call);*/
1453          if(call->callState < OO_CALL_CLEAR)
1454          {
1455             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1456             call->callState = OO_CALL_CLEAR;
1457          }
1458          return OO_OK;
1459       }
1460       
1461       if (0 != call->pH245Channel && 0 != call->pH245Channel->sock)
1462       {
1463          OOTRACEDBGC4("Sending %s H245 message over H.245 channel. "
1464                       "(%s, %s)\n", ooGetMsgTypeText(msgType), 
1465                       call->callType, call->callToken);
1466
1467          ret = ooSocketSend(call->pH245Channel->sock, msgptr+5, len);
1468          if(ret == ASN_OK)
1469          {
1470             memFreePtr (call->pctxt, msgptr);
1471             OOTRACEDBGA3("H245 Message sent successfully (%s, %s)\n", 
1472                           call->callType, call->callToken);
1473             ooOnSendMsg(call, msgType, tunneledMsgType, logicalChannelNo);
1474             return OO_OK;
1475          }
1476          else{
1477             memFreePtr (call->pctxt, msgptr);
1478             OOTRACEERR3("ERROR:H245 Message send failed (%s, %s)\n", 
1479                         call->callType, call->callToken);
1480             if(call->callState < OO_CALL_CLEAR)
1481             {
1482                call->callEndReason = OO_REASON_TRANSPORTFAILURE;
1483                call->callState = OO_CALL_CLEAR;
1484             }
1485             return OO_FAILED;
1486          }
1487       }
1488       else if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) {
1489          OOTRACEDBGC4("Sending %s H245 message as a tunneled message."
1490                       "(%s, %s)\n", ooGetMsgTypeText(msgType), 
1491                       call->callType, call->callToken);
1492
1493          ret = ooSendAsTunneledMessage
1494                   (call, msgptr+5,len,msgType, logicalChannelNo);
1495
1496          if(ret != OO_OK)
1497          {
1498             memFreePtr (call->pctxt, msgptr);
1499             OOTRACEERR3("ERROR:Failed to tunnel H.245 message (%s, %s)\n",
1500                          call->callType, call->callToken);
1501             if(call->callState < OO_CALL_CLEAR)
1502             {
1503                call->callEndReason = OO_REASON_INVALIDMESSAGE;
1504                call->callState = OO_CALL_CLEAR;
1505             }
1506             return OO_FAILED;
1507          }
1508          memFreePtr (call->pctxt, msgptr);
1509          return OO_OK;
1510       }
1511    }
1512    /* Need to add support for other messages such as T38 etc */
1513    OOTRACEWARN3("ERROR:Unknown message type - message not Sent (%s, %s)\n",
1514                 call->callType, call->callToken);
1515    return OO_FAILED;
1516 }       
1517
1518 int ooCloseH245Connection(OOH323CallData *call)
1519 {
1520    OOTRACEINFO3("Closing H.245 connection (%s, %s)\n", call->callType, 
1521                 call->callToken);
1522
1523    if (0 != call->pH245Channel)
1524    {
1525       if(0 != call->pH245Channel->sock)
1526          ooSocketClose (call->pH245Channel->sock);
1527       if (call->pH245Channel->outQueue.count > 0)
1528          dListFreeAll(call->pctxt, &(call->pH245Channel->outQueue));
1529       memFreePtr (call->pctxt, call->pH245Channel);
1530       call->pH245Channel = NULL;
1531       OOTRACEDBGC3("Closed H245 connection. (%s, %s)\n", call->callType, 
1532                                                        call->callToken);
1533    }
1534    call->h245SessionState = OO_H245SESSION_CLOSED;
1535
1536    return OO_OK;
1537 }
1538
1539 int ooCloseH245Listener(OOH323CallData *call)
1540 {
1541    OOTRACEINFO3("Closing H.245 Listener (%s, %s)\n", call->callType, 
1542                 call->callToken);
1543    if(call->h245listener)
1544    {
1545       ooSocketClose(*(call->h245listener));
1546       memFreePtr(call->pctxt, call->h245listener);
1547       call->h245listener = NULL;
1548    }
1549    return OO_OK;
1550 }
1551
1552 int ooOnSendMsg
1553    (OOH323CallData *call, int msgType, int tunneledMsgType, int associatedChan)
1554 {
1555    ooTimerCallback *cbData=NULL;
1556    switch(msgType)
1557    {
1558    case OOSetup:
1559       OOTRACEINFO3("Sent Message - Setup (%s, %s)\n", call->callType, 
1560                     call->callToken);
1561       /* Start call establishment timer */
1562       cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1563                                                      sizeof(ooTimerCallback));
1564       if(!cbData)
1565       {
1566          OOTRACEERR3("Error:Unable to allocate memory for timer callback."
1567                      "(%s, %s)\n", call->callType, call->callToken);
1568          return OO_FAILED;
1569       }
1570       cbData->call = call;
1571       cbData->timerType = OO_CALLESTB_TIMER;
1572       if(!ooTimerCreate(call->pctxt, &call->timerList, &ooCallEstbTimerExpired,
1573                         gH323ep.callEstablishmentTimeout, cbData, FALSE))
1574       {
1575          OOTRACEERR3("Error:Unable to create call establishment timer. "
1576                      "(%s, %s)\n", call->callType, call->callToken);
1577          memFreePtr(call->pctxt, cbData);
1578          return OO_FAILED;
1579       }
1580
1581       /* if(gH323ep.h323Callbacks.onOutgoingCall)
1582          gH323ep.h323Callbacks.onOutgoingCall(call); */
1583       break;
1584    case OOCallProceeding:
1585       OOTRACEINFO3("Sent Message - CallProceeding (%s, %s)\n", call->callType,
1586                     call->callToken);
1587       break;
1588    case OOAlert:
1589       OOTRACEINFO3("Sent Message - Alerting (%s, %s) \n", call->callType,
1590                     call->callToken);
1591       /* if(gH323ep.h323Callbacks.onAlerting && call->callState < OO_CALL_CLEAR)
1592          gH323ep.h323Callbacks.onAlerting(call); */
1593       break;
1594    case OOConnect:
1595       OOTRACEINFO3("Sent Message - Connect (%s, %s)\n", call->callType,
1596                     call->callToken);
1597       if(gH323ep.h323Callbacks.onCallEstablished)
1598          gH323ep.h323Callbacks.onCallEstablished(call);
1599       break;
1600    case OOReleaseComplete:
1601       OOTRACEINFO3("Sent Message - ReleaseComplete (%s, %s)\n", call->callType,
1602                     call->callToken);
1603
1604       if(call->callState == OO_CALL_CLEAR_RELEASERECVD)
1605          call->callState = OO_CALL_CLEARED;
1606       else{
1607          call->callState = OO_CALL_CLEAR_RELEASESENT;
1608          if(gH323ep.gkClient && !OO_TESTFLAG(call->flags, OO_M_DISABLEGK) && 
1609             gH323ep.gkClient->state == GkClientRegistered){
1610             OOTRACEDBGA3("Sending DRQ after sending ReleaseComplete."
1611                          "(%s, %s)\n",   call->callType, call->callToken);
1612
1613             call->endTime = (H235TimeStamp) time(NULL);
1614             ooGkClientSendDisengageRequest(gH323ep.gkClient, call);
1615          }
1616       }
1617
1618       if(call->callState == OO_CALL_CLEAR_RELEASESENT && 
1619          call->h245SessionState == OO_H245SESSION_IDLE)
1620       {
1621          cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1622                                                   sizeof(ooTimerCallback));
1623          if(!cbData)
1624          {
1625             OOTRACEERR3("Error:Unable to allocate memory for timer callback "
1626                         "data.(%s, %s)\n", call->callType, call->callToken);
1627             return OO_FAILED;
1628          }
1629          cbData->call = call;
1630          cbData->timerType = OO_SESSION_TIMER;
1631          cbData->channelNumber = 0;
1632          if(!ooTimerCreate(call->pctxt, &call->timerList, 
1633              &ooSessionTimerExpired, gH323ep.sessionTimeout, cbData, FALSE))
1634          {
1635             OOTRACEERR3("Error:Unable to create EndSession timer- "
1636                         "ReleaseComplete.(%s, %s)\n", call->callType, 
1637                         call->callToken);
1638             memFreePtr(call->pctxt, cbData);
1639             return OO_FAILED;
1640          }
1641       }
1642
1643       if(call->h245SessionState == OO_H245SESSION_CLOSED)
1644       {
1645          call->callState = OO_CALL_CLEARED;
1646       }
1647       break;
1648
1649    case OOFacility:
1650       if(tunneledMsgType == OOFacility)
1651       {
1652          OOTRACEINFO3("Sent Message - Facility. (%s, %s)\n", 
1653                       call->callType, call->callToken);
1654       }
1655       else{
1656          OOTRACEINFO4("Sent Message - Facility(%s) (%s, %s)\n", 
1657                       ooGetMsgTypeText(tunneledMsgType), 
1658                       call->callType, call->callToken);
1659
1660          ooOnSendMsg(call, tunneledMsgType, 0, associatedChan);
1661       }
1662       break;
1663
1664    case OOMasterSlaveDetermination:
1665      if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1666         OOTRACEINFO3("Tunneled Message - MasterSlaveDetermination (%s, %s)\n", 
1667                       call->callType, call->callToken);
1668       else
1669          OOTRACEINFO3("Sent Message - MasterSlaveDetermination (%s, %s)\n", 
1670                        call->callType, call->callToken);
1671        /* Start MSD timer */
1672       cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1673                                                      sizeof(ooTimerCallback));
1674       if(!cbData)
1675       {
1676          OOTRACEERR3("Error:Unable to allocate memory for timer callback data."
1677                      "(%s, %s)\n", call->callType, call->callToken);
1678          return OO_FAILED;
1679       }
1680       cbData->call = call;
1681       cbData->timerType = OO_MSD_TIMER;
1682       if(!ooTimerCreate(call->pctxt, &call->timerList, &ooMSDTimerExpired,
1683                         gH323ep.msdTimeout, cbData, FALSE))
1684       {
1685          OOTRACEERR3("Error:Unable to create MSD timer. "
1686                      "(%s, %s)\n", call->callType, call->callToken);
1687          memFreePtr(call->pctxt, cbData);
1688          return OO_FAILED;
1689       }
1690
1691       break;
1692    case OOMasterSlaveAck:
1693      if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1694          OOTRACEINFO3("Tunneled Message - MasterSlaveDeterminationAck (%s, %s)"
1695                       "\n",  call->callType, call->callToken);
1696      else
1697         OOTRACEINFO3("Sent Message - MasterSlaveDeterminationAck (%s, %s)\n", 
1698                     call->callType, call->callToken);
1699       break;
1700    case OOMasterSlaveReject:
1701      if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1702         OOTRACEINFO3("Tunneled Message - MasterSlaveDeterminationReject "
1703                      "(%s, %s)\n", call->callType, call->callToken);
1704      else
1705         OOTRACEINFO3("Sent Message - MasterSlaveDeterminationReject(%s, %s)\n",
1706                     call->callType, call->callToken);
1707       break;
1708    case OOMasterSlaveRelease:
1709       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1710          OOTRACEINFO3("Tunneled Message - MasterSlaveDeterminationRelease "
1711                       "(%s, %s)\n", call->callType, call->callToken);
1712       else
1713          OOTRACEINFO3("Sent Message - MasterSlaveDeterminationRelease "
1714                       "(%s, %s)\n", call->callType, call->callToken);
1715       break;
1716    case OOTerminalCapabilitySet:
1717       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING)) {
1718          /* If session isn't marked active yet, do it. possible in case of 
1719             tunneling */
1720          if(call->h245SessionState == OO_H245SESSION_IDLE ||
1721             call->h245SessionState == OO_H245SESSION_PAUSED) {
1722             call->h245SessionState = OO_H245SESSION_ACTIVE;
1723          }
1724          OOTRACEINFO3("Tunneled Message - TerminalCapabilitySet (%s, %s)\n", 
1725                        call->callType, call->callToken);
1726       }
1727       else {
1728          OOTRACEINFO3("Sent Message - TerminalCapabilitySet (%s, %s)\n", 
1729                        call->callType, call->callToken);
1730       }
1731       /* Start TCS timer */
1732       cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1733                                                      sizeof(ooTimerCallback));
1734       if(!cbData)
1735       {
1736          OOTRACEERR3("Error:Unable to allocate memory for timer callback data."
1737                      "(%s, %s)\n", call->callType, call->callToken);
1738          return OO_FAILED;
1739       }
1740       cbData->call = call;
1741       cbData->timerType = OO_TCS_TIMER;
1742       if(!ooTimerCreate(call->pctxt, &call->timerList, &ooTCSTimerExpired,
1743                         gH323ep.tcsTimeout, cbData, FALSE))
1744       {
1745          OOTRACEERR3("Error:Unable to create TCS timer. "
1746                      "(%s, %s)\n", call->callType, call->callToken);
1747          memFreePtr(call->pctxt, cbData);
1748          return OO_FAILED;
1749       }
1750       break;
1751
1752
1753    case OOTerminalCapabilitySetAck:
1754       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1755          OOTRACEINFO3("Tunneled Message - TerminalCapabilitySetAck (%s, %s)\n",
1756                        call->callType, call->callToken);
1757       else
1758          OOTRACEINFO3("Sent Message - TerminalCapabilitySetAck (%s, %s)\n", 
1759                        call->callType, call->callToken);
1760       break;
1761    case OOTerminalCapabilitySetReject:
1762       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1763          OOTRACEINFO3("Tunneled Message - TerminalCapabilitySetReject "
1764                       "(%s, %s)\n",  call->callType, call->callToken);
1765       else
1766          OOTRACEINFO3("Sent Message - TerminalCapabilitySetReject (%s, %s)\n", 
1767                        call->callType, call->callToken);
1768       break;
1769    case OOOpenLogicalChannel:
1770       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1771          OOTRACEINFO4("Tunneled Message - OpenLogicalChannel(%d). (%s, %s)\n", 
1772                        associatedChan, call->callType, call->callToken);
1773       else
1774          OOTRACEINFO4("Sent Message - OpenLogicalChannel(%d). (%s, %s)\n", 
1775                        associatedChan, call->callType, call->callToken);
1776       /* Start LogicalChannel timer */
1777       cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1778                                                      sizeof(ooTimerCallback));
1779       if(!cbData)
1780       {
1781          OOTRACEERR3("Error:Unable to allocate memory for timer callback data."
1782                      "(%s, %s)\n", call->callType, call->callToken);
1783          return OO_FAILED;
1784       }
1785       cbData->call = call;
1786       cbData->timerType = OO_OLC_TIMER;
1787       cbData->channelNumber = associatedChan;
1788       if(!ooTimerCreate(call->pctxt, &call->timerList, 
1789           &ooOpenLogicalChannelTimerExpired, gH323ep.logicalChannelTimeout, 
1790           cbData, FALSE))
1791       {
1792          OOTRACEERR3("Error:Unable to create OpenLogicalChannel timer. "
1793                      "(%s, %s)\n", call->callType, call->callToken);
1794          memFreePtr(call->pctxt, cbData);
1795          return OO_FAILED;
1796       }
1797       
1798       break;
1799    case OOOpenLogicalChannelAck:
1800       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1801          OOTRACEINFO4("Tunneled Message - OpenLogicalChannelAck(%d) (%s,%s)\n",
1802                        associatedChan, call->callType, call->callToken);
1803       else
1804          OOTRACEINFO4("Sent Message - OpenLogicalChannelAck(%d) (%s, %s)\n", 
1805                        associatedChan, call->callType, call->callToken);
1806       break;
1807    case OOOpenLogicalChannelReject:
1808       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1809          OOTRACEINFO4("Tunneled Message - OpenLogicalChannelReject(%d)"
1810                       "(%s, %s)\n", associatedChan, call->callType, 
1811                       call->callToken);
1812       else
1813          OOTRACEINFO4("Sent Message - OpenLogicalChannelReject(%d) (%s, %s)\n",
1814                        associatedChan, call->callType, call->callToken);
1815       break;
1816    case OOEndSessionCommand:
1817       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1818          OOTRACEINFO3("Tunneled Message - EndSessionCommand(%s, %s)\n", 
1819                                              call->callType, call->callToken);
1820       else
1821          OOTRACEINFO3("Sent Message - EndSessionCommand (%s, %s)\n", 
1822                                            call->callType, call->callToken);
1823       if((call->h245SessionState == OO_H245SESSION_ACTIVE))
1824       { 
1825          /* Start EndSession timer */
1826          call->h245SessionState = OO_H245SESSION_ENDSENT;
1827          cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1828                                                   sizeof(ooTimerCallback));
1829          if(!cbData)
1830          {
1831             OOTRACEERR3("Error:Unable to allocate memory for timer callback "
1832                         "data.(%s, %s)\n", call->callType, call->callToken);
1833             return OO_FAILED;
1834          }
1835          cbData->call = call;
1836          cbData->timerType = OO_SESSION_TIMER;
1837          cbData->channelNumber = 0;
1838          if(!ooTimerCreate(call->pctxt, &call->timerList, 
1839              &ooSessionTimerExpired, gH323ep.sessionTimeout, cbData, FALSE))
1840          {
1841             OOTRACEERR3("Error:Unable to create EndSession timer. "
1842                         "(%s, %s)\n", call->callType, call->callToken);
1843             memFreePtr(call->pctxt, cbData);
1844             return OO_FAILED;
1845          }
1846       }
1847       else{
1848          ooCloseH245Connection(call);
1849       }
1850       break;
1851    case OOCloseLogicalChannel:
1852       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1853          OOTRACEINFO3("Tunneled Message - CloseLogicalChannel (%s, %s)\n", 
1854                        call->callType, call->callToken);
1855       else
1856          OOTRACEINFO3("Sent Message - CloseLogicalChannel (%s, %s)\n", 
1857                        call->callType, call->callToken);
1858       /* Start LogicalChannel timer */
1859       cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1860                                                      sizeof(ooTimerCallback));
1861       if(!cbData)
1862       {
1863          OOTRACEERR3("Error:Unable to allocate memory for timer callback data."
1864                      "(%s, %s)\n", call->callType, call->callToken);
1865          return OO_FAILED;
1866       }
1867       cbData->call = call;
1868       cbData->timerType = OO_CLC_TIMER;
1869       cbData->channelNumber = associatedChan;
1870       if(!ooTimerCreate(call->pctxt, &call->timerList, 
1871           &ooCloseLogicalChannelTimerExpired, gH323ep.logicalChannelTimeout, 
1872           cbData, FALSE))
1873       {
1874          OOTRACEERR3("Error:Unable to create CloseLogicalChannel timer. "
1875                      "(%s, %s)\n", call->callType, call->callToken);
1876          memFreePtr(call->pctxt, cbData);
1877          return OO_FAILED;
1878       }
1879       
1880       break;
1881    case OOCloseLogicalChannelAck:
1882       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1883          OOTRACEINFO3("Tunneled Message - CloseLogicalChannelAck (%s, %s)\n", 
1884                        call->callType, call->callToken);
1885       else
1886          OOTRACEINFO3("Sent Message - CloseLogicalChannelAck (%s, %s)\n", 
1887                        call->callType, call->callToken);
1888       break;
1889    case OORequestChannelClose:
1890       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1891          OOTRACEINFO3("Tunneled Message - RequestChannelClose (%s, %s)\n", 
1892                        call->callType, call->callToken);
1893       else
1894          OOTRACEINFO3("Sent Message - RequestChannelClose (%s, %s)\n", 
1895                        call->callType, call->callToken);
1896       /* Start RequestChannelClose timer */
1897       cbData = (ooTimerCallback*) memAlloc(call->pctxt, 
1898                                                      sizeof(ooTimerCallback));
1899       if(!cbData)
1900       {
1901          OOTRACEERR3("Error:Unable to allocate memory for timer callback data."
1902                      "(%s, %s)\n", call->callType, call->callToken);
1903          return OO_FAILED;
1904       }
1905       cbData->call = call;
1906       cbData->timerType = OO_RCC_TIMER;
1907       cbData->channelNumber = associatedChan;
1908       if(!ooTimerCreate(call->pctxt, &call->timerList, 
1909           &ooRequestChannelCloseTimerExpired, gH323ep.logicalChannelTimeout, 
1910           cbData, FALSE))
1911       {
1912          OOTRACEERR3("Error:Unable to create RequestChannelClose timer. "
1913                      "(%s, %s)\n", call->callType, call->callToken);
1914          memFreePtr(call->pctxt, cbData);
1915          return OO_FAILED;
1916       }
1917       break;
1918    case OORequestChannelCloseAck:
1919       if(OO_TESTFLAG (call->flags, OO_M_TUNNELING))
1920          OOTRACEINFO3("Tunneled Message - RequestChannelCloseAck (%s, %s)\n", 
1921                        call->callType, call->callToken);
1922       else
1923          OOTRACEINFO3("Sent Message - RequestChannelCloseAck (%s, %s)\n", 
1924                        call->callType, call->callToken);
1925       break;
1926    
1927    default:
1928      ;
1929    }
1930    return OO_OK;
1931 }
1932
1933 void ooStopMonitorCallChannels(OOH323CallData * call) {
1934         if (call->Monitor)
1935          call->Monitor = FALSE;
1936         /* if (call->cmdSock)
1937          ooCloseCallCmdConnection(call); */
1938 }
1939
1940 int ooStopMonitorCalls()
1941 {
1942    OOH323CallData * call;
1943    if(gMonitor)
1944    {
1945       OOTRACEINFO1("Doing ooStopMonitorCalls\n");
1946       if(gH323ep.cmdSock)
1947       {
1948          ooCloseCmdConnection();
1949       }
1950
1951       if(gH323ep.callList)
1952       {
1953          OOTRACEWARN1("Warn:Abruptly ending calls as stack going down\n");
1954          call = gH323ep.callList;
1955          while(call)
1956          {
1957             OOTRACEWARN3("Clearing call (%s, %s)\n", call->callType, 
1958                           call->callToken);
1959             call->callEndReason = OO_REASON_LOCAL_CLEARED;
1960             ooCleanCall(call);
1961             call = NULL;
1962             call = gH323ep.callList;
1963          }
1964          gH323ep.callList = NULL;
1965       }
1966       OOTRACEINFO1("Stopping listener for incoming calls\n");   
1967       if(gH323ep.listener)
1968       {
1969          ooSocketClose(*(gH323ep.listener));
1970          memFreePtr(&gH323ep.ctxt, gH323ep.listener);
1971          gH323ep.listener = NULL;
1972       }
1973
1974       gMonitor = FALSE;
1975       OOTRACEINFO1("Done ooStopMonitorCalls\n");
1976    }
1977    return OO_OK;
1978 }
1979
1980 OOBOOL ooChannelsIsConnectionOK(OOH323CallData *call, OOSOCKET sock)
1981 {
1982    struct timeval to;
1983    fd_set readfds;
1984    int ret = 0, nfds=0; 
1985
1986    to.tv_sec = 0;
1987    to.tv_usec = 500;
1988    FD_ZERO(&readfds);
1989
1990    FD_SET(sock, &readfds);
1991    if(nfds < (int)sock)
1992       nfds = (int)sock;
1993
1994    nfds++;
1995
1996    ret = ooSocketSelect(nfds, &readfds, NULL, NULL, &to);
1997       
1998    if(ret == -1)
1999    {
2000       OOTRACEERR3("Error in select ...broken pipe check(%s, %s)\n",
2001                    call->callType, call->callToken );
2002       return FALSE;
2003    }
2004
2005    if(FD_ISSET(sock, &readfds))
2006    {
2007       char buf[2];      
2008       if(ooSocketRecvPeek(sock, (ASN1OCTET*) buf, 2) == 0)
2009       {
2010          OOTRACEWARN3("Broken pipe detected. (%s, %s)", call->callType, 
2011                        call->callToken);
2012          if(call->callState < OO_CALL_CLEAR)
2013             call->callEndReason = OO_REASON_TRANSPORTFAILURE;
2014          call->callState = OO_CALL_CLEARED;
2015          return FALSE;
2016       }
2017    }
2018    return TRUE;
2019 }