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