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