aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_iax2.c
diff options
context:
space:
mode:
authorbbryant <bbryant@f38db490-d61c-443f-a65b-d21fe96a405b>2010-09-09 18:51:52 +0000
committerbbryant <bbryant@f38db490-d61c-443f-a65b-d21fe96a405b>2010-09-09 18:51:52 +0000
commit722eb3c4c3cfa1c0cee915c949c5f95199ee24dd (patch)
tree25683963c5e51bdedd6211cd0ea92a85639505c3 /channels/chan_iax2.c
parent815b5b09da5e555add7bba3d8fca588e7611248a (diff)
Merged revisions 285710 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.6.2 ........ r285710 | bbryant | 2010-09-09 14:50:13 -0400 (Thu, 09 Sep 2010) | 8 lines Fixes an issue with dialplan pattern matching where the specificity for pattern ranges and pattern special characters was inconsistent. (closes issue #16903) Reported by: Nick_Lewis Patches: pbx.c-specificity.patch uploaded by Nick Lewis (license 657) Tested by: Nick_Lewis ........ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.8@285711 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/chan_iax2.c')
-rw-r--r--channels/chan_iax2.c114
1 files changed, 99 insertions, 15 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 5bb6b2c59..b05adaa1a 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -268,6 +268,9 @@ static char default_parkinglot[AST_MAX_CONTEXT];
static char language[MAX_LANGUAGE] = "";
static char regcontext[AST_MAX_CONTEXT] = "";
+static struct ast_event_sub *network_change_event_subscription; /*!< subscription id for network change events */
+static int network_change_event_sched_id = -1;
+
static int maxauthreq = 3;
static int max_retries = 4;
static int ping_time = 21;
@@ -355,6 +358,8 @@ static int (*iax2_regfunk)(const char *username, int onoff) = NULL;
static struct io_context *io;
static struct ast_sched_thread *sched;
+#define DONT_RESCHEDULE -2
+
static format_t iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH;
static int iaxdebug = 0;
@@ -1177,6 +1182,8 @@ static int iax2_setoption(struct ast_channel *c, int option, void *data, int dat
static int iax2_queryoption(struct ast_channel *c, int option, void *data, int *datalen);
static int iax2_transfer(struct ast_channel *c, const char *dest);
static int iax2_write(struct ast_channel *c, struct ast_frame *f);
+static int iax2_sched_add(struct ast_sched_thread *st, int when, ast_sched_cb callback, const void *data);
+
static int send_trunk(struct iax2_trunk_peer *tpeer, struct timeval *now);
static int send_command(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int);
static int send_command_final(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int);
@@ -1201,6 +1208,7 @@ static void build_rand_pad(unsigned char *buf, ssize_t len);
static struct callno_entry *get_unused_callno(int trunk, int validated);
static int replace_callno(const void *obj);
static void sched_delay_remove(struct sockaddr_in *sin, struct callno_entry *callno_entry);
+static void network_change_event_cb(const struct ast_event *, void *);
static const struct ast_channel_tech iax2_tech = {
.type = "IAX2",
@@ -1236,6 +1244,47 @@ static void mwi_event_cb(const struct ast_event *event, void *userdata)
* is time to send MWI, since it is only sent with a REGACK. */
}
+static void network_change_event_subscribe(void)
+{
+ if (!network_change_event_subscription) {
+ network_change_event_subscription = ast_event_subscribe(AST_EVENT_NETWORK_CHANGE,
+ network_change_event_cb,
+ "SIP Network Change ",
+ NULL,
+ AST_EVENT_IE_END);
+ }
+}
+
+static void network_change_event_unsubscribe(void)
+{
+ if (network_change_event_subscription) {
+ network_change_event_subscription = ast_event_unsubscribe(network_change_event_subscription);
+ }
+}
+
+static int network_change_event_sched_cb(const void *data)
+{
+ struct iax2_registry *reg;
+ network_change_event_sched_id = -1;
+ AST_LIST_LOCK(&registrations);
+ AST_LIST_TRAVERSE(&registrations, reg, entry) {
+ iax2_do_register(reg);
+ }
+ AST_LIST_UNLOCK(&registrations);
+
+ return 0;
+}
+
+static void network_change_event_cb(const struct ast_event *event, void *userdata)
+{
+ ast_debug(1, "IAX, got a network change event, renewing all IAX registrations.\n");
+ if (network_change_event_sched_id == -1) {
+ network_change_event_sched_id = iax2_sched_add(sched, 1000, network_change_event_sched_cb, NULL);
+ }
+
+}
+
+
/*! \brief Send manager event at call setup to link between Asterisk channel name
and IAX2 call identifiers */
static void iax2_ami_channelupdate(struct chan_iax2_pvt *pvt)
@@ -1246,7 +1295,6 @@ static void iax2_ami_channelupdate(struct chan_iax2_pvt *pvt)
pvt->callno, pvt->peercallno, pvt->peer ? pvt->peer : "");
}
-
static struct ast_datastore_info iax2_variable_datastore_info = {
.type = "IAX2_VARIABLE",
.duplicate = iax2_dup_variable_datastore,
@@ -1427,10 +1475,9 @@ static void __send_ping(const void *data)
if (iaxs[callno]) {
if (iaxs[callno]->peercallno) {
send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);
- iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data);
- } else {
- /* I am the schedule, so I'm allowed to do this */
- iaxs[callno]->pingid = -1;
+ if (iaxs[callno]->pingid != DONT_RESCHEDULE) {
+ iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data);
+ }
}
} else {
ast_debug(1, "I was supposed to send a PING with callno %d, but no such call exists.\n", callno);
@@ -1441,9 +1488,16 @@ static void __send_ping(const void *data)
static int send_ping(const void *data)
{
+ int callno = (long) data;
+ ast_mutex_lock(&iaxsl[callno]);
+ if (iaxs[callno] && iaxs[callno]->pingid != DONT_RESCHEDULE) {
+ iaxs[callno]->pingid = -1;
+ }
+ ast_mutex_unlock(&iaxsl[callno]);
+
#ifdef SCHED_MULTITHREADED
if (schedule_action(__send_ping, data))
-#endif
+#endif
__send_ping(data);
return 0;
@@ -1488,10 +1542,9 @@ static void __send_lagrq(const void *data)
if (iaxs[callno]) {
if (iaxs[callno]->peercallno) {
send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
- iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data);
- } else {
- /* I am the schedule, so I'm allowed to do this */
- iaxs[callno]->lagid = -1;
+ if (iaxs[callno]->lagid != DONT_RESCHEDULE) {
+ iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data);
+ }
}
} else {
ast_debug(1, "I was supposed to send a LAGRQ with callno %d, but no such call exists.\n", callno);
@@ -1502,11 +1555,17 @@ static void __send_lagrq(const void *data)
static int send_lagrq(const void *data)
{
+ int callno = (long) data;
+ ast_mutex_lock(&iaxsl[callno]);
+ if (iaxs[callno] && iaxs[callno]->lagid != DONT_RESCHEDULE) {
+ iaxs[callno]->lagid = -1;
+ }
+ ast_mutex_unlock(&iaxsl[callno]);
+
#ifdef SCHED_MULTITHREADED
if (schedule_action(__send_lagrq, data))
-#endif
+#endif
__send_lagrq(data);
-
return 0;
}
@@ -1688,7 +1747,9 @@ static void iax2_destroy_helper(struct chan_iax2_pvt *pvt)
}
/* No more pings or lagrq's */
AST_SCHED_DEL_SPINLOCK(ast_sched_thread_get_context(sched), pvt->pingid, &iaxsl[pvt->callno]);
+ pvt->pingid = DONT_RESCHEDULE;
AST_SCHED_DEL_SPINLOCK(ast_sched_thread_get_context(sched), pvt->lagid, &iaxsl[pvt->callno]);
+ pvt->lagid = DONT_RESCHEDULE;
ast_sched_thread_del(sched, pvt->autoid);
ast_sched_thread_del(sched, pvt->authid);
ast_sched_thread_del(sched, pvt->initid);
@@ -6986,13 +7047,14 @@ static int manager_iax2_show_registry(struct mansession *s, const struct message
astman_append(s,
"Event: RegistryEntry\r\n"
+ "%s"
"Host: %s\r\n"
"DNSmanager: %s\r\n"
"Username: %s\r\n"
"Perceived: %s\r\n"
"Refresh: %d\r\n"
"State: %s\r\n"
- "\r\n", host, (reg->dnsmgr) ? "Y" : "N", reg->username, perceived,
+ "\r\n", idtext, host, (reg->dnsmgr) ? "Y" : "N", reg->username, perceived,
reg->refresh, regstate2str(reg->regstate));
total++;
@@ -10428,6 +10490,7 @@ retryowner:
/* No authentication required, let them in */
memset(&ied1, 0, sizeof(ied1));
iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
+ iax_ie_append_versioned_uint64(&ied1, IAX_IE_FORMAT2, 0, format);
send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
if (strcmp(iaxs[fr->callno]->exten, "TBD")) {
ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
@@ -10893,6 +10956,7 @@ retryowner2:
/* Authentication received */
memset(&ied1, 0, sizeof(ied1));
iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
+ iax_ie_append_versioned_uint64(&ied1, IAX_IE_FORMAT2, 0, format);
send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
if (strcmp(iaxs[fr->callno]->exten, "TBD")) {
ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
@@ -12779,7 +12843,8 @@ static int set_config(const char *config_file, int reload)
int format;
int portno = IAX_DEFAULT_PORTNO;
int x;
- int mtuv;
+ int mtuv;
+ int subscribe_network_change = 1;
struct iax2_user *user;
struct iax2_peer *peer;
struct ast_netsock *ns;
@@ -13097,6 +13162,14 @@ static int set_config(const char *config_file, int reload)
if (add_calltoken_ignore(v->value)) {
ast_log(LOG_WARNING, "Invalid calltokenoptional address range - '%s' line %d\n", v->value, v->lineno);
}
+ } else if (!strcasecmp(v->name, "subscribe_network_change_event")) {
+ if (ast_true(v->value)) {
+ subscribe_network_change = 1;
+ } else if (ast_false(v->value)) {
+ subscribe_network_change = 0;
+ } else {
+ ast_log(LOG_WARNING, "subscribe_network_change_event value %s is not valid at line %d.\n", v->value, v->lineno);
+ }
} else if (!strcasecmp(v->name, "shrinkcallerid")) {
if (ast_true(v->value)) {
ast_set_flag64((&globalflags), IAX_SHRINKCALLERID);
@@ -13109,7 +13182,13 @@ static int set_config(const char *config_file, int reload)
/* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
v = v->next;
}
-
+
+ if (subscribe_network_change) {
+ network_change_event_subscribe();
+ } else {
+ network_change_event_unsubscribe();
+ }
+
if (defaultsockfd < 0) {
if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, qos.tos, qos.cos, socket_read, NULL))) {
ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
@@ -14050,6 +14129,8 @@ static int __unload_module(void)
struct ast_context *con;
int x;
+ network_change_event_unsubscribe();
+
ast_manager_unregister("IAXpeers");
ast_manager_unregister("IAXpeerlist");
ast_manager_unregister("IAXnetstats");
@@ -14530,6 +14611,8 @@ static int load_module(void)
ast_realtime_require_field("iaxpeers", "name", RQ_CHAR, 10, "ipaddr", RQ_CHAR, 15, "port", RQ_UINTEGER2, 5, "regseconds", RQ_UINTEGER2, 6, SENTINEL);
+ network_change_event_subscribe();
+
return AST_MODULE_LOAD_SUCCESS;
}
@@ -14538,4 +14621,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Inter Asterisk eXchan
.unload = unload_module,
.reload = reload,
.load_pri = AST_MODPRI_CHANNEL_DRIVER,
+ .nonoptreq = "res_crypto",
);