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