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