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