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