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