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