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