Move Asterisk-addons modules into the main Asterisk source tree.
[asterisk/asterisk.git] / addons / chan_ooh323.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
18 #include "chan_ooh323.h"
19
20 /*** MODULEINFO
21         <defaultenabled>no</defaultenabled>
22  ***/
23
24 /* Defaults */
25 #define DEFAULT_CONTEXT "default"
26 #define DEFAULT_H323ID "Asterisk PBX"
27 #define DEFAULT_LOGFILE "/var/log/asterisk/h323_log"
28 #define DEFAULT_H323ACCNT "ast_h323"
29
30 /* Flags */
31 #define H323_SILENCESUPPRESSION (1<<0)
32 #define H323_GKROUTED           (1<<1)
33 #define H323_TUNNELING          (1<<2)
34 #define H323_FASTSTART          (1<<3)
35 #define H323_OUTGOING           (1<<4)
36 #define H323_ALREADYGONE        (1<<5)
37 #define H323_NEEDDESTROY        (1<<6)
38 #define H323_DISABLEGK          (1<<7)
39
40 /* Channel description */
41 static const char type[] = "OOH323";
42 static const char tdesc[] = "Objective Systems H323 Channel Driver";
43 static const char config[] = "ooh323.conf";
44
45
46 /* Channel Definition */
47 static struct ast_channel *ooh323_request(const char *type, int format, 
48                                         void *data, int *cause);
49 static int ooh323_digit_begin(struct ast_channel *ast, char digit);
50 static int ooh323_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
51 static int ooh323_call(struct ast_channel *ast, char *dest, int timeout);
52 static int ooh323_hangup(struct ast_channel *ast);
53 static int ooh323_answer(struct ast_channel *ast);
54 static struct ast_frame *ooh323_read(struct ast_channel *ast);
55 static int ooh323_write(struct ast_channel *ast, struct ast_frame *f);
56 static int ooh323_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
57 static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
58
59 static enum ast_rtp_get_result ooh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
60 static enum ast_rtp_get_result ooh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
61 static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, 
62                              struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active);
63
64 static void print_codec_to_cli(int fd, struct ast_codec_pref *pref);
65
66 #if 0
67 static void ast_ooh323c_exit();
68 #endif
69
70 static const struct ast_channel_tech ooh323_tech = {
71         .type = type,
72         .description = tdesc,
73         .capabilities = -1,
74         .requester = ooh323_request,
75         .send_digit_begin = ooh323_digit_begin,
76         .send_digit_end = ooh323_digit_end,
77         .call = ooh323_call,
78         .hangup = ooh323_hangup,
79         .answer = ooh323_answer,
80         .read = ooh323_read,
81         .write = ooh323_write,
82         .exception = ooh323_read,
83         .indicate = ooh323_indicate,
84         .fixup = ooh323_fixup,
85         .send_html = 0,
86         .bridge = ast_rtp_bridge,
87 };
88
89 static struct ast_rtp_protocol ooh323_rtp = {
90         .type = type,
91         .get_rtp_info = ooh323_get_rtp_peer,
92         .get_vrtp_info = ooh323_get_vrtp_peer,
93         .set_rtp_peer = ooh323_set_rtp_peer
94 };
95
96 /* H.323 channel private structure */
97 static struct ooh323_pvt {
98         ast_mutex_t lock;               /* Channel private lock */
99         struct ast_rtp *rtp;
100         struct ast_rtp *vrtp; /* Placeholder for now */
101         struct ast_channel *owner;      /* Master Channel */
102         time_t lastrtptx;
103         time_t lastrtprx;
104         unsigned int flags;
105         unsigned int call_reference;
106         char *callToken;
107         char *username;
108         char *host;
109         char *callerid_name;
110         char *callerid_num;
111         char caller_h323id[AST_MAX_EXTENSION];
112         char caller_dialedDigits[AST_MAX_EXTENSION];
113         char caller_email[AST_MAX_EXTENSION];
114         char caller_url[256];
115         char callee_h323id[AST_MAX_EXTENSION];
116         char callee_dialedDigits[AST_MAX_EXTENSION];
117         char callee_email[AST_MAX_EXTENSION];
118         char callee_url[AST_MAX_EXTENSION];
119  
120         int port;
121         int readformat;   /* negotiated read format */
122         int writeformat;  /* negotiated write format */
123         int capability;
124         struct ast_codec_pref prefs;
125         int dtmfmode;
126         char exten[AST_MAX_EXTENSION];  /* Requested extension */
127         char context[AST_MAX_EXTENSION];        /* Context where to start */
128         char accountcode[256];  /* Account code */
129         int nat;
130         int amaflags;
131         struct ast_dsp *vad;
132         struct ooh323_pvt *next;        /* Next entity */
133 } *iflist = NULL;
134
135 /* Protect the channel/interface list (ooh323_pvt) */
136 AST_MUTEX_DEFINE_STATIC(iflock);
137
138 /* Profile of H.323 user registered with PBX*/
139 struct ooh323_user{
140         ast_mutex_t lock;
141         char        name[256];
142         char        context[AST_MAX_EXTENSION];
143         int         incominglimit;
144         unsigned    inUse;
145         char        accountcode[20];
146         int         amaflags;
147         int         capability;
148         struct ast_codec_pref prefs;
149         int         dtmfmode;
150         int         rtptimeout;
151         int         mUseIP;        /* Use IP address or H323-ID to search user */
152         char        mIP[20];
153         struct ooh323_user *next;
154 };
155
156 /* Profile of valid asterisk peers */
157 struct ooh323_peer{
158         ast_mutex_t lock;
159         char        name[256];
160         unsigned    outgoinglimit;
161         unsigned    outUse;
162         int         capability;
163         struct ast_codec_pref prefs;
164         char        accountcode[20];
165         int         amaflags;
166         int         dtmfmode;
167         int         mFriend;    /* indicates defined as friend */
168         char        ip[20];
169         int         port;
170         char        *h323id;    /* H323-ID alias, which asterisk will register with gk to reach this peer*/
171         char        *email;     /* Email alias, which asterisk will register with gk to reach this peer*/
172         char        *url;       /* url alias, which asterisk will register with gk to reach this peer*/
173         char        *e164;      /* e164 alias, which asterisk will register with gk to reach this peer*/
174         int         rtptimeout;
175         struct ooh323_peer *next;
176 };
177
178
179 /* List of H.323 users known to PBX */
180 static struct ast_user_list {
181         struct ooh323_user *users;
182         ast_mutex_t lock;
183 } userl;
184
185 static struct ast_peer_list {
186         struct ooh323_peer *peers;
187         ast_mutex_t lock;
188 } peerl;
189
190 /* Mutex to protect H.323 reload process */
191 static int h323_reloading = 0;
192 AST_MUTEX_DEFINE_STATIC(h323_reload_lock);
193
194 /* Mutex to protect usage counter */
195 static int usecnt = 0;
196 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
197
198 AST_MUTEX_DEFINE_STATIC(ooh323c_cmd_lock);
199
200 /* stack callbacks */
201 int onAlerting(ooCallData *call);
202 int onNewCallCreated(ooCallData *call);
203 int onCallEstablished(ooCallData *call);
204 int onCallCleared(ooCallData *call);
205
206 static char gLogFile[256] = DEFAULT_LOGFILE;
207 static int  gPort = 1720;
208 static char gIP[20];
209 static char gCallerID[AST_MAX_EXTENSION] = DEFAULT_H323ID;
210 static struct ooAliases *gAliasList;
211 static int  gCapability = AST_FORMAT_ULAW;
212 static struct ast_codec_pref gPrefs;
213 static int  gDTMFMode = H323_DTMF_RFC2833;
214 static char gGatekeeper[100];
215 static enum RasGatekeeperMode gRasGkMode = RasNoGatekeeper;
216
217 static int  gIsGateway = 0;
218 static int  gFastStart = 1;
219 static int  gTunneling = 1;
220 static int  gMediaWaitForConnect = 0;
221 static int  gTOS = 0;
222 static int  gRTPTimeout = 60;
223 static char gAccountcode[80] = DEFAULT_H323ACCNT;
224 static int  gAMAFLAGS;
225 static char gContext[AST_MAX_EXTENSION] = DEFAULT_CONTEXT;
226 static int  gIncomingLimit = 4;
227 static int  gOutgoingLimit = 4;
228 OOBOOL gH323Debug = FALSE;
229
230 static struct ooh323_config
231 {
232    int  mTCPPortStart;
233    int  mTCPPortEnd;
234 } ooconfig;
235
236 /** Asterisk RTP stuff*/
237 static struct sched_context *sched;
238 static struct io_context *io;
239
240 /* Protect the monitoring thread, so only one process can kill or start it, 
241    and not when it's doing something critical. */
242 AST_MUTEX_DEFINE_STATIC(monlock);
243
244
245 /* This is the thread for the monitor which checks for input on the channels
246    which are not currently in use.  */
247 static pthread_t monitor_thread = AST_PTHREADT_NULL;
248
249
250 static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
251                                              const char *host) 
252 {
253         struct ast_channel *ch = NULL;
254         int fmt;
255         if (gH323Debug)
256                 ast_verbose("---   ooh323_new - %s\n", host);
257
258
259         /* Don't hold a h323 pvt lock while we allocate a channel */
260         ast_mutex_unlock(&i->lock);
261         ch = ast_channel_alloc(1, state, i->callerid_num, i->callerid_name, i->accountcode, i->exten, i->context, i->amaflags, "OOH323/%s-%08x", host, (unsigned int)(unsigned long) i);
262         ast_mutex_lock(&i->lock);
263
264         if (ch) {
265                 ast_channel_lock(ch);
266                 ch->tech = &ooh323_tech;
267
268                 ch->nativeformats = i->capability;
269
270                 fmt = ast_best_codec(ch->nativeformats);
271
272                 ch->fds[0] = ast_rtp_fd(i->rtp);
273                 ch->fds[1] = ast_rtcp_fd(i->rtp);
274
275                 if (state == AST_STATE_RING)
276                         ch->rings = 1;
277
278                 ch->adsicpe = AST_ADSI_UNAVAILABLE;
279                 ch->writeformat = fmt;
280                 ch->rawwriteformat = fmt;
281                 ch->readformat = fmt;
282                 ch->rawreadformat = fmt;
283                 ch->tech_pvt = i;
284                 i->owner = ch;
285
286                 /* Allocate dsp for in-band DTMF support */
287                 if (i->dtmfmode & H323_DTMF_INBAND) {
288                         i->vad = ast_dsp_new();
289                         ast_dsp_set_features(i->vad, DSP_FEATURE_DIGIT_DETECT);
290                 }
291
292                 ast_mutex_lock(&usecnt_lock);
293                 usecnt++;
294                 ast_mutex_unlock(&usecnt_lock);
295
296                 /* Notify the module monitors that use count for resource has changed*/
297                 ast_update_use_count();
298
299                 ast_copy_string(ch->context, i->context, sizeof(ch->context));
300                 ast_copy_string(ch->exten, i->exten, sizeof(ch->exten));
301
302                 ch->priority = 1;
303                 if (i->callerid_name) {
304                         ch->cid.cid_name = strdup(i->callerid_name);
305                 }
306                 if (i->callerid_num) {
307
308                         ch->cid.cid_num = strdup(i->callerid_num);
309                 }
310
311                 if (!ast_test_flag(i, H323_OUTGOING)) {
312                 
313                         if (!ast_strlen_zero(i->caller_h323id)) {
314                                 pbx_builtin_setvar_helper(ch, "_CALLER_H323ID", i->caller_h323id);
315
316                         }
317                         if (!ast_strlen_zero(i->caller_dialedDigits)) {
318                                 pbx_builtin_setvar_helper(ch, "_CALLER_H323DIALEDDIGITS", 
319                                 i->caller_dialedDigits);
320                         }
321                         if (!ast_strlen_zero(i->caller_email)) {
322                                 pbx_builtin_setvar_helper(ch, "_CALLER_H323EMAIL", 
323                                 i->caller_email);
324                         }
325                         if (!ast_strlen_zero(i->caller_url)) {
326                                 pbx_builtin_setvar_helper(ch, "_CALLER_H323URL", i->caller_url);
327                         }
328                 }
329
330                 if (!ast_strlen_zero(i->accountcode))
331                         ast_string_field_set(ch, accountcode, i->accountcode);
332                 
333                 if (i->amaflags)
334                         ch->amaflags = i->amaflags;
335
336                 ast_setstate(ch, state);
337                 if (state != AST_STATE_DOWN) {
338                         if (ast_pbx_start(ch)) {
339                                 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name);
340                                 ast_channel_unlock(ch);
341                                 ast_hangup(ch);
342                                 ch = NULL;
343                         }
344                 }
345         } else
346                 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
347
348
349         if (ch)
350                 ast_channel_unlock(ch);
351
352         if (gH323Debug)
353                 ast_verbose("+++   h323_new\n");
354
355         return ch;
356 }
357
358
359
360 static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken) 
361 {
362         struct ooh323_pvt *pvt = NULL;
363         struct in_addr ipAddr;
364         if (gH323Debug)
365                 ast_verbose("---   ooh323_alloc\n");
366
367         if (!(pvt = ast_calloc(1, sizeof(*pvt)))) {
368                 ast_log(LOG_ERROR, "Couldn't allocate private ooh323 structure\n");
369                 return NULL;
370         }
371
372         ast_mutex_init(&pvt->lock);
373         ast_mutex_lock(&pvt->lock);
374
375         if (!inet_aton(gIP, &ipAddr)) {
376                 ast_log(LOG_ERROR, "Invalid OOH323 driver ip address\n");
377                 ast_mutex_unlock(&pvt->lock);
378                 ast_mutex_destroy(&pvt->lock);
379                 free(pvt);
380                 return NULL;
381         }
382
383         if (!(pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, ipAddr))) {
384                 ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", 
385                                   strerror(errno));
386                 ast_mutex_unlock(&pvt->lock);
387                 ast_mutex_destroy(&pvt->lock);
388                 free(pvt);
389                 return NULL;
390         }
391  
392         ast_rtp_setqos(pvt->rtp, gTOS, 0, "ooh323");
393
394         pvt->call_reference = callref;
395         if (callToken)
396                 pvt->callToken = strdup(callToken);
397
398         /* whether to use gk for this call */
399         if (gRasGkMode == RasNoGatekeeper)
400                 OO_SETFLAG(pvt->flags, H323_DISABLEGK);
401
402         pvt->dtmfmode = gDTMFMode;
403         ast_copy_string(pvt->context, gContext, sizeof(pvt->context));
404         ast_copy_string(pvt->accountcode, gAccountcode, sizeof(pvt->accountcode));
405         pvt->amaflags = gAMAFLAGS;
406         pvt->capability = gCapability;
407         memcpy(&pvt->prefs, &gPrefs, sizeof(pvt->prefs));
408
409         ast_mutex_unlock(&pvt->lock); 
410         /* Add to interface list */
411         ast_mutex_lock(&iflock);
412         pvt->next = iflist;
413         iflist = pvt;
414         ast_mutex_unlock(&iflock);
415
416         if (gH323Debug)
417                 ast_verbose("+++   ooh323_alloc\n");
418
419         return pvt;
420 }
421
422
423 /*
424         Possible data values - peername, exten/peername, exten@ip
425  */
426 static struct ast_channel *ooh323_request(const char *type, int format, 
427                                                                                                          void *data, int *cause)
428 {
429         struct ast_channel *chan = NULL;
430         struct ooh323_pvt *p = NULL;
431         struct ooh323_peer *peer = NULL;
432         char *dest = NULL; 
433         char *ext = NULL;
434         char tmp[256];
435         char formats[512];
436         int oldformat;
437         int port = 0;
438
439         if (gH323Debug)
440                 ast_verbose("---   ooh323_request - data %s format %s\n", (char*)data,  
441                                                                                 ast_getformatname_multiple(formats,512,format));
442
443         oldformat = format;
444         format &= AST_FORMAT_AUDIO_MASK;
445         if (!format) {
446                 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format "
447                                                                   "'%d'\n", format);
448                 return NULL;
449         }
450
451         p = ooh323_alloc(0,0); /* Initial callRef is zero */
452
453         if (!p) {
454                 ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char*)data);
455                 return NULL;
456         }
457         ast_mutex_lock(&p->lock);
458
459         /* This is an outgoing call, since ooh323_request is called */
460         ast_set_flag(p, H323_OUTGOING);
461
462         ast_copy_string(tmp, data, sizeof(data));
463
464         dest = strchr(tmp, '/');
465
466         if (dest) {  
467                 *dest = '\0';
468                 dest++;
469                 ext = tmp;
470         } else if ((dest = strchr(tmp, '@'))) {
471                 *dest = '\0';
472                 dest++;
473                 ext = tmp;
474         } else {
475                 dest = tmp;
476                 ext = NULL;
477         }
478
479 #if 0
480         if ((sport = strchr(dest, ':'))) {
481                 *sport = '\0';
482                 sport++;
483                 port = atoi(sport);
484         }
485 #endif
486
487         if (dest) {
488                 peer = find_peer(dest, port);
489         } else{
490                 ast_log(LOG_ERROR, "Destination format is not supported\n");
491                 return NULL;
492         }
493
494         if (peer) {
495                 p->username = strdup(peer->name);
496                 p->host = strdup(peer->ip);
497                 p->port = peer->port;
498                 /* Disable gk as we are going to call a known peer*/
499                 OO_SETFLAG(p->flags, H323_DISABLEGK);
500
501                 if (ext)
502                         ast_copy_string(p->exten, ext, sizeof(p->exten));
503
504                 if (peer->capability & format) {
505                         p->capability = peer->capability & format;
506                 } else {
507                   p->capability = peer->capability;
508                 }
509                 memcpy(&p->prefs, &peer->prefs, sizeof(struct ast_codec_pref));
510                 p->dtmfmode = peer->dtmfmode;
511                 ast_copy_string(p->accountcode, peer->accountcode, sizeof(p->accountcode));
512                 p->amaflags = peer->amaflags;
513         } else {
514                 p->dtmfmode = gDTMFMode;
515                 p->capability = gCapability;
516
517                 memcpy(&p->prefs, &gPrefs, sizeof(struct ast_codec_pref));
518                 p->username = strdup(dest);
519
520                 p->host = strdup(dest);
521                 if (port > 0) {
522                         p->port = port;
523                 }
524                 if (ext) {
525                         ast_copy_string(p->exten, ext, sizeof(p->exten));
526                 }
527         }
528
529
530         chan = ooh323_new(p, AST_STATE_DOWN, p->username);
531         
532         ast_mutex_unlock(&p->lock);
533
534         if (!chan) {
535                 ast_mutex_lock(&iflock);
536                 ooh323_destroy(p);
537                 ast_mutex_unlock(&iflock);
538         }
539
540         restart_monitor();
541         if (gH323Debug)
542                 ast_verbose("+++   ooh323_request\n");
543
544         return chan;
545
546 }
547
548
549 static struct ooh323_pvt* find_call(ooCallData *call)
550 {
551         struct ooh323_pvt *p;
552
553         if (gH323Debug)
554                 ast_verbose("---   find_call\n");
555
556         ast_mutex_lock(&iflock);
557
558         for (p = iflist; p; p = p->next) {
559                 if (p->callToken && !strcmp(p->callToken, call->callToken)) {
560                         break;
561                 }
562         }
563         ast_mutex_unlock(&iflock);
564
565         if (gH323Debug)
566                 ast_verbose("+++   find_call\n");
567
568         return p;
569 }
570
571 struct ooh323_user *find_user(const char * name, const char* ip)
572 {
573         struct ooh323_user *user;
574
575         if (gH323Debug)
576                 ast_verbose("---   find_user\n");
577
578         ast_mutex_lock(&userl.lock);
579         for (user = userl.users; user; user = user->next) {
580                 if (ip && user->mUseIP && !strcmp(user->mIP, ip)) {
581                         break;
582                 }
583                 if (name && !strcmp(user->name, name)) {
584                         break;
585                 }
586         }
587         ast_mutex_unlock(&userl.lock);
588
589         if (gH323Debug)
590                 ast_verbose("+++   find_user\n");
591
592         return user;
593 }
594
595 struct ooh323_peer *find_friend(const char *name, int port)
596 {
597         struct ooh323_peer *peer;  
598
599         if (gH323Debug)
600                 ast_verbose("---   find_friend \"%s\"\n", name);
601
602
603         ast_mutex_lock(&peerl.lock);
604         for (peer = peerl.peers; peer; peer = peer->next) {
605                 if (gH323Debug) {
606                         ast_verbose("           comparing with \"%s\"\n", peer->ip);
607                 }
608                 if (!strcmp(peer->ip, name)) {
609                         if (port <= 0 || (port > 0 && peer->port == port)) {
610                                 break;
611                         }
612                 }
613         }
614         ast_mutex_unlock(&peerl.lock);
615
616         if (gH323Debug) {
617                 if (peer) {
618                         ast_verbose("           found matching friend\n");
619                 }
620                 ast_verbose("+++   find_friend \"%s\"\n", name);
621         }
622
623         return peer;            
624 }
625
626
627 struct ooh323_peer *find_peer(const char * name, int port)
628 {
629         struct ooh323_peer *peer;
630
631         if (gH323Debug)
632                 ast_verbose("---   find_peer \"%s\"\n", name);
633
634         ast_mutex_lock(&peerl.lock);
635         for (peer = peerl.peers; peer; peer = peer->next) {
636                 if (gH323Debug) {
637                         ast_verbose("           comparing with \"%s\"\n", peer->ip);
638                 }
639                 if (!strcasecmp(peer->name, name))
640                         break;
641                 if (peer->h323id && !strcasecmp(peer->h323id, name))
642                         break;
643                 if (peer->e164 && !strcasecmp(peer->e164, name))
644                         break;
645                 /*
646                 if (!strcmp(peer->ip, name)) {
647                         if (port > 0 && peer->port == port) { break; }
648                         else if (port <= 0) { break; }
649                 }
650                 */
651         }
652         ast_mutex_unlock(&peerl.lock);
653
654         if (gH323Debug) {
655                 if (peer) {
656                         ast_verbose("           found matching peer\n");
657                 }
658                 ast_verbose("+++   find_peer \"%s\"\n", name);
659         }
660
661         return peer;            
662 }
663
664 static int ooh323_digit_begin(struct ast_channel *chan, char digit)
665 {
666         char dtmf[2];
667         struct ooh323_pvt *p = (struct ooh323_pvt *) chan->tech_pvt;
668         
669         if (gH323Debug)
670                 ast_verbose("---   ooh323_digit_begin\n");
671
672         if (!p) {
673                 ast_log(LOG_ERROR, "No private structure for call\n");
674                 return -1;
675         }
676         ast_mutex_lock(&p->lock);
677         if (p->rtp && (p->dtmfmode & H323_DTMF_RFC2833)) {
678                 ast_rtp_senddigit_begin(p->rtp, digit);
679         } else if (((p->dtmfmode & H323_DTMF_Q931) ||
680                                                  (p->dtmfmode & H323_DTMF_H245ALPHANUMERIC) ||
681                                                  (p->dtmfmode & H323_DTMF_H245SIGNAL))) {
682                 dtmf[0] = digit;
683                 dtmf[1] = '\0';
684                 ast_mutex_lock(&ooh323c_cmd_lock);
685                 ooSendDTMFDigit(p->callToken, dtmf);
686                 ast_mutex_unlock(&ooh323c_cmd_lock);
687         }
688         ast_mutex_unlock(&p->lock);
689         if (gH323Debug)
690                 ast_verbose("+++   ooh323_digit_begin\n");
691
692         return 0;
693 }
694
695 static int ooh323_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
696 {
697         struct ooh323_pvt *p = (struct ooh323_pvt *) chan->tech_pvt;
698
699         if (gH323Debug)
700                 ast_verbose("---   ooh323_digit_end\n");
701
702         if (!p) {
703                 ast_log(LOG_ERROR, "No private structure for call\n");
704                 return -1;
705         }
706         ast_mutex_lock(&p->lock);
707         if (p->rtp && (p->dtmfmode & H323_DTMF_RFC2833)) 
708                 ast_rtp_senddigit_end(p->rtp, digit);
709
710         ast_mutex_unlock(&p->lock);
711         if (gH323Debug)
712                 ast_verbose("+++   ooh323_digit_end\n");
713
714         return 0;
715 }
716
717
718 static int ooh323_call(struct ast_channel *ast, char *dest, int timeout)
719 {
720         struct ooh323_pvt *p = ast->tech_pvt;
721         char destination[256];
722         int res = 0;
723         const char *val = NULL;
724         ooCallOptions opts = {
725                 .fastStart = TRUE,
726                 .tunneling = TRUE,
727                 .disableGk = TRUE,
728                 .callMode = OO_CALLMODE_AUDIOCALL
729         };
730         if (gH323Debug)
731                 ast_verbose("---   ooh323_call- %s\n", dest);
732
733         if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
734                 ast_log(LOG_WARNING, "ooh323_call called on %s, neither down nor "
735                                                                         "reserved\n", ast->name);
736                 return -1;
737         }
738         ast_mutex_lock(&p->lock);
739         ast_set_flag(p, H323_OUTGOING);
740         if (ast->cid.cid_num) {
741                 if (p->callerid_num) {
742                         free(p->callerid_num);
743                 }
744                 p->callerid_num = strdup(ast->cid.cid_num);
745         }
746
747         if (ast->cid.cid_name) {
748                 if (p->callerid_name) {
749                         free(p->callerid_name);
750                 }
751                 p->callerid_name = strdup(ast->cid.cid_name);
752         }
753         else{
754                 ast->cid.cid_name = strdup(gCallerID);
755                 if (p->callerid_name) {
756                         free(p->callerid_name);
757                 }
758                 p->callerid_name = strdup(ast->cid.cid_name);
759         }
760
761         /* Retrieve vars */
762
763
764         if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323ID"))) {
765                 ast_copy_string(p->caller_h323id, val, sizeof(p->caller_h323id));
766         }
767         
768         if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323DIALEDDIGITS"))) {
769                 ast_copy_string(p->caller_dialedDigits, val, sizeof(p->caller_dialedDigits));
770                 if (!p->callerid_num) {
771                         p->callerid_num = strdup(val);
772                 }
773         }
774
775         if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323EMAIL"))) {
776                 ast_copy_string(p->caller_email, val, sizeof(p->caller_email));
777         }
778
779         if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323URL"))) {
780                 ast_copy_string(p->caller_url, val, sizeof(p->caller_url));
781         }
782
783
784         if (!(p->callToken = (char*)malloc(AST_MAX_EXTENSION))) {
785                 ast_mutex_unlock(&p->lock);
786                 ast_log(LOG_ERROR, "Failed to allocate memory for callToken\n");
787                 return -1; /* TODO: need to clean/hangup?? */
788         }               
789
790         if (p->host && p->port != 0)
791                 snprintf(destination, sizeof(destination), "%s:%d", p->host, p->port);
792         else if (p->host)
793                 snprintf(destination, sizeof(destination), "%s", p->host);
794         else
795                 ast_copy_string(destination, dest, sizeof(destination));
796
797         ast_mutex_lock(&ooh323c_cmd_lock);
798         if (OO_TESTFLAG(p->flags, H323_DISABLEGK))
799                 res = ooMakeCall(destination, p->callToken, AST_MAX_EXTENSION, &opts);
800         else
801                 res = ooMakeCall(destination, p->callToken, AST_MAX_EXTENSION, NULL);
802         ast_mutex_unlock(&ooh323c_cmd_lock);
803
804         ast_mutex_unlock(&p->lock);
805         if (res != OO_OK) {
806                 ast_log(LOG_ERROR, "Failed to make call\n");
807                 return -1; /* TODO: cleanup */
808         }
809         if (gH323Debug)
810                 ast_verbose("+++   ooh323_call\n");
811
812   return 0;
813 }
814
815 static int ooh323_hangup(struct ast_channel *ast)
816 {
817         struct ooh323_pvt *p = ast->tech_pvt;
818
819         if (gH323Debug)
820                 ast_verbose("---   ooh323_hangup\n");
821
822         if (p) {
823                 ast_mutex_lock(&p->lock);
824
825                 if (gH323Debug)
826                         ast_verbose("    hanging %s\n", p->username);
827                 ast->tech_pvt = NULL; 
828                 if (!ast_test_flag(p, H323_ALREADYGONE)) {
829                         ast_mutex_lock(&ooh323c_cmd_lock);
830                         ooHangCall(p->callToken, 
831                                  ooh323_convert_hangupcause_asteriskToH323(p->owner->hangupcause));
832                         ast_mutex_unlock(&ooh323c_cmd_lock);
833                         ast_set_flag(p, H323_ALREADYGONE);
834                         /* ast_mutex_unlock(&p->lock); */
835                 } else {
836                         ast_set_flag(p, H323_NEEDDESTROY);
837                 }
838                 /* detach channel here */
839                 if (p->owner) {
840                         p->owner->tech_pvt = NULL;
841                         p->owner = NULL;
842                 }
843
844                 ast_mutex_unlock(&p->lock);
845                 ast_mutex_lock(&usecnt_lock);
846                 usecnt--;
847                 ast_mutex_unlock(&usecnt_lock);
848
849                 /* Notify the module monitors that use count for resource has changed */
850                 ast_update_use_count();
851           
852         } else {
853                 ast_log(LOG_ERROR, "No call to hangup\n" );
854                 return -1;
855         }
856         
857         if (gH323Debug)
858                 ast_verbose("+++   ooh323_hangup\n");
859
860   return 0;
861 }
862
863 static int ooh323_answer(struct ast_channel *ast)
864 {
865         struct ooh323_pvt *p = ast->tech_pvt;
866
867         if (gH323Debug)
868                 ast_verbose("--- ooh323_answer\n");
869
870         ast_mutex_lock(&p->lock);
871         if (ast->_state != AST_STATE_UP) {
872                 ast_channel_lock(ast);
873                 ast_setstate(ast, AST_STATE_UP);
874                 ast_debug(1, "ooh323_answer(%s)\n", ast->name);
875                 ast_channel_unlock(ast);
876                 ast_mutex_lock(&ooh323c_cmd_lock);
877                 ooAnswerCall(p->callToken);
878                 ast_mutex_unlock(&ooh323c_cmd_lock);
879         }
880         ast_mutex_unlock(&p->lock);
881
882         if (gH323Debug)
883                 ast_verbose("+++ ooh323_answer\n");
884
885   return 0;
886 }
887
888 static struct ast_frame *ooh323_read(struct ast_channel *ast)
889 {
890         struct ast_frame *fr;
891         static struct ast_frame null_frame = { AST_FRAME_NULL, };
892         struct ooh323_pvt *p = ast->tech_pvt;
893
894         ast_mutex_lock(&p->lock);
895         if (p->rtp)
896                 fr = ooh323_rtp_read(ast, p);
897         else
898                 fr = &null_frame;
899         /* time(&p->lastrtprx); */
900         ast_mutex_unlock(&p->lock);
901         return fr;
902 }
903
904 static int ooh323_write(struct ast_channel *ast, struct ast_frame *f)
905 {
906         struct ooh323_pvt *p = ast->tech_pvt;
907         int res = 0;
908
909         if (f->frametype == AST_FRAME_VOICE) {
910                 if (!(f->subclass & ast->nativeformats)) {
911                         ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native "
912                                                                           "formats is %d (read/write = %d/%d)\n",
913                                                                         f->subclass, ast->nativeformats, ast->readformat,
914                                                                                 ast->writeformat);
915                         return 0;
916                 }
917                 if (p) {
918                         ast_mutex_lock(&p->lock);
919                         if (p->rtp)
920                                 res = ast_rtp_write(p->rtp, f);
921                         ast_mutex_unlock(&p->lock);
922                 }
923         } else if (f->frametype == AST_FRAME_IMAGE) {
924                 return 0;
925         } else {
926                 ast_log(LOG_WARNING, "Can't send %d type frames with SIP write\n", 
927                                                                          f->frametype);
928                 return 0;
929         }
930
931         return res;
932 }
933
934 static int ooh323_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
935 {
936
937         struct ooh323_pvt *p = (struct ooh323_pvt *) ast->tech_pvt;
938         char *callToken = (char *)NULL;
939
940         ast_mutex_lock(&p->lock);
941         callToken = (p->callToken ? strdup(p->callToken) : NULL);
942         ast_mutex_unlock(&p->lock);
943
944         if (!callToken) {
945                 if (gH323Debug)
946                         ast_verbose("   ooh323_indicate - No callToken\n");
947                 return -1;
948         }
949
950         if (gH323Debug)
951                 ast_verbose("----- ooh323_indicate %d on call %s\n", condition, callToken);
952          
953
954         switch (condition) {
955         case AST_CONTROL_CONGESTION:
956                 if (!ast_test_flag(p, H323_ALREADYGONE)) {
957                         ast_mutex_lock(&ooh323c_cmd_lock);
958                         ooHangCall(callToken, OO_REASON_LOCAL_CONGESTED);
959                         ast_mutex_unlock(&ooh323c_cmd_lock);
960                         ast_set_flag(p, H323_ALREADYGONE);
961                 }
962                 break;
963         case AST_CONTROL_BUSY:
964                 if (!ast_test_flag(p, H323_ALREADYGONE)) {
965                         ast_mutex_lock(&ooh323c_cmd_lock);
966                         ooHangCall(callToken, OO_REASON_LOCAL_BUSY);
967                         ast_mutex_unlock(&ooh323c_cmd_lock);
968                         ast_set_flag(p, H323_ALREADYGONE);
969                 }
970                 break;
971         case AST_CONTROL_HOLD:
972                 ast_moh_start(ast, data, NULL);         
973                 break;
974         case AST_CONTROL_UNHOLD:
975                 ast_moh_stop(ast);
976                 break;
977         case AST_CONTROL_PROCEEDING:
978         case AST_CONTROL_RINGING:
979         case AST_CONTROL_PROGRESS:
980         case -1:
981                 break;
982         default:
983                 ast_log(LOG_WARNING, "Don't know how to indicate condition %d on %s\n",
984                                                                         condition, callToken);
985         }
986
987         if (gH323Debug)
988                 ast_verbose("++++  ooh323_indicate %d on %s\n", condition, callToken);
989
990
991         return -1;
992 }
993
994 static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
995 {
996         struct ooh323_pvt *p = newchan->tech_pvt;
997
998         if (gH323Debug)
999                 ast_verbose("--- ooh323c ooh323_fixup\n");
1000
1001         ast_mutex_lock(&p->lock);
1002         if (p->owner != oldchan) {
1003                 ast_log(LOG_WARNING, "Old channel wasn't %p but was %p\n", oldchan, p->owner);
1004                 ast_mutex_unlock(&p->lock);
1005                 return -1;
1006         }
1007
1008         if (p->owner == oldchan) {
1009                 p->owner = newchan;
1010         } else {
1011                 p->owner = oldchan;
1012         }
1013
1014         ast_mutex_unlock(&p->lock);
1015
1016         if (gH323Debug)
1017                 ast_verbose("+++ ooh323c ooh323_fixup \n");
1018
1019         return 0;
1020 }
1021
1022
1023 void ooh323_set_write_format(ooCallData *call, int fmt)
1024 {
1025 #if 0
1026         struct ooh323_pvt *p = NULL;
1027         char formats[512];
1028 #ifdef print_debug
1029         printf("---   ooh323_update_writeformat %s\n", 
1030                                                                                 ast_getformatname_multiple(formats,512, fmt));
1031 #endif
1032         
1033         p = find_call(call);
1034         if (!p) {
1035                 ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
1036                 return;
1037         }
1038
1039         ast_mutex_lock(&p->lock);
1040
1041         p->writeformat = fmt;
1042         ast_mutex_unlock(&p->lock);
1043
1044         if (p->owner) {
1045           printf("Writeformat before update %s\n", 
1046                                   ast_getformatname_multiple(formats,512, p->owner->writeformat));
1047           ast_set_write_format(p->owner, fmt);
1048         }
1049         else
1050           ast_log(LOG_ERROR, "No owner found\n");
1051
1052
1053 #ifdef print_debug
1054   printf("+++   ooh323_update_writeformat\n");
1055 #endif
1056 #endif
1057 }
1058
1059
1060 void ooh323_set_read_format(ooCallData *call, int fmt)
1061 {
1062 #if 0
1063         struct ooh323_pvt *p = NULL;
1064         char formats[512];
1065 #ifdef print_debug
1066         printf("---   ooh323_update_readformat %s\n", 
1067                                                                                         ast_getformatname_multiple(formats,512, fmt));
1068 #endif
1069
1070         p = find_call(call);
1071         if (!p) {
1072                 ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
1073                 return;
1074         }
1075
1076         ast_mutex_lock(&p->lock);
1077         p->readformat = fmt;
1078         ast_mutex_unlock(&p->lock);
1079         ast_set_read_format(p->owner, fmt);     
1080         
1081 #ifdef print_debug
1082   printf("+++   ooh323_update_readformat\n");
1083 #endif
1084 #endif
1085 }
1086
1087 int onAlerting(ooCallData *call)
1088 {
1089         struct ooh323_pvt *p = NULL;
1090         struct ast_channel *c = NULL;
1091
1092         if (gH323Debug)
1093                 ast_verbose("--- onAlerting %s\n", call->callToken);
1094
1095         if (!(p = find_call(call))) {
1096                 ast_log(LOG_ERROR, "No matching call found\n");
1097                 return -1;
1098         }  
1099         ast_mutex_lock(&p->lock);
1100         if (!ast_test_flag(p, H323_OUTGOING)) {
1101                 if (!(c = ooh323_new(p, AST_STATE_RING, p->username))) {
1102                         ast_mutex_unlock(&p->lock);
1103                         ast_log(LOG_ERROR, "Could not create ast_channel\n");
1104                         return -1;
1105                 }
1106                 ast_mutex_unlock(&p->lock);
1107         } else {
1108                 if (!p->owner) {
1109                         ast_mutex_unlock(&p->lock);
1110                         ast_log(LOG_ERROR, "Channel has no owner\n");
1111                         return 0;
1112                 }
1113                 c = p->owner;
1114                 ast_mutex_unlock(&p->lock);
1115                 ast_channel_lock(c);
1116                 ast_setstate(c, AST_STATE_RINGING);
1117                 ast_channel_unlock(c);
1118                 ast_queue_control(c, AST_CONTROL_RINGING);
1119         }
1120
1121         if (gH323Debug)
1122                 ast_verbose("+++ onAlerting %s\n", call->callToken);
1123
1124         return OO_OK;
1125 }
1126
1127 /**
1128   * Callback for sending digits from H.323 up to asterisk
1129   *
1130   */
1131 int ooh323_onReceivedDigit(OOH323CallData *call, const char *digit)
1132 {
1133         struct ooh323_pvt *p = NULL;
1134         struct ast_frame f;
1135         int res;
1136
1137         ast_debug(1, "Received Digit: %c\n", digit[0]);
1138         p = find_call(call);
1139         if (!p) {
1140                 ast_log(LOG_ERROR, "Failed to find a matching call.\n");
1141                 return -1;
1142         }
1143         if (!p->owner) {
1144                 ast_log(LOG_ERROR, "Channel has no owner\n");
1145                 return -1;
1146         }
1147         ast_mutex_lock(&p->lock);
1148         memset(&f, 0, sizeof(f));
1149         f.frametype = AST_FRAME_DTMF;
1150         f.subclass = digit[0];
1151         f.datalen = 0;
1152         f.samples = 800;
1153         f.offset = 0;
1154         f.data.ptr = NULL;
1155         f.mallocd = 0;
1156         f.src = "SEND_DIGIT";
1157         ast_mutex_unlock(&p->lock);
1158         res = ast_queue_frame(p->owner, &f);
1159         return res;
1160 }
1161
1162 int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg)
1163 {
1164         struct ooh323_pvt *p = NULL;
1165         struct ooh323_user *user = NULL;
1166         ooAliases *alias = NULL;
1167         char *at = NULL;
1168         char number [OO_MAX_NUMBER_LENGTH];
1169
1170         if (gH323Debug)
1171                 ast_verbose("---   ooh323_onReceivedSetup %s\n", call->callToken);
1172
1173
1174         if (!(p = ooh323_alloc(call->callReference, call->callToken))) {
1175                 ast_log(LOG_ERROR, "Failed to create a new call.\n");
1176                 return -1;
1177         }
1178         ast_mutex_lock(&p->lock);
1179         ast_clear_flag(p, H323_OUTGOING);
1180   
1181
1182         if (call->remoteDisplayName) {
1183                 p->callerid_name = strdup(call->remoteDisplayName);
1184         }
1185
1186         if (ooCallGetCallingPartyNumber(call, number, OO_MAX_NUMBER_LENGTH) == OO_OK) {
1187                 p->callerid_num = strdup(number);
1188         }
1189
1190         if (call->remoteAliases) {
1191                 for (alias = call->remoteAliases; alias; alias = alias->next) {
1192                         if (alias->type == T_H225AliasAddress_h323_ID) {
1193                                 if (!p->callerid_name) {
1194                                         p->callerid_name = strdup(alias->value);
1195                                 }
1196                                 ast_copy_string(p->caller_h323id, alias->value, sizeof(p->caller_h323id));
1197                         } else if (alias->type == T_H225AliasAddress_dialedDigits) {
1198                                 if (!p->callerid_num) {
1199                                         p->callerid_num = strdup(alias->value);
1200                                 }
1201                                 ast_copy_string(p->caller_dialedDigits, alias->value, 
1202                                                                                                                         sizeof(p->caller_dialedDigits));
1203                         } else if (alias->type == T_H225AliasAddress_email_ID) {
1204                                 ast_copy_string(p->caller_email, alias->value, sizeof(p->caller_email));
1205                         } else if (alias->type == T_H225AliasAddress_url_ID) {
1206                                 ast_copy_string(p->caller_url, alias->value, sizeof(p->caller_url));
1207                         }
1208                 }
1209         }
1210
1211         number[0] = '\0';
1212         if (ooCallGetCalledPartyNumber(call, number, OO_MAX_NUMBER_LENGTH) == OO_OK) {
1213                 ast_copy_string(p->exten, number, sizeof(p->exten));
1214         } else {
1215                 update_our_aliases(call, p);
1216                 if (!ast_strlen_zero(p->callee_dialedDigits)) {
1217                         ast_copy_string(p->exten, p->callee_dialedDigits, sizeof(p->exten));
1218                 } else if (!ast_strlen_zero(p->callee_h323id)) {
1219                         ast_copy_string(p->exten, p->callee_h323id, sizeof(p->exten));
1220                 } else if (!ast_strlen_zero(p->callee_email)) {
1221                         ast_copy_string(p->exten, p->callee_email, sizeof(p->exten));
1222                         if ((at = strchr(p->exten, '@'))) {
1223                                 *at = '\0';
1224                         }
1225                 }
1226         }
1227
1228         /* if no extension found, set to default 's' */
1229         if (ast_strlen_zero(p->exten)) {
1230                 ast_copy_string(p->exten, "s", sizeof(p->exten));
1231         }
1232
1233         if (!p->callerid_name) {
1234                 p->callerid_name = strdup(call->remoteIP);
1235         }
1236         
1237         if (p->callerid_name) {
1238                 if ((user = find_user(p->callerid_name, call->remoteIP))) {
1239                         ast_mutex_lock(&user->lock);
1240                         p->username = strdup(user->name);
1241                         ast_copy_string(p->context, user->context, sizeof(p->context));
1242                         ast_copy_string(p->accountcode, user->accountcode, sizeof(p->accountcode));
1243                         p->amaflags = user->amaflags;
1244                         p->capability = user->capability;
1245                         memcpy(&p->prefs, &user->prefs, sizeof(struct ast_codec_pref));
1246                         p->dtmfmode = user->dtmfmode;
1247                         /* Since, call is coming from a pbx user, no need to use gk */
1248                         OO_SETFLAG(p->flags, H323_DISABLEGK);
1249                         OO_SETFLAG(call->flags, OO_M_DISABLEGK);
1250                         ast_mutex_unlock(&user->lock);
1251                 }
1252         }
1253
1254
1255         ooh323c_set_capability_for_call(call, &p->prefs, p->capability, p->dtmfmode);
1256         configure_local_rtp(p, call);
1257
1258         ast_mutex_unlock(&p->lock);
1259
1260         if (gH323Debug)
1261                 ast_verbose("+++   ooh323_onReceivedSetup - Determined context %s, "
1262                                                 "extension %s\n", p->context, p->exten);
1263
1264         return OO_OK;
1265 }
1266
1267
1268
1269 int onNewCallCreated(ooCallData *call)
1270 {
1271         struct ooh323_pvt *p = NULL;
1272         int i = 0;
1273
1274         if (gH323Debug)
1275                 ast_verbose("---   onNewCallCreated %s\n", call->callToken);
1276
1277         if (!strcmp(call->callType, "outgoing")) {
1278                 p = find_call(call);
1279                 if (!p) {
1280                         ast_log(LOG_ERROR, "No matching call found for outgoing call\n");
1281                         return -1;
1282                 }
1283                 ast_mutex_lock(&p->lock);
1284                 if (p->callerid_name) {
1285                         ooCallSetCallerId(call, p->callerid_name);
1286                 }
1287                 if (p->callerid_num) {
1288                         i = 0;
1289                         while (*(p->callerid_num + i) != '\0') {
1290                                 if (!isdigit(*(p->callerid_num + i))) {
1291                                         break;
1292                                 }
1293                                 i++;
1294                         }
1295                         if (*(p->callerid_num + i) == '\0') {
1296                                 ooCallSetCallingPartyNumber(call, p->callerid_num);
1297                         } else {
1298                                 if (!p->callerid_name) {
1299                                         ooCallSetCallerId(call, p->callerid_num);
1300                                 }
1301                         }
1302                 }
1303                 
1304                 if (!ast_strlen_zero(p->caller_h323id))
1305                         ooCallAddAliasH323ID(call, p->caller_h323id);
1306
1307                 if (!ast_strlen_zero(p->caller_dialedDigits)) {
1308                         if (gH323Debug) {
1309                                 ast_verbose("Setting dialed digits %s\n", p->caller_dialedDigits);
1310                         }
1311                         ooCallAddAliasDialedDigits(call, p->caller_dialedDigits);
1312                 } else if (p->callerid_num) {
1313                         if (ooIsDailedDigit(p->callerid_num)) {
1314                                 if (gH323Debug) {
1315                                         ast_verbose("setting callid number %s\n", p->callerid_num);
1316                                 }
1317                                 ooCallAddAliasDialedDigits(call, p->callerid_num);
1318                         } else if (ast_strlen_zero(p->caller_h323id)) {
1319                                 ooCallAddAliasH323ID(call, p->callerid_num);
1320                         }
1321                 }
1322   
1323
1324                 if (!ast_strlen_zero(p->exten))  {
1325                         if (ooIsDailedDigit(p->exten)) {
1326                                 ooCallSetCalledPartyNumber(call, p->exten);
1327                                 ooCallAddRemoteAliasDialedDigits(call, p->exten);
1328                         } else {
1329                           ooCallAddRemoteAliasH323ID(call, p->exten);
1330                         }
1331                 }
1332
1333                 if (gH323Debug) {
1334                         char prefsBuf[256];
1335                         ast_codec_pref_string(&p->prefs, prefsBuf, sizeof(prefsBuf));
1336                         ast_verbose(" Outgoing call %s(%s) - Codec prefs - %s\n", 
1337                                                   p->username?p->username:"NULL", call->callToken, prefsBuf);
1338                 }
1339
1340                 ooh323c_set_capability_for_call(call, &p->prefs, p->capability, p->dtmfmode);
1341
1342                 configure_local_rtp(p, call);
1343                 ast_mutex_unlock(&p->lock);
1344         }
1345         if (gH323Debug)
1346                 ast_verbose("+++   onNewCallCreated %s\n", call->callToken);
1347
1348         return OO_OK;
1349 }
1350
1351 int onCallEstablished(ooCallData *call)
1352 {
1353         struct ooh323_pvt *p = NULL;
1354
1355         if (gH323Debug)
1356                 ast_verbose("---   onCallEstablished %s\n", call->callToken);
1357
1358         if (!(p = find_call(call))) {
1359                 ast_log(LOG_ERROR, "Failed to find a matching call.\n");
1360                 return -1;
1361         }
1362         ast_mutex_lock(&p->lock);
1363         if (!p->owner) {
1364                 ast_mutex_unlock(&p->lock);
1365                 ast_log(LOG_ERROR, "Channel has no owner\n");
1366                 return -1;
1367         }
1368         
1369         while (ast_channel_trylock(p->owner)) {
1370                 ast_debug(1,"Failed to grab lock, trying again\n");
1371                 ast_mutex_unlock(&p->lock);
1372                 usleep(1);
1373                 ast_mutex_lock(&p->lock);
1374         }        
1375         if (p->owner->_state != AST_STATE_UP) {
1376                 ast_setstate(p->owner, AST_STATE_UP);
1377         }
1378         ast_channel_unlock(p->owner);
1379         if (ast_test_flag(p, H323_OUTGOING)) {
1380                 struct ast_channel* c = p->owner;
1381                 ast_mutex_unlock(&p->lock);
1382                 ast_queue_control(c, AST_CONTROL_ANSWER);
1383         } else {
1384                 ast_mutex_unlock(&p->lock);
1385         }
1386
1387         if (gH323Debug)
1388                 ast_verbose("+++   onCallEstablished %s\n", call->callToken);
1389
1390         return OO_OK;
1391 }
1392
1393 int onCallCleared(ooCallData *call)
1394 {
1395         struct ooh323_pvt *p = NULL;
1396         int ownerLock = 0;
1397
1398         if (gH323Debug)
1399                 ast_verbose("---   onCallCleared %s \n", call->callToken);
1400
1401         p = find_call(call); 
1402         if (!p) {
1403                 return 0;
1404         }
1405         ast_mutex_lock(&p->lock);
1406   
1407         while (p->owner) {
1408                 if (ast_channel_trylock(p->owner)) {
1409                         ooTrace(OOTRCLVLINFO, "Failed to grab lock, trying again\n");
1410                         ast_debug(1,"Failed to grab lock, trying again\n");
1411                         ast_mutex_unlock(&p->lock);
1412                         usleep(1);
1413                         ast_mutex_lock(&p->lock);
1414                 } else {
1415                         ownerLock = 1;
1416                         break;
1417                 }
1418         }
1419
1420         if (ownerLock) {
1421                 if (!ast_test_flag(p, H323_ALREADYGONE)) { 
1422
1423                         /* NOTE: Channel is not detached yet */
1424                         ast_set_flag(p, H323_ALREADYGONE);
1425                         p->owner->hangupcause = 
1426                                 ooh323_convert_hangupcause_h323ToAsterisk(call->callEndReason);
1427                         p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
1428                         ast_channel_unlock(p->owner);
1429                         ast_queue_hangup(p->owner);
1430                         ast_mutex_unlock(&p->lock);
1431                         return OO_OK;
1432                 }
1433                 ast_channel_unlock(p->owner);
1434         }
1435         ast_set_flag(p, H323_NEEDDESTROY);
1436         ast_mutex_unlock(&p->lock);
1437
1438         if (gH323Debug)
1439                 ast_verbose("+++   onCallCleared\n");
1440
1441         return OO_OK;
1442 }
1443
1444 #if 0
1445 static void ooh323_delete_user(struct ooh323_user *user)
1446 {
1447         struct ooh323_user *prev = NULL, *cur = NULL;
1448
1449         if (gH323Debug)
1450                 ast_verbose("---   ooh323_delete_user\n");
1451
1452         if (user) {     
1453                 cur = userl.users;
1454                 ast_mutex_lock(&userl.lock);
1455                 while (cur) {
1456                         if (cur == user) break;
1457                         prev = cur;
1458                         cur = cur->next;
1459                 }
1460
1461                 if (cur) {
1462                         if (prev)
1463                                 prev->next = cur->next;
1464                         else
1465                                 userl.users = cur->next;
1466                 }
1467                 ast_mutex_unlock(&userl.lock);
1468
1469                 free(user);
1470         }  
1471
1472         if (gH323Debug)
1473                 ast_verbose("+++   ooh323_delete_user\n");
1474
1475 }
1476 #endif
1477
1478 void ooh323_delete_peer(struct ooh323_peer *peer)
1479 {
1480         struct ooh323_peer *prev = NULL, *cur = NULL;
1481
1482         if (gH323Debug)
1483                 ast_verbose("---   ooh323_delete_peer\n");
1484
1485         if (peer) {     
1486                 ast_mutex_lock(&peerl.lock);
1487                 for (cur = peerl.peers; cur; prev = cur, cur = cur->next) {
1488                         if (cur == peer) {
1489                                 break;
1490                         }
1491                 }
1492
1493                 if (cur) {
1494                         if (prev) {
1495                                 prev->next = cur->next;
1496                         } else {
1497                                 peerl.peers = cur->next;
1498                         }
1499                 }
1500                 ast_mutex_unlock(&peerl.lock);
1501
1502                 if (peer->h323id)
1503                         free(peer->h323id);
1504                 if (peer->email)
1505                         free(peer->email);
1506                 if (peer->url)
1507                         free(peer->url);
1508                 if (peer->e164)
1509                         free(peer->e164);
1510
1511                 free(peer);
1512         }  
1513
1514         if (gH323Debug)
1515                 ast_verbose("+++   ooh323_delete_peer\n");
1516 }
1517
1518
1519
1520 static struct ooh323_user *build_user(const char *name, struct ast_variable *v)
1521 {
1522         struct ooh323_user *user = NULL;
1523
1524         if (gH323Debug)
1525                 ast_verbose("---   build_user\n");
1526
1527         user = ast_calloc(1, sizeof(*user));
1528         if (user) {
1529                 ast_mutex_init(&user->lock);
1530                 ast_copy_string(user->name, name, sizeof(user->name));
1531                 user->capability = gCapability;
1532                 memcpy(&user->prefs, &gPrefs, sizeof(user->prefs));
1533                 user->rtptimeout = gRTPTimeout;
1534                 user->dtmfmode = gDTMFMode;
1535                 /* set default context */
1536                 ast_copy_string(user->context, gContext, sizeof(user->context));
1537                 ast_copy_string(user->accountcode, gAccountcode, sizeof(user->accountcode));
1538                 user->amaflags = gAMAFLAGS;
1539
1540                 while (v) {
1541                         if (!strcasecmp(v->name, "context")) {
1542                                 ast_copy_string(user->context, v->value, sizeof(user->context));
1543                         } else if (!strcasecmp(v->name, "incominglimit")) {
1544                                 user->incominglimit = atoi(v->value);
1545                                 if (user->incominglimit < 0)
1546                                         user->incominglimit = 0;
1547                         } else if (!strcasecmp(v->name, "accountcode")) {
1548                                 ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
1549                         } else if (!strcasecmp(v->name, "rtptimeout")) {
1550                                 user->rtptimeout = atoi(v->value);
1551                                 if (user->rtptimeout < 0)
1552                                         user->rtptimeout = gRTPTimeout;
1553                         } else if (!strcasecmp(v->name, "disallow")) {
1554                                 ast_parse_allow_disallow(&user->prefs, &user->capability, 
1555                                                                                                  v->value, 0);
1556                         } else if (!strcasecmp(v->name, "allow")) {
1557                                 const char* tcodecs = v->value;
1558                                 if (!strcasecmp(v->value, "all")) {
1559                                         tcodecs = "ulaw,alaw,g729,g723,gsm";
1560                                 }
1561                                 ast_parse_allow_disallow(&user->prefs, &user->capability, 
1562                                                                                                  tcodecs, 1);
1563                         } else if (!strcasecmp(v->name, "amaflags")) {
1564                                 user->amaflags = ast_cdr_amaflags2int(v->value);
1565                         } else if (!strcasecmp(v->name, "ip")) {
1566                                 ast_copy_string(user->mIP, v->value, sizeof(user->mIP));
1567                                 user->mUseIP = 1;
1568                         } else if (!strcasecmp(v->name, "dtmfmode")) {
1569                                 if (!strcasecmp(v->value, "rfc2833"))
1570                                         user->dtmfmode = H323_DTMF_RFC2833;
1571                                 else if (!strcasecmp(v->value, "q931keypad"))
1572                                         user->dtmfmode = H323_DTMF_Q931;
1573                                 else if (!strcasecmp(v->value, "h245alphanumeric"))
1574                                         user->dtmfmode = H323_DTMF_H245ALPHANUMERIC;
1575                                 else if (!strcasecmp(v->value, "h245signal"))
1576                                         user->dtmfmode = H323_DTMF_H245SIGNAL;
1577                         }
1578                         v = v->next;
1579                 }
1580         }
1581
1582         if (gH323Debug)
1583                 ast_verbose("+++   build_user\n");
1584
1585         return user;
1586 }
1587
1588 static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v, int friend_type)
1589 {
1590         struct ooh323_peer *peer = NULL;
1591
1592         if (gH323Debug)
1593                 ast_verbose("---   build_peer\n");
1594
1595         peer = ast_calloc(1, sizeof(*peer));
1596         if (peer) {
1597                 memset(peer, 0, sizeof(struct ooh323_peer));
1598                 ast_mutex_init(&peer->lock);
1599                 ast_copy_string(peer->name, name, sizeof(peer->name));
1600                 peer->capability = gCapability;
1601                 memcpy(&peer->prefs, &gPrefs, sizeof(struct ast_codec_pref));
1602                 peer->rtptimeout = gRTPTimeout;
1603                 ast_copy_string(peer->accountcode, gAccountcode, sizeof(peer->accountcode));
1604                 peer->amaflags = gAMAFLAGS;
1605                 peer->dtmfmode = gDTMFMode;
1606                 if (0 == friend_type) {
1607                         peer->mFriend = 1;
1608                 }
1609
1610                 while (v) {
1611                         if (!strcasecmp(v->name, "h323id")) {
1612                                 if (!(peer->h323id = ast_strdup(v->value))) {
1613                                         ast_log(LOG_ERROR, "Could not allocate memory for h323id of "
1614                                                                                          "peer %s\n", name);
1615                                         ooh323_delete_peer(peer);
1616                                         return NULL;
1617                                 }
1618                         } else if (!strcasecmp(v->name, "e164")) {
1619                                 if (!(peer->e164 = ast_strdup(v->value))) {
1620                                         ast_log(LOG_ERROR, "Could not allocate memory for e164 of "
1621                                                                                          "peer %s\n", name);
1622                                         ooh323_delete_peer(peer);
1623                                         return NULL;
1624                                 }
1625                         } else  if (!strcasecmp(v->name, "email")) {
1626                                 if (!(peer->email = ast_strdup(v->value))) {
1627                                         ast_log(LOG_ERROR, "Could not allocate memory for email of "
1628                                                                                          "peer %s\n", name);
1629                                         ooh323_delete_peer(peer);
1630                                         return NULL;
1631                                 }
1632                         } else if (!strcasecmp(v->name, "url")) {
1633                                 if (!(peer->url = ast_strdup(v->value))) {
1634                                         ast_log(LOG_ERROR, "Could not allocate memory for h323id of "
1635                                                                                          "peer %s\n", name);
1636                                         ooh323_delete_peer(peer);
1637                                         return NULL;
1638                                 }
1639                         } else if (!strcasecmp(v->name, "port")) {
1640                                 peer->port = atoi(v->value);
1641                         } else if (!strcasecmp(v->name, "ip")) {
1642                                 ast_copy_string(peer->ip, v->value, sizeof(peer->ip));
1643                         } else if (!strcasecmp(v->name, "outgoinglimit")) {
1644                                 if ((peer->outgoinglimit = atoi(v->value)) < 0) {
1645                                         peer->outgoinglimit = 0;
1646                                 }
1647                         } else if (!strcasecmp(v->name, "accountcode")) {
1648                                 ast_copy_string(peer->accountcode, v->value, sizeof(peer->accountcode));
1649                         } else if (!strcasecmp(v->name, "rtptimeout")) {
1650                                 if ((peer->rtptimeout = atoi(v->value)) < 0) {
1651                                         peer->rtptimeout = gRTPTimeout;
1652                                 }
1653                         } else if (!strcasecmp(v->name, "disallow")) {
1654                                 ast_parse_allow_disallow(&peer->prefs, &peer->capability, 
1655                                                                                                  v->value, 0); 
1656                         } else if (!strcasecmp(v->name, "allow")) {
1657                                 const char* tcodecs = v->value;
1658                                 if (!strcasecmp(v->value, "all")) {
1659                                         tcodecs = "ulaw,alaw,g729,g723,gsm";
1660                                 }
1661                                 ast_parse_allow_disallow(&peer->prefs, &peer->capability, 
1662                                                                                                  tcodecs, 1);                            
1663                         } else if (!strcasecmp(v->name,  "amaflags")) {
1664                                 peer->amaflags = ast_cdr_amaflags2int(v->value);
1665                         } else if (!strcasecmp(v->name, "dtmfmode")) {
1666                                 if (!strcasecmp(v->value, "rfc2833"))
1667                                         peer->dtmfmode = H323_DTMF_RFC2833;
1668                                 else if (!strcasecmp(v->value, "q931keypad"))
1669                                         peer->dtmfmode = H323_DTMF_Q931;
1670                                 else if (!strcasecmp(v->value, "h245alphanumeric"))
1671                                         peer->dtmfmode = H323_DTMF_H245ALPHANUMERIC;
1672                                 else if (!strcasecmp(v->value, "h245signal"))
1673                                         peer->dtmfmode = H323_DTMF_H245SIGNAL;
1674                         }
1675                         v = v->next;
1676                 }
1677         }
1678
1679         if (gH323Debug)
1680                 ast_verbose("+++   build_peer\n");
1681
1682         return peer;
1683 }
1684
1685 static int ooh323_do_reload(void)
1686 {
1687         if (gH323Debug) {
1688                 ast_verbose("---   ooh323_do_reload\n");
1689         }
1690
1691         reload_config(1);
1692
1693         if (gH323Debug) {
1694                 ast_verbose("+++   ooh323_do_reload\n");
1695         }
1696
1697         return 0;
1698 }
1699
1700 #if 0
1701 /*--- h323_reload: Force reload of module from cli ---*/
1702 static int ooh323_reload(int fd, int argc, char *argv[])
1703 {
1704
1705         if (gH323Debug)
1706                 ast_verbose("---   ooh323_reload\n");
1707
1708         ast_mutex_lock(&h323_reload_lock);
1709         if (h323_reloading) {
1710                 ast_verbose("Previous OOH323 reload not yet done\n");
1711         } 
1712         else {
1713                 h323_reloading = 1;
1714         }
1715         ast_mutex_unlock(&h323_reload_lock);
1716         restart_monitor();
1717
1718         if (gH323Debug)
1719                 ast_verbose("+++   ooh323_reload\n");
1720
1721         return 0;
1722 }
1723 #endif
1724
1725 #if 0
1726 static int reload(void *mod)
1727 {
1728         return ooh323_reload(0, 0, NULL);
1729 }
1730 #endif
1731
1732 int reload_config(int reload)
1733 {
1734         int format;
1735         struct ooAliases  *pNewAlias = NULL;
1736         struct ast_config *cfg;
1737         struct ast_variable *v;
1738         struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1739         struct ooh323_user *user = NULL;
1740         struct ooh323_peer *peer = NULL;
1741         char *cat;
1742         const char *utype;
1743
1744         if (gH323Debug)
1745                 ast_verbose("---   reload_config\n");
1746
1747         cfg = ast_config_load((char*)config, config_flags);
1748
1749         /* We *must* have a config file otherwise stop immediately */
1750         if (!cfg) {
1751                 ast_log(LOG_NOTICE, "Unable to load config %s, OOH323 disabled\n", config);
1752                 return 1;
1753         } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
1754                 return RESULT_SUCCESS;
1755
1756         if (reload) {
1757                 delete_users();
1758                 delete_peers();
1759         }
1760
1761         /* Inintialize everything to default */
1762         strcpy(gLogFile, DEFAULT_LOGFILE);
1763         gPort = 1720;
1764         gIP[0] = '\0';
1765         strcpy(gCallerID, DEFAULT_H323ID);
1766         gCapability = AST_FORMAT_ULAW;
1767         memset(&gPrefs, 0, sizeof(struct ast_codec_pref));
1768         gDTMFMode = H323_DTMF_RFC2833;
1769         gRasGkMode = RasNoGatekeeper;
1770         gGatekeeper[0] = '\0';
1771         gRTPTimeout = 60;
1772         strcpy(gAccountcode, DEFAULT_H323ACCNT);
1773         gFastStart = 1;
1774         gTunneling = 1;
1775         gTOS = 0;
1776         strcpy(gContext, DEFAULT_CONTEXT);
1777         gAliasList = NULL;
1778         gMediaWaitForConnect = 0;
1779         ooconfig.mTCPPortStart = 12030;
1780         ooconfig.mTCPPortEnd = 12230;
1781
1782         v = ast_variable_browse(cfg, "general");
1783         while (v) {
1784         
1785                 if (!strcasecmp(v->name, "port")) {
1786                         gPort = (int)strtol(v->value, NULL, 10);
1787                 } else if (!strcasecmp(v->name, "bindaddr")) {
1788                         ast_copy_string(gIP, v->value, sizeof(gIP));
1789                 } else if (!strcasecmp(v->name, "h225portrange")) {
1790                         char* endlimit = 0;
1791                         char temp[256];
1792                         ast_copy_string(temp, v->value, sizeof(temp));
1793                         endlimit = strchr(temp, ',');
1794                         if (endlimit) {
1795                                 *endlimit = '\0';
1796                                 endlimit++;
1797                                 ooconfig.mTCPPortStart = atoi(temp);
1798                                 ooconfig.mTCPPortEnd = atoi(endlimit);
1799
1800                                 if (ooH323EpSetTCPPortRange(ooconfig.mTCPPortStart, 
1801                                                                                                         ooconfig.mTCPPortEnd) == OO_FAILED) {
1802                                         ast_log(LOG_ERROR, "h225portrange: Failed to set range\n");
1803                                 }
1804                         } else {
1805                                 ast_log(LOG_ERROR, "h225portrange: Invalid format, separate port range with \",\"\n");
1806                         }
1807                 } else if (!strcasecmp(v->name, "gateway")) {
1808                         gIsGateway = ast_true(v->value);
1809                 } else if (!strcasecmp(v->name, "faststart")) {
1810                         gFastStart = ast_true(v->value);
1811                         if (gFastStart)
1812                                 ooH323EpEnableFastStart();
1813                         else
1814                                 ooH323EpDisableFastStart();
1815                 } else if (!strcasecmp(v->name, "mediawaitforconnect")) {
1816                         gMediaWaitForConnect = ast_true(v->value);
1817                         if (gMediaWaitForConnect)
1818                                 ooH323EpEnableMediaWaitForConnect();
1819                         else 
1820                                 ooH323EpDisableMediaWaitForConnect();
1821                 } else if (!strcasecmp(v->name, "h245tunneling")) {
1822                         gTunneling = ast_true(v->value);
1823                         if (gTunneling)
1824                                 ooH323EpEnableH245Tunneling();
1825                         else
1826                                 ooH323EpDisableH245Tunneling();
1827                 } else if (!strcasecmp(v->name, "h323id")) {
1828                         pNewAlias = malloc(sizeof(*pNewAlias));
1829                         if (!pNewAlias) {
1830                                 ast_log(LOG_ERROR, "Failed to allocate memory for h323id alias\n");
1831                                 return 1;
1832                         }
1833                         pNewAlias->type =  T_H225AliasAddress_h323_ID;
1834                         pNewAlias->value = strdup(v->value);
1835                         pNewAlias->next = gAliasList;
1836                         gAliasList = pNewAlias;
1837                         pNewAlias = NULL;
1838                 } else if (!strcasecmp(v->name, "e164")) {
1839                         pNewAlias = malloc(sizeof(*pNewAlias));
1840                         if (!pNewAlias) {
1841                                 ast_log(LOG_ERROR, "Failed to allocate memory for e164 alias\n");
1842                                 return 1;
1843                         }
1844                         pNewAlias->type =  T_H225AliasAddress_dialedDigits;
1845                         pNewAlias->value = strdup(v->value);
1846                         pNewAlias->next = gAliasList;
1847                         gAliasList = pNewAlias;
1848                         pNewAlias = NULL;
1849                 } else if (!strcasecmp(v->name, "email")) {
1850                         pNewAlias = malloc(sizeof(*pNewAlias));
1851                         if (!pNewAlias) {
1852                                 ast_log(LOG_ERROR, "Failed to allocate memory for email alias\n");
1853                                 return 1;
1854                         }
1855                         pNewAlias->type =  T_H225AliasAddress_email_ID;
1856                         pNewAlias->value = strdup(v->value);
1857                         pNewAlias->next = gAliasList;
1858                         gAliasList = pNewAlias;
1859                         pNewAlias = NULL;
1860                 } else if (!strcasecmp(v->name, "callerid")) {
1861                         ast_copy_string(gCallerID, v->value, sizeof(gCallerID));
1862                 } else if (!strcasecmp(v->name, "incominglimit")) {
1863                         gIncomingLimit = atoi(v->value);
1864                 } else if (!strcasecmp(v->name, "outgoinglimit")) {
1865                         gOutgoingLimit = atoi(v->value);
1866                 } else if (!strcasecmp(v->name, "gatekeeper")) {
1867                         if (!strcasecmp(v->value, "DISABLE")) {
1868                                 gRasGkMode = RasNoGatekeeper;
1869                         } else if (!strcasecmp(v->value, "DISCOVER")) {
1870                                 gRasGkMode = RasDiscoverGatekeeper;
1871                         } else {
1872                                 gRasGkMode = RasUseSpecificGatekeeper;
1873                                 ast_copy_string(gGatekeeper, v->value, sizeof(gGatekeeper));
1874                         }
1875                 } else if (!strcasecmp(v->name, "logfile")) {
1876                         ast_copy_string(gLogFile, v->value, sizeof(gLogFile));
1877                 } else if (!strcasecmp(v->name, "context")) {
1878                         ast_copy_string(gContext, v->value, sizeof(gContext));
1879                         ast_verb(3, "  == Setting default context to %s\n", gContext);
1880                 } else if (!strcasecmp(v->name, "rtptimeout")) {
1881                         gRTPTimeout = atoi(v->value);
1882                         if (gRTPTimeout <= 0)
1883                                 gRTPTimeout = 60;
1884                 } else if (!strcasecmp(v->name, "tos")) {
1885                         if (sscanf(v->value, "%i", &format) == 1)
1886                                 gTOS = format & 0xff;
1887                         else if (!strcasecmp(v->value, "lowdelay"))
1888                                 gTOS = IPTOS_LOWDELAY;
1889                         else if (!strcasecmp(v->value, "throughput"))
1890                                 gTOS = IPTOS_THROUGHPUT;
1891                         else if (!strcasecmp(v->value, "reliability"))
1892                                 gTOS = IPTOS_RELIABILITY;
1893                         else if (!strcasecmp(v->value, "mincost"))
1894                                 gTOS = IPTOS_MINCOST;
1895                         else if (!strcasecmp(v->value, "none"))
1896                                 gTOS = 0;
1897                         else
1898                                 ast_log(LOG_WARNING, "Invalid tos value at line %d, should be "
1899                                                                                         "'lowdelay', 'throughput', 'reliability', "
1900                                                                                         "'mincost', or 'none'\n", v->lineno);
1901                 } else if (!strcasecmp(v->name, "amaflags")) {
1902                         gAMAFLAGS = ast_cdr_amaflags2int(v->value);
1903                 } else if (!strcasecmp(v->name, "accountcode")) {
1904                         ast_copy_string(gAccountcode, v->value, sizeof(gAccountcode)-1);
1905                 } else if (!strcasecmp(v->name, "disallow")) {
1906                         ast_parse_allow_disallow(&gPrefs, &gCapability, v->value, 0);
1907                 } else if (!strcasecmp(v->name, "allow")) {
1908                         const char* tcodecs = v->value;
1909                         if (!strcasecmp(v->value, "all")) {
1910                                 tcodecs = "ulaw,alaw,g729,g723,gsm";
1911                         }
1912                         ast_parse_allow_disallow(&gPrefs, &gCapability, tcodecs, 1);
1913                 } else if (!strcasecmp(v->name, "dtmfmode")) {
1914                         if (!strcasecmp(v->value, "inband"))
1915                                 gDTMFMode = H323_DTMF_INBAND;
1916                         else if (!strcasecmp(v->value, "rfc2833"))
1917                                 gDTMFMode = H323_DTMF_RFC2833;
1918                         else if (!strcasecmp(v->value, "q931keypad"))
1919                                 gDTMFMode = H323_DTMF_Q931;
1920                         else if (!strcasecmp(v->value, "h245alphanumeric"))
1921                                 gDTMFMode = H323_DTMF_H245ALPHANUMERIC;
1922                         else if (!strcasecmp(v->value, "h245signal"))
1923                                 gDTMFMode = H323_DTMF_H245SIGNAL;
1924                         else {
1925                                 ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
1926                                 gDTMFMode = H323_DTMF_RFC2833;
1927                         }
1928                 }  
1929                 v = v->next;
1930         }
1931         
1932         for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
1933                 if (strcasecmp(cat, "general")) {
1934                         int friend_type = 0;
1935                         utype = ast_variable_retrieve(cfg, cat, "type");
1936                         if (utype) {
1937                                 friend_type = strcasecmp(utype, "friend");
1938                                 if (!strcmp(utype, "user") || 0 == friend_type) {
1939                                         user = build_user(cat, ast_variable_browse(cfg, cat));
1940                                         if (user) {
1941                                                 ast_mutex_lock(&userl.lock);
1942                                                 user->next = userl.users;
1943                                                 userl.users = user;
1944                                                 ast_mutex_unlock(&userl.lock);
1945                                         } else {
1946                                                 ast_log(LOG_WARNING, "Failed to build user %s\n", cat);
1947                                         }
1948                                 }
1949                                 if (!strcasecmp(utype, "peer") || 0 == friend_type) {
1950                                         peer = build_peer(cat, ast_variable_browse(cfg, cat), friend_type);
1951                                         if (peer) {
1952                                                 ast_mutex_lock(&peerl.lock);
1953                                                 peer->next = peerl.peers;
1954                                                 peerl.peers = peer;
1955                                                 ast_mutex_unlock(&peerl.lock);
1956                                         } else {
1957                                                 ast_log(LOG_WARNING, "Failed to build peer %s\n", cat);
1958                                         }
1959                                 }
1960                         }
1961                 }
1962         }
1963         ast_config_destroy(cfg);
1964
1965
1966         /* Determine ip address if neccessary */
1967         if (ast_strlen_zero(gIP)) {
1968                 ooGetLocalIPAddress(gIP);
1969                 if (!strcmp(gIP, "127.0.0.1")) {
1970                         ast_log(LOG_NOTICE, "Failed to determine local ip address. Please "
1971                                                                          "specify it in ooh323.conf. OOH323 Disabled\n");
1972                         return 1;
1973                 }
1974         }
1975
1976         if (gH323Debug)
1977                 ast_verbose("+++   reload_config\n");
1978
1979         return 0;
1980 }
1981
1982 static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1983 {
1984         char ip_port[30];
1985         struct ooh323_peer *prev = NULL, *peer = NULL;
1986         
1987         switch (cmd) {
1988         case CLI_INIT:
1989                 e->command = "ooh323 show peer";
1990                 e->usage =
1991                         "Usage: ooh323 show peer <name>\n"
1992                         "                List details of specific OOH323 peer.\n";
1993                 return NULL;
1994         case CLI_GENERATE:
1995                 return NULL;
1996         }
1997
1998         if (a->argc != 4)
1999                 return CLI_SHOWUSAGE;
2000
2001         ast_mutex_lock(&peerl.lock);
2002         peer = peerl.peers;
2003         while (peer) {
2004                 ast_mutex_lock(&peer->lock);
2005                 if (!strcmp(peer->name, a->argv[3]))
2006                         break;
2007                 else {
2008                         prev = peer;
2009                         peer = peer->next;
2010                         ast_mutex_unlock(&prev->lock);
2011                 }
2012         }
2013
2014         if (peer) {
2015                 snprintf(ip_port, sizeof(ip_port), "%s:%d", peer->ip, peer->port);
2016                 ast_cli(a->fd, "%-15.15s%s\n", "Name: ", peer->name);
2017                 ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "(");
2018                 print_codec_to_cli(a->fd, &peer->prefs);
2019                 ast_cli(a->fd, ")\n");
2020                 ast_cli(a->fd, "%-15.15s", "DTMF Mode: ");
2021                 if (peer->dtmfmode & H323_DTMF_RFC2833)
2022                         ast_cli(a->fd, "%s\n", "rfc2833");
2023                 else if (peer->dtmfmode & H323_DTMF_Q931)
2024                         ast_cli(a->fd, "%s\n", "q931keypad");
2025                 else if (peer->dtmfmode & H323_DTMF_H245ALPHANUMERIC)
2026                         ast_cli(a->fd, "%s\n", "h245alphanumeric");
2027                 else if (peer->dtmfmode & H323_DTMF_H245SIGNAL)
2028                         ast_cli(a->fd, "%s\n", "h245signal");
2029                 else
2030                         ast_cli(a->fd, "%s\n", "unknown");
2031                 ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", peer->accountcode);
2032                 ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ",
2033                 ast_cdr_flags2str(peer->amaflags));
2034                 ast_cli(a->fd, "%-15.15s%s\n", "Ip:Port: ", ip_port);
2035                 ast_cli(a->fd, "%-15.15s%d\n", "OutgoingLimit: ", peer->outgoinglimit);
2036                 ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", peer->rtptimeout);
2037                 ast_mutex_unlock(&peer->lock);
2038         } else {
2039                 ast_cli(a->fd, "Peer %s not found\n", a->argv[3]);
2040                 ast_cli(a->fd, "\n");
2041         }
2042         ast_mutex_unlock(&peerl.lock);
2043
2044         return CLI_SUCCESS;
2045 }
2046
2047 static char *handle_cli_ooh323_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2048 {
2049         char ip_port[30];
2050         char formats[512];
2051         struct ooh323_peer *prev = NULL, *peer = NULL;
2052
2053 #define FORMAT  "%-15.15s  %-15.15s  %-23.23s  %-s\n"
2054
2055         switch (cmd) {
2056         case CLI_INIT:
2057                 e->command = "ooh323 show peers";
2058                 e->usage =
2059                         "Usage: ooh323 show peers\n"
2060                         "                Lists all known OOH323 peers.\n";
2061                 return NULL;
2062         case CLI_GENERATE:
2063                 return NULL;
2064         }
2065
2066         if (a->argc != 3)
2067                 return CLI_SHOWUSAGE;
2068
2069         ast_cli(a->fd, FORMAT, "Name", "Accountcode", "ip:port", "Formats");
2070
2071         ast_mutex_lock(&peerl.lock);
2072         peer = peerl.peers;
2073         while (peer) {
2074                 ast_mutex_lock(&peer->lock);
2075                 snprintf(ip_port, sizeof(ip_port), "%s:%d", peer->ip, peer->port);
2076                 ast_cli(a->fd, FORMAT, peer->name,
2077                                         peer->accountcode,
2078                                         ip_port,
2079                                         ast_getformatname_multiple(formats, sizeof(formats), peer->capability));
2080                 prev = peer;
2081                 peer = peer->next;
2082                 ast_mutex_unlock(&prev->lock);
2083         }
2084         ast_mutex_unlock(&peerl.lock);
2085
2086 #undef FORMAT
2087
2088         return CLI_SUCCESS;
2089 }
2090
2091 /*! \brief Print codec list from preference to CLI/manager */
2092 static void print_codec_to_cli(int fd, struct ast_codec_pref *pref)
2093 {
2094         int x, codec;
2095
2096         for (x = 0; x < 32; x++) {
2097                 codec = ast_codec_pref_index(pref, x);
2098                 if (!codec)
2099                         break;
2100                 ast_cli(fd, "%s", ast_getformatname(codec));
2101                 ast_cli(fd, ":%d", pref->framing[x]);
2102                 if (x < 31 && ast_codec_pref_index(pref, x + 1))
2103                         ast_cli(fd, ",");
2104         }
2105         if (!x)
2106                 ast_cli(fd, "none");
2107 }
2108
2109 static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2110 {
2111         struct ooh323_user *prev = NULL, *user = NULL;
2112
2113         switch (cmd) {
2114         case CLI_INIT:
2115                 e->command = "ooh323 show user";
2116                 e->usage =
2117                         "Usage: ooh323 show user <name>\n"
2118                         "                List details of specific OOH323 user.\n";
2119                 return NULL;
2120         case CLI_GENERATE:
2121                 return NULL;
2122         }
2123
2124         if (a->argc != 4)
2125                 return CLI_SHOWUSAGE;
2126
2127         ast_mutex_lock(&userl.lock);
2128         user = userl.users;
2129         while (user) {
2130                 ast_mutex_lock(&user->lock);
2131                 if (!strcmp(user->name, a->argv[3]))
2132                         break;
2133                 else {
2134                         prev = user;
2135                         user = user->next;
2136                         ast_mutex_unlock(&prev->lock);
2137                 }
2138         }
2139
2140         if (user) {
2141                 ast_cli(a->fd, "%-15.15s%s\n", "Name: ", user->name);
2142                 ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "(");
2143                 print_codec_to_cli(a->fd, &user->prefs);
2144                 ast_cli(a->fd, ")\n");
2145                 ast_cli(a->fd, "%-15.15s", "DTMF Mode: ");
2146                 if (user->dtmfmode & H323_DTMF_RFC2833)
2147                         ast_cli(a->fd, "%s\n", "rfc2833");
2148                 else if (user->dtmfmode & H323_DTMF_Q931)
2149                         ast_cli(a->fd, "%s\n", "q931keypad");
2150                 else if (user->dtmfmode & H323_DTMF_H245ALPHANUMERIC)
2151                         ast_cli(a->fd, "%s\n", "h245alphanumeric");
2152                 else if (user->dtmfmode & H323_DTMF_H245SIGNAL)
2153                         ast_cli(a->fd, "%s\n", "h245signal");
2154                 else
2155                         ast_cli(a->fd, "%s\n", "unknown");
2156                 ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", user->accountcode);
2157                 ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", ast_cdr_flags2str(user->amaflags));
2158                 ast_cli(a->fd, "%-15.15s%s\n", "Context: ", user->context);
2159                 ast_cli(a->fd, "%-15.15s%d\n", "IncomingLimit: ", user->incominglimit);
2160                 ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", user->rtptimeout);
2161                 ast_mutex_unlock(&user->lock);
2162         } else {
2163                 ast_cli(a->fd, "User %s not found\n", a->argv[3]);
2164                 ast_cli(a->fd, "\n");
2165         }
2166         ast_mutex_unlock(&userl.lock);
2167
2168         return CLI_SUCCESS;
2169 }
2170
2171 static char *handle_cli_ooh323_show_users(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2172 {
2173         char formats[512];
2174         struct ooh323_user *prev = NULL, *user = NULL;
2175
2176 #define FORMAT1  "%-15.15s  %-15.15s  %-15.15s  %-s\n"
2177
2178         switch (cmd) {
2179         case CLI_INIT:
2180                 e->command = "ooh323 show users";
2181                 e->usage =
2182                         "Usage: ooh323 show users \n"
2183                         "                Lists all known OOH323 users.\n";
2184                 return NULL;
2185         case CLI_GENERATE:
2186                 return NULL;
2187         }
2188
2189         if (a->argc != 3)
2190                 return CLI_SHOWUSAGE;
2191
2192         ast_cli(a->fd, FORMAT1, "Username", "Accountcode", "Context", "Formats");
2193
2194         ast_mutex_lock(&userl.lock);
2195         user = userl.users;
2196         while (user) {
2197                 ast_mutex_lock(&user->lock);
2198                 ast_cli(a->fd, FORMAT1, user->name,
2199                                         user->accountcode, user->context,
2200                                         ast_getformatname_multiple(formats, 512, user->capability));
2201                 prev = user;
2202                 user = user->next;
2203                 ast_mutex_unlock(&prev->lock);
2204         }
2205         ast_mutex_unlock(&userl.lock);
2206
2207 #undef FORMAT1
2208
2209         return CLI_SUCCESS;
2210 }
2211
2212 static char *handle_cli_ooh323_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2213 {
2214         switch (cmd) {
2215         case CLI_INIT:
2216                 e->command = "ooh323 set debug [off]";
2217                 e->usage =
2218                         "Usage: ooh323 set debug [off]\n"
2219                         "                Enables/Disables debugging of OOH323 channel driver\n";
2220                 return NULL;
2221         case CLI_GENERATE:
2222                 return NULL;
2223         }
2224
2225         if (a->argc < 3 || a->argc > 4)
2226                 return CLI_SHOWUSAGE;
2227         if (a->argc == 4 && strcasecmp(a->argv[3], "off"))
2228                 return CLI_SHOWUSAGE;
2229
2230         gH323Debug = (a->argc == 4) ? FALSE : TRUE;
2231         ast_cli(a->fd, "OOH323 Debugging %s\n", gH323Debug ? "Enabled" : "Disabled");
2232
2233         return CLI_SUCCESS;
2234 }
2235
2236 #if 0
2237 static int ooh323_show_channels(int fd, int argc, char *argv[])
2238 {
2239         return RESULT_SUCCESS;
2240 }
2241 #endif
2242
2243 static char *handle_cli_ooh323_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2244 {
2245         char value[512];
2246         ooAliases *pAlias = NULL, *pAliasNext = NULL;;
2247
2248         switch (cmd) {
2249         case CLI_INIT:
2250                 e->command = "ooh323 show config";
2251                 e->usage =
2252                         "Usage: ooh323 show config\n"
2253                         "                Shows global configuration of H.323 channel driver\n";
2254                 return NULL;
2255         case CLI_GENERATE:
2256                 return NULL;
2257         }
2258
2259         if (a->argc != 3)
2260                 return CLI_SHOWUSAGE;
2261
2262         snprintf(value, sizeof(value), "%s:%d", gIP, gPort);
2263         ast_cli(a->fd, "\nObjective Open H.323 Channel Driver's Config:\n");
2264         ast_cli(a->fd, "%-20s%s\n", "IP:Port: ", value);
2265         ast_cli(a->fd, "%-20s%s\n", "FastStart", gFastStart?"yes":"no");
2266         ast_cli(a->fd, "%-20s%s\n", "Tunneling", gTunneling?"yes":"no");
2267         ast_cli(a->fd, "%-20s%s\n", "CallerId", gCallerID);
2268         ast_cli(a->fd, "%-20s%s\n", "MediaWaitForConnect", gMediaWaitForConnect ? "yes" : "no");
2269
2270 #if 0
2271         {
2272                 extern OOH323EndPoint gH323ep;
2273
2274                 ast_cli(a->fd, "%-20s%s\n", "FASTSTART",
2275                         (OO_TESTFLAG(gH323ep.flags, OO_M_FASTSTART) != 0) ? "yes" : "no");
2276                 ast_cli(a->fd, "%-20s%s\n", "TUNNELING",
2277                         (OO_TESTFLAG(gH323ep.flags, OO_M_TUNNELING) != 0) ? "yes" : "no");
2278                 ast_cli(a->fd, "%-20s%s\n", "MEDIAWAITFORCONN",
2279                         (OO_TESTFLAG(gH323ep.flags, OO_M_MEDIAWAITFORCONN) != 0) ? "yes" : "no");
2280         }
2281 #endif
2282
2283         if (gRasGkMode == RasNoGatekeeper)
2284                 snprintf(value, sizeof(value), "%s", "No Gatekeeper");
2285         else if (gRasGkMode == RasDiscoverGatekeeper)
2286                 snprintf(value, sizeof(value), "%s", "Discover");
2287         else
2288                 snprintf(value, sizeof(value), "%s", gGatekeeper);
2289
2290         ast_cli(a->fd, "%-20s%s\n", "Gatekeeper:", value);
2291         ast_cli(a->fd, "%-20s%s\n", "H.323 LogFile:", gLogFile);
2292         ast_cli(a->fd, "%-20s%s\n", "Context:", gContext);
2293         ast_cli(a->fd, "%-20s%s\n", "Capability:", ast_getformatname_multiple(value, sizeof(value), gCapability));
2294         ast_cli(a->fd, "%-20s", "DTMF Mode: ");
2295         if (gDTMFMode & H323_DTMF_RFC2833)
2296                 ast_cli(a->fd, "%s\n", "rfc2833");
2297         else if (gDTMFMode & H323_DTMF_Q931)
2298                 ast_cli(a->fd, "%s\n", "q931keypad");
2299         else if (gDTMFMode & H323_DTMF_H245ALPHANUMERIC)
2300                 ast_cli(a->fd, "%s\n", "h245alphanumeric");
2301         else if (gDTMFMode & H323_DTMF_H245SIGNAL)
2302                 ast_cli(a->fd, "%s\n", "h245signal");
2303         else
2304                 ast_cli(a->fd, "%s\n", "unknown");
2305         ast_cli(a->fd, "%-20s%s\n", "AccountCode: ", gAccountcode);
2306         ast_cli(a->fd, "%-20s%s\n", "AMA flags: ", ast_cdr_flags2str(gAMAFLAGS));
2307
2308         pAlias = gAliasList;
2309         if (pAlias)
2310                 ast_cli(a->fd, "%-20s\n", "Aliases: ");
2311         while (pAlias) {
2312                 pAliasNext = pAlias->next;
2313                 if (pAliasNext) {
2314                         ast_cli(a->fd, "\t%-30s\t%-30s\n", pAlias->value, pAliasNext->value);
2315                         pAlias = pAliasNext->next;
2316                 } else {
2317                         ast_cli(a->fd, "\t%-30s\n", pAlias->value);
2318                         pAlias = pAlias->next;
2319                 }
2320         }
2321
2322         return CLI_SUCCESS;
2323 }
2324
2325 static struct ast_cli_entry cli_ooh323[] = {
2326         AST_CLI_DEFINE(handle_cli_ooh323_set_debug,     "Enable/Disable OOH323 debugging"),
2327         AST_CLI_DEFINE(handle_cli_ooh323_show_config, "Show details on global configuration of H.323 channel driver"),
2328         AST_CLI_DEFINE(handle_cli_ooh323_show_peer,     "Show details on specific OOH323 peer"),
2329         AST_CLI_DEFINE(handle_cli_ooh323_show_peers,  "Show defined OOH323 peers"),
2330         AST_CLI_DEFINE(handle_cli_ooh323_show_user,     "Show details on specific OOH323 user"),
2331         AST_CLI_DEFINE(handle_cli_ooh323_show_users,  "Show defined OOH323 users"),
2332 };
2333
2334 static int load_module(void)
2335 {
2336         int res;
2337         struct ooAliases * pNewAlias = NULL;
2338         struct ooh323_peer *peer = NULL;
2339         OOH225MsgCallbacks h225Callbacks = {0, 0, 0, 0};
2340
2341         OOH323CALLBACKS h323Callbacks = {
2342                 .onNewCallCreated = onNewCallCreated,
2343                 .onAlerting = onAlerting,
2344                 .onIncomingCall = NULL,
2345                 .onOutgoingCall = NULL,
2346                 .onCallEstablished = onCallEstablished,
2347                 .onCallCleared = onCallCleared,
2348                 .openLogicalChannels = NULL,
2349                 .onReceivedDTMF = &ooh323_onReceivedDigit
2350         };
2351
2352         ast_log(LOG_NOTICE, 
2353                 "---------------------------------------------------------------------------------\n"
2354                 "---  ******* IMPORTANT NOTE ***********\n"
2355                 "---\n"
2356                 "---  This module is currently unsupported.  Use it at your own risk.\n"
2357                 "---\n"
2358                 "---------------------------------------------------------------------------------\n");
2359
2360         h225Callbacks.onReceivedSetup = &ooh323_onReceivedSetup;
2361
2362         userl.users = NULL;
2363         ast_mutex_init(&userl.lock);
2364         peerl.peers = NULL;
2365         ast_mutex_init(&peerl.lock);
2366  
2367 #if 0           
2368         ast_register_atexit(&ast_ooh323c_exit);
2369 #endif
2370
2371         if (!(sched = sched_context_create())) {
2372                 ast_log(LOG_WARNING, "Unable to create schedule context\n");
2373         }
2374         if (!(io = io_context_create())) {
2375                 ast_log(LOG_WARNING, "Unable to create I/O context\n");
2376         }
2377
2378
2379         if (!(res = reload_config(0))) {
2380                 /* Make sure we can register our OOH323 channel type */
2381                 if (ast_channel_register(&ooh323_tech)) {
2382                         ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
2383                         return 0;
2384                 }
2385                 ast_rtp_proto_register(&ooh323_rtp);
2386                 ast_cli_register_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry));
2387
2388                  /* fire up the H.323 Endpoint */                
2389                 if (OO_OK != ooH323EpInitialize(OO_CALLMODE_AUDIOCALL, gLogFile)) {
2390                         ast_log(LOG_ERROR, "Failed to initialize OOH323 endpoint-OOH323 Disabled\n");
2391                         return 1;
2392                 }
2393
2394                 if (gIsGateway)
2395                         ooH323EpSetAsGateway();
2396
2397                 ooH323EpDisableAutoAnswer();
2398                 ooH323EpSetH225MsgCallbacks(h225Callbacks);
2399                 ooH323EpSetTraceLevel(OOTRCLVLDBGC);
2400                 ooH323EpSetLocalAddress(gIP, gPort);
2401                 ooH323EpSetCallerID(gCallerID);
2402  
2403                 /* Set aliases if any */
2404                 for (pNewAlias = gAliasList; pNewAlias; pNewAlias = pNewAlias->next) {
2405                         switch (pNewAlias->type) {
2406                         case T_H225AliasAddress_h323_ID:
2407                                 ooH323EpAddAliasH323ID(pNewAlias->value);
2408                                 break;
2409                         case T_H225AliasAddress_dialedDigits:   
2410                                 ooH323EpAddAliasDialedDigits(pNewAlias->value);
2411                                 break;
2412                         case T_H225AliasAddress_email_ID:       
2413                                 ooH323EpAddAliasEmailID(pNewAlias->value);
2414                                 break;
2415                         }
2416                 }
2417
2418                 ast_mutex_lock(&peerl.lock);
2419                 peer = peerl.peers;
2420                 while (peer) {
2421                         if (peer->h323id)
2422                                 ooH323EpAddAliasH323ID(peer->h323id);
2423                         if (peer->email)
2424                                 ooH323EpAddAliasEmailID(peer->email);
2425                         if (peer->e164)
2426                                 ooH323EpAddAliasDialedDigits(peer->e164);
2427                         if (peer->url)
2428                                 ooH323EpAddAliasURLID(peer->url);
2429                         peer = peer->next;
2430                 }
2431                 ast_mutex_unlock(&peerl.lock);
2432         
2433
2434                 if (gMediaWaitForConnect)
2435                         ooH323EpEnableMediaWaitForConnect();
2436                 else 
2437                         ooH323EpDisableMediaWaitForConnect();
2438
2439                 /* Fast start and tunneling options */
2440                 if (gFastStart)
2441                         ooH323EpEnableFastStart();
2442                 else
2443                         ooH323EpDisableFastStart();
2444
2445                 if (!gTunneling)
2446                         ooH323EpDisableH245Tunneling();
2447
2448                 /* Gatekeeper */
2449                 if (gRasGkMode == RasUseSpecificGatekeeper)
2450                         ooGkClientInit(gRasGkMode, gGatekeeper, 0);
2451                 else if (gRasGkMode == RasDiscoverGatekeeper)
2452                         ooGkClientInit(gRasGkMode, 0, 0);
2453
2454                 /* Register callbacks */
2455                 ooH323EpSetH323Callbacks(h323Callbacks);
2456
2457                 /* Add endpoint capabilities */
2458                 if (ooh323c_set_capability(&gPrefs, gCapability, gDTMFMode) < 0) {
2459                         ast_log(LOG_ERROR, "Capabilities failure for OOH323. OOH323 Disabled.\n");
2460                         return 1;
2461                 }
2462   
2463
2464                 /* Create H.323 listener */
2465                 if (ooCreateH323Listener() != OO_OK) {
2466                         ast_log(LOG_ERROR, "OOH323 Listener Creation failure. OOH323 DISABLED\n");
2467                 
2468                         ooH323EpDestroy();
2469                         return 1;
2470                 }
2471
2472                 if (ooh323c_start_stack_thread() < 0) {
2473                         ast_log(LOG_ERROR, "Failed to start OOH323 stack thread. OOH323 DISABLED\n");
2474                         ooH323EpDestroy();
2475                         return 1;
2476                 }
2477                 /* And start the monitor for the first time */
2478                 restart_monitor();
2479         }
2480
2481         return 0;
2482 }
2483
2484
2485 static void *do_monitor(void *data)
2486 {
2487         int res;
2488         int reloading;
2489         struct ooh323_pvt *h323 = NULL;
2490         time_t t;
2491
2492         for (;;) {
2493                 struct ooh323_pvt *h323_next;
2494                 /* Check for a reload request */
2495                 ast_mutex_lock(&h323_reload_lock);
2496                 reloading = h323_reloading;
2497                 h323_reloading = 0;
2498                 ast_mutex_unlock(&h323_reload_lock);
2499                 if (reloading) {
2500                         ast_verb(1, "Reloading H.323\n");
2501                         ooh323_do_reload();
2502                 }
2503                 /* Check for interfaces needing to be killed */
2504                 ast_mutex_lock(&iflock);
2505                 time(&t);
2506                 h323 = iflist;
2507                 while (h323) {
2508                         h323_next = h323->next;
2509
2510                         /* TODO: Need to add rtptimeout keepalive support */
2511                         if (ast_test_flag(h323, H323_NEEDDESTROY)) {
2512                                 ooh323_destroy (h323);
2513                         }
2514                         h323 = h323_next;
2515                 }
2516                 ast_mutex_unlock(&iflock);
2517                 pthread_testcancel();
2518                 /* Wait for sched or io */
2519                 res = ast_sched_wait(sched);
2520                 if ((res < 0) || (res > 1000)) {
2521                         res = 1000;
2522                 }
2523                 res = ast_io_wait(io, res);
2524                 pthread_testcancel();
2525                 ast_mutex_lock(&monlock);
2526                 if (res >= 0) {
2527                         ast_sched_runq(sched);
2528                 }
2529                 ast_mutex_unlock(&monlock);
2530         }
2531         /* Never reached */
2532         return NULL;
2533 }
2534
2535 int restart_monitor(void)
2536 {
2537         pthread_attr_t attr;
2538
2539         /* If we're supposed to be stopped -- stay stopped */
2540         if (monitor_thread == AST_PTHREADT_STOP)
2541                 return 0;
2542         if (ast_mutex_lock(&monlock)) {
2543                 ast_log(LOG_WARNING, "Unable to lock monitor\n");
2544                 return -1;
2545         }
2546         if (monitor_thread == pthread_self()) {
2547                 ast_mutex_unlock(&monlock);
2548                 ast_log(LOG_WARNING, "Cannot kill myself\n");
2549                 return -1;
2550         }
2551         if (monitor_thread != AST_PTHREADT_NULL) {
2552                 /* Wake up the thread */
2553                 pthread_kill(monitor_thread, SIGURG);
2554         } else {
2555                 pthread_attr_init(&attr);
2556                 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2557                 /* Start a new monitor */
2558                 if (ast_pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
2559                         ast_mutex_unlock(&monlock);
2560                         ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
2561                         return -1;
2562                 }
2563         }
2564         ast_mutex_unlock(&monlock);
2565         return 0;
2566 }
2567
2568
2569
2570 int ooh323_destroy(struct ooh323_pvt *p)
2571 {
2572         /* NOTE: Assumes iflock already acquired */
2573         struct ooh323_pvt *prev = NULL, *cur = NULL;
2574
2575
2576         if (gH323Debug) {
2577                 ast_verbose("---   ooh323_destroy \n");
2578
2579                 if (p)
2580                         ast_verbose(" Destroying %s\n", p->username);
2581         }
2582
2583         cur = iflist;
2584         while (cur) {
2585                 if (cur == p) { break; }
2586                 prev = cur;
2587                 cur = cur->next;
2588         }
2589
2590         if (cur) {
2591                 ast_mutex_lock(&cur->lock);
2592                 if (prev)
2593                         prev->next = cur->next;
2594                 else
2595                         iflist = cur->next;
2596
2597                 if (cur->callToken) {
2598                         free(cur->callToken);
2599                         cur->callToken = 0;
2600                 }
2601
2602                 if (cur->username) {
2603                         free(cur->username);
2604                         cur->username = 0;
2605                 }
2606
2607                 if (cur->host) {
2608                         free(cur->host);
2609                         cur->host = 0;
2610                 }
2611
2612                 if (cur->callerid_name) {
2613                         free(cur->callerid_name);
2614                         cur->callerid_name = 0;
2615                 }
2616                 
2617                 if (cur->callerid_num) {
2618                         free(cur->callerid_num);
2619                         cur->callerid_num = 0;
2620                 }
2621
2622
2623                 if (cur->rtp) {
2624                         ast_rtp_destroy(cur->rtp);
2625                         cur->rtp = 0;
2626                 }
2627         
2628                 /* Unlink us from the owner if we have one */
2629                 if (cur->owner) {
2630                         ast_channel_lock(cur->owner);
2631                         ast_debug(1, "Detaching from %s\n", cur->owner->name);
2632                         cur->owner->tech_pvt = NULL;
2633                         ast_channel_unlock(cur->owner);
2634                         cur->owner = NULL;
2635                 }
2636   
2637                 if (cur->vad) {
2638                         ast_dsp_free(cur->vad);
2639                         cur->vad = NULL;
2640                 }
2641                 ast_mutex_unlock(&cur->lock);
2642                 ast_mutex_destroy(&cur->lock);
2643
2644                 free(cur);
2645         }
2646
2647         if (gH323Debug)
2648                 ast_verbose("+++   ooh323_destroy\n");
2649
2650         return 0;
2651 }
2652
2653 int delete_peers()
2654 {
2655         struct ooh323_peer *cur = NULL, *prev = NULL;
2656         ast_mutex_lock(&peerl.lock);
2657         cur = peerl.peers;
2658         while (cur) {
2659                 prev = cur;
2660                 cur = cur->next;
2661
2662                 ast_mutex_destroy(&prev->lock);
2663                 if (prev->h323id)
2664                         free(prev->h323id);
2665                 if (prev->email)
2666                         free(prev->email);
2667                 if (prev->url)
2668                         free(prev->url);
2669                 if (prev->e164)
2670                         free(prev->e164);
2671                 free(prev);
2672
2673                 if (cur == peerl.peers) {
2674                         break;
2675                 }
2676         }
2677         peerl.peers = NULL;
2678         ast_mutex_unlock(&peerl.lock);
2679         return 0;
2680 }
2681
2682 int delete_users()
2683 {
2684         struct ooh323_user *cur = NULL, *prev = NULL;
2685         ast_mutex_lock(&userl.lock);
2686         cur = userl.users;
2687         while (cur) {
2688                 prev = cur;
2689                 cur = cur->next;
2690                 ast_mutex_destroy(&prev->lock);
2691                 free(prev);
2692                 if (cur == userl.users) {
2693                         break;
2694                 }
2695         }
2696         userl.users = NULL;
2697         ast_mutex_unlock(&userl.lock);
2698         return 0;
2699 }
2700   
2701 static int unload_module(void)
2702 {
2703         struct ooh323_pvt *p;
2704         struct ooAliases *cur = NULL, *prev = NULL;
2705
2706         if (gH323Debug) {
2707                 ast_verbose("--- ooh323  unload_module \n");
2708         }
2709         /* First, take us out of the channel loop */
2710         ast_cli_unregister_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry));
2711         ast_rtp_proto_unregister(&ooh323_rtp);
2712         ast_channel_unregister(&ooh323_tech);
2713
2714 #if 0
2715         ast_unregister_atexit(&ast_ooh323c_exit);
2716 #endif
2717
2718         if (gH323Debug) {
2719                 ast_verbose("  unload_module - hanging up all interfaces\n");
2720         }
2721         if (!ast_mutex_lock(&iflock)) {
2722                 /* Hangup all interfaces if they have an owner */
2723                 p = iflist;
2724                 while (p) {
2725                         if (p->owner) {
2726                                 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
2727                         }
2728                         p = p->next;
2729                 }
2730                 iflist = NULL;
2731                 ast_mutex_unlock(&iflock);
2732         } else {
2733                 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
2734                 return -1;
2735         }
2736
2737
2738         if (gH323Debug) {
2739                 ast_verbose("  unload_module - stopping monitor thread\n");
2740         }  
2741         if (monitor_thread != AST_PTHREADT_NULL) {
2742                 if (!ast_mutex_lock(&monlock)) {
2743                         if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
2744                                 pthread_cancel(monitor_thread);
2745                                 pthread_kill(monitor_thread, SIGURG);
2746                                 pthread_join(monitor_thread, NULL);
2747                         }
2748                         monitor_thread = AST_PTHREADT_STOP;
2749                         ast_mutex_unlock(&monlock);
2750                 } else {
2751                         ast_log(LOG_WARNING, "Unable to lock the monitor\n");
2752                         return -1;
2753                 }
2754         }
2755
2756
2757         if (gH323Debug) {
2758                 ast_verbose("   unload_module - stopping stack thread\n");
2759         }
2760         ooh323c_stop_stack_thread();
2761
2762
2763         if (gH323Debug) {
2764                 ast_verbose("   unload_module - freeing up memory used by interfaces\n");
2765         }
2766         if (!ast_mutex_lock(&iflock)) {
2767                 struct ooh323_pvt *pl;
2768
2769                 /* Destroy all the interfaces and free their memory */
2770                 p = iflist;
2771                 while (p) {
2772                         pl = p;
2773                         p = p->next;
2774                         /* Free associated memory */
2775                         ooh323_destroy(pl);
2776                 }
2777                 iflist = NULL;
2778                 ast_mutex_unlock(&iflock);
2779         } else {
2780                 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
2781                 return -1;
2782         }
2783  
2784
2785         if (gH323Debug) {
2786                 ast_verbose("  unload_module - deleting users\n");
2787         }
2788         delete_users();
2789
2790
2791         if (gH323Debug) {
2792                 ast_verbose("  unload_module - deleting peers\n");
2793         }
2794         delete_peers();
2795
2796
2797         if (gH323Debug) {
2798                 ast_verbose("  unload_module - Freeing up alias list\n");
2799         }
2800         cur = gAliasList;
2801         while (cur) {
2802           prev = cur;
2803           cur = cur->next;
2804           free(prev->value);
2805           free(prev);
2806         }
2807         gAliasList = NULL;
2808
2809
2810         if (gH323Debug) {
2811                 ast_verbose("   unload_module- destroying OOH323 endpoint \n");
2812         }
2813         ooH323EpDestroy();
2814
2815         if (gH323Debug) {
2816                 ast_verbose("+++ ooh323  unload_module \n");    
2817         }
2818
2819         return 0;
2820 }
2821
2822
2823
2824 static enum ast_rtp_get_result ooh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
2825 {
2826         struct ooh323_pvt *p = NULL;
2827         enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
2828
2829         if (!(p = (struct ooh323_pvt *) chan->tech_pvt))
2830         return AST_RTP_GET_FAILED;
2831
2832         *rtp = p->rtp;
2833
2834         if (!(p->rtp)) {
2835                 return AST_RTP_GET_FAILED;
2836         }
2837         res = AST_RTP_TRY_NATIVE;
2838
2839         return res;
2840 }
2841
2842 static enum ast_rtp_get_result ooh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
2843 {
2844         struct ooh323_pvt *p = NULL;
2845         enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
2846
2847         if (!(p = (struct ooh323_pvt *) chan->tech_pvt))
2848                 return AST_RTP_GET_FAILED;
2849
2850         *rtp = p->vrtp;
2851
2852         if (!(p->rtp)) {
2853                 return AST_RTP_GET_FAILED;
2854         }
2855         res = AST_RTP_TRY_NATIVE;
2856
2857         return res;
2858 }
2859
2860
2861 int ooh323_update_capPrefsOrderForCall
2862         (ooCallData *call, struct ast_codec_pref *prefs)
2863 {
2864         int i = 0;
2865         int codec = ast_codec_pref_index(prefs, i);
2866
2867         ooResetCapPrefs(call);
2868         while (codec) {
2869                 ooAppendCapToCapPrefs(call, ooh323_convertAsteriskCapToH323Cap(codec));
2870                 codec = ast_codec_pref_index(prefs, ++i);
2871         }
2872
2873         return 0;
2874 }
2875
2876
2877 int ooh323_convertAsteriskCapToH323Cap(int cap)
2878 {
2879         char formats[512];
2880         switch (cap) {
2881         case AST_FORMAT_ULAW:
2882                 return OO_G711ULAW64K;
2883         case AST_FORMAT_ALAW:
2884                 return OO_G711ALAW64K;
2885         case AST_FORMAT_GSM:
2886                 return OO_GSMFULLRATE;
2887         case AST_FORMAT_G729A:
2888                 return OO_G729A;
2889         case AST_FORMAT_G723_1:
2890                 return OO_G7231;
2891         case AST_FORMAT_H263:
2892                 return OO_H263VIDEO;
2893         default:
2894                 ast_log(LOG_NOTICE, "Don't know how to deal with mode %s\n", 
2895                                                         ast_getformatname_multiple(formats, sizeof(formats), cap));
2896                 return -1;
2897         }
2898 }
2899
2900 static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
2901          struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
2902 {
2903         /* XXX Deal with Video */
2904         struct ooh323_pvt *p;
2905         struct sockaddr_in them;
2906         struct sockaddr_in us;
2907         int mode;
2908
2909         if (gH323Debug)
2910                 ast_verbose("---   ooh323_set_peer - %s\n", chan->name);
2911
2912         if (!rtp) {
2913                 return 0;
2914         }
2915
2916         mode = ooh323_convertAsteriskCapToH323Cap(chan->writeformat); 
2917         p = (struct ooh323_pvt *) chan->tech_pvt;
2918         if (!p) {
2919                 ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
2920                 return -1;
2921         }
2922         ast_rtp_get_peer(rtp, &them);
2923         ast_rtp_get_us(rtp, &us);
2924         return 0;
2925 }
2926
2927
2928
2929
2930 int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
2931 {
2932         struct sockaddr_in us;
2933         ooMediaInfo mediaInfo;
2934         int x, format = 0;        
2935
2936         if (gH323Debug)
2937                 ast_verbose("---   configure_local_rtp\n");
2938
2939         if (p->rtp) {
2940                 ast_rtp_codec_setpref(p->rtp, &p->prefs);
2941         }
2942
2943         /* figure out our local RTP port and tell the H.323 stack about it*/
2944         ast_rtp_get_us(p->rtp, &us);
2945
2946         ast_copy_string(mediaInfo.lMediaIP, ast_inet_ntoa(us.sin_addr), sizeof(mediaInfo.lMediaIP));
2947         mediaInfo.lMediaPort = ntohs(us.sin_port);
2948         mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort +1;
2949         for (x = 0; 0 != (format = ast_codec_pref_index(&p->prefs, x)); x++) {
2950                 strcpy(mediaInfo.dir, "transmit");
2951                 mediaInfo.cap = ooh323_convertAsteriskCapToH323Cap(format);
2952                 ooAddMediaInfo(call, mediaInfo);
2953                 strcpy(mediaInfo.dir, "receive");
2954                 ooAddMediaInfo(call, mediaInfo);
2955                 if (mediaInfo.cap == OO_G729A) {
2956                         strcpy(mediaInfo.dir, "transmit");
2957                         mediaInfo.cap = OO_G729;
2958                         ooAddMediaInfo(call, mediaInfo);
2959                         strcpy(mediaInfo.dir, "receive");
2960                         ooAddMediaInfo(call, mediaInfo);
2961                 }
2962         }
2963
2964         if (gH323Debug)
2965                 ast_verbose("+++   configure_local_rtp\n");
2966
2967         return 1;
2968 }
2969
2970 void setup_rtp_connection(ooCallData *call, const char *remoteIp, 
2971                                                                   int remotePort)
2972 {
2973         struct ooh323_pvt *p = NULL;
2974         struct sockaddr_in them;
2975
2976         if (gH323Debug)
2977                 ast_verbose("---   setup_rtp_connection\n");
2978
2979         /* Find the call or allocate a private structure if call not found */
2980         p = find_call(call); 
2981
2982         if (!p) {
2983                 ast_log(LOG_ERROR, "Something is wrong: rtp\n");
2984                 return;
2985         }
2986
2987         them.sin_family = AF_INET;
2988         them.sin_addr.s_addr = inet_addr(remoteIp); /* only works for IPv4 */
2989         them.sin_port = htons(remotePort);
2990         ast_rtp_set_peer(p->rtp, &them);
2991
2992         if (gH323Debug) {
2993                 ast_verbose("+++   setup_rtp_connection\n");
2994         }
2995
2996         return;
2997 }
2998
2999 void close_rtp_connection(ooCallData *call)
3000 {
3001         struct ooh323_pvt *p = NULL;
3002
3003         if (gH323Debug) {
3004                 ast_verbose("---   close_rtp_connection\n");
3005         }
3006
3007         p = find_call(call);
3008         if (!p) {
3009                 ast_log(LOG_ERROR, "Couldn't find matching call to close rtp connection\n");
3010                 return;
3011         }
3012         ast_mutex_lock(&p->lock);
3013         if (p->rtp) {
3014                 ast_rtp_stop(p->rtp);
3015         }
3016         ast_mutex_unlock(&p->lock);
3017
3018         if (gH323Debug) {
3019                 ast_verbose("+++   close_rtp_connection\n");
3020         }
3021
3022         return;
3023 }
3024
3025
3026 int update_our_aliases(ooCallData *call, struct ooh323_pvt *p)
3027 {
3028         int updated = -1;
3029         ooAliases *psAlias = NULL;
3030         
3031         if (!call->ourAliases)
3032                 return updated;
3033         for (psAlias = call->ourAliases; psAlias; psAlias = psAlias->next) {
3034                 if (psAlias->type == T_H225AliasAddress_h323_ID) {
3035                         ast_copy_string(p->callee_h323id, psAlias->value, sizeof(p->callee_h323id));
3036                         updated = 1;
3037                 }
3038                 if (psAlias->type == T_H225AliasAddress_dialedDigits) {
3039                         ast_copy_string(p->callee_dialedDigits, psAlias->value, sizeof(p->callee_dialedDigits));
3040                         updated = 1;
3041                 }
3042                 if (psAlias->type == T_H225AliasAddress_url_ID) {
3043                         ast_copy_string(p->callee_url, psAlias->value, sizeof(p->callee_url));
3044                         updated = 1;
3045                 }
3046                 if (psAlias->type == T_H225AliasAddress_email_ID) {
3047                         ast_copy_string(p->callee_email, psAlias->value, sizeof(p->callee_email));
3048                         updated = 1;
3049                 }
3050         }
3051         return updated;
3052 }
3053
3054 struct ast_frame *ooh323_rtp_read(struct ast_channel *ast, struct ooh323_pvt *p)
3055 {
3056         /* Retrieve audio/etc from channel.  Assumes p->lock is already held. */
3057         struct ast_frame *f;
3058         static struct ast_frame null_frame = { AST_FRAME_NULL, };
3059         switch (ast->fdno) {
3060         case 0:
3061                 f = ast_rtp_read(p->rtp);       /* RTP Audio */
3062                 break;
3063         case 1:
3064                 f = ast_rtcp_read(p->rtp);      /* RTCP Control Channel */
3065                 break;
3066         case 2:
3067                 f = ast_rtp_read(p->vrtp);      /* RTP Video */
3068                 break;
3069         case 3:
3070                 f = ast_rtcp_read(p->vrtp);     /* RTCP Control Channel for video */
3071                 break;
3072         default:
3073                 f = &null_frame;
3074         }
3075         /* Don't send RFC2833 if we're not supposed to */
3076         if (f && (f->frametype == AST_FRAME_DTMF) && !(p->dtmfmode & H323_DTMF_RFC2833)) {
3077                 return &null_frame;
3078         }
3079         if (p->owner) {
3080                 /* We already hold the channel lock */
3081                 if (f->frametype == AST_FRAME_VOICE) {
3082                         if (f->subclass != p->owner->nativeformats) {
3083                                 ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
3084                                 p->owner->nativeformats = f->subclass;
3085                                 ast_set_read_format(p->owner, p->owner->readformat);
3086                                 ast_set_write_format(p->owner, p->owner->writeformat);
3087                         }
3088                         if ((p->dtmfmode & H323_DTMF_INBAND) && p->vad) {
3089                                 f = ast_dsp_process(p->owner, p->vad, f);
3090                                 if (f && (f->frametype == AST_FRAME_DTMF)) {
3091                                         ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass);
3092                                 }
3093                         }
3094                 }
3095         }
3096         return f;
3097 }
3098
3099
3100 int ooh323_convert_hangupcause_asteriskToH323(int cause)
3101 {
3102         switch (cause) {
3103         case AST_CAUSE_CALL_REJECTED:
3104                 return OO_REASON_REMOTE_REJECTED;
3105         case AST_CAUSE_UNALLOCATED:
3106                 return OO_REASON_NOUSER;
3107         case AST_CAUSE_BUSY:
3108                 return OO_REASON_REMOTE_BUSY;
3109         case AST_CAUSE_BEARERCAPABILITY_NOTAVAIL:
3110                 return OO_REASON_NOCOMMON_CAPABILITIES;
3111         case AST_CAUSE_CONGESTION:
3112                 return OO_REASON_REMOTE_BUSY;
3113         case AST_CAUSE_NO_ANSWER:
3114                 return OO_REASON_REMOTE_NOANSWER;
3115         case AST_CAUSE_NORMAL:
3116                 return OO_REASON_REMOTE_CLEARED;
3117         case AST_CAUSE_FAILURE:
3118         default:
3119                 return OO_REASON_UNKNOWN;
3120         }
3121
3122         return 0;
3123 }
3124
3125 int ooh323_convert_hangupcause_h323ToAsterisk(int cause)
3126 {
3127         switch (cause) {
3128         case OO_REASON_REMOTE_REJECTED:
3129                 return AST_CAUSE_CALL_REJECTED;
3130         case OO_REASON_NOUSER: 
3131                 return AST_CAUSE_UNALLOCATED;
3132         case OO_REASON_REMOTE_BUSY:
3133         case OO_REASON_LOCAL_BUSY:
3134                 return AST_CAUSE_BUSY;
3135         case OO_REASON_NOCOMMON_CAPABILITIES:   /* No codecs approved */
3136                 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
3137         case OO_REASON_REMOTE_CONGESTED:
3138         case OO_REASON_LOCAL_CONGESTED:
3139                 return AST_CAUSE_CONGESTION;
3140         case OO_REASON_REMOTE_NOANSWER:
3141                 return AST_CAUSE_NO_ANSWER;
3142         case OO_REASON_UNKNOWN: 
3143         case OO_REASON_INVALIDMESSAGE:
3144         case OO_REASON_TRANSPORTFAILURE:
3145                 return AST_CAUSE_FAILURE;
3146         case OO_REASON_REMOTE_CLEARED:
3147                 return AST_CAUSE_NORMAL;
3148         default:
3149                 return AST_CAUSE_NORMAL;
3150         }
3151         /* Never reached */
3152         return 0;
3153 }
3154
3155 #if 0
3156 void ast_ooh323c_exit()
3157 {
3158         ooGkClientDestroy();
3159 }
3160 #endif
3161
3162 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Objective Systems H323 Channel");