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