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