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