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