Merged revisions 313142 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         int res = -1;
1197
1198         if (!p) return -1;
1199
1200         ast_mutex_lock(&p->lock);
1201         callToken = (p->callToken ? strdup(p->callToken) : NULL);
1202         ast_mutex_unlock(&p->lock);
1203
1204         if (!callToken) {
1205                 if (gH323Debug)
1206                         ast_verbose("   ooh323_indicate - No callToken\n");
1207                 return -1;
1208         }
1209
1210         if (gH323Debug)
1211                 ast_verbose("----- ooh323_indicate %d on call %s\n", condition, callToken);
1212
1213         ast_mutex_lock(&p->lock);
1214         switch (condition) {
1215         case AST_CONTROL_CONGESTION:
1216                 if (!ast_test_flag(p, H323_ALREADYGONE)) {
1217                         ooHangCall(callToken, OO_REASON_LOCAL_CONGESTED,
1218                                                 AST_CAUSE_SWITCH_CONGESTION);
1219                         ast_set_flag(p, H323_ALREADYGONE);
1220                 }
1221                 break;
1222         case AST_CONTROL_BUSY:
1223                 if (!ast_test_flag(p, H323_ALREADYGONE)) {
1224                         ooHangCall(callToken, OO_REASON_LOCAL_BUSY, AST_CAUSE_USER_BUSY);
1225                         ast_set_flag(p, H323_ALREADYGONE);
1226                 }
1227                 break;
1228         case AST_CONTROL_HOLD:
1229                 ast_moh_start(ast, data, NULL);
1230                 break;
1231         case AST_CONTROL_UNHOLD:
1232                 ast_moh_stop(ast);
1233                 break;
1234         case AST_CONTROL_PROGRESS:
1235                 if (ast->_state != AST_STATE_UP) {
1236                         if (!p->progsent) {
1237                                 if (gH323Debug) {
1238                                         ast_debug(1, "Sending manual progress for %s, res = %d\n", callToken,
1239                                         ooManualProgress(callToken));
1240                                 } else {
1241                                         ooManualProgress(callToken);
1242                                 }
1243                                 p->progsent = 1;
1244                         }
1245                 }
1246             break;
1247       case AST_CONTROL_RINGING:
1248                 if (ast->_state == AST_STATE_RING || ast->_state == AST_STATE_RINGING) {
1249                         if (!p->alertsent) {
1250                                 if (gH323Debug) {
1251                                         ast_debug(1, "Sending manual ringback for %s, res = %d\n",
1252                                                 callToken,
1253                                                 ooManualRingback(callToken));
1254                                 } else {
1255                                         ooManualRingback(callToken);
1256                                 }
1257                                 p->alertsent = 1;
1258                         }
1259                 }
1260          break;
1261         case AST_CONTROL_SRCUPDATE:
1262                 if (p->rtp) {
1263                         ast_rtp_instance_update_source(p->rtp);
1264                 }
1265                 break;
1266         case AST_CONTROL_SRCCHANGE:
1267                 if (p->rtp) {
1268                         ast_rtp_instance_change_source(p->rtp);
1269                 }
1270                 break;
1271         case AST_CONTROL_CONNECTED_LINE:
1272                 if (!ast->connected.id.name.valid
1273                         || ast_strlen_zero(ast->connected.id.name.str)) {
1274                         break;
1275                 }
1276                 if (gH323Debug) {
1277                         ast_debug(1, "Sending connected line info for %s (%s)\n",
1278                                 callToken, ast->connected.id.name.str);
1279                 }
1280                 ooSetANI(callToken, ast->connected.id.name.str);
1281                 break;
1282
1283       case AST_CONTROL_T38_PARAMETERS:
1284                 if (p->t38support != T38_ENABLED) {
1285                         struct ast_control_t38_parameters parameters = { .request_response = 0 };
1286                         parameters.request_response = AST_T38_REFUSED;
1287                         ast_queue_control_data(ast, AST_CONTROL_T38_PARAMETERS,
1288                                                  &parameters, sizeof(parameters));
1289                         break;
1290                 }
1291                 if (datalen != sizeof(struct ast_control_t38_parameters)) {
1292                         ast_log(LOG_ERROR, "Invalid datalen for AST_CONTROL_T38. "
1293                                            "Expected %d, got %d\n",
1294                                 (int)sizeof(enum ast_control_t38), (int)datalen);
1295                 } else {
1296                         const struct ast_control_t38_parameters *parameters = data;
1297                         enum ast_control_t38 message = parameters->request_response;
1298                         switch (message) {
1299
1300                         case AST_T38_REQUEST_NEGOTIATE:
1301
1302                                 if (!p->chmodepend && !p->faxmode) {
1303                                         ooRequestChangeMode(p->callToken, 1);
1304                                         p->chmodepend = 1;
1305                                         res = 0;
1306                                 }
1307                                 break;
1308
1309                         case AST_T38_REQUEST_TERMINATE:
1310
1311                                 if (!p->chmodepend && p->faxmode) {
1312                                         ooRequestChangeMode(p->callToken, 0);
1313                                         p->chmodepend = 1;
1314                                         res = 0;
1315                                 }
1316                                 break;
1317
1318
1319                         default:
1320                                 ;
1321
1322                         }
1323
1324                 }
1325                 break;
1326       case AST_CONTROL_PROCEEDING:
1327         case -1:
1328                 break;
1329         default:
1330                 ast_log(LOG_WARNING, "Don't know how to indicate condition %d on %s\n",
1331                                                                         condition, callToken);
1332         }
1333
1334         ast_mutex_unlock(&p->lock);
1335
1336         if (gH323Debug)
1337                 ast_verbose("++++  ooh323_indicate %d on %s\n", condition, callToken);
1338
1339         free(callToken);
1340         return res;
1341 }
1342
1343 static int ooh323_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
1344 {
1345
1346         struct ooh323_pvt *p = (struct ooh323_pvt *) ast->tech_pvt;
1347         int res = -1;
1348         enum ast_t38_state state = T38_STATE_UNAVAILABLE;
1349         char* cp;
1350
1351         if (!p) return -1;
1352
1353         ast_mutex_lock(&p->lock);
1354
1355         if (gH323Debug)
1356                 ast_verbose("----- ooh323_queryoption %d on channel %s\n", option, ast->name);
1357          
1358         switch (option) {
1359
1360                 case AST_OPTION_T38_STATE:
1361
1362                         if (*datalen != sizeof(enum ast_t38_state)) {
1363                                 ast_log(LOG_ERROR, "Invalid datalen for AST_OPTION_T38_STATE option."
1364                                 " Expected %d, got %d\n", (int)sizeof(enum ast_t38_state), *datalen);
1365                                 break;
1366                         }
1367                         if (p->t38support != T38_DISABLED)
1368                                 state = T38_STATE_UNKNOWN;
1369                         if (p->faxmode)
1370                                 state = (p->chmodepend) ? T38_STATE_UNKNOWN : T38_STATE_NEGOTIATED;
1371                         else if (p->chmodepend)
1372                                 state = T38_STATE_NEGOTIATING;
1373
1374
1375                         *((enum ast_t38_state *) data) = state;
1376                         res = 0;
1377                         break;
1378
1379
1380                 case AST_OPTION_DIGIT_DETECT:
1381
1382                         cp = (char *) data;
1383                         *cp = p->vad ? 1 : 0;
1384                         ast_debug(1, "Reporting digit detection %sabled on %s\n",
1385                                                          *cp ? "en" : "dis", ast->name);
1386
1387                         res = 0;
1388                         break;
1389
1390                 default:        ;
1391
1392         }
1393
1394         if (gH323Debug)
1395                 ast_verbose("+++++ ooh323_queryoption %d on channel %s\n", option, ast->name);
1396
1397         ast_mutex_unlock(&p->lock);
1398
1399         return res;
1400 }
1401
1402
1403
1404 static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
1405 {
1406         struct ooh323_pvt *p = newchan->tech_pvt;
1407
1408         if (!p) return -1;
1409
1410         if (gH323Debug)
1411                 ast_verbose("--- ooh323c ooh323_fixup\n");
1412
1413         ast_mutex_lock(&p->lock);
1414         if (p->owner != oldchan) {
1415                 ast_log(LOG_WARNING, "Old channel wasn't %p but was %p\n", oldchan, p->owner);
1416                 ast_mutex_unlock(&p->lock);
1417                 return -1;
1418         }
1419
1420         if (p->owner == oldchan) {
1421                 p->owner = newchan;
1422         } else {
1423                 p->owner = oldchan;
1424         }
1425
1426         ast_mutex_unlock(&p->lock);
1427
1428         if (gH323Debug)
1429                 ast_verbose("+++ ooh323c ooh323_fixup \n");
1430
1431         return 0;
1432 }
1433
1434
1435 void ooh323_set_write_format(ooCallData *call, struct ast_format *fmt, int txframes)
1436 {
1437         struct ooh323_pvt *p = NULL;
1438         char formats[FORMAT_STRING_SIZE];
1439
1440         if (gH323Debug)
1441                 ast_verbose("---   ooh323_update_writeformat %s/%d\n",
1442                                 ast_getformatname(fmt), txframes);
1443
1444         p = find_call(call);
1445         if (!p) {
1446                 ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
1447                 return;
1448         }
1449
1450         ast_mutex_lock(&p->lock);
1451
1452         ast_format_copy(&(p->writeformat), fmt);
1453
1454         if (p->owner) {
1455                 while (p->owner && ast_channel_trylock(p->owner)) {
1456                         ast_debug(1, "Failed to grab lock, trying again\n");
1457                         DEADLOCK_AVOIDANCE(&p->lock);
1458                 }
1459                 if (!p->owner) {
1460                         ast_mutex_unlock(&p->lock);
1461                         ast_log(LOG_ERROR, "Channel has no owner\n");
1462                         return;
1463                 }
1464                 if (gH323Debug)
1465                         ast_verbose("Writeformat before update %s/%s\n",
1466                           ast_getformatname(&p->owner->writeformat),
1467                           ast_getformatname_multiple(formats, sizeof(formats), p->owner->nativeformats));
1468                 if (txframes)
1469                         ast_codec_pref_setsize(&p->prefs, fmt, txframes);
1470                 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &p->prefs);
1471                 if (p->dtmfmode & H323_DTMF_RFC2833 && p->dtmfcodec) {
1472                         ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
1473                                  p->rtp, p->dtmfcodec, "audio", "telephone-event", 0);
1474                 }
1475                 if (p->dtmfmode & H323_DTMF_CISCO && p->dtmfcodec) {
1476                         ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
1477                                  p->rtp, p->dtmfcodec, "audio", "cisco-telephone-event", 0);
1478                 }
1479
1480                 ast_format_cap_set(p->owner->nativeformats, fmt);
1481                 ast_set_write_format(p->owner, &p->owner->writeformat);
1482                 ast_set_read_format(p->owner, &p->owner->readformat);
1483                 ast_channel_unlock(p->owner);
1484         } else
1485                 ast_log(LOG_ERROR, "No owner found\n");
1486
1487
1488         ast_mutex_unlock(&p->lock);
1489
1490         if (gH323Debug)
1491                 ast_verbose("+++   ooh323_update_writeformat\n");
1492 }
1493
1494 void ooh323_set_read_format(ooCallData *call, struct ast_format *fmt)
1495 {
1496         struct ooh323_pvt *p = NULL;
1497
1498         if (gH323Debug)
1499                 ast_verbose("---   ooh323_update_readformat %s\n", 
1500                                 ast_getformatname(fmt));
1501
1502         p = find_call(call);
1503         if (!p) {
1504                 ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
1505                 return;
1506         }
1507
1508         ast_mutex_lock(&p->lock);
1509
1510         ast_format_copy(&(p->readformat), fmt);
1511
1512         if (p->owner) {
1513                 while (p->owner && ast_channel_trylock(p->owner)) {
1514                         ast_debug(1, "Failed to grab lock, trying again\n");
1515                         DEADLOCK_AVOIDANCE(&p->lock);
1516                 }
1517                 if (!p->owner) {
1518                         ast_mutex_unlock(&p->lock);
1519                         ast_log(LOG_ERROR, "Channel has no owner\n");
1520                         return;
1521                 }
1522
1523                 if (gH323Debug)
1524                         ast_verbose("Readformat before update %s\n",
1525                                   ast_getformatname(&p->owner->readformat));
1526                 ast_format_cap_set(p->owner->nativeformats, fmt);
1527                 ast_set_read_format(p->owner, &p->owner->readformat);
1528                 ast_channel_unlock(p->owner);
1529         } else
1530                 ast_log(LOG_ERROR, "No owner found\n");
1531
1532         ast_mutex_unlock(&p->lock);
1533
1534         if (gH323Debug)
1535                 ast_verbose("+++   ooh323_update_readformat\n");
1536 }
1537
1538
1539 int onAlerting(ooCallData *call)
1540 {
1541         struct ooh323_pvt *p = NULL;
1542         struct ast_channel *c = NULL;
1543
1544         if (gH323Debug)
1545                 ast_verbose("--- onAlerting %s\n", call->callToken);
1546
1547         p = find_call(call);
1548
1549         if(!p) {
1550                 ast_log(LOG_ERROR, "No matching call found\n");
1551                 return -1;
1552         }
1553         ast_mutex_lock(&p->lock);
1554         if (!p->owner) {
1555                 ast_mutex_unlock(&p->lock);
1556                 ast_log(LOG_ERROR, "Channel has no owner\n");
1557                 return 0;
1558         }
1559         while (p->owner && ast_channel_trylock(p->owner)) {
1560                 ast_debug(1, "Failed to grab lock, trying again\n");
1561                 DEADLOCK_AVOIDANCE(&p->lock);
1562         }
1563         if (!p->owner) {
1564                 ast_mutex_unlock(&p->lock);
1565                 ast_log(LOG_ERROR, "Channel has no owner\n");
1566                 return 0;
1567         }
1568         c = p->owner;
1569
1570         if (call->remoteDisplayName) {
1571                 struct ast_party_connected_line connected;
1572                 struct ast_set_party_connected_line update_connected;
1573
1574                 memset(&update_connected, 0, sizeof(update_connected));
1575                 update_connected.id.name = 1;
1576                 ast_party_connected_line_init(&connected);
1577                 connected.id.name.valid = 1;
1578                 connected.id.name.str = (char *) call->remoteDisplayName;
1579                 connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
1580                 ast_channel_queue_connected_line_update(c, &connected, &update_connected);
1581         }
1582         if (c->_state != AST_STATE_UP)
1583                 ast_setstate(c, AST_STATE_RINGING);
1584
1585         ast_queue_control(c, AST_CONTROL_RINGING);
1586         ast_channel_unlock(c);
1587         ast_mutex_unlock(&p->lock);
1588
1589         if (gH323Debug)
1590                 ast_verbose("+++ onAlerting %s\n", call->callToken);
1591
1592         return OO_OK;
1593 }
1594
1595 int onProgress(ooCallData *call)
1596 {
1597         struct ooh323_pvt *p = NULL;
1598         struct ast_channel *c = NULL;
1599
1600         if (gH323Debug)
1601                 ast_verbose("--- onProgress %s\n", call->callToken);
1602
1603         p = find_call(call);
1604
1605         if(!p) {
1606                 ast_log(LOG_ERROR, "No matching call found\n");
1607                 return -1;
1608         }
1609         ast_mutex_lock(&p->lock);
1610         if (!p->owner) {
1611                 ast_mutex_unlock(&p->lock);
1612                 ast_log(LOG_ERROR, "Channel has no owner\n");
1613                 return 0;
1614         }
1615         while (p->owner && ast_channel_trylock(p->owner)) {
1616                 ast_debug(1, "Failed to grab lock, trying again\n");
1617                 DEADLOCK_AVOIDANCE(&p->lock);
1618         }
1619         if (!p->owner) {
1620                 ast_mutex_unlock(&p->lock);
1621                 ast_log(LOG_ERROR, "Channel has no owner\n");
1622                 return 0;
1623         }
1624         c = p->owner;
1625
1626         if (call->remoteDisplayName) {
1627                 struct ast_party_connected_line connected;
1628                 struct ast_set_party_connected_line update_connected;
1629
1630                 memset(&update_connected, 0, sizeof(update_connected));
1631                 update_connected.id.name = 1;
1632                 ast_party_connected_line_init(&connected);
1633                 connected.id.name.valid = 1;
1634                 connected.id.name.str = (char *) call->remoteDisplayName;
1635                 connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
1636                 ast_channel_queue_connected_line_update(c, &connected, &update_connected);
1637         }
1638         if (c->_state != AST_STATE_UP)
1639                 ast_setstate(c, AST_STATE_RINGING);
1640
1641         ast_queue_control(c, AST_CONTROL_PROGRESS);
1642         ast_channel_unlock(c);
1643         ast_mutex_unlock(&p->lock);
1644
1645         if (gH323Debug)
1646                 ast_verbose("+++ onProgress %s\n", call->callToken);
1647
1648         return OO_OK;
1649 }
1650
1651 /**
1652   * Callback for sending digits from H.323 up to asterisk
1653   *
1654   */
1655 int ooh323_onReceivedDigit(OOH323CallData *call, const char *digit)
1656 {
1657         struct ooh323_pvt *p = NULL;
1658         struct ast_frame f;
1659         int res;
1660
1661         ast_debug(1, "Received Digit: %c\n", digit[0]);
1662         p = find_call(call);
1663         if (!p) {
1664                 ast_log(LOG_ERROR, "Failed to find a matching call.\n");
1665                 return -1;
1666         }
1667         if (!p->owner) {
1668                 ast_log(LOG_ERROR, "Channel has no owner\n");
1669                 return -1;
1670         }
1671         ast_mutex_lock(&p->lock);
1672         memset(&f, 0, sizeof(f));
1673         f.frametype = AST_FRAME_DTMF;
1674         f.subclass.integer = digit[0];
1675         f.datalen = 0;
1676         f.samples = 800;
1677         f.offset = 0;
1678         f.data.ptr = NULL;
1679         f.mallocd = 0;
1680         f.src = "SEND_DIGIT";
1681
1682         while (p->owner && ast_channel_trylock(p->owner)) {
1683                 ast_debug(1, "Failed to grab lock, trying again\n");
1684                 DEADLOCK_AVOIDANCE(&p->lock);
1685         }
1686         if (!p->owner) {
1687                 ast_mutex_unlock(&p->lock);
1688                 ast_log(LOG_ERROR, "Channel has no owner\n");
1689                 return 0;
1690         }
1691         res = ast_queue_frame(p->owner, &f);
1692         ast_channel_unlock(p->owner);
1693         ast_mutex_unlock(&p->lock);
1694         return res;
1695 }
1696
1697 int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg)
1698 {
1699         struct ooh323_pvt *p = NULL;
1700         struct ooh323_user *user = NULL;
1701         struct ast_channel *c = NULL;
1702         ooAliases *alias = NULL;
1703         char *at = NULL;
1704         char number [OO_MAX_NUMBER_LENGTH];
1705
1706         if (gH323Debug)
1707                 ast_verbose("---   ooh323_onReceivedSetup %s\n", call->callToken);
1708
1709
1710         if (!(p = ooh323_alloc(call->callReference, call->callToken))) {
1711                 ast_log(LOG_ERROR, "Failed to create a new call.\n");
1712                 return -1;
1713         }
1714         ast_mutex_lock(&p->lock);
1715         ast_clear_flag(p, H323_OUTGOING);
1716   
1717
1718         if (call->remoteDisplayName) {
1719                 p->callerid_name = strdup(call->remoteDisplayName);
1720         }
1721
1722         if (ooCallGetCallingPartyNumber(call, number, OO_MAX_NUMBER_LENGTH) == OO_OK) {
1723                 p->callerid_num = strdup(number);
1724         }
1725
1726         if (call->remoteAliases) {
1727                 for (alias = call->remoteAliases; alias; alias = alias->next) {
1728                         if (alias->type == T_H225AliasAddress_h323_ID) {
1729                                 if (!p->callerid_name) {
1730                                         p->callerid_name = strdup(alias->value);
1731                                 }
1732                                 ast_copy_string(p->caller_h323id, alias->value, sizeof(p->caller_h323id));
1733                                 }
1734          else if(alias->type == T_H225AliasAddress_dialedDigits)
1735          {
1736             if(!p->callerid_num)
1737                p->callerid_num = strdup(alias->value);
1738                                 ast_copy_string(p->caller_dialedDigits, alias->value, 
1739                                                                                                                         sizeof(p->caller_dialedDigits));
1740          }
1741          else if(alias->type == T_H225AliasAddress_email_ID)
1742          {
1743                                 ast_copy_string(p->caller_email, alias->value, sizeof(p->caller_email));
1744          }
1745          else if(alias->type == T_H225AliasAddress_url_ID)
1746          {
1747                                 ast_copy_string(p->caller_url, alias->value, sizeof(p->caller_url));
1748                         }
1749                 }
1750         }
1751
1752         number[0] = '\0';
1753         if(ooCallGetCalledPartyNumber(call, number, OO_MAX_NUMBER_LENGTH)== OO_OK) {
1754                 strncpy(p->exten, number, sizeof(p->exten)-1);
1755         } else {
1756                 update_our_aliases(call, p);
1757                 if (!ast_strlen_zero(p->callee_dialedDigits)) {
1758                         ast_copy_string(p->exten, p->callee_dialedDigits, sizeof(p->exten));
1759                 } else if(!ast_strlen_zero(p->callee_h323id)) {
1760                         ast_copy_string(p->exten, p->callee_h323id, sizeof(p->exten));
1761                 } else if(!ast_strlen_zero(p->callee_email)) {
1762                         ast_copy_string(p->exten, p->callee_email, sizeof(p->exten));
1763                         if ((at = strchr(p->exten, '@'))) {
1764                                 *at = '\0';
1765                         }
1766                 }
1767         }
1768
1769         /* if no extension found, set to default 's' */
1770         if (ast_strlen_zero(p->exten)) {
1771                 p->exten[0]='s';
1772                 p->exten[1]='\0';
1773         }
1774
1775         user = find_user(p->callerid_name, call->remoteIP);
1776         if(user && (user->incominglimit == 0 || user->inUse < user->incominglimit)) {
1777                 ast_mutex_lock(&user->lock);
1778                 p->username = strdup(user->name);
1779                 p->neighbor.user = user->mUseIP ? ast_strdup(user->mIP) :
1780                                                   ast_strdup(user->name);
1781                 ast_copy_string(p->context, user->context, sizeof(p->context));
1782                 ast_copy_string(p->accountcode, user->accountcode, sizeof(p->accountcode));
1783                 p->amaflags = user->amaflags;
1784                 ast_format_cap_copy(p->cap, user->cap);
1785                 p->g729onlyA = user->g729onlyA;
1786                 memcpy(&p->prefs, &user->prefs, sizeof(struct ast_codec_pref));
1787                 p->dtmfmode |= user->dtmfmode;
1788                 p->dtmfcodec = user->dtmfcodec;
1789                 p->t38support = user->t38support;
1790                 p->rtptimeout = user->rtptimeout;
1791                 p->h245tunneling = user->h245tunneling;
1792                 p->faststart = user->faststart;
1793
1794                 if (p->faststart)
1795                         OO_SETFLAG(call->flags, OO_M_FASTSTART);
1796                 else
1797                         OO_CLRFLAG(call->flags, OO_M_FASTSTART);
1798                 /* if we disable h245tun for this user then we clear flag */
1799                 /* in any other case we don't must touch this */
1800                 /* ie if we receive setup without h245tun but enabled
1801                                                 we can't enable it per call */
1802                 if (!p->h245tunneling)
1803                         OO_CLRFLAG(call->flags, OO_M_TUNNELING);
1804
1805                 if (user->rtpmask && user->rtpmaskstr[0]) {
1806                         p->rtpmask = user->rtpmask;
1807                         ast_copy_string(p->rtpmaskstr, user->rtpmaskstr, 
1808                                                          sizeof(p->rtpmaskstr));
1809                 }
1810                 if (user->rtdrcount > 0 && user->rtdrinterval > 0) {
1811                         p->rtdrcount = user->rtdrcount;
1812                         p->rtdrinterval = user->rtdrinterval;
1813                 }
1814                 if (user->incominglimit) user->inUse++;
1815                 ast_mutex_unlock(&user->lock);
1816         } else {
1817          if (!OO_TESTFLAG(p->flags,H323_DISABLEGK)) {
1818                 p->username = strdup(call->remoteIP);
1819         } else {
1820           ast_mutex_unlock(&p->lock);
1821           ast_log(LOG_ERROR, "Unacceptable ip %s\n", call->remoteIP);
1822           if (!user) 
1823            ooHangCall(call->callToken, ooh323_convert_hangupcause_asteriskToH323(AST_CAUSE_CALL_REJECTED), AST_CAUSE_CALL_REJECTED);
1824           else
1825            ooHangCall(call->callToken, ooh323_convert_hangupcause_asteriskToH323(AST_CAUSE_NORMAL_CIRCUIT_CONGESTION), AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
1826           ast_set_flag(p, H323_NEEDDESTROY);
1827           return -1;
1828          }
1829         }
1830
1831         ooh323c_set_capability_for_call(call, &p->prefs, p->cap, p->dtmfmode, p->dtmfcodec,
1832                                          p->t38support, p->g729onlyA);
1833         configure_local_rtp(p, call);
1834
1835 /* Incoming call */
1836         c = ooh323_new(p, AST_STATE_RING, p->username, 0, NULL);
1837         if(!c) {
1838         ast_mutex_unlock(&p->lock);
1839         ast_log(LOG_ERROR, "Could not create ast_channel\n");
1840          return -1;
1841   }
1842         ast_mutex_unlock(&p->lock);
1843
1844         if (gH323Debug)
1845                 ast_verbose("+++   ooh323_onReceivedSetup - Determined context %s, "
1846                                                 "extension %s\n", p->context, p->exten);
1847
1848         return OO_OK;
1849 }
1850
1851
1852
1853 int onOutgoingCall(ooCallData *call)
1854 {
1855         struct ooh323_pvt *p = NULL;
1856         int i = 0;
1857
1858         if (gH323Debug)
1859                 ast_verbose("---   onOutgoingCall %lx: %s\n", (long unsigned int) call, call->callToken);
1860
1861         if (!strcmp(call->callType, "outgoing")) {
1862                 p = find_call(call);
1863                 if (!p) {
1864                         ast_log(LOG_ERROR, "Failed to find a matching call.\n");
1865                         return -1;
1866                 }
1867                 ast_mutex_lock(&p->lock);
1868
1869                 if (!ast_strlen_zero(p->callerid_name)) {
1870                         ooCallSetCallerId(call, p->callerid_name);
1871                 }
1872                 if (!ast_strlen_zero(p->callerid_num)) {
1873                         i = 0;
1874                         while (*(p->callerid_num + i) != '\0') {
1875                                 if(!isdigit(*(p->callerid_num+i))) { break; }
1876                                 i++;
1877                         }
1878                         if(*(p->callerid_num+i) == '\0')
1879                                 ooCallSetCallingPartyNumber(call, p->callerid_num);
1880                         else {
1881                                 if(!p->callerid_name)
1882                                         ooCallSetCallerId(call, p->callerid_num);
1883                         }
1884                 }
1885                 
1886                 if (!ast_strlen_zero(p->caller_h323id))
1887                         ooCallAddAliasH323ID(call, p->caller_h323id);
1888
1889                 if (!ast_strlen_zero(p->caller_dialedDigits)) {
1890                         if (gH323Debug) {
1891                                 ast_verbose("Setting dialed digits %s\n", p->caller_dialedDigits);
1892                         }
1893                         ooCallAddAliasDialedDigits(call, p->caller_dialedDigits);
1894                 } else if (!ast_strlen_zero(p->callerid_num)) {
1895                         if (ooIsDailedDigit(p->callerid_num)) {
1896                                 if (gH323Debug) {
1897                                         ast_verbose("setting callid number %s\n", p->callerid_num);
1898                                 }
1899                                 ooCallAddAliasDialedDigits(call, p->callerid_num);
1900                         } else if (ast_strlen_zero(p->caller_h323id)) {
1901                                 ooCallAddAliasH323ID(call, p->callerid_num);
1902                         }
1903                 }
1904                 if (p->rtpmask && p->rtpmaskstr[0]) {
1905                         call->rtpMask = p->rtpmask;
1906                         ast_mutex_lock(&call->rtpMask->lock);
1907                         call->rtpMask->inuse++;
1908                         ast_mutex_unlock(&call->rtpMask->lock);
1909                         ast_copy_string(call->rtpMaskStr, p->rtpmaskstr, sizeof(call->rtpMaskStr));
1910                 }
1911
1912                 ast_mutex_unlock(&p->lock);
1913         }
1914
1915         if (gH323Debug)
1916                 ast_verbose("+++   onOutgoingCall %s\n", call->callToken);
1917         return OO_OK;
1918 }
1919
1920
1921 int onNewCallCreated(ooCallData *call)
1922 {
1923         struct ooh323_pvt *p = NULL;
1924         int i = 0;
1925
1926         if (gH323Debug)
1927                 ast_verbose("---   onNewCallCreated %lx: %s\n", (long unsigned int) call, call->callToken);
1928
1929         ast_mutex_lock(&call->Lock);
1930         if (ooh323c_start_call_thread(call)) {
1931                 ast_log(LOG_ERROR,"Failed to create call thread.\n");
1932                 ast_mutex_unlock(&call->Lock);
1933                 return -1;
1934         }
1935
1936         if (!strcmp(call->callType, "outgoing")) {
1937                 p = find_call(call);
1938                 if (!p) {
1939                         ast_log(LOG_ERROR, "Failed to find a matching call.\n");
1940                         ast_mutex_unlock(&call->Lock);
1941                         return -1;
1942                 }
1943                 ast_mutex_lock(&p->lock);
1944
1945                 if (!ast_strlen_zero(p->callerid_name)) {
1946                         ooCallSetCallerId(call, p->callerid_name);
1947                 }
1948                 if (!ast_strlen_zero(p->callerid_num)) {
1949                         i = 0;
1950                         while (*(p->callerid_num + i) != '\0') {
1951                                 if(!isdigit(*(p->callerid_num+i))) { break; }
1952                                 i++;
1953                         }
1954                         if(*(p->callerid_num+i) == '\0')
1955                                 ooCallSetCallingPartyNumber(call, p->callerid_num);
1956                         else {
1957                                 if(ast_strlen_zero(p->callerid_name))
1958                                         ooCallSetCallerId(call, p->callerid_num);
1959                         }
1960                 }
1961                 
1962                 if (!ast_strlen_zero(p->caller_h323id))
1963                         ooCallAddAliasH323ID(call, p->caller_h323id);
1964
1965                 if (!ast_strlen_zero(p->caller_dialedDigits)) {
1966                         if (gH323Debug) {
1967                                 ast_verbose("Setting dialed digits %s\n", p->caller_dialedDigits);
1968                         }
1969                         ooCallAddAliasDialedDigits(call, p->caller_dialedDigits);
1970                 } else if (!ast_strlen_zero(p->callerid_num)) {
1971                         if (ooIsDailedDigit(p->callerid_num)) {
1972                                 if (gH323Debug) {
1973                                         ast_verbose("setting callid number %s\n", p->callerid_num);
1974                                 }
1975                                 ooCallAddAliasDialedDigits(call, p->callerid_num);
1976                         } else if (ast_strlen_zero(p->caller_h323id)) {
1977                                 ooCallAddAliasH323ID(call, p->callerid_num);
1978                         }
1979                 }
1980   
1981
1982                 if (!ast_strlen_zero(p->exten))  {
1983                         if (ooIsDailedDigit(p->exten)) {
1984                                 ooCallSetCalledPartyNumber(call, p->exten);
1985                                 ooCallAddRemoteAliasDialedDigits(call, p->exten);
1986                         } else {
1987                           ooCallAddRemoteAliasH323ID(call, p->exten);
1988                         }
1989                 }
1990
1991                 if (gH323Debug) {
1992                         char prefsBuf[256];
1993                         ast_codec_pref_string(&p->prefs, prefsBuf, sizeof(prefsBuf));
1994                         ast_verbose(" Outgoing call %s(%s) - Codec prefs - %s\n", 
1995                                 p->username?p->username:"NULL", call->callToken, prefsBuf);
1996                 }
1997
1998                 ooh323c_set_capability_for_call(call, &p->prefs, p->cap,
1999                                      p->dtmfmode, p->dtmfcodec, p->t38support, p->g729onlyA);
2000
2001                 configure_local_rtp(p, call);
2002                 ast_mutex_unlock(&p->lock);
2003         }
2004
2005         ast_mutex_unlock(&call->Lock);
2006         if (gH323Debug)
2007                 ast_verbose("+++   onNewCallCreated %s\n", call->callToken);
2008         return OO_OK;
2009 }
2010
2011 int onCallEstablished(ooCallData *call)
2012 {
2013         struct ooh323_pvt *p = NULL;
2014
2015         if (gH323Debug)
2016                 ast_verbose("---   onCallEstablished %s\n", call->callToken);
2017
2018
2019         if (!(p = find_call(call))) {
2020                 ast_log(LOG_ERROR, "Failed to find a matching call.\n");
2021                 return -1;
2022         }
2023
2024         if(ast_test_flag(p, H323_OUTGOING)) {
2025                 ast_mutex_lock(&p->lock);
2026                 if (!p->owner) {
2027                         ast_mutex_unlock(&p->lock);
2028                         ast_log(LOG_ERROR, "Channel has no owner\n");
2029                         return -1;
2030                 }
2031
2032                 while (p->owner && ast_channel_trylock(p->owner)) {
2033                         ast_debug(1, "Failed to grab lock, trying again\n");
2034                         DEADLOCK_AVOIDANCE(&p->lock);
2035                 }
2036                 if (p->owner) {
2037                         struct ast_channel* c = p->owner;
2038
2039                         if (call->remoteDisplayName) {
2040                                 struct ast_party_connected_line connected;
2041                                 struct ast_set_party_connected_line update_connected;
2042
2043                                 memset(&update_connected, 0, sizeof(update_connected));
2044                                 update_connected.id.name = 1;
2045                                 ast_party_connected_line_init(&connected);
2046                                 connected.id.name.valid = 1;
2047                                 connected.id.name.str = (char *) call->remoteDisplayName;
2048                                 connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
2049                                 ast_channel_queue_connected_line_update(c, &connected, &update_connected);
2050                         }
2051
2052                         ast_queue_control(c, AST_CONTROL_ANSWER);
2053                         ast_channel_unlock(p->owner);
2054                         manager_event(EVENT_FLAG_SYSTEM,"ChannelUpdate","Channel: %s\r\nChanneltype: %s\r\n"
2055                                 "CallRef: %d\r\n", c->name, "OOH323", p->call_reference);
2056                 }
2057                 ast_mutex_unlock(&p->lock);
2058
2059         }
2060
2061         if (gH323Debug)
2062                 ast_verbose("+++   onCallEstablished %s\n", call->callToken);
2063
2064         return OO_OK;
2065 }
2066
2067 int onCallCleared(ooCallData *call)
2068 {
2069         struct ooh323_pvt *p = NULL;
2070         int ownerLock = 0;
2071
2072         if (gH323Debug)
2073                 ast_verbose("---   onCallCleared %s \n", call->callToken);
2074
2075
2076    if ((p = find_call(call))) {
2077         ast_mutex_lock(&p->lock);
2078
2079         while (p->owner) {
2080                 if (ast_channel_trylock(p->owner)) {
2081                         ooTrace(OOTRCLVLINFO, "Failed to grab lock, trying again\n");
2082                         ast_debug(1, "Failed to grab lock, trying again\n");
2083                         DEADLOCK_AVOIDANCE(&p->lock);
2084                 } else {
2085                         ownerLock = 1; break;
2086                 }
2087         }
2088
2089         if (ownerLock) {
2090                 if (!ast_test_flag(p, H323_ALREADYGONE)) {
2091
2092                         ast_set_flag(p, H323_ALREADYGONE);
2093                         p->owner->hangupcause = call->q931cause;
2094                         p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
2095                         ast_queue_hangup_with_cause(p->owner,call->q931cause);
2096                 }
2097         }
2098
2099         if(p->owner) {
2100                 p->owner->tech_pvt = NULL;
2101                 ast_channel_unlock(p->owner);
2102                 p->owner = NULL;
2103                 ast_module_unref(myself);
2104         }
2105
2106         ast_set_flag(p, H323_NEEDDESTROY);
2107
2108         ooh323c_stop_call_thread(call);
2109
2110         ast_mutex_unlock(&p->lock);
2111         ast_mutex_lock(&usecnt_lock);
2112         usecnt--;
2113         ast_mutex_unlock(&usecnt_lock);
2114
2115     }
2116
2117         if (gH323Debug)
2118                 ast_verbose("+++   onCallCleared\n");
2119
2120         return OO_OK;
2121 }
2122
2123 /* static void ooh323_delete_user(struct ooh323_user *user)
2124 {
2125         struct ooh323_user *prev = NULL, *cur = NULL;
2126
2127         if (gH323Debug)
2128                 ast_verbose("---   ooh323_delete_user\n");
2129
2130         if (user) {     
2131                 cur = userl.users;
2132                 ast_mutex_lock(&userl.lock);
2133                 while (cur) {
2134                         if (cur == user) break;
2135                         prev = cur;
2136                         cur = cur->next;
2137                 }
2138
2139                 if (cur) {
2140                         if (prev)
2141                                 prev->next = cur->next;
2142                         else
2143                                 userl.users = cur->next;
2144                 }
2145                 ast_mutex_unlock(&userl.lock);
2146
2147                 free(user);
2148         }  
2149
2150         if (gH323Debug)
2151                 ast_verbose("+++   ooh323_delete_user\n");
2152
2153 } */
2154
2155 void ooh323_delete_peer(struct ooh323_peer *peer)
2156 {
2157         struct ooh323_peer *prev = NULL, *cur = NULL;
2158
2159         if (gH323Debug)
2160                 ast_verbose("---   ooh323_delete_peer\n");
2161
2162         if (peer) {     
2163       cur = peerl.peers;
2164                 ast_mutex_lock(&peerl.lock);
2165       while(cur) {
2166          if(cur==peer) break;
2167          prev = cur;
2168          cur = cur->next;
2169                 }
2170
2171                 if (cur) {
2172          if(prev)
2173                                 prev->next = cur->next;
2174          else
2175                                 peerl.peers = cur->next;
2176                         }
2177                 ast_mutex_unlock(&peerl.lock);
2178
2179       if(peer->h323id)   free(peer->h323id);
2180       if(peer->email)    free(peer->email);
2181       if(peer->url)      free(peer->url);
2182       if(peer->e164)     free(peer->e164);
2183
2184                 peer->cap = ast_format_cap_destroy(peer->cap);
2185                 free(peer);
2186         }  
2187
2188         if (gH323Debug)
2189                 ast_verbose("+++   ooh323_delete_peer\n");
2190
2191 }
2192
2193
2194
2195 static struct ooh323_user *build_user(const char *name, struct ast_variable *v)
2196 {
2197         struct ooh323_user *user = NULL;
2198
2199         if (gH323Debug)
2200                 ast_verbose("---   build_user\n");
2201
2202         user = ast_calloc(1,sizeof(struct ooh323_user));
2203         if (user) {
2204                 memset(user, 0, sizeof(struct ooh323_user));
2205                 if (!(user->cap = ast_format_cap_alloc())) {
2206                         ast_free(user);
2207                         return NULL;
2208                 }
2209                 ast_mutex_init(&user->lock);
2210                 ast_copy_string(user->name, name, sizeof(user->name));
2211                 ast_format_cap_copy(user->cap, gCap);
2212                 memcpy(&user->prefs, &gPrefs, sizeof(user->prefs));
2213                 user->rtptimeout = gRTPTimeout;
2214                 user->dtmfmode = gDTMFMode;
2215                 user->dtmfcodec = gDTMFCodec;
2216                 user->t38support = gT38Support;
2217                 user->faststart = gFastStart;
2218                 user->h245tunneling = gTunneling;
2219                 user->g729onlyA = g729onlyA;
2220                 /* set default context */
2221                 ast_copy_string(user->context, gContext, sizeof(user->context));
2222                 ast_copy_string(user->accountcode, gAccountcode, sizeof(user->accountcode));
2223                 user->amaflags = gAMAFLAGS;
2224
2225                 while (v) {
2226                         if (!strcasecmp(v->name, "context")) {
2227                                 ast_copy_string(user->context, v->value, sizeof(user->context));
2228                         } else if (!strcasecmp(v->name, "incominglimit")) {
2229                                 user->incominglimit = atoi(v->value);
2230                                 if (user->incominglimit < 0)
2231                                         user->incominglimit = 0;
2232                         } else if (!strcasecmp(v->name, "accountcode")) {
2233                                 strncpy(user->accountcode, v->value, 
2234                                                 sizeof(user->accountcode)-1);
2235                         } else if (!strcasecmp(v->name, "roundtrip")) {
2236                                 sscanf(v->value, "%d,%d", &user->rtdrcount, &user->rtdrinterval);
2237                         } else if (!strcasecmp(v->name, "faststart")) {
2238                                 user->faststart = ast_true(v->value);
2239                         } else if (!strcasecmp(v->name, "h245tunneling")) {
2240                                 user->h245tunneling = ast_true(v->value);
2241                         } else if (!strcasecmp(v->name, "g729onlyA")) {
2242                                 user->g729onlyA = ast_true(v->value);
2243                         } else if (!strcasecmp(v->name, "rtptimeout")) {
2244                                 user->rtptimeout = atoi(v->value);
2245                                 if (user->rtptimeout < 0)
2246                                         user->rtptimeout = gRTPTimeout;
2247                         } else if (!strcasecmp(v->name, "rtpmask")) {
2248                                 if ((user->rtpmask = ast_calloc(1, sizeof(struct OOH323Regex))) &&
2249                                         (regcomp(&user->rtpmask->regex, v->value, REG_EXTENDED) 
2250                                                                                         == 0)) {
2251                                         ast_mutex_init(&user->rtpmask->lock);
2252                                         user->rtpmask->inuse = 1;
2253                                         ast_copy_string(user->rtpmaskstr, v->value, 
2254                                                                 sizeof(user->rtpmaskstr));
2255                                 } else user->rtpmask = NULL;
2256                         } else if (!strcasecmp(v->name, "disallow")) {
2257                                 ast_parse_allow_disallow(&user->prefs, 
2258                                         user->cap,  v->value, 0);
2259                         } else if (!strcasecmp(v->name, "allow")) {
2260                                 const char* tcodecs = v->value;
2261                                 if (!strcasecmp(v->value, "all")) {
2262                                         tcodecs = "ulaw,alaw,g729,g723,gsm";
2263                                 }
2264                                 ast_parse_allow_disallow(&user->prefs,
2265                                          user->cap,  tcodecs, 1);
2266                         } else if (!strcasecmp(v->name, "amaflags")) {
2267                                 user->amaflags = ast_cdr_amaflags2int(v->value);
2268                         } else if (!strcasecmp(v->name, "ip")) {
2269                                 strncpy(user->mIP, v->value, sizeof(user->mIP)-1);
2270                                 user->mUseIP = 1;
2271                         } else if (!strcasecmp(v->name, "host")) {
2272                                 strncpy(user->mIP, v->value, sizeof(user->mIP)-1);
2273                                 user->mUseIP = 1;
2274                         } else if (!strcasecmp(v->name, "dtmfmode")) {
2275                                 if (!strcasecmp(v->value, "rfc2833"))
2276                                         user->dtmfmode = H323_DTMF_RFC2833;
2277                                 if (!strcasecmp(v->value, "cisco"))
2278                                         user->dtmfmode = H323_DTMF_CISCO;
2279                                 else if (!strcasecmp(v->value, "q931keypad"))
2280                                         user->dtmfmode = H323_DTMF_Q931;
2281                                 else if (!strcasecmp(v->value, "h245alphanumeric"))
2282                                         user->dtmfmode = H323_DTMF_H245ALPHANUMERIC;
2283                                 else if (!strcasecmp(v->value, "h245signal"))
2284                                         user->dtmfmode = H323_DTMF_H245SIGNAL;
2285                                 else if (!strcasecmp(v->value, "inband"))
2286                                         user->dtmfmode = H323_DTMF_INBAND;
2287                         } else if (!strcasecmp(v->name, "relaxdtmf")) {
2288                                 user->dtmfmode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0;
2289                         } else if (!strcasecmp(v->name, "dtmfcodec") && atoi(v->value)) {
2290                                 user->dtmfcodec = atoi(v->value);
2291                         } else if (!strcasecmp(v->name, "t38support")) {
2292                                 if (!strcasecmp(v->value, "disabled"))
2293                                         user->t38support = T38_DISABLED;
2294                                 if (!strcasecmp(v->value, "no"))
2295                                         user->t38support = T38_DISABLED;
2296                                 else if (!strcasecmp(v->value, "faxgw"))
2297                                         user->t38support = T38_FAXGW;
2298                                 else if (!strcasecmp(v->value, "yes"))
2299                                         user->t38support = T38_ENABLED;
2300                         }
2301                         v = v->next;
2302                 }
2303         }
2304
2305         if (gH323Debug)
2306                 ast_verbose("+++   build_user\n");
2307
2308         return user;
2309 }
2310
2311 static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v, int friend_type)
2312 {
2313         struct ooh323_peer *peer = NULL;
2314
2315         if (gH323Debug)
2316                 ast_verbose("---   build_peer\n");
2317
2318         peer = ast_calloc(1, sizeof(*peer));
2319         if (peer) {
2320                 memset(peer, 0, sizeof(struct ooh323_peer));
2321                 if (!(peer->cap = ast_format_cap_alloc())) {
2322                         ast_free(peer);
2323                         return NULL;
2324                 }
2325                 ast_mutex_init(&peer->lock);
2326                 ast_copy_string(peer->name, name, sizeof(peer->name));
2327                 ast_format_cap_copy(peer->cap, gCap);
2328                 memcpy(&peer->prefs, &gPrefs, sizeof(peer->prefs));
2329                 peer->rtptimeout = gRTPTimeout;
2330                 ast_copy_string(peer->accountcode, gAccountcode, sizeof(peer->accountcode));
2331                 peer->amaflags = gAMAFLAGS;
2332                 peer->dtmfmode = gDTMFMode;
2333                 peer->dtmfcodec = gDTMFCodec;
2334                 peer->t38support = gT38Support;
2335                 peer->faststart = gFastStart;
2336                 peer->h245tunneling = gTunneling;
2337                 peer->g729onlyA = g729onlyA;
2338                 peer->port = 1720;
2339                 if (0 == friend_type) {
2340                         peer->mFriend = 1;
2341                 }
2342
2343                 while (v) {
2344                         if (!strcasecmp(v->name, "h323id")) {
2345             if (!(peer->h323id = ast_strdup(v->value))) {
2346                                         ast_log(LOG_ERROR, "Could not allocate memory for h323id of "
2347                                                                                          "peer %s\n", name);
2348                                         ooh323_delete_peer(peer);
2349                                         return NULL;
2350                                 }
2351                         } else if (!strcasecmp(v->name, "e164")) {
2352                                 if (!(peer->e164 = ast_strdup(v->value))) {
2353                                         ast_log(LOG_ERROR, "Could not allocate memory for e164 of "
2354                                                                                          "peer %s\n", name);
2355                                         ooh323_delete_peer(peer);
2356                                         return NULL;
2357                                 }
2358                         } else  if (!strcasecmp(v->name, "email")) {
2359                                 if (!(peer->email = ast_strdup(v->value))) {
2360                                         ast_log(LOG_ERROR, "Could not allocate memory for email of "
2361                                                                                          "peer %s\n", name);
2362                                         ooh323_delete_peer(peer);
2363                                         return NULL;
2364                                 }
2365                         } else if (!strcasecmp(v->name, "url")) {
2366                                 if (!(peer->url = ast_strdup(v->value))) {
2367                                         ast_log(LOG_ERROR, "Could not allocate memory for h323id of "
2368                                                                                          "peer %s\n", name);
2369                                         ooh323_delete_peer(peer);
2370                                         return NULL;
2371                                 }
2372                         } else if (!strcasecmp(v->name, "port")) {
2373                                 peer->port = atoi(v->value);
2374                         } else if (!strcasecmp(v->name, "ip")) {
2375                                 ast_copy_string(peer->ip, v->value, sizeof(peer->ip));
2376                         } else if (!strcasecmp(v->name, "host")) {
2377                                 ast_copy_string(peer->ip, v->value, sizeof(peer->ip));
2378                         } else if (!strcasecmp(v->name, "outgoinglimit")) {
2379                                 peer->outgoinglimit = atoi(v->value);
2380                                 if (peer->outgoinglimit < 0)
2381                                         peer->outgoinglimit = 0;
2382                         } else if (!strcasecmp(v->name, "accountcode")) {
2383                                 ast_copy_string(peer->accountcode, v->value, sizeof(peer->accountcode));
2384                         } else if (!strcasecmp(v->name, "faststart")) {
2385                                 peer->faststart = ast_true(v->value);
2386                         } else if (!strcasecmp(v->name, "h245tunneling")) {
2387                                 peer->h245tunneling = ast_true(v->value);
2388                         } else if (!strcasecmp(v->name, "g729onlyA")) {
2389                                 peer->g729onlyA = ast_true(v->value);
2390                         } else if (!strcasecmp(v->name, "rtptimeout")) {
2391                                 peer->rtptimeout = atoi(v->value);
2392                                 if(peer->rtptimeout < 0)
2393                                         peer->rtptimeout = gRTPTimeout;
2394                         } else if (!strcasecmp(v->name, "rtpmask")) {
2395                                 if ((peer->rtpmask = ast_calloc(1, sizeof(struct OOH323Regex))) &&
2396                                         (regcomp(&peer->rtpmask->regex, v->value, REG_EXTENDED) 
2397                                                                                         == 0)) {
2398                                         ast_mutex_init(&peer->rtpmask->lock);
2399                                         peer->rtpmask->inuse = 1;
2400                                         ast_copy_string(peer->rtpmaskstr, v->value, 
2401                                                                 sizeof(peer->rtpmaskstr));
2402                                 } else peer->rtpmask = NULL;
2403                         } else if (!strcasecmp(v->name, "disallow")) {
2404                                 ast_parse_allow_disallow(&peer->prefs, peer->cap, 
2405                                                                                                  v->value, 0); 
2406                         } else if (!strcasecmp(v->name, "allow")) {
2407                                 const char* tcodecs = v->value;
2408                                 if (!strcasecmp(v->value, "all")) {
2409                                         tcodecs = "ulaw,alaw,g729,g723,gsm";
2410                                 }
2411                                 ast_parse_allow_disallow(&peer->prefs, peer->cap, 
2412                                                                                                  tcodecs, 1);                            
2413                         } else if (!strcasecmp(v->name,  "amaflags")) {
2414                                 peer->amaflags = ast_cdr_amaflags2int(v->value);
2415                         } else if (!strcasecmp(v->name, "roundtrip")) {
2416                                 sscanf(v->value, "%d,%d", &peer->rtdrcount, &peer->rtdrinterval);
2417                         } else if (!strcasecmp(v->name, "dtmfmode")) {
2418                                 if (!strcasecmp(v->value, "rfc2833"))
2419                                         peer->dtmfmode = H323_DTMF_RFC2833;
2420                                 if (!strcasecmp(v->value, "cisco"))
2421                                         peer->dtmfmode = H323_DTMF_CISCO;
2422                                 else if (!strcasecmp(v->value, "q931keypad"))
2423                                         peer->dtmfmode = H323_DTMF_Q931;
2424                                 else if (!strcasecmp(v->value, "h245alphanumeric"))
2425                                         peer->dtmfmode = H323_DTMF_H245ALPHANUMERIC;
2426                                 else if (!strcasecmp(v->value, "h245signal"))
2427                                         peer->dtmfmode = H323_DTMF_H245SIGNAL;
2428                                 else if (!strcasecmp(v->value, "inband"))
2429                                         peer->dtmfmode = H323_DTMF_INBAND;
2430                         } else if (!strcasecmp(v->name, "relaxdtmf")) {
2431                                 peer->dtmfmode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0;
2432                         } else if (!strcasecmp(v->name, "dtmfcodec") && atoi(v->value)) {
2433                                 peer->dtmfcodec = atoi(v->value);
2434                         } else if (!strcasecmp(v->name, "t38support")) {
2435                                 if (!strcasecmp(v->value, "disabled"))
2436                                         peer->t38support = T38_DISABLED;
2437                                 if (!strcasecmp(v->value, "no"))
2438                                         peer->t38support = T38_DISABLED;
2439                                 else if (!strcasecmp(v->value, "faxgw"))
2440                                         peer->t38support = T38_FAXGW;
2441                                 else if (!strcasecmp(v->value, "yes"))
2442                                         peer->t38support = T38_ENABLED;
2443                         }
2444                         v = v->next;
2445                 }
2446         }
2447
2448         if (gH323Debug)
2449                 ast_verbose("+++   build_peer\n");
2450
2451         return peer;
2452 }
2453
2454 static int ooh323_do_reload(void)
2455 {
2456         if (gH323Debug) {
2457                 ast_verbose("---   ooh323_do_reload\n");
2458         }
2459
2460         reload_config(1);
2461
2462         if (gH323Debug) {
2463                 ast_verbose("+++   ooh323_do_reload\n");
2464         }
2465
2466         return 0;
2467 }
2468
2469 /*--- h323_reload: Force reload of module from cli ---*/
2470
2471 char *handle_cli_ooh323_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2472 {
2473
2474        switch (cmd) {
2475        case CLI_INIT:
2476                e->command = "ooh323 reload";
2477                e->usage =
2478                        "Usage: ooh323 reload\n"
2479                        "                Reload OOH323 config.\n";
2480                return NULL;
2481        case CLI_GENERATE:
2482                return NULL;
2483        }
2484
2485        if (a->argc != 2)
2486                return CLI_SHOWUSAGE;
2487
2488         if (gH323Debug)
2489                 ast_verbose("---   ooh323_reload\n");
2490
2491         ast_mutex_lock(&h323_reload_lock);
2492         if (h323_reloading) {
2493                 ast_verbose("Previous OOH323 reload not yet done\n");
2494    } else {
2495                 h323_reloading = 1;
2496         }
2497         ast_mutex_unlock(&h323_reload_lock);
2498         restart_monitor();
2499
2500         if (gH323Debug)
2501                 ast_verbose("+++   ooh323_reload\n");
2502
2503         return 0;
2504 }
2505
2506 int reload_config(int reload)
2507 {
2508         int format;
2509         struct ooAliases  *pNewAlias = NULL, *cur, *prev;
2510         struct ast_config *cfg;
2511         struct ast_variable *v;
2512         struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2513         struct ooh323_user *user = NULL;
2514         struct ooh323_peer *peer = NULL;
2515         char *cat;
2516         const char *utype;
2517         struct ast_format tmpfmt;
2518
2519         if (gH323Debug)
2520                 ast_verbose("---   reload_config\n");
2521
2522         cfg = ast_config_load((char*)config, config_flags);
2523
2524         /* We *must* have a config file otherwise stop immediately */
2525         if (!cfg) {
2526                 ast_log(LOG_NOTICE, "Unable to load config %s, OOH323 disabled\n", config);
2527                 return 1;
2528         } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
2529                 return RESULT_SUCCESS;
2530
2531         if (reload) {
2532                 delete_users();
2533                 delete_peers();
2534                 if (gH323Debug) {
2535                         ast_verbose("  reload_config - Freeing up alias list\n");
2536                 }
2537                 cur = gAliasList;
2538                 while (cur) {
2539                         prev = cur;
2540                         cur = cur->next;
2541                         free(prev->value);
2542                         free(prev);
2543                 }
2544                 gAliasList = NULL;
2545         }
2546
2547         /* Inintialize everything to default */
2548         strcpy(gLogFile, DEFAULT_LOGFILE);
2549         gPort = 1720;
2550         gIP[0] = '\0';
2551         strcpy(gCallerID, DEFAULT_H323ID);
2552         ast_format_cap_set(gCap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
2553         memset(&gPrefs, 0, sizeof(struct ast_codec_pref));
2554         gDTMFMode = H323_DTMF_RFC2833;
2555         gDTMFCodec = 101;
2556         gT38Support = T38_FAXGW;
2557         gTRCLVL = OOTRCLVLERR;
2558         gRasGkMode = RasNoGatekeeper;
2559         gGatekeeper[0] = '\0';
2560         gRTPTimeout = 60;
2561         gRTDRInterval = 0;
2562         gRTDRCount = 0;
2563         strcpy(gAccountcode, DEFAULT_H323ACCNT);
2564         gFastStart = 1;
2565         gTunneling = 1;
2566         gTOS = 0;
2567         strcpy(gContext, DEFAULT_CONTEXT);
2568         gAliasList = NULL;
2569         gMediaWaitForConnect = 0;
2570         ooconfig.mTCPPortStart = 12030;
2571         ooconfig.mTCPPortEnd = 12230;
2572         memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
2573
2574         v = ast_variable_browse(cfg, "general");
2575         while (v) {
2576
2577                 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
2578                         v = v->next;
2579                         continue;
2580                 }
2581         
2582                 if (!strcasecmp(v->name, "port")) {
2583                         gPort = (int)strtol(v->value, NULL, 10);
2584                 } else if (!strcasecmp(v->name, "bindaddr")) {
2585                         ast_copy_string(gIP, v->value, sizeof(gIP));
2586                 } else if (!strcasecmp(v->name, "h225portrange")) {
2587                         char* endlimit = 0;
2588                         char temp[512];
2589                         ast_copy_string(temp, v->value, sizeof(temp));
2590                         endlimit = strchr(temp, ',');
2591                         if (endlimit) {
2592                                 *endlimit = '\0';
2593                                 endlimit++;
2594                                 ooconfig.mTCPPortStart = atoi(temp);
2595                                 ooconfig.mTCPPortEnd = atoi(endlimit);
2596
2597                         } else {
2598                                 ast_log(LOG_ERROR, "h225portrange: Invalid format, separate port range with \",\"\n");
2599                         }
2600                 } else if (!strcasecmp(v->name, "gateway")) {
2601                         gIsGateway = ast_true(v->value);
2602                 } else if (!strcasecmp(v->name, "faststart")) {
2603                         gFastStart = ast_true(v->value);
2604                         if (gFastStart)
2605                                 ooH323EpEnableFastStart();
2606                         else
2607                                 ooH323EpDisableFastStart();
2608                 } else if (!strcasecmp(v->name, "mediawaitforconnect")) {
2609                         gMediaWaitForConnect = ast_true(v->value);
2610                         if (gMediaWaitForConnect)
2611                                 ooH323EpEnableMediaWaitForConnect();
2612                         else 
2613                                 ooH323EpDisableMediaWaitForConnect();
2614                 } else if (!strcasecmp(v->name, "h245tunneling")) {
2615                         gTunneling = ast_true(v->value);
2616                         if (gTunneling)
2617                                 ooH323EpEnableH245Tunneling();
2618                         else
2619                                 ooH323EpDisableH245Tunneling();
2620                 } else if (!strcasecmp(v->name, "g729onlyA")) {
2621                         g729onlyA = ast_true(v->value);
2622                 } else if (!strcasecmp(v->name, "roundtrip")) {
2623                         sscanf(v->value, "%d,%d", &gRTDRCount, &gRTDRInterval);
2624                 } else if (!strcasecmp(v->name, "trybemaster")) {
2625                         gBeMaster = ast_true(v->value);
2626                         if (gBeMaster)
2627                                 ooH323EpTryBeMaster(1);
2628                         else 
2629                                 ooH323EpTryBeMaster(0);
2630                 } else if (!strcasecmp(v->name, "h323id")) {
2631                         pNewAlias = ast_calloc(1, sizeof(struct ooAliases));
2632                         if (!pNewAlias) {
2633                                 ast_log(LOG_ERROR, "Failed to allocate memory for h323id alias\n");
2634                                 return 1;
2635                         }
2636                         if (gAliasList == NULL) { /* first h323id - set as callerid if callerid is not set */
2637                                 ast_copy_string(gCallerID, v->value, sizeof(gCallerID));
2638                         }
2639                         pNewAlias->type =  T_H225AliasAddress_h323_ID;
2640                         pNewAlias->value = strdup(v->value);
2641                         pNewAlias->next = gAliasList;
2642                         gAliasList = pNewAlias;
2643                         pNewAlias = NULL;
2644                 } else if (!strcasecmp(v->name, "e164")) {
2645                         pNewAlias = ast_calloc(1, sizeof(struct ooAliases));
2646                         if (!pNewAlias) {
2647                                 ast_log(LOG_ERROR, "Failed to allocate memory for e164 alias\n");
2648                                 return 1;
2649                         }
2650                         pNewAlias->type =  T_H225AliasAddress_dialedDigits;
2651                         pNewAlias->value = strdup(v->value);
2652                         pNewAlias->next = gAliasList;
2653                         gAliasList = pNewAlias;
2654                         pNewAlias = NULL;
2655                 } else if (!strcasecmp(v->name, "email")) {
2656                         pNewAlias = ast_calloc(1, sizeof(struct ooAliases));
2657                         if (!pNewAlias) {
2658                                 ast_log(LOG_ERROR, "Failed to allocate memory for email alias\n");
2659                                 return 1;
2660                         }
2661                         pNewAlias->type =  T_H225AliasAddress_email_ID;
2662                         pNewAlias->value = strdup(v->value);
2663                         pNewAlias->next = gAliasList;
2664                         gAliasList = pNewAlias;
2665                         pNewAlias = NULL;
2666       } else if (!strcasecmp(v->name, "t35country")) {
2667          t35countrycode = atoi(v->value);
2668       } else if (!strcasecmp(v->name, "t35extensions")) {
2669          t35extensions = atoi(v->value);
2670       } else if (!strcasecmp(v->name, "manufacturer")) {
2671          manufacturer = atoi(v->value);
2672       } else if (!strcasecmp(v->name, "vendorid")) {
2673          ast_copy_string(vendor, v->value, sizeof(vendor));
2674       } else if (!strcasecmp(v->name, "versionid")) {
2675          ast_copy_string(version, v->value, sizeof(version));
2676                 } else if (!strcasecmp(v->name, "callerid")) {
2677                         ast_copy_string(gCallerID, v->value, sizeof(gCallerID));
2678                 } else if (!strcasecmp(v->name, "incominglimit")) {
2679                         gIncomingLimit = atoi(v->value);
2680                 } else if (!strcasecmp(v->name, "outgoinglimit")) {
2681                         gOutgoingLimit = atoi(v->value);
2682                 } else if (!strcasecmp(v->name, "gatekeeper")) {
2683                         if (!strcasecmp(v->value, "DISABLE")) {
2684                                 gRasGkMode = RasNoGatekeeper;
2685                         } else if (!strcasecmp(v->value, "DISCOVER")) {
2686                                 gRasGkMode = RasDiscoverGatekeeper;
2687                         } else {
2688                                 gRasGkMode = RasUseSpecificGatekeeper;
2689                                 strncpy(gGatekeeper, v->value, sizeof(gGatekeeper)-1);
2690                         }
2691                 } else if (!strcasecmp(v->name, "logfile")) {
2692          strncpy(gLogFile, v->value, sizeof(gLogFile)-1);
2693                 } else if (!strcasecmp(v->name, "context")) {
2694          strncpy(gContext, v->value, sizeof(gContext)-1);
2695          ast_verbose(VERBOSE_PREFIX_3 "  == Setting default context to %s\n", 
2696                                                       gContext);
2697                 } else if (!strcasecmp(v->name, "rtptimeout")) {
2698                         gRTPTimeout = atoi(v->value);
2699                         if (gRTPTimeout <= 0)
2700                                 gRTPTimeout = 60;
2701                 } else if (!strcasecmp(v->name, "tos")) {
2702                         if (sscanf(v->value, "%30i", &format) == 1)
2703                                 gTOS = format & 0xff;
2704                         else if (!strcasecmp(v->value, "lowdelay"))
2705                                 gTOS = IPTOS_LOWDELAY;
2706                         else if (!strcasecmp(v->value, "throughput"))
2707                                 gTOS = IPTOS_THROUGHPUT;
2708                         else if (!strcasecmp(v->value, "reliability"))
2709                                 gTOS = IPTOS_RELIABILITY;
2710                         else if (!strcasecmp(v->value, "mincost"))
2711                                 gTOS = IPTOS_MINCOST;
2712                         else if (!strcasecmp(v->value, "none"))
2713                                 gTOS = 0;
2714                         else
2715                                 ast_log(LOG_WARNING, "Invalid tos value at line %d, should be "
2716                                                                                         "'lowdelay', 'throughput', 'reliability', "
2717                                                                                         "'mincost', or 'none'\n", v->lineno);
2718                 } else if (!strcasecmp(v->name, "amaflags")) {
2719                         gAMAFLAGS = ast_cdr_amaflags2int(v->value);
2720                 } else if (!strcasecmp(v->name, "accountcode")) {
2721          ast_copy_string(gAccountcode, v->value, sizeof(gAccountcode));
2722                 } else if (!strcasecmp(v->name, "disallow")) {
2723                         ast_parse_allow_disallow(&gPrefs, gCap, v->value, 0);
2724                 } else if (!strcasecmp(v->name, "allow")) {
2725                         const char* tcodecs = v->value;
2726                         if (!strcasecmp(v->value, "all")) {
2727                                 tcodecs = "ulaw,alaw,g729,g723,gsm";
2728                         }
2729                         ast_parse_allow_disallow(&gPrefs, gCap, tcodecs, 1);
2730                 } else if (!strcasecmp(v->name, "dtmfmode")) {
2731                         if (!strcasecmp(v->value, "inband"))
2732                                 gDTMFMode = H323_DTMF_INBAND;
2733                         else if (!strcasecmp(v->value, "rfc2833"))
2734                                 gDTMFMode = H323_DTMF_RFC2833;
2735                         else if (!strcasecmp(v->value, "cisco"))
2736                                 gDTMFMode = H323_DTMF_CISCO;
2737                         else if (!strcasecmp(v->value, "q931keypad"))
2738                                 gDTMFMode = H323_DTMF_Q931;
2739                         else if (!strcasecmp(v->value, "h245alphanumeric"))
2740                                 gDTMFMode = H323_DTMF_H245ALPHANUMERIC;
2741                         else if (!strcasecmp(v->value, "h245signal"))
2742                                 gDTMFMode = H323_DTMF_H245SIGNAL;
2743                         else {
2744             ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", 
2745                                                                     v->value);
2746                                 gDTMFMode = H323_DTMF_RFC2833;
2747                         }
2748                 } else if (!strcasecmp(v->name, "relaxdtmf")) {
2749                         gDTMFMode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0;
2750                 } else if (!strcasecmp(v->name, "dtmfcodec") && atoi(v->value)) {
2751                         gDTMFCodec = atoi(v->value);
2752                 } else if (!strcasecmp(v->name, "t38support")) {
2753                         if (!strcasecmp(v->value, "disabled"))
2754                                 gT38Support = T38_DISABLED;
2755                         if (!strcasecmp(v->value, "no"))
2756                                 gT38Support = T38_DISABLED;
2757                         else if (!strcasecmp(v->value, "faxgw"))
2758                                 gT38Support = T38_FAXGW;
2759                         else if (!strcasecmp(v->value, "yes"))
2760                                 gT38Support = T38_ENABLED;
2761                 } else if (!strcasecmp(v->name, "tracelevel")) {
2762                         gTRCLVL = atoi(v->value);
2763                         ooH323EpSetTraceLevel(gTRCLVL);
2764                 }
2765                 v = v->next;
2766         }
2767         
2768         for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
2769                 if (strcasecmp(cat, "general")) {
2770                         int friend_type = 0;
2771                         utype = ast_variable_retrieve(cfg, cat, "type");
2772                         if (utype) {
2773                                 friend_type = strcasecmp(utype, "friend");
2774                                 if (!strcmp(utype, "user") || 0 == friend_type) {
2775                                         user = build_user(cat, ast_variable_browse(cfg, cat));
2776                                         if (user) {
2777                                                 ast_mutex_lock(&userl.lock);
2778                                                 user->next = userl.users;
2779                                                 userl.users = user;
2780                                                 ast_mutex_unlock(&userl.lock);
2781                                         } else {
2782                                                 ast_log(LOG_WARNING, "Failed to build user %s\n", cat);
2783                                         }
2784                                 }
2785                                 if (!strcasecmp(utype, "peer") || 0 == friend_type) {
2786                                         peer = build_peer(cat, ast_variable_browse(cfg, cat), friend_type);
2787                                         if (peer) {
2788                                                 ast_mutex_lock(&peerl.lock);
2789                                                 peer->next = peerl.peers;
2790                                                 peerl.peers = peer;
2791                                                 ast_mutex_unlock(&peerl.lock);
2792                                         } else {
2793                                                 ast_log(LOG_WARNING, "Failed to build peer %s\n", cat);
2794                                         }
2795                                 }
2796                         }
2797                 }
2798         }
2799         ast_config_destroy(cfg);
2800
2801
2802         /* Determine ip address if neccessary */
2803         if (ast_strlen_zero(gIP)) {
2804                 ooGetLocalIPAddress(gIP);
2805                 if (!strcmp(gIP, "127.0.0.1")) {
2806                         ast_log(LOG_NOTICE, "Failed to determine local ip address. Please "
2807                                                                          "specify it in ooh323.conf. OOH323 Disabled\n");
2808                         return 1;
2809                 }
2810         }
2811
2812         if (gH323Debug)
2813                 ast_verbose("+++   reload_config\n");
2814
2815         return 0;
2816
2817 }
2818
2819
2820 static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2821 {
2822         char ip_port[30];
2823         struct ooh323_peer *prev = NULL, *peer = NULL;
2824         
2825         switch (cmd) {
2826         case CLI_INIT:
2827                 e->command = "ooh323 show peer";
2828                 e->usage =
2829                         "Usage: ooh323 show peer <name>\n"
2830                         "                List details of specific OOH323 peer.\n";
2831                 return NULL;
2832         case CLI_GENERATE:
2833                 return NULL;
2834         }
2835
2836         if (a->argc != 4)
2837                 return CLI_SHOWUSAGE;
2838
2839  
2840         ast_mutex_lock(&peerl.lock);
2841         peer = peerl.peers;
2842         while (peer) {
2843                 ast_mutex_lock(&peer->lock);
2844                 if(!strcmp(peer->name, a->argv[3]))
2845                         break;
2846                 else {
2847                         prev = peer;
2848                         peer = peer->next;
2849                         ast_mutex_unlock(&prev->lock);
2850                 }
2851         }
2852
2853         if (peer) {
2854       sprintf(ip_port, "%s:%d", peer->ip, peer->port);
2855       ast_cli(a->fd, "%-15.15s%s\n", "Name: ", peer->name);
2856       ast_cli(a->fd, "%s:%s,%s\n", "FastStart/H.245 Tunneling", peer->faststart?"yes":"no",
2857                                         peer->h245tunneling?"yes":"no");
2858       ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "(");
2859       print_codec_to_cli(a->fd, &peer->prefs);
2860       ast_cli(a->fd, ")\n");
2861       ast_cli(a->fd, "%-15.15s", "DTMF Mode: ");
2862                 if (peer->dtmfmode & H323_DTMF_CISCO) {
2863          ast_cli(a->fd, "%s\n", "cisco");
2864          ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec);
2865                 } else if (peer->dtmfmode & H323_DTMF_RFC2833) {
2866          ast_cli(a->fd, "%s\n", "rfc2833");
2867          ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec);
2868                 } else if (peer->dtmfmode & H323_DTMF_Q931)
2869          ast_cli(a->fd, "%s\n", "q931keypad");
2870                 else if (peer->dtmfmode & H323_DTMF_H245ALPHANUMERIC)
2871          ast_cli(a->fd, "%s\n", "h245alphanumeric");
2872                 else if (peer->dtmfmode & H323_DTMF_H245SIGNAL)
2873          ast_cli(a->fd, "%s\n", "h245signal");
2874                 else if (peer->dtmfmode & H323_DTMF_INBAND && peer->dtmfmode & H323_DTMF_INBANDRELAX)
2875          ast_cli(a->fd, "%s\n", "inband-relaxed");
2876                 else if (peer->dtmfmode & H323_DTMF_INBAND)
2877          ast_cli(a->fd, "%s\n", "inband");
2878                 else
2879          ast_cli(a->fd, "%s\n", "unknown");
2880
2881         ast_cli(a->fd,"%-15s", "T.38 Mode: ");
2882         if (peer->t38support == T38_DISABLED)
2883                 ast_cli(a->fd, "%s\n", "disabled");
2884         else if (peer->t38support == T38_FAXGW)
2885                 ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible");
2886
2887         ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", peer->accountcode);
2888         ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", 
2889                 ast_cdr_flags2str(peer->amaflags));
2890         ast_cli(a->fd, "%-15.15s%s\n", "IP:Port: ", ip_port);
2891         ast_cli(a->fd, "%-15.15s%d\n", "OutgoingLimit: ", peer->outgoinglimit);
2892         ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", peer->rtptimeout);
2893         if (peer->rtpmaskstr[0])
2894                 ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", peer->rtpmaskstr);
2895         if (peer->rtdrcount && peer->rtdrinterval) 
2896                 ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", peer->rtdrcount, peer->rtdrinterval);
2897         ast_mutex_unlock(&peer->lock);
2898         } else {
2899         ast_cli(a->fd, "Peer %s not found\n", a->argv[3]);
2900         ast_cli(a->fd, "\n");
2901         }
2902         ast_mutex_unlock(&peerl.lock);
2903
2904         return CLI_SUCCESS;
2905 }
2906
2907 static char *handle_cli_ooh323_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2908 {
2909         struct ooh323_peer *prev = NULL, *peer = NULL;
2910    char formats[FORMAT_STRING_SIZE];
2911    char ip_port[30];
2912 #define FORMAT  "%-15.15s  %-15.15s  %-23.23s  %-s\n"
2913
2914         switch (cmd) {
2915         case CLI_INIT:
2916                 e->command = "ooh323 show peers";
2917                 e->usage =
2918                         "Usage: ooh323 show peers\n"
2919                         "                Lists all known OOH323 peers.\n";
2920                 return NULL;
2921         case CLI_GENERATE:
2922                 return NULL;
2923         }
2924
2925         if (a->argc != 3)
2926                 return CLI_SHOWUSAGE;
2927
2928    ast_cli(a->fd, FORMAT, "Name", "Accountcode", "ip:port", "Formats");
2929
2930         ast_mutex_lock(&peerl.lock);
2931         peer = peerl.peers;
2932         while (peer) {
2933                 ast_mutex_lock(&peer->lock);
2934                 snprintf(ip_port, sizeof(ip_port), "%s:%d", peer->ip, peer->port);
2935      ast_cli(a->fd, FORMAT, peer->name, 
2936                                         peer->accountcode,
2937                                         ip_port,
2938                  ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,peer->cap));
2939                 prev = peer;
2940                 peer = peer->next;
2941                 ast_mutex_unlock(&prev->lock);
2942
2943         }
2944         ast_mutex_unlock(&peerl.lock);
2945 #undef FORMAT
2946         return CLI_SUCCESS;
2947 }
2948
2949 /*! \brief Print codec list from preference to CLI/manager */
2950 static void print_codec_to_cli(int fd, struct ast_codec_pref *pref)
2951 {
2952         int x;
2953         struct ast_format tmpfmt;
2954         for (x = 0; x < 32; x++) {
2955                 ast_codec_pref_index(pref, x, &tmpfmt);
2956                 if (!tmpfmt.id)
2957                         break;
2958                 ast_cli(fd, "%s", ast_getformatname(&tmpfmt));
2959                 ast_cli(fd, ":%d", pref->framing[x]);
2960                 if (x < 31 && ast_codec_pref_index(pref, x + 1, &tmpfmt))
2961                         ast_cli(fd, ",");
2962         }
2963         if (!x)
2964                 ast_cli(fd, "none");
2965 }
2966
2967 static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2968 {
2969         struct ooh323_user *prev = NULL, *user = NULL;
2970
2971         switch (cmd) {
2972         case CLI_INIT:
2973                 e->command = "ooh323 show user";
2974                 e->usage =
2975                         "Usage: ooh323 show user <name>\n"
2976                         "                List details of specific OOH323 user.\n";
2977                 return NULL;
2978         case CLI_GENERATE:
2979                 return NULL;
2980         }
2981
2982         if (a->argc != 4)
2983                 return CLI_SHOWUSAGE;
2984
2985
2986         ast_mutex_lock(&userl.lock);
2987         user = userl.users;
2988         while (user) {
2989                 ast_mutex_lock(&user->lock);
2990       if(!strcmp(user->name, a->argv[3])) {
2991                         break;
2992       } else {
2993                         prev = user;
2994                         user = user->next;
2995                         ast_mutex_unlock(&prev->lock);
2996                 }
2997         }
2998
2999         if (user) {
3000       ast_cli(a->fd, "%-15.15s%s\n", "Name: ", user->name);
3001       ast_cli(a->fd, "%s:%s,%s\n", "FastStart/H.245 Tunneling", user->faststart?"yes":"no",
3002                                         user->h245tunneling?"yes":"no");
3003       ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "(");
3004       print_codec_to_cli(a->fd, &user->prefs);
3005       ast_cli(a->fd, ")\n");
3006       ast_cli(a->fd, "%-15.15s", "DTMF Mode: ");
3007                 if (user->dtmfmode & H323_DTMF_CISCO) {
3008          ast_cli(a->fd, "%s\n", "cisco");
3009          ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec);
3010                 } else if (user->dtmfmode & H323_DTMF_RFC2833) {
3011          ast_cli(a->fd, "%s\n", "rfc2833");
3012          ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec);
3013                 } else if (user->dtmfmode & H323_DTMF_Q931)
3014          ast_cli(a->fd, "%s\n", "q931keypad");
3015                 else if (user->dtmfmode & H323_DTMF_H245ALPHANUMERIC)
3016          ast_cli(a->fd, "%s\n", "h245alphanumeric");
3017                 else if (user->dtmfmode & H323_DTMF_H245SIGNAL)
3018          ast_cli(a->fd, "%s\n", "h245signal");
3019                 else if (user->dtmfmode & H323_DTMF_INBAND && user->dtmfmode & H323_DTMF_INBANDRELAX)
3020          ast_cli(a->fd, "%s\n", "inband-relaxed");
3021                 else if (user->dtmfmode & H323_DTMF_INBAND)
3022          ast_cli(a->fd, "%s\n", "inband");
3023                 else
3024          ast_cli(a->fd, "%s\n", "unknown");
3025
3026         ast_cli(a->fd,"%-15s", "T.38 Mode: ");
3027         if (user->t38support == T38_DISABLED)
3028                 ast_cli(a->fd, "%s\n", "disabled");
3029         else if (user->t38support == T38_FAXGW)
3030                 ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible");
3031
3032       ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", user->accountcode);
3033       ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", 
3034                                             ast_cdr_flags2str(user->amaflags));
3035       ast_cli(a->fd, "%-15.15s%s\n", "Context: ", user->context);
3036       ast_cli(a->fd, "%-15.15s%d\n", "IncomingLimit: ", user->incominglimit);
3037       ast_cli(a->fd, "%-15.15s%d\n", "InUse: ", user->inUse);
3038       ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", user->rtptimeout);
3039         if (user->rtpmaskstr[0])
3040                 ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", user->rtpmaskstr);
3041                 ast_mutex_unlock(&user->lock);
3042         if (user->rtdrcount && user->rtdrinterval) 
3043                 ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", user->rtdrcount, user->rtdrinterval);
3044         } else {
3045      ast_cli(a->fd, "User %s not found\n", a->argv[3]);
3046      ast_cli(a->fd, "\n");
3047         }
3048         ast_mutex_unlock(&userl.lock);
3049
3050         return CLI_SUCCESS;
3051 }
3052
3053 static char *handle_cli_ooh323_show_users(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3054 {
3055         struct ooh323_user *prev = NULL, *user = NULL;
3056    char formats[FORMAT_STRING_SIZE];
3057 #define FORMAT1  "%-15.15s  %-15.15s  %-15.15s  %-s\n"
3058
3059         switch (cmd) {
3060         case CLI_INIT:
3061                 e->command = "ooh323 show users";
3062                 e->usage =
3063                         "Usage: ooh323 show users \n"
3064                         "                Lists all known OOH323 users.\n";
3065                 return NULL;
3066         case CLI_GENERATE:
3067                 return NULL;
3068         }
3069
3070         if (a->argc != 3)
3071                 return CLI_SHOWUSAGE;
3072
3073
3074    ast_cli(a->fd, FORMAT1, "Username", "Accountcode", "Context", "Formats");
3075
3076         ast_mutex_lock(&userl.lock);
3077         user = userl.users;
3078    while(user)
3079    {
3080                 ast_mutex_lock(&user->lock);
3081                 ast_cli(a->fd, FORMAT1, user->name, 
3082                                         user->accountcode, user->context,
3083                                         ast_getformatname_multiple(formats, FORMAT_STRING_SIZE, user->cap));
3084                 prev = user;
3085                 user = user->next;
3086                 ast_mutex_unlock(&prev->lock);
3087
3088         }
3089         ast_mutex_unlock(&userl.lock);
3090 #undef FORMAT1
3091    return RESULT_SUCCESS;
3092
3093 }
3094
3095 static char *handle_cli_ooh323_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3096 {
3097         switch (cmd) {
3098         case CLI_INIT:
3099                 e->command = "ooh323 set debug [off]";
3100                 e->usage =
3101                         "Usage: ooh323 set debug [off]\n"
3102                         "                Enables/Disables debugging of OOH323 channel driver\n";
3103                 return NULL;
3104         case CLI_GENERATE:
3105                 return NULL;
3106         }
3107
3108         if (a->argc < 3 || a->argc > 4)
3109                 return CLI_SHOWUSAGE;
3110         if (a->argc == 4 && strcasecmp(a->argv[3], "off"))
3111                 return CLI_SHOWUSAGE;
3112
3113         gH323Debug = (a->argc == 4) ? FALSE : TRUE;
3114         ast_cli(a->fd, "OOH323 Debugging %s\n", gH323Debug ? "Enabled" : "Disabled");
3115
3116         return CLI_SUCCESS;
3117 }
3118
3119 #if 0
3120 static int ooh323_show_channels(int fd, int argc, char *argv[])
3121 {
3122         return RESULT_SUCCESS;
3123 }
3124 #endif
3125
3126 static char *handle_cli_ooh323_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3127 {
3128         char value[FORMAT_STRING_SIZE];
3129         ooAliases *pAlias = NULL, *pAliasNext = NULL;;
3130
3131         switch (cmd) {
3132         case CLI_INIT:
3133                 e->command = "ooh323 show config";
3134                 e->usage =
3135                         "Usage: ooh323 show config\n"
3136                         "                Shows global configuration of H.323 channel driver\n";
3137                 return NULL;
3138         case CLI_GENERATE:
3139                 return NULL;
3140         }
3141
3142         if (a->argc != 3)
3143                 return CLI_SHOWUSAGE;
3144
3145
3146
3147    ast_cli(a->fd, "\nObjective Open H.323 Channel Driver's Config:\n");
3148         snprintf(value, sizeof(value), "%s:%d", gIP, gPort);
3149    ast_cli(a->fd, "%-20s%s\n", "IP:Port: ", value);
3150    ast_cli(a->fd, "%-20s%d-%d\n", "H.225 port range: ", 
3151       ooconfig.mTCPPortStart, ooconfig.mTCPPortEnd);
3152    ast_cli(a->fd, "%-20s%s\n", "FastStart", gFastStart?"yes":"no");
3153    ast_cli(a->fd, "%-20s%s\n", "Tunneling", gTunneling?"yes":"no");
3154    ast_cli(a->fd, "%-20s%s\n", "CallerId", gCallerID);
3155    ast_cli(a->fd, "%-20s%s\n", "MediaWaitForConnect", 
3156       gMediaWaitForConnect?"yes":"no");
3157
3158 #if (0)
3159                 extern OOH323EndPoint gH323ep;
3160    ast_cli(a->fd, "%-20s%s\n", "FASTSTART", 
3161                         (OO_TESTFLAG(gH323ep.flags, OO_M_FASTSTART) != 0) ? "yes" : "no");
3162    ast_cli(a->fd, "%-20s%s\n", "TUNNELING", 
3163                         (OO_TESTFLAG(gH323ep.flags, OO_M_TUNNELING) != 0) ? "yes" : "no");
3164    ast_cli(a->fd, "%-20s%s\n", "MEDIAWAITFORCONN",
3165                         (OO_TESTFLAG(gH323ep.flags, OO_M_MEDIAWAITFORCONN) != 0) ? "yes" : "no");
3166 #endif
3167
3168         if (gRasGkMode == RasNoGatekeeper)
3169                 snprintf(value, sizeof(value), "%s", "No Gatekeeper");
3170         else if (gRasGkMode == RasDiscoverGatekeeper)
3171                 snprintf(value, sizeof(value), "%s", "Discover");
3172         else
3173                 snprintf(value, sizeof(value), "%s", gGatekeeper);
3174
3175    ast_cli(a->fd,  "%-20s%s\n", "Gatekeeper:", value);
3176
3177    ast_cli(a->fd,  "%-20s%s\n", "H.323 LogFile:", gLogFile);   
3178
3179    ast_cli(a->fd,  "%-20s%s\n", "Context:", gContext);
3180    
3181    ast_cli(a->fd,  "%-20s%s\n", "Capability:", 
3182            ast_getformatname_multiple(value,FORMAT_STRING_SIZE,gCap));
3183
3184    ast_cli(a->fd, "%-20s", "DTMF Mode: ");
3185         if (gDTMFMode & H323_DTMF_CISCO) {
3186       ast_cli(a->fd, "%s\n", "cisco");
3187       ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", gDTMFCodec);
3188         } else if (gDTMFMode & H323_DTMF_RFC2833) {
3189       ast_cli(a->fd, "%s\n", "rfc2833");
3190       ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", gDTMFCodec);
3191         } else if (gDTMFMode & H323_DTMF_Q931)
3192       ast_cli(a->fd, "%s\n", "q931keypad");
3193         else if (gDTMFMode & H323_DTMF_H245ALPHANUMERIC)
3194       ast_cli(a->fd, "%s\n", "h245alphanumeric");
3195         else if (gDTMFMode & H323_DTMF_H245SIGNAL)
3196       ast_cli(a->fd, "%s\n", "h245signal");
3197                 else if (gDTMFMode & H323_DTMF_INBAND && gDTMFMode & H323_DTMF_INBANDRELAX)
3198          ast_cli(a->fd, "%s\n", "inband-relaxed");
3199                 else if (gDTMFMode & H323_DTMF_INBAND)
3200          ast_cli(a->fd, "%s\n", "inband");
3201         else
3202                 ast_cli(a->fd, "%s\n", "unknown");
3203
3204         ast_cli(a->fd,"%-20s", "T.38 Mode: ");
3205         if (gT38Support == T38_DISABLED)
3206                 ast_cli(a->fd, "%s\n", "disabled");
3207         else if (gT38Support == T38_FAXGW)
3208                 ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible");
3209
3210         if (gRTDRCount && gRTDRInterval)
3211                 ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", gRTDRCount, gRTDRInterval);
3212
3213    ast_cli(a->fd, "%-20s%ld\n", "Call counter: ", callnumber);
3214    ast_cli(a->fd, "%-20s%s\n", "AccountCode: ", gAccountcode);
3215
3216    ast_cli(a->fd, "%-20s%s\n", "AMA flags: ", ast_cdr_flags2str(gAMAFLAGS));
3217
3218         pAlias = gAliasList;
3219    if(pAlias) {
3220      ast_cli(a->fd, "%-20s\n", "Aliases: ");
3221    }
3222         while (pAlias) {
3223                 pAliasNext = pAlias->next;
3224                 if (pAliasNext) {
3225          ast_cli(a->fd,"\t%-30s\t%-30s\n",pAlias->value, pAliasNext->value);
3226                         pAlias = pAliasNext->next;
3227       }
3228       else{
3229          ast_cli(a->fd,"\t%-30s\n",pAlias->value);
3230                         pAlias = pAlias->next;
3231                 }
3232         }
3233         return CLI_SUCCESS;
3234 }
3235
3236 static struct ast_cli_entry cli_ooh323[] = {
3237         AST_CLI_DEFINE(handle_cli_ooh323_set_debug,     "Enable/Disable OOH323 debugging"),
3238         AST_CLI_DEFINE(handle_cli_ooh323_show_config, "Show details on global configuration of H.323 channel driver"),
3239         AST_CLI_DEFINE(handle_cli_ooh323_show_peer,     "Show details on specific OOH323 peer"),
3240         AST_CLI_DEFINE(handle_cli_ooh323_show_peers,  "Show defined OOH323 peers"),
3241         AST_CLI_DEFINE(handle_cli_ooh323_show_user,     "Show details on specific OOH323 user"),
3242         AST_CLI_DEFINE(handle_cli_ooh323_show_users,  "Show defined OOH323 users"),
3243         AST_CLI_DEFINE(handle_cli_ooh323_reload, "reload ooh323 config")
3244 };
3245
3246
3247 static int load_module(void)
3248 {
3249         int res;
3250         struct ooAliases * pNewAlias = NULL;
3251         struct ooh323_peer *peer = NULL;
3252         struct ast_format tmpfmt;
3253         OOH225MsgCallbacks h225Callbacks = {0, 0, 0, 0};
3254
3255         OOH323CALLBACKS h323Callbacks = {
3256                 .onNewCallCreated = onNewCallCreated,
3257                 .onAlerting = onAlerting,
3258                 .onProgress = onProgress,
3259                 .onIncomingCall = NULL,
3260                 .onOutgoingCall = onOutgoingCall,
3261                 .onCallEstablished = onCallEstablished,
3262                 .onCallCleared = onCallCleared,
3263                 .openLogicalChannels = NULL,
3264                 .onReceivedDTMF = ooh323_onReceivedDigit,
3265                 .onModeChanged = onModeChanged
3266         };
3267         if (!(gCap = ast_format_cap_alloc())) {
3268                 return 1; 
3269         }
3270         if (!(ooh323_tech.capabilities = ast_format_cap_alloc())) {
3271                 return 1;
3272         }
3273         ast_format_cap_add(gCap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
3274         ast_format_cap_add_all(ooh323_tech.capabilities);
3275
3276         myself = ast_module_info->self;
3277
3278         h225Callbacks.onReceivedSetup = &ooh323_onReceivedSetup;
3279
3280         userl.users = NULL;
3281         ast_mutex_init(&userl.lock);
3282         peerl.peers = NULL;
3283         ast_mutex_init(&peerl.lock);
3284  
3285 #if 0           
3286         ast_register_atexit(&ast_ooh323c_exit);
3287 #endif
3288
3289         if (!(sched = ast_sched_context_create())) {
3290                 ast_log(LOG_WARNING, "Unable to create schedule context\n");
3291         }
3292         if (!(io = io_context_create())) {
3293                 ast_log(LOG_WARNING, "Unable to create I/O context\n");
3294         }
3295
3296
3297         if (!(res = reload_config(0))) {
3298                 /* Make sure we can register our OOH323 channel type */
3299                 if (ast_channel_register(&ooh323_tech)) {
3300                         ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
3301                         return 0;
3302                 }
3303                 ast_rtp_glue_register(&ooh323_rtp);
3304                 ast_udptl_proto_register(&ooh323_udptl);
3305                 ast_cli_register_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry));
3306
3307                  /* fire up the H.323 Endpoint */                
3308                 if (OO_OK != ooH323EpInitialize(OO_CALLMODE_AUDIOCALL, gLogFile)) {
3309          ast_log(LOG_ERROR, "Failed to initialize OOH323 endpoint-"
3310                             "OOH323 Disabled\n");
3311                         return 1;
3312                 }
3313
3314                 if (gIsGateway)
3315                         ooH323EpSetAsGateway();
3316
3317                 ooH323EpSetVersionInfo(t35countrycode, t35extensions, manufacturer,
3318                                                                          vendor, version);
3319                 ooH323EpDisableAutoAnswer();
3320                 ooH323EpSetH225MsgCallbacks(h225Callbacks);
3321                 ooH323EpSetTraceLevel(gTRCLVL);
3322                 ooH323EpSetLocalAddress(gIP, gPort);
3323                 ooH323EpSetCallerID(gCallerID);
3324  
3325       if(ooH323EpSetTCPPortRange(ooconfig.mTCPPortStart, 
3326                                  ooconfig.mTCPPortEnd) == OO_FAILED) {
3327          ast_log(LOG_ERROR, "h225portrange: Failed to set range\n");
3328       }
3329
3330                 /* Set aliases if any */
3331                 for (pNewAlias = gAliasList; pNewAlias; pNewAlias = pNewAlias->next) {
3332                         switch (pNewAlias->type) {
3333                         case T_H225AliasAddress_h323_ID:
3334                                 ooH323EpAddAliasH323ID(pNewAlias->value);
3335                                 break;
3336                         case T_H225AliasAddress_dialedDigits:   
3337                                 ooH323EpAddAliasDialedDigits(pNewAlias->value);
3338                                 break;
3339                         case T_H225AliasAddress_email_ID:       
3340                                 ooH323EpAddAliasEmailID(pNewAlias->value);
3341                                 break;
3342          default:
3343             ;
3344                         }
3345                 }
3346
3347                 ast_mutex_lock(&peerl.lock);
3348                 peer = peerl.peers;
3349                 while (peer) {
3350          if(peer->h323id) ooH323EpAddAliasH323ID(peer->h323id);
3351          if(peer->email)  ooH323EpAddAliasEmailID(peer->email);
3352          if(peer->e164)   ooH323EpAddAliasDialedDigits(peer->e164);
3353          if(peer->url)    ooH323EpAddAliasURLID(peer->url);
3354                         peer = peer->next;
3355                 }
3356                 ast_mutex_unlock(&peerl.lock);
3357         
3358
3359                 if (gMediaWaitForConnect)
3360                         ooH323EpEnableMediaWaitForConnect();
3361                 else 
3362                         ooH323EpDisableMediaWaitForConnect();
3363
3364                 /* Fast start and tunneling options */
3365                 if (gFastStart)
3366                         ooH323EpEnableFastStart();
3367                 else
3368                         ooH323EpDisableFastStart();
3369
3370                 if (!gTunneling)
3371                         ooH323EpDisableH245Tunneling();
3372
3373                 if (gBeMaster)
3374                         ooH323EpTryBeMaster(1);
3375
3376                 ooH323EpEnableManualRingback();
3377
3378                 /* Gatekeeper */
3379                 if (gRasGkMode == RasUseSpecificGatekeeper)
3380                         ooGkClientInit(gRasGkMode, gGatekeeper, 0);
3381                 else if (gRasGkMode == RasDiscoverGatekeeper)
3382                         ooGkClientInit(gRasGkMode, 0, 0);
3383
3384                 /* Register callbacks */
3385                 ooH323EpSetH323Callbacks(h323Callbacks);
3386
3387                 /* Add endpoint capabilities */
3388                 if (ooh323c_set_capability(&gPrefs, gCap, gDTMFMode, gDTMFCodec) < 0) {
3389                         ast_log(LOG_ERROR, "Capabilities failure for OOH323. OOH323 Disabled.\n");
3390                         return 1;
3391                 }
3392   
3393                 /* Create H.323 listener */
3394                 if (ooCreateH323Listener() != OO_OK) {
3395          ast_log(LOG_ERROR, "OOH323 Listener Creation failure. "
3396                             "OOH323 DISABLED\n");
3397                 
3398                         ooH323EpDestroy();
3399                         return 1;
3400                 }
3401
3402                 if (ooh323c_start_stack_thread() < 0) {
3403          ast_log(LOG_ERROR, "Failed to start OOH323 stack thread. "
3404                             "OOH323 DISABLED\n");
3405                         ooH323EpDestroy();
3406                         return 1;
3407                 }
3408                 /* And start the monitor for the first time */
3409                 restart_monitor();
3410         }
3411
3412         return 0;
3413 }
3414
3415
3416 static void *do_monitor(void *data)
3417 {
3418         int res;
3419         int reloading;
3420         struct ooh323_pvt *h323 = NULL;
3421         time_t t;
3422
3423         for (;;) {
3424                 struct ooh323_pvt *h323_next;
3425                 /* Check for a reload request */
3426                 ast_mutex_lock(&h323_reload_lock);
3427                 reloading = h323_reloading;
3428                 h323_reloading = 0;
3429                 ast_mutex_unlock(&h323_reload_lock);
3430                 if (reloading) {
3431                         ast_verb(1, "Reloading H.323\n");
3432                         ooh323_do_reload();
3433                 }
3434
3435                 /* Check for interfaces needing to be killed */
3436                 ast_mutex_lock(&iflock);
3437                 time(&t);
3438                 h323 = iflist;
3439                 while (h323) {
3440                         h323_next = h323->next;
3441
3442                         /* TODO: Need to add rtptimeout keepalive support */
3443                         if (ast_test_flag(h323, H323_NEEDDESTROY)) {
3444                                 ooh323_destroy (h323);
3445          } /* else if (ast_test_flag(h323, H323_NEEDSTART) && h323->owner) {
3446           ast_channel_lock(h323->owner);
3447           if (ast_pbx_start(h323->owner)) {
3448             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", h323->owner->name);
3449             ast_channel_unlock(h323->owner);
3450             ast_hangup(h323->owner);
3451           }
3452           ast_channel_unlock(h323->owner);
3453           ast_clear_flag(h323, H323_NEEDSTART);
3454          } */
3455                         h323 = h323_next;
3456                 }
3457                 ast_mutex_unlock(&iflock);
3458                 pthread_testcancel();
3459
3460                 /* Wait for sched or io */
3461                 res = ast_sched_wait(sched);
3462                 if ((res < 0) || (res > 1000)) {
3463                         res = 1000;
3464                 }
3465                 res = ast_io_wait(io, res);
3466                 pthread_testcancel();
3467                 ast_mutex_lock(&monlock);
3468                 if (res >= 0) {
3469                         ast_sched_runq(sched);
3470                 }
3471                 ast_mutex_unlock(&monlock);