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