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