when building a version string for a developer branch, include the base branch in...
[asterisk-bristuff.git] / channels / chan_h323.c
blobe006dc821ca3065491ca2f12b0eba6f0d984efaa
1 /*
2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005
6 * OpenH323 Channel Driver for ASTERISK PBX.
7 * By Jeremy McNamara
8 * For The NuFone Network
10 * chan_h323 has been derived from code created by
11 * Michael Manousos and Mark Spencer
13 * See http://www.asterisk.org for more information about
14 * the Asterisk project. Please do not directly contact
15 * any of the maintainers of this project for assistance;
16 * the project provides a web site, mailing lists and IRC
17 * channels for your use.
19 * This program is free software, distributed under the terms of
20 * the GNU General Public License Version 2. See the LICENSE file
21 * at the top of the source tree.
24 /*! \file
26 * \brief This file is part of the chan_h323 driver for Asterisk
28 * \author Jeremy McNamara
30 * \par See also
31 * \arg Config_h323
33 * \ingroup channel_drivers
36 /*** MODULEINFO
37 <depend>openh323</depend>
38 <defaultenabled>yes</defaultenabled>
39 ***/
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
45 #include "asterisk.h"
47 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
49 #ifdef __cplusplus
51 #endif
53 #include <sys/socket.h>
54 #include <sys/signal.h>
55 #include <sys/param.h>
56 #if defined(BSD)
57 #ifndef IPTOS_MINCOST
58 #define IPTOS_MINCOST 0x02
59 #endif
60 #endif
61 #include <arpa/inet.h>
62 #include <net/if.h>
63 #include <netinet/in.h>
64 #include <netinet/in_systm.h>
65 #include <netinet/ip.h>
66 #include <unistd.h>
67 #include <stdlib.h>
68 #include <netdb.h>
69 #include <stdio.h>
70 #include <string.h>
71 #include <errno.h>
72 #include <fcntl.h>
74 #ifdef __cplusplus
75 extern "C" {
76 #endif
78 #include "asterisk/lock.h"
79 #include "asterisk/logger.h"
80 #include "asterisk/channel.h"
81 #include "asterisk/config.h"
82 #include "asterisk/module.h"
83 #include "asterisk/musiconhold.h"
84 #include "asterisk/pbx.h"
85 #include "asterisk/options.h"
86 #include "asterisk/utils.h"
87 #include "asterisk/lock.h"
88 #include "asterisk/sched.h"
89 #include "asterisk/io.h"
90 #include "asterisk/rtp.h"
91 #include "asterisk/acl.h"
92 #include "asterisk/callerid.h"
93 #include "asterisk/cli.h"
94 #include "asterisk/dsp.h"
95 #include "asterisk/causes.h"
96 #include "asterisk/stringfields.h"
97 #include "asterisk/abstract_jb.h"
98 #include "asterisk/astobj.h"
100 #ifdef __cplusplus
102 #endif
104 #include "h323/chan_h323.h"
106 receive_digit_cb on_receive_digit;
107 on_rtp_cb on_external_rtp_create;
108 start_rtp_cb on_start_rtp_channel;
109 setup_incoming_cb on_incoming_call;
110 setup_outbound_cb on_outgoing_call;
111 chan_ringing_cb on_chan_ringing;
112 con_established_cb on_connection_established;
113 clear_con_cb on_connection_cleared;
114 answer_call_cb on_answer_call;
115 progress_cb on_progress;
116 rfc2833_cb on_set_rfc2833_payload;
117 hangup_cb on_hangup;
118 setcapabilities_cb on_setcapabilities;
119 setpeercapabilities_cb on_setpeercapabilities;
121 /* global debug flag */
122 int h323debug;
124 /*! Global jitterbuffer configuration - by default, jb is disabled */
125 static struct ast_jb_conf default_jbconf =
127 .flags = 0,
128 .max_size = -1,
129 .resync_threshold = -1,
130 .impl = ""
132 static struct ast_jb_conf global_jbconf;
134 /** Variables required by Asterisk */
135 static const char tdesc[] = "The NuFone Network's Open H.323 Channel Driver";
136 static const char config[] = "h323.conf";
137 static char default_context[AST_MAX_CONTEXT] = "default";
138 static struct sockaddr_in bindaddr;
140 #define GLOBAL_CAPABILITY (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_H261)
142 /** H.323 configuration values */
143 static int h323_signalling_port = 1720;
144 static char gatekeeper[100];
145 static int gatekeeper_disable = 1;
146 static int gatekeeper_discover = 0;
147 static int gkroute = 0;
148 /* Find user by alias (h.323 id) is default, alternative is the incomming call's source IP address*/
149 static int userbyalias = 1;
150 static int acceptAnonymous = 1;
151 static int tos = 0;
152 static char secret[50];
153 static unsigned int unique = 0;
155 static call_options_t global_options;
157 /** Private structure of a OpenH323 channel */
158 struct oh323_pvt {
159 ast_mutex_t lock; /* Channel private lock */
160 call_options_t options; /* Options to be used during call setup */
161 int alreadygone; /* Whether or not we've already been destroyed by our peer */
162 int needdestroy; /* if we need to be destroyed */
163 call_details_t cd; /* Call details */
164 struct ast_channel *owner; /* Who owns us */
165 struct sockaddr_in sa; /* Our peer */
166 struct sockaddr_in redirip; /* Where our RTP should be going if not to us */
167 int nonCodecCapability; /* non-audio capability */
168 int outgoing; /* Outgoing or incoming call? */
169 char exten[AST_MAX_EXTENSION]; /* Requested extension */
170 char context[AST_MAX_CONTEXT]; /* Context where to start */
171 char accountcode[256]; /* Account code */
172 char rdnis[80]; /* Referring DNIS, if available */
173 int amaflags; /* AMA Flags */
174 struct ast_rtp *rtp; /* RTP Session */
175 struct ast_dsp *vad; /* Used for in-band DTMF detection */
176 int nativeformats; /* Codec formats supported by a channel */
177 int needhangup; /* Send hangup when Asterisk is ready */
178 int hangupcause; /* Hangup cause from OpenH323 layer */
179 int newstate; /* Pending state change */
180 int newcontrol; /* Pending control to send */
181 int newdigit; /* Pending DTMF digit to send */
182 int newduration; /* Pending DTMF digit duration to send */
183 int pref_codec; /* Preferred codec */
184 int peercapability; /* Capabilities learned from peer */
185 int jointcapability; /* Common capabilities for local and remote side */
186 struct ast_codec_pref peer_prefs; /* Preferenced list of codecs which remote side supports */
187 int dtmf_pt; /* Payload code used for RFC2833 messages */
188 int curDTMF; /* DTMF tone being generated to Asterisk side */
189 int DTMFsched; /* Scheduler descriptor for DTMF */
190 int update_rtp_info; /* Configuration of fd's array is pending */
191 int recvonly; /* Peer isn't wish to receive our voice stream */
192 int txDtmfDigit; /* DTMF digit being to send to H.323 side */
193 int noInbandDtmf; /* Inband DTMF processing by DSP isn't available */
194 int connection_established; /* Call got CONNECT message */
195 int got_progress; /* Call got PROGRESS message, pass inband audio */
196 struct oh323_pvt *next; /* Next channel in list */
197 } *iflist = NULL;
199 static struct ast_user_list {
200 ASTOBJ_CONTAINER_COMPONENTS(struct oh323_user);
201 } userl;
203 static struct ast_peer_list {
204 ASTOBJ_CONTAINER_COMPONENTS(struct oh323_peer);
205 } peerl;
207 static struct ast_alias_list {
208 ASTOBJ_CONTAINER_COMPONENTS(struct oh323_alias);
209 } aliasl;
211 /** Asterisk RTP stuff */
212 static struct sched_context *sched;
213 static struct io_context *io;
215 /** Protect the interface list (oh323_pvt) */
216 AST_MUTEX_DEFINE_STATIC(iflock);
218 /* Protect the monitoring thread, so only one process can kill or start it, and not
219 when it's doing something critical. */
220 AST_MUTEX_DEFINE_STATIC(monlock);
222 /* Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack. */
223 AST_MUTEX_DEFINE_STATIC(caplock);
225 /* Protect the reload process */
226 AST_MUTEX_DEFINE_STATIC(h323_reload_lock);
227 static int h323_reloading = 0;
229 /* This is the thread for the monitor which checks for input on the channels
230 which are not currently in use. */
231 static pthread_t monitor_thread = AST_PTHREADT_NULL;
232 static int restart_monitor(void);
233 static int h323_do_reload(void);
235 static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause);
236 static int oh323_digit_begin(struct ast_channel *c, char digit);
237 static int oh323_digit_end(struct ast_channel *c, char digit, unsigned int duration);
238 static int oh323_call(struct ast_channel *c, char *dest, int timeout);
239 static int oh323_hangup(struct ast_channel *c);
240 static int oh323_answer(struct ast_channel *c);
241 static struct ast_frame *oh323_read(struct ast_channel *c);
242 static int oh323_write(struct ast_channel *c, struct ast_frame *frame);
243 static int oh323_indicate(struct ast_channel *c, int condition, const void *data, size_t datalen);
244 static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
246 static const struct ast_channel_tech oh323_tech = {
247 .type = "H323",
248 .description = tdesc,
249 .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
250 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
251 .requester = oh323_request,
252 .send_digit_begin = oh323_digit_begin,
253 .send_digit_end = oh323_digit_end,
254 .call = oh323_call,
255 .hangup = oh323_hangup,
256 .answer = oh323_answer,
257 .read = oh323_read,
258 .write = oh323_write,
259 .indicate = oh323_indicate,
260 .fixup = oh323_fixup,
261 /* disable, for now */
262 #if 0
263 .bridge = ast_rtp_bridge,
264 #endif
267 static const char* redirectingreason2str(int redirectingreason)
269 switch (redirectingreason) {
270 case 0:
271 return "UNKNOWN";
272 case 1:
273 return "BUSY";
274 case 2:
275 return "NO_REPLY";
276 case 0xF:
277 return "UNCONDITIONAL";
278 default:
279 return "NOREDIRECT";
283 static void oh323_destroy_alias(struct oh323_alias *alias)
285 if (h323debug)
286 ast_log(LOG_DEBUG, "Destroying alias '%s'\n", alias->name);
287 free(alias);
290 static void oh323_destroy_user(struct oh323_user *user)
292 if (h323debug)
293 ast_log(LOG_DEBUG, "Destroying user '%s'\n", user->name);
294 ast_free_ha(user->ha);
295 free(user);
298 static void oh323_destroy_peer(struct oh323_peer *peer)
300 if (h323debug)
301 ast_log(LOG_DEBUG, "Destroying peer '%s'\n", peer->name);
302 ast_free_ha(peer->ha);
303 free(peer);
306 static int oh323_simulate_dtmf_end(void *data)
308 struct oh323_pvt *pvt = data;
310 if (pvt) {
311 ast_mutex_lock(&pvt->lock);
312 /* Don't hold pvt lock while trying to lock the channel */
313 while(pvt->owner && ast_channel_trylock(pvt->owner)) {
314 ast_mutex_unlock(&pvt->lock);
315 usleep(1);
316 ast_mutex_lock(&pvt->lock);
319 if (pvt->owner) {
320 struct ast_frame f = {
321 .frametype = AST_FRAME_DTMF_END,
322 .subclass = pvt->curDTMF,
323 .samples = 0,
324 .src = "SIMULATE_DTMF_END",
326 ast_queue_frame(pvt->owner, &f);
327 ast_channel_unlock(pvt->owner);
330 pvt->DTMFsched = -1;
331 ast_mutex_unlock(&pvt->lock);
334 return 0;
337 /* Channel and private structures should be already locked */
338 static void __oh323_update_info(struct ast_channel *c, struct oh323_pvt *pvt)
340 if (c->nativeformats != pvt->nativeformats) {
341 if (h323debug)
342 ast_log(LOG_DEBUG, "Preparing %s for new native format\n", c->name);
343 c->nativeformats = pvt->nativeformats;
344 ast_set_read_format(c, c->readformat);
345 ast_set_write_format(c, c->writeformat);
347 if (pvt->needhangup) {
348 if (h323debug)
349 ast_log(LOG_DEBUG, "Process pending hangup for %s\n", c->name);
350 c->_softhangup |= AST_SOFTHANGUP_DEV;
351 c->hangupcause = pvt->hangupcause;
352 ast_queue_hangup(c);
353 pvt->needhangup = 0;
354 pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->DTMFsched = -1;
356 if (pvt->newstate >= 0) {
357 ast_setstate(c, pvt->newstate);
358 pvt->newstate = -1;
360 if (pvt->newcontrol >= 0) {
361 ast_queue_control(c, pvt->newcontrol);
362 pvt->newcontrol = -1;
364 if (pvt->newdigit >= 0) {
365 struct ast_frame f = {
366 .frametype = AST_FRAME_DTMF_END,
367 .subclass = pvt->newdigit,
368 .samples = pvt->newduration * 8,
369 .len = pvt->newduration,
370 .src = "UPDATE_INFO",
372 if (pvt->newdigit == ' ') { /* signalUpdate message */
373 f.subclass = pvt->curDTMF;
374 if (pvt->DTMFsched >= 0) {
375 ast_sched_del(sched, pvt->DTMFsched);
376 pvt->DTMFsched = -1;
378 } else { /* Regular input or signal message */
379 if (pvt->newduration) { /* This is a signal, signalUpdate follows */
380 f.frametype = AST_FRAME_DTMF_BEGIN;
381 if (pvt->DTMFsched >= 0)
382 ast_sched_del(sched, pvt->DTMFsched);
383 pvt->DTMFsched = ast_sched_add(sched, pvt->newduration, oh323_simulate_dtmf_end, pvt);
384 if (h323debug)
385 ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", pvt->newduration, pvt->DTMFsched);
387 pvt->curDTMF = pvt->newdigit;
389 ast_queue_frame(c, &f);
390 pvt->newdigit = -1;
392 if (pvt->update_rtp_info > 0) {
393 if (pvt->rtp) {
394 ast_jb_configure(c, &global_jbconf);
395 c->fds[0] = ast_rtp_fd(pvt->rtp);
396 c->fds[1] = ast_rtcp_fd(pvt->rtp);
397 ast_queue_frame(pvt->owner, &ast_null_frame); /* Tell Asterisk to apply changes */
399 pvt->update_rtp_info = -1;
403 /* Only channel structure should be locked */
404 static void oh323_update_info(struct ast_channel *c)
406 struct oh323_pvt *pvt = c->tech_pvt;
408 if (pvt) {
409 ast_mutex_lock(&pvt->lock);
410 __oh323_update_info(c, pvt);
411 ast_mutex_unlock(&pvt->lock);
415 static void cleanup_call_details(call_details_t *cd)
417 if (cd->call_token) {
418 free(cd->call_token);
419 cd->call_token = NULL;
421 if (cd->call_source_aliases) {
422 free(cd->call_source_aliases);
423 cd->call_source_aliases = NULL;
425 if (cd->call_dest_alias) {
426 free(cd->call_dest_alias);
427 cd->call_dest_alias = NULL;
429 if (cd->call_source_name) {
430 free(cd->call_source_name);
431 cd->call_source_name = NULL;
433 if (cd->call_source_e164) {
434 free(cd->call_source_e164);
435 cd->call_source_e164 = NULL;
437 if (cd->call_dest_e164) {
438 free(cd->call_dest_e164);
439 cd->call_dest_e164 = NULL;
441 if (cd->sourceIp) {
442 free(cd->sourceIp);
443 cd->sourceIp = NULL;
445 if (cd->redirect_number) {
446 free(cd->redirect_number);
447 cd->redirect_number = NULL;
451 static void __oh323_destroy(struct oh323_pvt *pvt)
453 struct oh323_pvt *cur, *prev = NULL;
455 if (pvt->DTMFsched >= 0) {
456 ast_sched_del(sched, pvt->DTMFsched);
457 pvt->DTMFsched = -1;
460 if (pvt->rtp) {
461 ast_rtp_destroy(pvt->rtp);
464 /* Free dsp used for in-band DTMF detection */
465 if (pvt->vad) {
466 ast_dsp_free(pvt->vad);
468 cleanup_call_details(&pvt->cd);
470 /* Unlink us from the owner if we have one */
471 if (pvt->owner) {
472 ast_channel_lock(pvt->owner);
473 if (h323debug)
474 ast_log(LOG_DEBUG, "Detaching from %s\n", pvt->owner->name);
475 pvt->owner->tech_pvt = NULL;
476 ast_channel_unlock(pvt->owner);
478 cur = iflist;
479 while(cur) {
480 if (cur == pvt) {
481 if (prev)
482 prev->next = cur->next;
483 else
484 iflist = cur->next;
485 break;
487 prev = cur;
488 cur = cur->next;
490 if (!cur) {
491 ast_log(LOG_WARNING, "%p is not in list?!?! \n", cur);
492 } else {
493 ast_mutex_unlock(&pvt->lock);
494 ast_mutex_destroy(&pvt->lock);
495 free(pvt);
499 static void oh323_destroy(struct oh323_pvt *pvt)
501 if (h323debug) {
502 ast_log(LOG_DEBUG, "Destroying channel %s\n", (pvt->owner ? pvt->owner->name : "<unknown>"));
504 ast_mutex_lock(&iflock);
505 ast_mutex_lock(&pvt->lock);
506 __oh323_destroy(pvt);
507 ast_mutex_unlock(&iflock);
510 static int oh323_digit_begin(struct ast_channel *c, char digit)
512 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
513 char *token;
515 if (!pvt) {
516 ast_log(LOG_ERROR, "No private structure?! This is bad\n");
517 return -1;
519 ast_mutex_lock(&pvt->lock);
520 if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833) && (pvt->dtmf_pt > 0)) {
521 /* out-of-band DTMF */
522 if (h323debug) {
523 ast_log(LOG_DTMF, "Begin sending out-of-band digit %c on %s\n", digit, c->name);
525 ast_rtp_senddigit_begin(pvt->rtp, digit);
526 ast_mutex_unlock(&pvt->lock);
527 } else if (pvt->txDtmfDigit != digit) {
528 /* in-band DTMF */
529 if (h323debug) {
530 ast_log(LOG_DTMF, "Begin sending inband digit %c on %s\n", digit, c->name);
532 pvt->txDtmfDigit = digit;
533 token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
534 ast_mutex_unlock(&pvt->lock);
535 h323_send_tone(token, digit);
536 if (token) {
537 free(token);
539 } else
540 ast_mutex_unlock(&pvt->lock);
541 oh323_update_info(c);
542 return 0;
546 * Send (play) the specified digit to the channel.
549 static int oh323_digit_end(struct ast_channel *c, char digit, unsigned int duration)
551 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
552 char *token;
554 if (!pvt) {
555 ast_log(LOG_ERROR, "No private structure?! This is bad\n");
556 return -1;
558 ast_mutex_lock(&pvt->lock);
559 if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833) && (pvt->dtmf_pt > 0)) {
560 /* out-of-band DTMF */
561 if (h323debug) {
562 ast_log(LOG_DTMF, "End sending out-of-band digit %c on %s, duration %d\n", digit, c->name, duration);
564 ast_rtp_senddigit_end(pvt->rtp, digit);
565 ast_mutex_unlock(&pvt->lock);
566 } else {
567 /* in-band DTMF */
568 if (h323debug) {
569 ast_log(LOG_DTMF, "End sending inband digit %c on %s, duration %d\n", digit, c->name, duration);
571 pvt->txDtmfDigit = ' ';
572 token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
573 ast_mutex_unlock(&pvt->lock);
574 h323_send_tone(token, ' ');
575 if (token) {
576 free(token);
579 oh323_update_info(c);
580 return 0;
584 * Make a call over the specified channel to the specified
585 * destination.
586 * Returns -1 on error, 0 on success.
588 static int oh323_call(struct ast_channel *c, char *dest, int timeout)
590 int res = 0;
591 struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;
592 const char *addr;
593 char called_addr[1024];
595 if (h323debug) {
596 ast_log(LOG_DEBUG, "Calling to %s on %s\n", dest, c->name);
598 if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
599 ast_log(LOG_WARNING, "Line is already in use (%s)\n", c->name);
600 return -1;
602 ast_mutex_lock(&pvt->lock);
603 if (!gatekeeper_disable) {
604 if (ast_strlen_zero(pvt->exten)) {
605 ast_copy_string(called_addr, dest, sizeof(called_addr));
606 } else {
607 snprintf(called_addr, sizeof(called_addr), "%s@%s", pvt->exten, dest);
609 } else {
610 res = htons(pvt->sa.sin_port);
611 addr = ast_inet_ntoa(pvt->sa.sin_addr);
612 if (ast_strlen_zero(pvt->exten)) {
613 snprintf(called_addr, sizeof(called_addr), "%s:%d", addr, res);
614 } else {
615 snprintf(called_addr, sizeof(called_addr), "%s@%s:%d", pvt->exten, addr, res);
618 /* make sure null terminated */
619 called_addr[sizeof(called_addr) - 1] = '\0';
621 if (c->cid.cid_num)
622 ast_copy_string(pvt->options.cid_num, c->cid.cid_num, sizeof(pvt->options.cid_num));
624 if (c->cid.cid_name)
625 ast_copy_string(pvt->options.cid_name, c->cid.cid_name, sizeof(pvt->options.cid_name));
627 if (c->cid.cid_rdnis) {
628 ast_copy_string(pvt->options.cid_rdnis, c->cid.cid_rdnis, sizeof(pvt->options.cid_rdnis));
631 pvt->options.presentation = c->cid.cid_pres;
632 pvt->options.type_of_number = c->cid.cid_ton;
634 if ((addr = pbx_builtin_getvar_helper(c, "PRIREDIRECTREASON"))) {
635 if (!strcasecmp(addr, "UNKNOWN"))
636 pvt->options.redirect_reason = 0;
637 else if (!strcasecmp(addr, "BUSY"))
638 pvt->options.redirect_reason = 1;
639 else if (!strcasecmp(addr, "NO_REPLY"))
640 pvt->options.redirect_reason = 2;
641 else if (!strcasecmp(addr, "UNCONDITIONAL"))
642 pvt->options.redirect_reason = 15;
643 else
644 pvt->options.redirect_reason = -1;
645 } else
646 pvt->options.redirect_reason = -1;
648 pvt->options.transfer_capability = c->transfercapability;
650 /* indicate that this is an outgoing call */
651 pvt->outgoing = 1;
653 if (option_verbose > 2)
654 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", c->transfercapability, ast_transfercapability2str(c->transfercapability));
655 if (h323debug)
656 ast_log(LOG_DEBUG, "Placing outgoing call to %s, %d\n", called_addr, pvt->options.dtmfcodec);
657 ast_mutex_unlock(&pvt->lock);
658 res = h323_make_call(called_addr, &(pvt->cd), &pvt->options);
659 if (res) {
660 ast_log(LOG_NOTICE, "h323_make_call failed(%s)\n", c->name);
661 return -1;
663 oh323_update_info(c);
664 return 0;
667 static int oh323_answer(struct ast_channel *c)
669 int res;
670 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
671 char *token;
673 if (h323debug)
674 ast_log(LOG_DEBUG, "Answering on %s\n", c->name);
676 ast_mutex_lock(&pvt->lock);
677 token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
678 ast_mutex_unlock(&pvt->lock);
679 res = h323_answering_call(token, 0);
680 if (token)
681 free(token);
683 oh323_update_info(c);
684 if (c->_state != AST_STATE_UP) {
685 ast_setstate(c, AST_STATE_UP);
687 return res;
690 static int oh323_hangup(struct ast_channel *c)
692 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
693 int q931cause = AST_CAUSE_NORMAL_CLEARING;
694 char *call_token;
697 if (h323debug)
698 ast_log(LOG_DEBUG, "Hanging up and scheduling destroy of call %s\n", c->name);
700 if (!c->tech_pvt) {
701 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
702 return 0;
704 ast_mutex_lock(&pvt->lock);
705 /* Determine how to disconnect */
706 if (pvt->owner != c) {
707 ast_log(LOG_WARNING, "Huh? We aren't the owner?\n");
708 ast_mutex_unlock(&pvt->lock);
709 return 0;
712 pvt->owner = NULL;
713 c->tech_pvt = NULL;
715 if (c->hangupcause) {
716 q931cause = c->hangupcause;
717 } else {
718 const char *cause = pbx_builtin_getvar_helper(c, "DIALSTATUS");
719 if (cause) {
720 if (!strcmp(cause, "CONGESTION")) {
721 q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
722 } else if (!strcmp(cause, "BUSY")) {
723 q931cause = AST_CAUSE_USER_BUSY;
724 } else if (!strcmp(cause, "CHANISUNVAIL")) {
725 q931cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
726 } else if (!strcmp(cause, "NOANSWER")) {
727 q931cause = AST_CAUSE_NO_ANSWER;
728 } else if (!strcmp(cause, "CANCEL")) {
729 q931cause = AST_CAUSE_CALL_REJECTED;
734 /* Start the process if it's not already started */
735 if (!pvt->alreadygone && !pvt->hangupcause) {
736 call_token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
737 if (call_token) {
738 /* Release lock to eliminate deadlock */
739 ast_mutex_unlock(&pvt->lock);
740 if (h323_clear_call(call_token, q931cause)) {
741 ast_log(LOG_WARNING, "ClearCall failed.\n");
743 free(call_token);
744 ast_mutex_lock(&pvt->lock);
747 pvt->needdestroy = 1;
748 ast_mutex_unlock(&pvt->lock);
750 /* Update usage counter */
751 ast_module_unref(ast_module_info->self);
753 return 0;
756 static struct ast_frame *oh323_rtp_read(struct oh323_pvt *pvt)
758 /* Retrieve audio/etc from channel. Assumes pvt->lock is already held. */
759 struct ast_frame *f;
761 /* Only apply it for the first packet, we just need the correct ip/port */
762 if (pvt->options.nat) {
763 ast_rtp_setnat(pvt->rtp, pvt->options.nat);
764 pvt->options.nat = 0;
767 f = ast_rtp_read(pvt->rtp);
768 /* Don't send RFC2833 if we're not supposed to */
769 if (f && (f->frametype == AST_FRAME_DTMF) && !(pvt->options.dtmfmode & H323_DTMF_RFC2833)) {
770 return &ast_null_frame;
772 if (pvt->owner) {
773 /* We already hold the channel lock */
774 if (f->frametype == AST_FRAME_VOICE) {
775 if (f->subclass != pvt->owner->nativeformats) {
776 /* Try to avoid deadlock */
777 if (ast_channel_trylock(pvt->owner)) {
778 ast_log(LOG_NOTICE, "Format changed but channel is locked. Ignoring frame...\n");
779 return &ast_null_frame;
781 if (h323debug)
782 ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
783 pvt->owner->nativeformats = f->subclass;
784 pvt->nativeformats = f->subclass;
785 ast_set_read_format(pvt->owner, pvt->owner->readformat);
786 ast_set_write_format(pvt->owner, pvt->owner->writeformat);
787 ast_channel_unlock(pvt->owner);
789 /* Do in-band DTMF detection */
790 if ((pvt->options.dtmfmode & H323_DTMF_INBAND) && pvt->vad) {
791 if ((pvt->nativeformats & (AST_FORMAT_SLINEAR | AST_FORMAT_ALAW | AST_FORMAT_ULAW))) {
792 if (!ast_channel_trylock(pvt->owner)) {
793 f = ast_dsp_process(pvt->owner, pvt->vad, f);
794 ast_channel_unlock(pvt->owner);
796 else
797 ast_log(LOG_NOTICE, "Unable to process inband DTMF while channel is locked\n");
798 } else if (pvt->nativeformats && !pvt->noInbandDtmf) {
799 ast_log(LOG_NOTICE, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(f->subclass));
800 pvt->noInbandDtmf = 1;
802 if (f &&(f->frametype == AST_FRAME_DTMF)) {
803 if (h323debug)
804 ast_log(LOG_DTMF, "Received in-band digit %c.\n", f->subclass);
809 return f;
812 static struct ast_frame *oh323_read(struct ast_channel *c)
814 struct ast_frame *fr;
815 struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;
816 ast_mutex_lock(&pvt->lock);
817 __oh323_update_info(c, pvt);
818 switch(c->fdno) {
819 case 0:
820 fr = oh323_rtp_read(pvt);
821 break;
822 case 1:
823 if (pvt->rtp)
824 fr = ast_rtcp_read(pvt->rtp);
825 else
826 fr = &ast_null_frame;
827 break;
828 default:
829 ast_log(LOG_ERROR, "Unable to handle fd %d on channel %s\n", c->fdno, c->name);
830 fr = &ast_null_frame;
831 break;
833 ast_mutex_unlock(&pvt->lock);
834 return fr;
837 static int oh323_write(struct ast_channel *c, struct ast_frame *frame)
839 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
840 int res = 0;
841 if (frame->frametype != AST_FRAME_VOICE) {
842 if (frame->frametype == AST_FRAME_IMAGE) {
843 return 0;
844 } else {
845 ast_log(LOG_WARNING, "Can't send %d type frames with H323 write\n", frame->frametype);
846 return 0;
848 } else {
849 if (!(frame->subclass & c->nativeformats)) {
850 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
851 frame->subclass, c->nativeformats, c->readformat, c->writeformat);
852 return 0;
855 if (pvt) {
856 ast_mutex_lock(&pvt->lock);
857 if (pvt->rtp && !pvt->recvonly)
858 res = ast_rtp_write(pvt->rtp, frame);
859 __oh323_update_info(c, pvt);
860 ast_mutex_unlock(&pvt->lock);
862 return res;
865 static int oh323_indicate(struct ast_channel *c, int condition, const void *data, size_t datalen)
868 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
869 char *token = (char *)NULL;
870 int res = -1;
871 int got_progress;
873 ast_mutex_lock(&pvt->lock);
874 token = (pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL);
875 got_progress = pvt->got_progress;
876 if (condition == AST_CONTROL_PROGRESS)
877 pvt->got_progress = 1;
878 else if ((condition == AST_CONTROL_BUSY) || (condition == AST_CONTROL_CONGESTION))
879 pvt->alreadygone = 1;
880 ast_mutex_unlock(&pvt->lock);
882 if (h323debug)
883 ast_log(LOG_DEBUG, "OH323: Indicating %d on %s\n", condition, token);
885 switch(condition) {
886 case AST_CONTROL_RINGING:
887 if (c->_state == AST_STATE_RING || c->_state == AST_STATE_RINGING) {
888 h323_send_alerting(token);
889 res = (got_progress ? 0 : -1); /* Do not simulate any audio tones if we got PROGRESS message */
891 break;
892 case AST_CONTROL_PROGRESS:
893 if (c->_state != AST_STATE_UP) {
894 /* Do not send PROGRESS message more than once */
895 if (!got_progress)
896 h323_send_progress(token);
897 res = 0;
899 break;
900 case AST_CONTROL_BUSY:
901 if (c->_state != AST_STATE_UP) {
902 h323_answering_call(token, 1);
903 ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
904 res = 0;
906 break;
907 case AST_CONTROL_CONGESTION:
908 if (c->_state != AST_STATE_UP) {
909 h323_answering_call(token, 1);
910 ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
911 res = 0;
913 break;
914 case AST_CONTROL_HOLD:
915 ast_moh_start(c, data, NULL);
916 res = 0;
917 break;
918 case AST_CONTROL_UNHOLD:
919 ast_moh_stop(c);
920 res = 0;
921 break;
922 case AST_CONTROL_PROCEEDING:
923 case -1:
924 break;
925 default:
926 ast_log(LOG_WARNING, "OH323: Don't know how to indicate condition %d on %s\n", condition, token);
927 break;
930 if (h323debug)
931 ast_log(LOG_DEBUG, "OH323: Indicated %d on %s, res=%d\n", condition, token, res);
932 if (token)
933 free(token);
934 oh323_update_info(c);
936 return res;
939 static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
941 struct oh323_pvt *pvt = (struct oh323_pvt *) newchan->tech_pvt;
943 ast_mutex_lock(&pvt->lock);
944 if (pvt->owner != oldchan) {
945 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, pvt->owner);
946 return -1;
948 pvt->owner = newchan;
949 ast_mutex_unlock(&pvt->lock);
950 return 0;
953 static int __oh323_rtp_create(struct oh323_pvt *pvt)
955 struct in_addr our_addr;
957 if (pvt->rtp)
958 return 0;
960 if (ast_find_ourip(&our_addr, bindaddr)) {
961 ast_mutex_unlock(&pvt->lock);
962 ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n");
963 return -1;
965 pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, our_addr);
966 if (!pvt->rtp) {
967 ast_mutex_unlock(&pvt->lock);
968 ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
969 return -1;
971 if (h323debug)
972 ast_log(LOG_DEBUG, "Created RTP channel\n");
974 ast_rtp_settos(pvt->rtp, tos);
976 if (h323debug)
977 ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat);
978 ast_rtp_setnat(pvt->rtp, pvt->options.nat);
980 if (pvt->dtmf_pt > 0)
981 ast_rtp_set_rtpmap_type(pvt->rtp, pvt->dtmf_pt, "audio", "telephone-event", 0);
983 if (pvt->peercapability)
984 ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
986 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
987 ast_jb_configure(pvt->owner, &global_jbconf);
988 pvt->owner->fds[0] = ast_rtp_fd(pvt->rtp);
989 pvt->owner->fds[1] = ast_rtcp_fd(pvt->rtp);
990 ast_queue_frame(pvt->owner, &ast_null_frame); /* Tell Asterisk to apply changes */
991 ast_channel_unlock(pvt->owner);
992 } else
993 pvt->update_rtp_info = 1;
995 return 0;
998 /* Private structure should be locked on a call */
999 static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const char *host)
1001 struct ast_channel *ch;
1002 char *cid_num, *cid_name;
1003 int fmt;
1005 if (!ast_strlen_zero(pvt->options.cid_num))
1006 cid_num = pvt->options.cid_num;
1007 else
1008 cid_num = pvt->cd.call_source_e164;
1010 if (!ast_strlen_zero(pvt->options.cid_name))
1011 cid_name = pvt->options.cid_name;
1012 else
1013 cid_name = pvt->cd.call_source_name;
1015 /* Don't hold a oh323_pvt lock while we allocate a chanel */
1016 ast_mutex_unlock(&pvt->lock);
1017 ch = ast_channel_alloc(1, state, cid_num, cid_name, pvt->accountcode, pvt->exten, pvt->context, pvt->amaflags, "H323/%s", host);
1018 /* Update usage counter */
1019 ast_module_ref(ast_module_info->self);
1020 ast_mutex_lock(&pvt->lock);
1021 if (ch) {
1022 ch->tech = &oh323_tech;
1023 if (!(fmt = pvt->jointcapability) && !(fmt = pvt->options.capability))
1024 fmt = global_options.capability;
1025 ch->nativeformats = ast_codec_choose(&pvt->options.prefs, fmt, 1)/* | (pvt->jointcapability & AST_FORMAT_VIDEO_MASK)*/;
1026 pvt->nativeformats = ch->nativeformats;
1027 fmt = ast_best_codec(ch->nativeformats);
1028 ch->writeformat = fmt;
1029 ch->rawwriteformat = fmt;
1030 ch->readformat = fmt;
1031 ch->rawreadformat = fmt;
1032 #if 0
1033 ch->fds[0] = ast_rtp_fd(pvt->rtp);
1034 ch->fds[1] = ast_rtcp_fd(pvt->rtp);
1035 #endif
1036 #ifdef VIDEO_SUPPORT
1037 if (pvt->vrtp) {
1038 ch->fds[2] = ast_rtp_fd(pvt->vrtp);
1039 ch->fds[3] = ast_rtcp_fd(pvt->vrtp);
1041 #endif
1042 #ifdef T38_SUPPORT
1043 if (pvt->udptl) {
1044 ch->fds[4] = ast_udptl_fd(pvt->udptl);
1046 #endif
1047 if (state == AST_STATE_RING) {
1048 ch->rings = 1;
1050 /* Allocate dsp for in-band DTMF support */
1051 if (pvt->options.dtmfmode & H323_DTMF_INBAND) {
1052 pvt->vad = ast_dsp_new();
1053 ast_dsp_set_features(pvt->vad, DSP_FEATURE_DTMF_DETECT);
1055 /* Register channel functions. */
1056 ch->tech_pvt = pvt;
1057 /* Set the owner of this channel */
1058 pvt->owner = ch;
1060 ast_copy_string(ch->context, pvt->context, sizeof(ch->context));
1061 ast_copy_string(ch->exten, pvt->exten, sizeof(ch->exten));
1062 ch->priority = 1;
1063 if (!ast_strlen_zero(pvt->accountcode)) {
1064 ast_string_field_set(ch, accountcode, pvt->accountcode);
1066 if (pvt->amaflags) {
1067 ch->amaflags = pvt->amaflags;
1070 /* Don't use ast_set_callerid() here because it will
1071 * generate a needless NewCallerID event */
1072 ch->cid.cid_num = ast_strdup(cid_num);
1073 ch->cid.cid_ani = ast_strdup(cid_num);
1074 ch->cid.cid_name = ast_strdup(cid_name);
1076 if (pvt->cd.redirect_reason >= 0) {
1077 ch->cid.cid_rdnis = ast_strdup(pvt->cd.redirect_number);
1078 pbx_builtin_setvar_helper(ch, "PRIREDIRECTREASON", redirectingreason2str(pvt->cd.redirect_reason));
1080 ch->cid.cid_pres = pvt->cd.presentation;
1081 ch->cid.cid_ton = pvt->cd.type_of_number;
1083 if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) {
1084 ch->cid.cid_dnid = strdup(pvt->exten);
1086 if (pvt->cd.transfer_capability >= 0)
1087 ch->transfercapability = pvt->cd.transfer_capability;
1088 if (state != AST_STATE_DOWN) {
1089 if (ast_pbx_start(ch)) {
1090 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name);
1091 ast_hangup(ch);
1092 ch = NULL;
1095 } else {
1096 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
1098 return ch;
1101 static struct oh323_pvt *oh323_alloc(int callid)
1103 struct oh323_pvt *pvt;
1105 pvt = (struct oh323_pvt *) malloc(sizeof(struct oh323_pvt));
1106 if (!pvt) {
1107 ast_log(LOG_ERROR, "Couldn't allocate private structure. This is bad\n");
1108 return NULL;
1110 memset(pvt, 0, sizeof(struct oh323_pvt));
1111 pvt->cd.redirect_reason = -1;
1112 pvt->cd.transfer_capability = -1;
1113 /* Ensure the call token is allocated for outgoing call */
1114 if (!callid) {
1115 if ((pvt->cd).call_token == NULL) {
1116 (pvt->cd).call_token = (char *)malloc(128);
1118 if (!pvt->cd.call_token) {
1119 ast_log(LOG_ERROR, "Not enough memory to alocate call token\n");
1120 ast_rtp_destroy(pvt->rtp);
1121 free(pvt);
1122 return NULL;
1124 memset((char *)(pvt->cd).call_token, 0, 128);
1125 pvt->cd.call_reference = callid;
1127 memcpy(&pvt->options, &global_options, sizeof(pvt->options));
1128 pvt->jointcapability = pvt->options.capability;
1129 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
1130 pvt->nonCodecCapability |= AST_RTP_DTMF;
1131 } else {
1132 pvt->nonCodecCapability &= ~AST_RTP_DTMF;
1134 ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
1135 pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->update_rtp_info = pvt->DTMFsched = -1;
1136 ast_mutex_init(&pvt->lock);
1137 /* Add to interface list */
1138 ast_mutex_lock(&iflock);
1139 pvt->next = iflist;
1140 iflist = pvt;
1141 ast_mutex_unlock(&iflock);
1142 return pvt;
1145 static struct oh323_pvt *find_call_locked(int call_reference, const char *token)
1147 struct oh323_pvt *pvt;
1149 ast_mutex_lock(&iflock);
1150 pvt = iflist;
1151 while(pvt) {
1152 if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) {
1153 /* Found the call */
1154 if ((token != NULL) && (!strcmp(pvt->cd.call_token, token))) {
1155 ast_mutex_lock(&pvt->lock);
1156 ast_mutex_unlock(&iflock);
1157 return pvt;
1158 } else if (token == NULL) {
1159 ast_log(LOG_WARNING, "Call Token is NULL\n");
1160 ast_mutex_lock(&pvt->lock);
1161 ast_mutex_unlock(&iflock);
1162 return pvt;
1165 pvt = pvt->next;
1167 ast_mutex_unlock(&iflock);
1168 return NULL;
1171 static int update_state(struct oh323_pvt *pvt, int state, int signal)
1173 if (!pvt)
1174 return 0;
1175 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
1176 if (state >= 0)
1177 ast_setstate(pvt->owner, state);
1178 if (signal >= 0)
1179 ast_queue_control(pvt->owner, signal);
1180 ast_channel_unlock(pvt->owner);
1181 return 1;
1183 else {
1184 if (state >= 0)
1185 pvt->newstate = state;
1186 if (signal >= 0)
1187 pvt->newcontrol = signal;
1188 return 0;
1192 static struct oh323_alias *build_alias(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
1194 struct oh323_alias *alias;
1195 int found = 0;
1197 alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&aliasl, name, name, 0, 0, strcasecmp);
1199 if (alias)
1200 found++;
1201 else {
1202 if (!(alias = (struct oh323_alias *)calloc(1, sizeof(*alias))))
1203 return NULL;
1204 ASTOBJ_INIT(alias);
1206 if (!found && name)
1207 ast_copy_string(alias->name, name, sizeof(alias->name));
1208 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
1209 if (!strcasecmp(v->name, "e164")) {
1210 ast_copy_string(alias->e164, v->value, sizeof(alias->e164));
1211 } else if (!strcasecmp(v->name, "prefix")) {
1212 ast_copy_string(alias->prefix, v->value, sizeof(alias->prefix));
1213 } else if (!strcasecmp(v->name, "context")) {
1214 ast_copy_string(alias->context, v->value, sizeof(alias->context));
1215 } else if (!strcasecmp(v->name, "secret")) {
1216 ast_copy_string(alias->secret, v->value, sizeof(alias->secret));
1217 } else {
1218 if (strcasecmp(v->value, "h323")) {
1219 ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->name);
1223 ASTOBJ_UNMARK(alias);
1224 return alias;
1227 static struct oh323_alias *realtime_alias(const char *alias)
1229 struct ast_variable *var, *tmp;
1230 struct oh323_alias *a;
1232 var = ast_load_realtime("h323", "name", alias, NULL);
1234 if (!var)
1235 return NULL;
1237 for (tmp = var; tmp; tmp = tmp->next) {
1238 if (!strcasecmp(tmp->name, "type") &&
1239 !(!strcasecmp(tmp->value, "alias") || !strcasecmp(tmp->value, "h323"))) {
1240 ast_variables_destroy(var);
1241 return NULL;
1245 a = build_alias(alias, var, NULL, 1);
1247 ast_variables_destroy(var);
1249 return a;
1252 #define DEPRECATED(_v, _new_opt) \
1253 ast_log(LOG_WARNING, "Option %s found at line %d has beed deprecated. Use %s instead.\n", (_v)->name, (_v)->lineno, (_new_opt))
1255 static int update_common_options(struct ast_variable *v, struct call_options *options)
1257 int tmp;
1259 if (!strcasecmp(v->name, "allow")) {
1260 ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 1);
1261 } else if (!strcasecmp(v->name, "disallow")) {
1262 ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0);
1263 } else if (!strcasecmp(v->name, "dtmfmode")) {
1264 if (!strcasecmp(v->value, "inband")) {
1265 options->dtmfmode = H323_DTMF_INBAND;
1266 } else if (!strcasecmp(v->value, "rfc2833")) {
1267 options->dtmfmode = H323_DTMF_RFC2833;
1268 } else {
1269 ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
1270 options->dtmfmode = H323_DTMF_RFC2833;
1272 } else if (!strcasecmp(v->name, "dtmfcodec")) {
1273 tmp = atoi(v->value);
1274 if (tmp < 96)
1275 ast_log(LOG_WARNING, "Invalid %s value %s at line %d\n", v->name, v->value, v->lineno);
1276 else
1277 options->dtmfcodec = tmp;
1278 } else if (!strcasecmp(v->name, "bridge")) {
1279 options->bridge = ast_true(v->value);
1280 } else if (!strcasecmp(v->name, "nat")) {
1281 options->nat = ast_true(v->value);
1282 } else if (!strcasecmp(v->name, "noFastStart")) {
1283 DEPRECATED(v, "fastStart");
1284 options->fastStart = !ast_true(v->value);
1285 } else if (!strcasecmp(v->name, "fastStart")) {
1286 options->fastStart = ast_true(v->value);
1287 } else if (!strcasecmp(v->name, "noH245Tunneling")) {
1288 DEPRECATED(v, "h245Tunneling");
1289 options->h245Tunneling = !ast_true(v->value);
1290 } else if (!strcasecmp(v->name, "h245Tunneling")) {
1291 options->h245Tunneling = ast_true(v->value);
1292 } else if (!strcasecmp(v->name, "noSilenceSuppression")) {
1293 DEPRECATED(v, "silenceSuppression");
1294 options->silenceSuppression = !ast_true(v->value);
1295 } else if (!strcasecmp(v->name, "silenceSuppression")) {
1296 options->silenceSuppression = ast_true(v->value);
1297 } else if (!strcasecmp(v->name, "progress_setup")) {
1298 tmp = atoi(v->value);
1299 if ((tmp != 0) && (tmp != 1) && (tmp != 3) && (tmp != 8)) {
1300 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
1301 tmp = 0;
1303 options->progress_setup = tmp;
1304 } else if (!strcasecmp(v->name, "progress_alert")) {
1305 tmp = atoi(v->value);
1306 if ((tmp != 0) && (tmp != 1) && (tmp != 8)) {
1307 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
1308 tmp = 0;
1310 options->progress_alert = tmp;
1311 } else if (!strcasecmp(v->name, "progress_audio")) {
1312 options->progress_audio = ast_true(v->value);
1313 } else if (!strcasecmp(v->name, "callerid")) {
1314 ast_callerid_split(v->value, options->cid_name, sizeof(options->cid_name), options->cid_num, sizeof(options->cid_num));
1315 } else if (!strcasecmp(v->name, "fullname")) {
1316 ast_copy_string(options->cid_name, v->value, sizeof(options->cid_name));
1317 } else if (!strcasecmp(v->name, "cid_number")) {
1318 ast_copy_string(options->cid_num, v->value, sizeof(options->cid_num));
1319 } else if (!strcasecmp(v->name, "tunneling")) {
1320 if (!strcasecmp(v->value, "none"))
1321 options->tunnelOptions = 0;
1322 else if (!strcasecmp(v->value, "cisco"))
1323 options->tunnelOptions |= H323_TUNNEL_CISCO;
1324 else if (!strcasecmp(v->value, "qsig"))
1325 options->tunnelOptions |= H323_TUNNEL_QSIG;
1326 else
1327 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
1328 } else
1329 return 1;
1331 return 0;
1333 #undef DEPRECATED
1335 static struct oh323_user *build_user(char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
1337 struct oh323_user *user;
1338 struct ast_ha *oldha;
1339 int found = 0;
1340 int format;
1342 user = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&userl, name, name, 0, 0, strcmp);
1344 if (user)
1345 found++;
1346 else {
1347 if (!(user = (struct oh323_user *)calloc(1, sizeof(*user))))
1348 return NULL;
1349 ASTOBJ_INIT(user);
1351 oldha = user->ha;
1352 user->ha = (struct ast_ha *)NULL;
1353 memcpy(&user->options, &global_options, sizeof(user->options));
1354 /* Set default context */
1355 ast_copy_string(user->context, default_context, sizeof(user->context));
1356 if (user && !found)
1357 ast_copy_string(user->name, name, sizeof(user->name));
1359 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */
1360 if (user->chanvars) {
1361 ast_variables_destroy(user->chanvars);
1362 user->chanvars = NULL;
1364 #endif
1366 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
1367 if (!update_common_options(v, &user->options))
1368 continue;
1369 if (!strcasecmp(v->name, "context")) {
1370 ast_copy_string(user->context, v->value, sizeof(user->context));
1371 } else if (!strcasecmp(v->name, "secret")) {
1372 ast_copy_string(user->secret, v->value, sizeof(user->secret));
1373 } else if (!strcasecmp(v->name, "accountcode")) {
1374 ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
1375 } else if (!strcasecmp(v->name, "host")) {
1376 if (!strcasecmp(v->value, "dynamic")) {
1377 ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n");
1378 ASTOBJ_UNREF(user, oh323_destroy_user);
1379 return NULL;
1380 } else if (ast_get_ip(&user->addr, v->value)) {
1381 ASTOBJ_UNREF(user, oh323_destroy_user);
1382 return NULL;
1384 /* Let us know we need to use ip authentication */
1385 user->host = 1;
1386 } else if (!strcasecmp(v->name, "amaflags")) {
1387 format = ast_cdr_amaflags2int(v->value);
1388 if (format < 0) {
1389 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
1390 } else {
1391 user->amaflags = format;
1393 } else if (!strcasecmp(v->name, "permit") ||
1394 !strcasecmp(v->name, "deny")) {
1395 user->ha = ast_append_ha(v->name, v->value, user->ha);
1398 ASTOBJ_UNMARK(user);
1399 ast_free_ha(oldha);
1400 return user;
1403 static struct oh323_user *realtime_user(const call_details_t *cd)
1405 struct ast_variable *var, *tmp;
1406 struct oh323_user *user;
1407 char *username;
1409 if (userbyalias)
1410 var = ast_load_realtime("h323", "name", username = cd->call_source_aliases, NULL);
1411 else {
1412 username = (char *)NULL;
1413 var = ast_load_realtime("h323", "host", cd->sourceIp, NULL);
1416 if (!var)
1417 return NULL;
1419 for (tmp = var; tmp; tmp = tmp->next) {
1420 if (!strcasecmp(tmp->name, "type") &&
1421 !(!strcasecmp(tmp->value, "user") || !strcasecmp(tmp->value, "friend"))) {
1422 ast_variables_destroy(var);
1423 return NULL;
1424 } else if (!username && !strcasecmp(tmp->name, "name"))
1425 username = tmp->value;
1428 if (!username) {
1429 ast_log(LOG_WARNING, "Cannot determine user name for IP address %s\n", cd->sourceIp);
1430 ast_variables_destroy(var);
1431 return NULL;
1434 user = build_user(username, var, NULL, 1);
1436 ast_variables_destroy(var);
1438 return user;
1441 static struct oh323_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
1443 struct oh323_peer *peer;
1444 struct ast_ha *oldha;
1445 int found = 0;
1447 peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp);
1449 if (peer)
1450 found++;
1451 else {
1452 if (!(peer = (struct oh323_peer*)calloc(1, sizeof(*peer))))
1453 return NULL;
1454 ASTOBJ_INIT(peer);
1456 oldha = peer->ha;
1457 peer->ha = NULL;
1458 memcpy(&peer->options, &global_options, sizeof(peer->options));
1459 peer->addr.sin_port = htons(h323_signalling_port);
1460 peer->addr.sin_family = AF_INET;
1461 if (!found && name)
1462 ast_copy_string(peer->name, name, sizeof(peer->name));
1464 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */
1465 if (peer->chanvars) {
1466 ast_variables_destroy(peer->chanvars);
1467 peer->chanvars = NULL;
1469 #endif
1470 /* Default settings for mailbox */
1471 peer->mailbox[0] = '\0';
1473 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
1474 if (!update_common_options(v, &peer->options))
1475 continue;
1476 if (!strcasecmp(v->name, "host")) {
1477 if (!strcasecmp(v->value, "dynamic")) {
1478 ast_log(LOG_ERROR, "Dynamic host configuration not implemented.\n");
1479 ASTOBJ_UNREF(peer, oh323_destroy_peer);
1480 return NULL;
1482 if (ast_get_ip(&peer->addr, v->value)) {
1483 ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value);
1484 ASTOBJ_UNREF(peer, oh323_destroy_peer);
1485 return NULL;
1487 } else if (!strcasecmp(v->name, "port")) {
1488 peer->addr.sin_port = htons(atoi(v->value));
1489 } else if (!strcasecmp(v->name, "permit") ||
1490 !strcasecmp(v->name, "deny")) {
1491 peer->ha = ast_append_ha(v->name, v->value, peer->ha);
1492 } else if (!strcasecmp(v->name, "mailbox")) {
1493 ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox));
1496 ASTOBJ_UNMARK(peer);
1497 ast_free_ha(oldha);
1498 return peer;
1501 static struct oh323_peer *realtime_peer(const char *peername, struct sockaddr_in *sin)
1503 struct oh323_peer *peer;
1504 struct ast_variable *var;
1505 struct ast_variable *tmp;
1506 const char *addr;
1508 /* First check on peer name */
1509 if (peername)
1510 var = ast_load_realtime("h323", "name", peername, addr = NULL);
1511 else if (sin) /* Then check on IP address for dynamic peers */
1512 var = ast_load_realtime("h323", "host", addr = ast_inet_ntoa(sin->sin_addr), NULL);
1513 else
1514 return NULL;
1516 if (!var)
1517 return NULL;
1519 for (tmp = var; tmp; tmp = tmp->next) {
1520 /* If this is type=user, then skip this object. */
1521 if (!strcasecmp(tmp->name, "type") &&
1522 !(!strcasecmp(tmp->value, "peer") || !strcasecmp(tmp->value, "friend"))) {
1523 ast_variables_destroy(var);
1524 return NULL;
1525 } else if (!peername && !strcasecmp(tmp->name, "name")) {
1526 peername = tmp->value;
1530 if (!peername) { /* Did not find peer in realtime */
1531 ast_log(LOG_WARNING, "Cannot determine peer name for IP address %s\n", addr);
1532 ast_variables_destroy(var);
1533 return NULL;
1536 /* Peer found in realtime, now build it in memory */
1537 peer = build_peer(peername, var, NULL, 1);
1539 ast_variables_destroy(var);
1541 return peer;
1544 static int oh323_addrcmp_str(struct in_addr inaddr, char *addr)
1546 return strcmp(ast_inet_ntoa(inaddr), addr);
1549 static struct oh323_user *find_user(const call_details_t *cd, int realtime)
1551 struct oh323_user *u;
1553 if (userbyalias)
1554 u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases);
1555 else
1556 u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str);
1558 if (!u && realtime)
1559 u = realtime_user(cd);
1561 if (!u && h323debug)
1562 ast_log(LOG_DEBUG, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp);
1564 return u;
1567 static int oh323_addrcmp(struct sockaddr_in addr, struct sockaddr_in *sin)
1569 int res;
1571 if (!sin)
1572 res = -1;
1573 else
1574 res = inaddrcmp(&addr , sin);
1576 return res;
1579 static struct oh323_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime)
1581 struct oh323_peer *p;
1583 if (peer)
1584 p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
1585 else
1586 p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
1588 if (!p && realtime)
1589 p = realtime_peer(peer, sin);
1591 if (!p && h323debug)
1592 ast_log(LOG_DEBUG, "Could not find peer by name %s or address %s\n", (peer ? peer : "<NONE>"), (sin ? ast_inet_ntoa(sin->sin_addr) : "<NONE>"));
1594 return p;
1597 static int create_addr(struct oh323_pvt *pvt, char *opeer)
1599 struct hostent *hp;
1600 struct ast_hostent ahp;
1601 struct oh323_peer *p;
1602 int portno;
1603 int found = 0;
1604 char *port;
1605 char *hostn;
1606 char peer[256] = "";
1608 ast_copy_string(peer, opeer, sizeof(peer));
1609 port = strchr(peer, ':');
1610 if (port) {
1611 *port = '\0';
1612 port++;
1614 pvt->sa.sin_family = AF_INET;
1615 p = find_peer(peer, NULL, 1);
1616 if (p) {
1617 found++;
1618 memcpy(&pvt->options, &p->options, sizeof(pvt->options));
1619 pvt->jointcapability = pvt->options.capability;
1620 if (pvt->options.dtmfmode) {
1621 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
1622 pvt->nonCodecCapability |= AST_RTP_DTMF;
1623 } else {
1624 pvt->nonCodecCapability &= ~AST_RTP_DTMF;
1627 if (p->addr.sin_addr.s_addr) {
1628 pvt->sa.sin_addr = p->addr.sin_addr;
1629 pvt->sa.sin_port = p->addr.sin_port;
1631 ASTOBJ_UNREF(p, oh323_destroy_peer);
1633 if (!p && !found) {
1634 hostn = peer;
1635 if (port) {
1636 portno = atoi(port);
1637 } else {
1638 portno = h323_signalling_port;
1640 hp = ast_gethostbyname(hostn, &ahp);
1641 if (hp) {
1642 memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
1643 pvt->sa.sin_port = htons(portno);
1644 /* Look peer by address */
1645 p = find_peer(NULL, &pvt->sa, 1);
1646 memcpy(&pvt->options, (p ? &p->options : &global_options), sizeof(pvt->options));
1647 pvt->jointcapability = pvt->options.capability;
1648 if (p) {
1649 ASTOBJ_UNREF(p, oh323_destroy_peer);
1651 if (pvt->options.dtmfmode) {
1652 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
1653 pvt->nonCodecCapability |= AST_RTP_DTMF;
1654 } else {
1655 pvt->nonCodecCapability &= ~AST_RTP_DTMF;
1658 return 0;
1659 } else {
1660 ast_log(LOG_WARNING, "No such host: %s\n", peer);
1661 return -1;
1663 } else if (!found) {
1664 return -1;
1665 } else {
1666 return 0;
1669 static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause)
1671 int oldformat;
1672 struct oh323_pvt *pvt;
1673 struct ast_channel *tmpc = NULL;
1674 char *dest = (char *)data;
1675 char *ext, *host;
1676 char *h323id = NULL;
1677 char tmp[256], tmp1[256];
1679 if (h323debug)
1680 ast_log(LOG_DEBUG, "type=%s, format=%d, data=%s.\n", type, format, (char *)data);
1682 pvt = oh323_alloc(0);
1683 if (!pvt) {
1684 ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data);
1685 return NULL;
1687 oldformat = format;
1688 format &= ((AST_FORMAT_MAX_AUDIO << 1) - 1);
1689 if (!format) {
1690 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
1691 oh323_destroy(pvt);
1692 if (cause)
1693 *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
1694 return NULL;
1696 ast_copy_string(tmp, dest, sizeof(tmp));
1697 host = strchr(tmp, '@');
1698 if (host) {
1699 *host = '\0';
1700 host++;
1701 ext = tmp;
1702 } else {
1703 ext = strrchr(tmp, '/');
1704 if (ext)
1705 *ext++ = '\0';
1706 host = tmp;
1708 strtok_r(host, "/", &(h323id));
1709 if (!ast_strlen_zero(h323id)) {
1710 h323_set_id(h323id);
1712 if (ext) {
1713 ast_copy_string(pvt->exten, ext, sizeof(pvt->exten));
1715 if (h323debug)
1716 ast_log(LOG_DEBUG, "Extension: %s Host: %s\n", pvt->exten, host);
1718 if (gatekeeper_disable) {
1719 if (create_addr(pvt, host)) {
1720 oh323_destroy(pvt);
1721 if (cause)
1722 *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
1723 return NULL;
1726 else {
1727 memcpy(&pvt->options, &global_options, sizeof(pvt->options));
1728 pvt->jointcapability = pvt->options.capability;
1729 if (pvt->options.dtmfmode) {
1730 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
1731 pvt->nonCodecCapability |= AST_RTP_DTMF;
1732 } else {
1733 pvt->nonCodecCapability &= ~AST_RTP_DTMF;
1738 ast_mutex_lock(&caplock);
1739 /* Generate unique channel identifier */
1740 snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
1741 tmp1[sizeof(tmp1)-1] = '\0';
1742 ast_mutex_unlock(&caplock);
1744 ast_mutex_lock(&pvt->lock);
1745 tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1);
1746 ast_mutex_unlock(&pvt->lock);
1747 if (!tmpc) {
1748 oh323_destroy(pvt);
1749 if (cause)
1750 *cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
1752 ast_update_use_count();
1753 restart_monitor();
1754 return tmpc;
1757 /** Find a call by alias */
1758 static struct oh323_alias *find_alias(const char *source_aliases, int realtime)
1760 struct oh323_alias *a;
1762 a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
1764 if (!a && realtime)
1765 a = realtime_alias(source_aliases);
1767 return a;
1771 * Callback for sending digits from H.323 up to asterisk
1774 static int receive_digit(unsigned call_reference, char digit, const char *token, int duration)
1776 struct oh323_pvt *pvt;
1777 int res;
1779 pvt = find_call_locked(call_reference, token);
1780 if (!pvt) {
1781 ast_log(LOG_ERROR, "Received digit '%c' (%u ms) for call %s without private structure\n", digit, duration, token);
1782 return -1;
1784 if (h323debug)
1785 ast_log(LOG_DTMF, "Received %s digit '%c' (%u ms) for call %s\n", (digit == ' ' ? "update for" : "new"), (digit == ' ' ? pvt->curDTMF : digit), duration, token);
1787 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
1788 if (digit == '!')
1789 res = ast_queue_control(pvt->owner, AST_CONTROL_FLASH);
1790 else {
1791 struct ast_frame f = {
1792 .frametype = AST_FRAME_DTMF_END,
1793 .subclass = digit,
1794 .samples = duration * 8,
1795 .len = duration,
1796 .src = "SEND_DIGIT",
1798 if (digit == ' ') { /* signalUpdate message */
1799 f.subclass = pvt->curDTMF;
1800 if (pvt->DTMFsched >= 0) {
1801 ast_sched_del(sched, pvt->DTMFsched);
1802 pvt->DTMFsched = -1;
1804 } else { /* Regular input or signal message */
1805 if (pvt->DTMFsched >= 0) {
1806 /* We still don't send DTMF END from previous event, send it now */
1807 ast_sched_del(sched, pvt->DTMFsched);
1808 pvt->DTMFsched = -1;
1809 f.subclass = pvt->curDTMF;
1810 f.samples = f.len = 0;
1811 ast_queue_frame(pvt->owner, &f);
1812 /* Restore values */
1813 f.subclass = digit;
1814 f.samples = duration * 8;
1815 f.len = duration;
1817 if (duration) { /* This is a signal, signalUpdate follows */
1818 f.frametype = AST_FRAME_DTMF_BEGIN;
1819 pvt->DTMFsched = ast_sched_add(sched, duration, oh323_simulate_dtmf_end, pvt);
1820 if (h323debug)
1821 ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", duration, pvt->DTMFsched);
1823 pvt->curDTMF = digit;
1825 res = ast_queue_frame(pvt->owner, &f);
1827 ast_channel_unlock(pvt->owner);
1828 } else {
1829 if (digit == '!')
1830 pvt->newcontrol = AST_CONTROL_FLASH;
1831 else {
1832 pvt->newduration = duration;
1833 pvt->newdigit = digit;
1835 res = 0;
1837 ast_mutex_unlock(&pvt->lock);
1838 return res;
1842 * Callback function used to inform the H.323 stack of the local rtp ip/port details
1844 * Returns the local RTP information
1846 static struct rtp_info *external_rtp_create(unsigned call_reference, const char * token)
1848 struct oh323_pvt *pvt;
1849 struct sockaddr_in us;
1850 struct rtp_info *info;
1852 info = (struct rtp_info *)malloc(sizeof(struct rtp_info));
1853 if (!info) {
1854 ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
1855 return NULL;
1857 pvt = find_call_locked(call_reference, token);
1858 if (!pvt) {
1859 free(info);
1860 ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
1861 return NULL;
1863 if (!pvt->rtp)
1864 __oh323_rtp_create(pvt);
1865 if (!pvt->rtp) {
1866 ast_mutex_unlock(&pvt->lock);
1867 free(info);
1868 ast_log(LOG_ERROR, "No RTP stream is available for call %s (%d)", token, call_reference);
1869 return NULL;
1871 /* figure out our local RTP port and tell the H.323 stack about it */
1872 ast_rtp_get_us(pvt->rtp, &us);
1873 ast_mutex_unlock(&pvt->lock);
1875 ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
1876 info->port = ntohs(us.sin_port);
1877 if (h323debug)
1878 ast_log(LOG_DEBUG, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
1879 return info;
1883 * Definition taken from rtp.c for rtpPayloadType because we need it here.
1885 struct rtpPayloadType {
1886 int isAstFormat; /* whether the following code is an AST_FORMAT */
1887 int code;
1891 * Call-back function passing remote ip/port information from H.323 to asterisk
1893 * Returns nothing
1895 static void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt)
1897 struct oh323_pvt *pvt;
1898 struct sockaddr_in them;
1899 struct rtpPayloadType rtptype;
1900 int nativeformats_changed;
1901 enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE;
1903 if (h323debug)
1904 ast_log(LOG_DEBUG, "Setting up RTP connection for %s\n", token);
1906 /* Find the call or allocate a private structure if call not found */
1907 pvt = find_call_locked(call_reference, token);
1908 if (!pvt) {
1909 ast_log(LOG_ERROR, "Something is wrong: rtp\n");
1910 return;
1912 if (pvt->alreadygone) {
1913 ast_mutex_unlock(&pvt->lock);
1914 return;
1917 if (!pvt->rtp)
1918 __oh323_rtp_create(pvt);
1920 them.sin_family = AF_INET;
1921 /* only works for IPv4 */
1922 them.sin_addr.s_addr = inet_addr(remoteIp);
1923 them.sin_port = htons(remotePort);
1925 if (them.sin_addr.s_addr) {
1926 ast_rtp_set_peer(pvt->rtp, &them);
1927 if (pvt->recvonly) {
1928 pvt->recvonly = 0;
1929 rtp_change = NEED_UNHOLD;
1931 } else {
1932 ast_rtp_stop(pvt->rtp);
1933 if (!pvt->recvonly) {
1934 pvt->recvonly = 1;
1935 rtp_change = NEED_HOLD;
1939 /* Change native format to reflect information taken from OLC/OLCAck */
1940 nativeformats_changed = 0;
1941 if (pt != 128 && pvt->rtp) { /* Payload type is invalid, so try to use previously decided */
1942 rtptype = ast_rtp_lookup_pt(pvt->rtp, pt);
1943 if (h323debug)
1944 ast_log(LOG_DEBUG, "Native format is set to %d from %d by RTP payload type %d\n", rtptype.code, pvt->nativeformats, pt);
1945 if (pvt->nativeformats != rtptype.code) {
1946 pvt->nativeformats = rtptype.code;
1947 nativeformats_changed = 1;
1949 } else if (h323debug)
1950 ast_log(LOG_NOTICE, "Payload type is unknown, formats isn't changed\n");
1952 /* Don't try to lock the channel if nothing changed */
1953 if (nativeformats_changed || pvt->options.progress_audio || (rtp_change != NEED_NONE)) {
1954 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
1955 /* Re-build translation path only if native format(s) has been changed */
1956 if (pvt->owner->nativeformats != pvt->nativeformats) {
1957 if (h323debug)
1958 ast_log(LOG_DEBUG, "Native format changed to %d from %d, read format is %d, write format is %d\n", pvt->nativeformats, pvt->owner->nativeformats, pvt->owner->readformat, pvt->owner->writeformat);
1959 pvt->owner->nativeformats = pvt->nativeformats;
1960 ast_set_read_format(pvt->owner, pvt->owner->readformat);
1961 ast_set_write_format(pvt->owner, pvt->owner->writeformat);
1963 if (pvt->options.progress_audio)
1964 ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);
1965 switch (rtp_change) {
1966 case NEED_HOLD:
1967 ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
1968 break;
1969 case NEED_UNHOLD:
1970 ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
1971 break;
1972 default:
1973 break;
1975 ast_channel_unlock(pvt->owner);
1977 else {
1978 if (pvt->options.progress_audio)
1979 pvt->newcontrol = AST_CONTROL_PROGRESS;
1980 else if (rtp_change == NEED_HOLD)
1981 pvt->newcontrol = AST_CONTROL_HOLD;
1982 else if (rtp_change == NEED_UNHOLD)
1983 pvt->newcontrol = AST_CONTROL_UNHOLD;
1984 if (h323debug)
1985 ast_log(LOG_DEBUG, "RTP connection preparation for %s is pending...\n", token);
1988 ast_mutex_unlock(&pvt->lock);
1990 if (h323debug)
1991 ast_log(LOG_DEBUG, "RTP connection prepared for %s\n", token);
1993 return;
1997 * Call-back function to signal asterisk that the channel has been answered
1998 * Returns nothing
2000 static void connection_made(unsigned call_reference, const char *token)
2002 struct oh323_pvt *pvt;
2004 if (h323debug)
2005 ast_log(LOG_DEBUG, "Call %s answered\n", token);
2007 pvt = find_call_locked(call_reference, token);
2008 if (!pvt) {
2009 ast_log(LOG_ERROR, "Something is wrong: connection\n");
2010 return;
2013 /* Inform asterisk about remote party connected only on outgoing calls */
2014 if (!pvt->outgoing) {
2015 ast_mutex_unlock(&pvt->lock);
2016 return;
2018 /* Do not send ANSWER message more than once */
2019 if (!pvt->connection_established) {
2020 pvt->connection_established = 1;
2021 update_state(pvt, -1, AST_CONTROL_ANSWER);
2023 ast_mutex_unlock(&pvt->lock);
2024 return;
2027 static int progress(unsigned call_reference, const char *token, int inband)
2029 struct oh323_pvt *pvt;
2031 if (h323debug)
2032 ast_log(LOG_DEBUG, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
2034 pvt = find_call_locked(call_reference, token);
2035 if (!pvt) {
2036 ast_log(LOG_ERROR, "Private structure not found in progress.\n");
2037 return -1;
2039 if (!pvt->owner) {
2040 ast_mutex_unlock(&pvt->lock);
2041 ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");
2042 return -1;
2044 update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));
2045 ast_mutex_unlock(&pvt->lock);
2047 return 0;
2051 * Call-back function for incoming calls
2053 * Returns 1 on success
2055 static call_options_t *setup_incoming_call(call_details_t *cd)
2057 struct oh323_pvt *pvt;
2058 struct oh323_user *user = NULL;
2059 struct oh323_alias *alias = NULL;
2061 if (h323debug)
2062 ast_log(LOG_DEBUG, "Setting up incoming call for %s\n", cd->call_token);
2064 /* allocate the call*/
2065 pvt = oh323_alloc(cd->call_reference);
2067 if (!pvt) {
2068 ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
2069 cleanup_call_details(cd);
2070 return NULL;
2073 /* Populate the call details in the private structure */
2074 memcpy(&pvt->cd, cd, sizeof(pvt->cd));
2075 memcpy(&pvt->options, &global_options, sizeof(pvt->options));
2076 pvt->jointcapability = pvt->options.capability;
2078 if (h323debug) {
2079 ast_verbose(VERBOSE_PREFIX_3 "Setting up Call\n");
2080 ast_verbose(VERBOSE_PREFIX_3 " \tCall token: [%s]\n", pvt->cd.call_token);
2081 ast_verbose(VERBOSE_PREFIX_3 " \tCalling party name: [%s]\n", pvt->cd.call_source_name);
2082 ast_verbose(VERBOSE_PREFIX_3 " \tCalling party number: [%s]\n", pvt->cd.call_source_e164);
2083 ast_verbose(VERBOSE_PREFIX_3 " \tCalled party name: [%s]\n", pvt->cd.call_dest_alias);
2084 ast_verbose(VERBOSE_PREFIX_3 " \tCalled party number: [%s]\n", pvt->cd.call_dest_e164);
2085 if (pvt->cd.redirect_reason >= 0)
2086 ast_verbose(VERBOSE_PREFIX_3 " \tRedirecting party number: [%s] (reason %d)\n", pvt->cd.redirect_number, pvt->cd.redirect_reason);
2087 ast_verbose(VERBOSE_PREFIX_3 " \tCalling party IP: [%s]\n", pvt->cd.sourceIp);
2090 /* Decide if we are allowing Gatekeeper routed calls*/
2091 if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && !gatekeeper_disable) {
2092 if (!ast_strlen_zero(cd->call_dest_e164)) {
2093 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
2094 ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
2095 } else {
2096 alias = find_alias(cd->call_dest_alias, 1);
2097 if (!alias) {
2098 ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias);
2099 oh323_destroy(pvt);
2100 return NULL;
2102 ast_copy_string(pvt->exten, alias->name, sizeof(pvt->exten));
2103 ast_copy_string(pvt->context, alias->context, sizeof(pvt->context));
2105 } else {
2106 /* Either this call is not from the Gatekeeper
2107 or we are not allowing gk routed calls */
2108 user = find_user(cd, 1);
2109 if (!user) {
2110 if (!acceptAnonymous) {
2111 ast_log(LOG_NOTICE, "Anonymous call from '%s@%s' rejected\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
2112 oh323_destroy(pvt);
2113 return NULL;
2115 if (ast_strlen_zero(default_context)) {
2116 ast_log(LOG_ERROR, "Call from '%s@%s' rejected due to no default context\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
2117 oh323_destroy(pvt);
2118 return NULL;
2120 ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
2121 if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
2122 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
2123 } else {
2124 ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
2126 if (h323debug)
2127 ast_log(LOG_DEBUG, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten);
2128 } else {
2129 if (user->host) {
2130 if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) {
2131 if (ast_strlen_zero(user->context)) {
2132 if (ast_strlen_zero(default_context)) {
2133 ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp);
2134 oh323_destroy(pvt);
2135 ASTOBJ_UNREF(user, oh323_destroy_user);
2136 return NULL;
2138 ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
2139 } else {
2140 ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
2142 pvt->exten[0] = 'i';
2143 pvt->exten[1] = '\0';
2144 ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp);
2145 oh323_destroy(pvt);
2146 ASTOBJ_UNREF(user, oh323_destroy_user);
2147 return NULL; /* XXX: Hmmm... Why to setup context if we drop connection immediately??? */
2150 ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
2151 memcpy(&pvt->options, &user->options, sizeof(pvt->options));
2152 pvt->jointcapability = pvt->options.capability;
2153 if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
2154 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
2155 } else {
2156 ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
2158 if (!ast_strlen_zero(user->accountcode)) {
2159 ast_copy_string(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode));
2161 if (user->amaflags) {
2162 pvt->amaflags = user->amaflags;
2164 ASTOBJ_UNREF(user, oh323_destroy_user);
2167 return &pvt->options;
2171 * Call-back function to start PBX when OpenH323 ready to serve incoming call
2173 * Returns 1 on success
2175 static int answer_call(unsigned call_reference, const char *token)
2177 struct oh323_pvt *pvt;
2178 struct ast_channel *c = NULL;
2179 enum {ext_original, ext_s, ext_i, ext_notexists} try_exten;
2180 char tmp_exten[sizeof(pvt->exten)];
2182 if (h323debug)
2183 ast_log(LOG_DEBUG, "Preparing Asterisk to answer for %s\n", token);
2185 /* Find the call or allocate a private structure if call not found */
2186 pvt = find_call_locked(call_reference, token);
2187 if (!pvt) {
2188 ast_log(LOG_ERROR, "Something is wrong: answer_call\n");
2189 return 0;
2191 /* Check if requested extension@context pair exists in the dialplan */
2192 ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten));
2194 /* Try to find best extension in specified context */
2195 if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) {
2196 if (tmp_exten[0] == 's')
2197 try_exten = ext_s;
2198 else if (tmp_exten[0] == 'i')
2199 try_exten = ext_i;
2200 else
2201 try_exten = ext_original;
2202 } else
2203 try_exten = ext_original;
2204 do {
2205 if (ast_exists_extension(NULL, pvt->context, tmp_exten, 1, NULL))
2206 break;
2207 switch (try_exten) {
2208 case ext_original:
2209 tmp_exten[0] = 's';
2210 tmp_exten[1] = '\0';
2211 try_exten = ext_s;
2212 break;
2213 case ext_s:
2214 tmp_exten[0] = 'i';
2215 try_exten = ext_i;
2216 break;
2217 case ext_i:
2218 try_exten = ext_notexists;
2219 break;
2220 default:
2221 break;
2223 } while (try_exten != ext_notexists);
2225 /* Drop the call if we don't have <exten>, s and i extensions */
2226 if (try_exten == ext_notexists) {
2227 ast_log(LOG_NOTICE, "Dropping call because extensions '%s', 's' and 'i' doesn't exists in context [%s]\n", pvt->exten, pvt->context);
2228 ast_mutex_unlock(&pvt->lock);
2229 h323_clear_call(token, AST_CAUSE_UNALLOCATED);
2230 return 0;
2231 } else if ((try_exten != ext_original) && (strcmp(pvt->exten, tmp_exten) != 0)) {
2232 if (h323debug)
2233 ast_log(LOG_DEBUG, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context);
2234 ast_copy_string(pvt->exten, tmp_exten, sizeof(pvt->exten));
2237 /* allocate a channel and tell asterisk about it */
2238 c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token);
2240 /* And release when done */
2241 ast_mutex_unlock(&pvt->lock);
2242 if (!c) {
2243 ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n");
2244 return 0;
2246 return 1;
2250 * Call-back function to establish an outgoing H.323 call
2252 * Returns 1 on success
2254 static int setup_outgoing_call(call_details_t *cd)
2256 /* Use argument here or free it immediately */
2257 cleanup_call_details(cd);
2259 return 1;
2263 * Call-back function to signal asterisk that the channel is ringing
2264 * Returns nothing
2266 static void chan_ringing(unsigned call_reference, const char *token)
2268 struct oh323_pvt *pvt;
2270 if (h323debug)
2271 ast_log(LOG_DEBUG, "Ringing on %s\n", token);
2273 pvt = find_call_locked(call_reference, token);
2274 if (!pvt) {
2275 ast_log(LOG_ERROR, "Something is wrong: ringing\n");
2276 return;
2278 if (!pvt->owner) {
2279 ast_mutex_unlock(&pvt->lock);
2280 ast_log(LOG_ERROR, "Channel has no owner\n");
2281 return;
2283 update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING);
2284 ast_mutex_unlock(&pvt->lock);
2285 return;
2289 * Call-back function to cleanup communication
2290 * Returns nothing,
2292 static void cleanup_connection(unsigned call_reference, const char *call_token)
2294 struct oh323_pvt *pvt;
2296 if (h323debug)
2297 ast_log(LOG_DEBUG, "Cleaning connection to %s\n", call_token);
2299 while (1) {
2300 pvt = find_call_locked(call_reference, call_token);
2301 if (!pvt) {
2302 if (h323debug)
2303 ast_log(LOG_DEBUG, "No connection for %s\n", call_token);
2304 return;
2306 if (!pvt->owner || !ast_channel_trylock(pvt->owner))
2307 break;
2308 #if 1
2309 #ifdef DEBUG_THREADS
2310 ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s, locked at %ld/%d by %s (%s:%d)\n", call_token, pvt->owner->lock.thread[0], pvt->owner->lock.reentrancy, pvt->owner->lock.func[0], pvt->owner->lock.file[0], pvt->owner->lock.lineno[0]);
2311 #else
2312 ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token);
2313 #endif
2314 #endif
2315 ast_mutex_unlock(&pvt->lock);
2316 usleep(1);
2318 if (pvt->rtp) {
2319 /* Immediately stop RTP */
2320 ast_rtp_destroy(pvt->rtp);
2321 pvt->rtp = NULL;
2323 /* Free dsp used for in-band DTMF detection */
2324 if (pvt->vad) {
2325 ast_dsp_free(pvt->vad);
2326 pvt->vad = NULL;
2328 cleanup_call_details(&pvt->cd);
2329 pvt->alreadygone = 1;
2330 /* Send hangup */
2331 if (pvt->owner) {
2332 pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
2333 ast_queue_hangup(pvt->owner);
2334 ast_channel_unlock(pvt->owner);
2336 ast_mutex_unlock(&pvt->lock);
2337 if (h323debug)
2338 ast_log(LOG_DEBUG, "Connection to %s cleaned\n", call_token);
2339 return;
2342 static void hangup_connection(unsigned int call_reference, const char *token, int cause)
2344 struct oh323_pvt *pvt;
2346 if (h323debug) {
2347 ast_log(LOG_DEBUG, "Hanging up connection to %s with cause %d\n", token, cause);
2350 pvt = find_call_locked(call_reference, token);
2351 if (!pvt) {
2352 if (h323debug) {
2353 ast_log(LOG_DEBUG, "Connection to %s already cleared\n", token);
2355 return;
2357 if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
2358 pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
2359 pvt->owner->hangupcause = pvt->hangupcause = cause;
2360 ast_queue_hangup(pvt->owner);
2361 ast_channel_unlock(pvt->owner);
2363 else {
2364 pvt->needhangup = 1;
2365 pvt->hangupcause = cause;
2366 if (h323debug)
2367 ast_log(LOG_DEBUG, "Hangup for %s is pending\n", token);
2369 ast_mutex_unlock(&pvt->lock);
2372 static void set_dtmf_payload(unsigned call_reference, const char *token, int payload)
2374 struct oh323_pvt *pvt;
2376 if (h323debug)
2377 ast_log(LOG_DEBUG, "Setting DTMF payload to %d on %s\n", payload, token);
2379 pvt = find_call_locked(call_reference, token);
2380 if (!pvt) {
2381 return;
2383 if (pvt->rtp) {
2384 ast_rtp_set_rtpmap_type(pvt->rtp, payload, "audio", "telephone-event", 0);
2386 pvt->dtmf_pt = payload;
2387 ast_mutex_unlock(&pvt->lock);
2388 if (h323debug)
2389 ast_log(LOG_DEBUG, "DTMF payload on %s set to %d\n", token, payload);
2392 static void set_peer_capabilities(unsigned call_reference, const char *token, int capabilities, struct ast_codec_pref *prefs)
2394 struct oh323_pvt *pvt;
2396 if (h323debug)
2397 ast_log(LOG_DEBUG, "Got remote capabilities from connection %s\n", token);
2399 pvt = find_call_locked(call_reference, token);
2400 if (!pvt)
2401 return;
2402 pvt->peercapability = capabilities;
2403 pvt->jointcapability = pvt->options.capability & capabilities;
2404 if (prefs) {
2405 memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs));
2406 if (h323debug) {
2407 int i;
2408 for (i = 0; i < 32; ++i) {
2409 if (!prefs->order[i])
2410 break;
2411 ast_log(LOG_DEBUG, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]);
2414 if (pvt->rtp)
2415 ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
2417 ast_mutex_unlock(&pvt->lock);
2420 static void set_local_capabilities(unsigned call_reference, const char *token)
2422 struct oh323_pvt *pvt;
2423 int capability, dtmfmode, pref_codec;
2424 struct ast_codec_pref prefs;
2426 if (h323debug)
2427 ast_log(LOG_DEBUG, "Setting capabilities for connection %s\n", token);
2429 pvt = find_call_locked(call_reference, token);
2430 if (!pvt)
2431 return;
2432 capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
2433 dtmfmode = pvt->options.dtmfmode;
2434 prefs = pvt->options.prefs;
2435 pref_codec = pvt->pref_codec;
2436 ast_mutex_unlock(&pvt->lock);
2437 h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
2439 if (h323debug)
2440 ast_log(LOG_DEBUG, "Capabilities for connection %s is set\n", token);
2443 static void *do_monitor(void *data)
2445 int res;
2446 int reloading;
2447 struct oh323_pvt *oh323 = NULL;
2449 for(;;) {
2450 /* Check for a reload request */
2451 ast_mutex_lock(&h323_reload_lock);
2452 reloading = h323_reloading;
2453 h323_reloading = 0;
2454 ast_mutex_unlock(&h323_reload_lock);
2455 if (reloading) {
2456 if (option_verbose > 0) {
2457 ast_verbose(VERBOSE_PREFIX_1 "Reloading H.323\n");
2459 h323_do_reload();
2461 /* Check for interfaces needing to be killed */
2462 if (!ast_mutex_trylock(&iflock)) {
2463 #if 1
2464 do {
2465 for (oh323 = iflist; oh323; oh323 = oh323->next) {
2466 if (!ast_mutex_trylock(&oh323->lock)) {
2467 if (oh323->needdestroy) {
2468 __oh323_destroy(oh323);
2469 break;
2471 ast_mutex_unlock(&oh323->lock);
2474 } while (/*oh323*/ 0);
2475 #else
2476 restartsearch:
2477 oh323 = iflist;
2478 while(oh323) {
2479 if (!ast_mutex_trylock(&oh323->lock)) {
2480 if (oh323->needdestroy) {
2481 __oh323_destroy(oh323);
2482 goto restartsearch;
2484 ast_mutex_unlock(&oh323->lock);
2485 oh323 = oh323->next;
2488 #endif
2489 ast_mutex_unlock(&iflock);
2490 } else
2491 oh323 = (struct oh323_pvt *)1; /* Force fast loop */
2492 pthread_testcancel();
2493 /* Wait for sched or io */
2494 res = ast_sched_wait(sched);
2495 if ((res < 0) || (res > 1000)) {
2496 res = 1000;
2498 /* Do not wait if some channel(s) is destroyed, probably, more available too */
2499 if (oh323)
2500 res = 1;
2501 res = ast_io_wait(io, res);
2502 pthread_testcancel();
2503 ast_mutex_lock(&monlock);
2504 if (res >= 0) {
2505 ast_sched_runq(sched);
2507 ast_mutex_unlock(&monlock);
2509 /* Never reached */
2510 return NULL;
2513 static int restart_monitor(void)
2515 pthread_attr_t attr;
2516 /* If we're supposed to be stopped -- stay stopped */
2517 if (ast_mutex_lock(&monlock)) {
2518 ast_log(LOG_WARNING, "Unable to lock monitor\n");
2519 return -1;
2521 if (monitor_thread == AST_PTHREADT_STOP) {
2522 ast_mutex_unlock(&monlock);
2523 return 0;
2525 if (monitor_thread == pthread_self()) {
2526 ast_mutex_unlock(&monlock);
2527 ast_log(LOG_WARNING, "Cannot kill myself\n");
2528 return -1;
2530 if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) {
2531 /* Wake up the thread */
2532 pthread_kill(monitor_thread, SIGURG);
2533 } else {
2534 pthread_attr_init(&attr);
2535 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2536 /* Start a new monitor */
2537 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
2538 monitor_thread = AST_PTHREADT_NULL;
2539 ast_mutex_unlock(&monlock);
2540 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
2541 pthread_attr_destroy(&attr);
2542 return -1;
2544 pthread_attr_destroy(&attr);
2546 ast_mutex_unlock(&monlock);
2547 return 0;
2550 static int h323_do_trace(int fd, int argc, char *argv[])
2552 if (argc != 4) {
2553 return RESULT_SHOWUSAGE;
2555 h323_debug(1, atoi(argv[3]));
2556 ast_cli(fd, "H.323 trace set to level %s\n", argv[2]);
2557 return RESULT_SUCCESS;
2560 static int h323_no_trace(int fd, int argc, char *argv[])
2562 if (argc < 3 || argc > 4) {
2563 return RESULT_SHOWUSAGE;
2565 h323_debug(0,0);
2566 ast_cli(fd, "H.323 trace disabled\n");
2567 return RESULT_SUCCESS;
2570 static int h323_do_debug(int fd, int argc, char *argv[])
2572 if (argc < 2 || argc > 3) {
2573 return RESULT_SHOWUSAGE;
2575 h323debug = 1;
2576 ast_cli(fd, "H.323 debug enabled\n");
2577 return RESULT_SUCCESS;
2580 static int h323_no_debug(int fd, int argc, char *argv[])
2582 if (argc < 3 || argc > 4) {
2583 return RESULT_SHOWUSAGE;
2585 h323debug = 0;
2586 ast_cli(fd, "H.323 debug disabled\n");
2587 return RESULT_SUCCESS;
2590 static int h323_gk_cycle(int fd, int argc, char *argv[])
2592 if (argc != 3) {
2593 return RESULT_SHOWUSAGE;
2595 h323_gk_urq();
2597 /* Possibly register with a GK */
2598 if (!gatekeeper_disable) {
2599 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
2600 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
2603 return RESULT_SUCCESS;
2606 static int h323_ep_hangup(int fd, int argc, char *argv[])
2608 if (argc != 3) {
2609 return RESULT_SHOWUSAGE;
2611 if (h323_soft_hangup(argv[2])) {
2612 ast_verbose(VERBOSE_PREFIX_3 "Hangup succeeded on %s\n", argv[2]);
2613 } else {
2614 ast_verbose(VERBOSE_PREFIX_3 "Hangup failed for %s\n", argv[2]);
2616 return RESULT_SUCCESS;
2619 static int h323_tokens_show(int fd, int argc, char *argv[])
2621 if (argc != 3) {
2622 return RESULT_SHOWUSAGE;
2624 h323_show_tokens();
2625 return RESULT_SUCCESS;
2628 static char trace_usage[] =
2629 "Usage: h.323 trace <level num>\n"
2630 " Enables H.323 stack tracing for debugging purposes\n";
2632 static char no_trace_usage[] =
2633 "Usage: h.323 trace off\n"
2634 " Disables H.323 stack tracing for debugging purposes\n";
2636 static char debug_usage[] =
2637 "Usage: h.323 debug\n"
2638 " Enables H.323 debug output\n";
2640 static char no_debug_usage[] =
2641 "Usage: h.323 debug off\n"
2642 " Disables H.323 debug output\n";
2644 static char show_cycle_usage[] =
2645 "Usage: h.323 gk cycle\n"
2646 " Manually re-register with the Gatekeper (Currently Disabled)\n";
2648 static char show_hangup_usage[] =
2649 "Usage: h.323 hangup <token>\n"
2650 " Manually try to hang up call identified by <token>\n";
2652 static char show_tokens_usage[] =
2653 "Usage: h.323 show tokens\n"
2654 " Print out all active call tokens\n";
2656 static char h323_reload_usage[] =
2657 "Usage: h323 reload\n"
2658 " Reloads H.323 configuration from h323.conf\n";
2660 static struct ast_cli_entry cli_h323_no_trace_deprecated = {
2661 { "h.323", "no", "trace", NULL },
2662 h323_no_trace, "Disable H.323 Stack Tracing",
2663 no_trace_usage };
2665 static struct ast_cli_entry cli_h323_no_debug_deprecated = {
2666 { "h.323", "no", "debug", NULL },
2667 h323_no_debug, "Disable H.323 debug",
2668 no_debug_usage };
2670 static struct ast_cli_entry cli_h323_debug_deprecated = {
2671 { "h.323", "debug", NULL },
2672 h323_do_debug, "Enable H.323 debug",
2673 debug_usage };
2675 static struct ast_cli_entry cli_h323_trace_deprecated = {
2676 { "h.323", "trace", NULL },
2677 h323_do_trace, "Enable H.323 Stack Tracing",
2678 trace_usage };
2680 static struct ast_cli_entry cli_h323_gk_cycle_deprecated = {
2681 { "h.323", "gk", "cycle", NULL },
2682 h323_gk_cycle, "Manually re-register with the Gatekeper",
2683 show_cycle_usage };
2685 static struct ast_cli_entry cli_h323[] = {
2686 { { "h323", "set", "trace", NULL },
2687 h323_do_trace, "Enable H.323 Stack Tracing",
2688 trace_usage, NULL, &cli_h323_trace_deprecated },
2690 { { "h323", "set", "trace", "off", NULL },
2691 h323_no_trace, "Disable H.323 Stack Tracing",
2692 no_trace_usage, NULL, &cli_h323_no_trace_deprecated },
2694 { { "h323", "set", "debug", NULL },
2695 h323_do_debug, "Enable H.323 debug",
2696 debug_usage, NULL, &cli_h323_debug_deprecated },
2698 { { "h323", "set", "debug", "off", NULL },
2699 h323_no_debug, "Disable H.323 debug",
2700 no_debug_usage, NULL, &cli_h323_no_debug_deprecated },
2702 { { "h323", "cycle", "gk", NULL },
2703 h323_gk_cycle, "Manually re-register with the Gatekeper",
2704 show_cycle_usage, NULL, &cli_h323_gk_cycle_deprecated },
2706 { { "h323", "hangup", NULL },
2707 h323_ep_hangup, "Manually try to hang up a call",
2708 show_hangup_usage },
2710 { { "h323", "show", "tokens", NULL },
2711 h323_tokens_show, "Show all active call tokens",
2712 show_tokens_usage },
2715 static int reload_config(int is_reload)
2717 int format;
2718 struct ast_config *cfg, *ucfg;
2719 struct ast_variable *v;
2720 struct oh323_peer *peer = NULL;
2721 struct oh323_user *user = NULL;
2722 struct oh323_alias *alias = NULL;
2723 struct ast_hostent ahp; struct hostent *hp;
2724 char *cat;
2725 const char *utype;
2726 int is_user, is_peer, is_alias;
2727 char _gatekeeper[100];
2728 int gk_discover, gk_disable, gk_changed;
2730 cfg = ast_config_load(config);
2732 /* We *must* have a config file otherwise stop immediately */
2733 if (!cfg) {
2734 ast_log(LOG_NOTICE, "Unable to load config %s, H.323 disabled\n", config);
2735 return 1;
2738 /* fire up the H.323 Endpoint */
2739 if (!h323_end_point_exist()) {
2740 h323_end_point_create();
2742 ast_copy_string(_gatekeeper, gatekeeper, sizeof(_gatekeeper));
2743 gk_discover = gatekeeper_discover;
2744 gk_disable = gatekeeper_disable;
2745 memset(&bindaddr, 0, sizeof(bindaddr));
2746 memset(&global_options, 0, sizeof(global_options));
2747 global_options.fastStart = 1;
2748 global_options.h245Tunneling = 1;
2749 global_options.dtmfcodec = 101;
2750 global_options.dtmfmode = H323_DTMF_RFC2833;
2751 global_options.capability = GLOBAL_CAPABILITY;
2752 global_options.bridge = 1; /* Do native bridging by default */
2753 strcpy(default_context, "default");
2754 h323_signalling_port = 1720;
2755 gatekeeper_disable = 1;
2756 gatekeeper_discover = 0;
2757 gkroute = 0;
2758 userbyalias = 1;
2759 acceptAnonymous = 1;
2760 tos = 0;
2762 /* Copy the default jb config over global_jbconf */
2763 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
2765 /* Load configuration from users.conf */
2766 ucfg = ast_config_load("users.conf");
2767 if (ucfg) {
2768 struct ast_variable *gen;
2769 int genhas_h323;
2770 const char *has_h323;
2772 genhas_h323 = ast_true(ast_variable_retrieve(ucfg, "general", "hash323"));
2773 gen = ast_variable_browse(ucfg, "general");
2774 for (cat = ast_category_browse(ucfg, NULL); cat; cat = ast_category_browse(ucfg, cat)) {
2775 if (strcasecmp(cat, "general")) {
2776 has_h323 = ast_variable_retrieve(ucfg, cat, "hash323");
2777 if (ast_true(has_h323) || (!has_h323 && genhas_h323)) {
2778 user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
2779 if (user) {
2780 ASTOBJ_CONTAINER_LINK(&userl, user);
2781 ASTOBJ_UNREF(user, oh323_destroy_user);
2786 ast_config_destroy(ucfg);
2789 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
2790 /* handle jb conf */
2791 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
2792 continue;
2793 /* Create the interface list */
2794 if (!strcasecmp(v->name, "port")) {
2795 h323_signalling_port = (int)strtol(v->value, NULL, 10);
2796 } else if (!strcasecmp(v->name, "bindaddr")) {
2797 if (!(hp = ast_gethostbyname(v->value, &ahp))) {
2798 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
2799 } else {
2800 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
2802 } else if (!strcasecmp(v->name, "tos")) {
2803 if (sscanf(v->value, "%d", &format)) {
2804 tos = format & 0xff;
2805 } else if (!strcasecmp(v->value, "lowdelay")) {
2806 tos = IPTOS_LOWDELAY;
2807 } else if (!strcasecmp(v->value, "throughput")) {
2808 tos = IPTOS_THROUGHPUT;
2809 } else if (!strcasecmp(v->value, "reliability")) {
2810 tos = IPTOS_RELIABILITY;
2811 } else if (!strcasecmp(v->value, "mincost")) {
2812 tos = IPTOS_MINCOST;
2813 } else if (!strcasecmp(v->value, "none")) {
2814 tos = 0;
2815 } else {
2816 ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
2818 } else if (!strcasecmp(v->name, "gatekeeper")) {
2819 if (!strcasecmp(v->value, "DISABLE")) {
2820 gatekeeper_disable = 1;
2821 } else if (!strcasecmp(v->value, "DISCOVER")) {
2822 gatekeeper_disable = 0;
2823 gatekeeper_discover = 1;
2824 } else {
2825 gatekeeper_disable = 0;
2826 ast_copy_string(gatekeeper, v->value, sizeof(gatekeeper));
2828 } else if (!strcasecmp(v->name, "secret")) {
2829 ast_copy_string(secret, v->value, sizeof(secret));
2830 } else if (!strcasecmp(v->name, "AllowGKRouted")) {
2831 gkroute = ast_true(v->value);
2832 } else if (!strcasecmp(v->name, "context")) {
2833 ast_copy_string(default_context, v->value, sizeof(default_context));
2834 ast_verbose(VERBOSE_PREFIX_2 "Setting default context to %s\n", default_context);
2835 } else if (!strcasecmp(v->name, "UserByAlias")) {
2836 userbyalias = ast_true(v->value);
2837 } else if (!strcasecmp(v->name, "AcceptAnonymous")) {
2838 acceptAnonymous = ast_true(v->value);
2839 } else if (!update_common_options(v, &global_options)) {
2840 /* dummy */
2844 for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
2845 if (strcasecmp(cat, "general")) {
2846 utype = ast_variable_retrieve(cfg, cat, "type");
2847 if (utype) {
2848 is_user = is_peer = is_alias = 0;
2849 if (!strcasecmp(utype, "user"))
2850 is_user = 1;
2851 else if (!strcasecmp(utype, "peer"))
2852 is_peer = 1;
2853 else if (!strcasecmp(utype, "friend"))
2854 is_user = is_peer = 1;
2855 else if (!strcasecmp(utype, "h323") || !strcasecmp(utype, "alias"))
2856 is_alias = 1;
2857 else {
2858 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config);
2859 continue;
2861 if (is_user) {
2862 user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
2863 if (user) {
2864 ASTOBJ_CONTAINER_LINK(&userl, user);
2865 ASTOBJ_UNREF(user, oh323_destroy_user);
2868 if (is_peer) {
2869 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
2870 if (peer) {
2871 ASTOBJ_CONTAINER_LINK(&peerl, peer);
2872 ASTOBJ_UNREF(peer, oh323_destroy_peer);
2875 if (is_alias) {
2876 alias = build_alias(cat, ast_variable_browse(cfg, cat), NULL, 0);
2877 if (alias) {
2878 ASTOBJ_CONTAINER_LINK(&aliasl, alias);
2879 ASTOBJ_UNREF(alias, oh323_destroy_alias);
2882 } else {
2883 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
2887 ast_config_destroy(cfg);
2889 /* Register our H.323 aliases if any*/
2890 ASTOBJ_CONTAINER_WRLOCK(&aliasl);
2891 ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
2892 ASTOBJ_RDLOCK(iterator);
2893 if (h323_set_alias(iterator)) {
2894 ast_log(LOG_ERROR, "Alias %s rejected by endpoint\n", alias->name);
2895 ASTOBJ_UNLOCK(iterator);
2896 continue;
2898 ASTOBJ_UNLOCK(iterator);
2899 } while (0) );
2900 ASTOBJ_CONTAINER_UNLOCK(&aliasl);
2902 /* Don't touch GK if nothing changed because URQ will drop all existing calls */
2903 gk_changed = 0;
2904 if (gatekeeper_disable != gk_disable)
2905 gk_changed = is_reload;
2906 else if(!gatekeeper_disable && (gatekeeper_discover != gk_discover))
2907 gk_changed = is_reload;
2908 else if(!gatekeeper_disable && (strncmp(_gatekeeper, gatekeeper, sizeof(_gatekeeper)) != 0))
2909 gk_changed = is_reload;
2910 if (gk_changed) {
2911 if(!gk_disable)
2912 h323_gk_urq();
2913 if (!gatekeeper_disable) {
2914 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
2915 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
2916 gatekeeper_disable = 1;
2920 return 0;
2923 static void delete_users(void)
2925 int pruned = 0;
2927 /* Delete all users */
2928 ASTOBJ_CONTAINER_WRLOCK(&userl);
2929 ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
2930 ASTOBJ_RDLOCK(iterator);
2931 ASTOBJ_MARK(iterator);
2932 ++pruned;
2933 ASTOBJ_UNLOCK(iterator);
2934 } while (0) );
2935 if (pruned) {
2936 ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
2938 ASTOBJ_CONTAINER_UNLOCK(&userl);
2940 ASTOBJ_CONTAINER_WRLOCK(&peerl);
2941 ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
2942 ASTOBJ_RDLOCK(iterator);
2943 ASTOBJ_MARK(iterator);
2944 ASTOBJ_UNLOCK(iterator);
2945 } while (0) );
2946 ASTOBJ_CONTAINER_UNLOCK(&peerl);
2949 static void delete_aliases(void)
2951 int pruned = 0;
2953 /* Delete all aliases */
2954 ASTOBJ_CONTAINER_WRLOCK(&aliasl);
2955 ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
2956 ASTOBJ_RDLOCK(iterator);
2957 ASTOBJ_MARK(iterator);
2958 ++pruned;
2959 ASTOBJ_UNLOCK(iterator);
2960 } while (0) );
2961 if (pruned) {
2962 ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
2964 ASTOBJ_CONTAINER_UNLOCK(&aliasl);
2967 static void prune_peers(void)
2969 /* Prune peers who still are supposed to be deleted */
2970 ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
2973 static int h323_reload(int fd, int argc, char *argv[])
2975 ast_mutex_lock(&h323_reload_lock);
2976 if (h323_reloading) {
2977 ast_verbose("Previous H.323 reload not yet done\n");
2978 } else {
2979 h323_reloading = 1;
2981 ast_mutex_unlock(&h323_reload_lock);
2982 restart_monitor();
2983 return 0;
2986 static int h323_do_reload(void)
2988 delete_users();
2989 delete_aliases();
2990 prune_peers();
2991 reload_config(1);
2992 return 0;
2995 static int reload(void)
2997 return h323_reload(0, 0, NULL);
3000 static struct ast_cli_entry cli_h323_reload =
3001 { { "h.323", "reload", NULL },
3002 h323_reload, "Reload H.323 configuration",
3003 h323_reload_usage
3006 static enum ast_rtp_get_result oh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
3008 struct oh323_pvt *pvt;
3009 enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
3011 if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
3012 return res;
3014 ast_mutex_lock(&pvt->lock);
3015 if (pvt->rtp && pvt->options.bridge) {
3016 *rtp = pvt->rtp;
3017 res = AST_RTP_TRY_NATIVE;
3019 ast_mutex_unlock(&pvt->lock);
3021 return res;
3024 static enum ast_rtp_get_result oh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
3026 return AST_RTP_GET_FAILED;
3029 static char *convertcap(int cap)
3031 switch (cap) {
3032 case AST_FORMAT_G723_1:
3033 return "G.723";
3034 case AST_FORMAT_GSM:
3035 return "GSM";
3036 case AST_FORMAT_ULAW:
3037 return "ULAW";
3038 case AST_FORMAT_ALAW:
3039 return "ALAW";
3040 case AST_FORMAT_G722:
3041 return "G.722";
3042 case AST_FORMAT_ADPCM:
3043 return "G.728";
3044 case AST_FORMAT_G729A:
3045 return "G.729";
3046 case AST_FORMAT_SPEEX:
3047 return "SPEEX";
3048 case AST_FORMAT_ILBC:
3049 return "ILBC";
3050 default:
3051 ast_log(LOG_NOTICE, "Don't know how to deal with mode %d\n", cap);
3052 return NULL;
3056 static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
3058 /* XXX Deal with Video */
3059 struct oh323_pvt *pvt;
3060 struct sockaddr_in them;
3061 struct sockaddr_in us;
3062 char *mode;
3064 if (!rtp) {
3065 return 0;
3068 mode = convertcap(chan->writeformat);
3069 pvt = (struct oh323_pvt *) chan->tech_pvt;
3070 if (!pvt) {
3071 ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
3072 return -1;
3074 ast_rtp_get_peer(rtp, &them);
3075 ast_rtp_get_us(rtp, &us);
3076 #if 0 /* Native bridge still isn't ready */
3077 h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
3078 #endif
3079 return 0;
3082 static struct ast_rtp_protocol oh323_rtp = {
3083 .type = "H323",
3084 .get_rtp_info = oh323_get_rtp_peer,
3085 .get_vrtp_info = oh323_get_vrtp_peer,
3086 .set_rtp_peer = oh323_set_rtp_peer,
3089 static enum ast_module_load_result load_module(void)
3091 int res;
3093 h323debug = 0;
3094 sched = sched_context_create();
3095 if (!sched) {
3096 ast_log(LOG_WARNING, "Unable to create schedule context\n");
3097 return AST_MODULE_LOAD_FAILURE;
3099 io = io_context_create();
3100 if (!io) {
3101 ast_log(LOG_WARNING, "Unable to create I/O context\n");
3102 return AST_MODULE_LOAD_FAILURE;
3104 ast_cli_register(&cli_h323_reload);
3105 ASTOBJ_CONTAINER_INIT(&userl);
3106 ASTOBJ_CONTAINER_INIT(&peerl);
3107 ASTOBJ_CONTAINER_INIT(&aliasl);
3108 res = reload_config(0);
3109 if (res) {
3110 /* No config entry */
3111 ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
3112 ast_cli_unregister(&cli_h323_reload);
3113 io_context_destroy(io);
3114 io = NULL;
3115 sched_context_destroy(sched);
3116 sched = NULL;
3117 ASTOBJ_CONTAINER_DESTROY(&userl);
3118 ASTOBJ_CONTAINER_DESTROY(&peerl);
3119 ASTOBJ_CONTAINER_DESTROY(&aliasl);
3120 return AST_MODULE_LOAD_DECLINE;
3121 } else {
3122 /* Make sure we can register our channel type */
3123 if (ast_channel_register(&oh323_tech)) {
3124 ast_log(LOG_ERROR, "Unable to register channel class 'H323'\n");
3125 ast_cli_unregister(&cli_h323_reload);
3126 h323_end_process();
3127 io_context_destroy(io);
3128 sched_context_destroy(sched);
3130 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
3131 ASTOBJ_CONTAINER_DESTROY(&userl);
3132 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
3133 ASTOBJ_CONTAINER_DESTROY(&peerl);
3134 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
3135 ASTOBJ_CONTAINER_DESTROY(&aliasl);
3137 return AST_MODULE_LOAD_FAILURE;
3139 ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
3141 ast_rtp_proto_register(&oh323_rtp);
3143 /* Register our callback functions */
3144 h323_callback_register(setup_incoming_call,
3145 setup_outgoing_call,
3146 external_rtp_create,
3147 setup_rtp_connection,
3148 cleanup_connection,
3149 chan_ringing,
3150 connection_made,
3151 receive_digit,
3152 answer_call,
3153 progress,
3154 set_dtmf_payload,
3155 hangup_connection,
3156 set_local_capabilities,
3157 set_peer_capabilities);
3158 /* start the h.323 listener */
3159 if (h323_start_listener(h323_signalling_port, bindaddr)) {
3160 ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
3161 ast_rtp_proto_unregister(&oh323_rtp);
3162 ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
3163 ast_cli_unregister(&cli_h323_reload);
3164 h323_end_process();
3165 io_context_destroy(io);
3166 sched_context_destroy(sched);
3168 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
3169 ASTOBJ_CONTAINER_DESTROY(&userl);
3170 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
3171 ASTOBJ_CONTAINER_DESTROY(&peerl);
3172 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
3173 ASTOBJ_CONTAINER_DESTROY(&aliasl);
3175 return AST_MODULE_LOAD_FAILURE;
3177 /* Possibly register with a GK */
3178 if (!gatekeeper_disable) {
3179 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
3180 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
3181 gatekeeper_disable = 1;
3182 res = AST_MODULE_LOAD_SUCCESS;
3185 /* And start the monitor for the first time */
3186 restart_monitor();
3188 return res;
3191 static int unload_module(void)
3193 struct oh323_pvt *p, *pl;
3195 /* unregister commands */
3196 ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
3197 ast_cli_unregister(&cli_h323_reload);
3199 ast_channel_unregister(&oh323_tech);
3200 ast_rtp_proto_unregister(&oh323_rtp);
3202 if (!ast_mutex_lock(&iflock)) {
3203 /* hangup all interfaces if they have an owner */
3204 p = iflist;
3205 while(p) {
3206 if (p->owner) {
3207 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
3209 p = p->next;
3211 iflist = NULL;
3212 ast_mutex_unlock(&iflock);
3213 } else {
3214 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
3215 return -1;
3217 if (!ast_mutex_lock(&monlock)) {
3218 if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
3219 /* this causes a seg, anyone know why? */
3220 if (monitor_thread != pthread_self())
3221 pthread_cancel(monitor_thread);
3222 pthread_kill(monitor_thread, SIGURG);
3223 pthread_join(monitor_thread, NULL);
3225 monitor_thread = AST_PTHREADT_STOP;
3226 ast_mutex_unlock(&monlock);
3227 } else {
3228 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
3229 return -1;
3231 if (!ast_mutex_lock(&iflock)) {
3232 /* destroy all the interfaces and free their memory */
3233 p = iflist;
3234 while(p) {
3235 pl = p;
3236 p = p->next;
3237 /* free associated memory */
3238 ast_mutex_destroy(&pl->lock);
3239 free(pl);
3241 iflist = NULL;
3242 ast_mutex_unlock(&iflock);
3243 } else {
3244 ast_log(LOG_WARNING, "Unable to lock the interface list\n");
3245 return -1;
3247 if (!gatekeeper_disable)
3248 h323_gk_urq();
3249 h323_end_process();
3250 if (io)
3251 io_context_destroy(io);
3252 if (sched)
3253 sched_context_destroy(sched);
3255 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
3256 ASTOBJ_CONTAINER_DESTROY(&userl);
3257 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
3258 ASTOBJ_CONTAINER_DESTROY(&peerl);
3259 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
3260 ASTOBJ_CONTAINER_DESTROY(&aliasl);
3262 return 0;
3265 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "The NuFone Network's OpenH323 Channel Driver",
3266 .load = load_module,
3267 .unload = unload_module,
3268 .reload = reload,