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