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