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