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