aboutsummaryrefslogtreecommitdiffstats
path: root/channels
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
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')
-rw-r--r--channels/chan_agent.c2
-rw-r--r--channels/chan_dahdi.c52
-rw-r--r--channels/chan_iax2.c114
-rw-r--r--channels/chan_local.c32
-rw-r--r--channels/chan_mgcp.c5
-rw-r--r--channels/chan_misdn.c105
-rw-r--r--channels/chan_multicast_rtp.c10
-rw-r--r--channels/chan_phone.c80
-rw-r--r--channels/chan_sip.c606
-rw-r--r--channels/chan_usbradio.c161
-rw-r--r--channels/console_video.c239
-rw-r--r--channels/sig_analog.c10
-rw-r--r--channels/sig_analog.h2
-rw-r--r--channels/sig_pri.c69
-rw-r--r--channels/sig_pri.h6
-rw-r--r--channels/sip/config_parser.c12
-rw-r--r--channels/sip/include/sip.h14
17 files changed, 927 insertions, 592 deletions
diff --git a/channels/chan_agent.c b/channels/chan_agent.c
index b8e142d04..37a6688d7 100644
--- a/channels/chan_agent.c
+++ b/channels/chan_agent.c
@@ -32,6 +32,7 @@
*/
/*** MODULEINFO
<depend>chan_local</depend>
+ <depend>res_monitor</depend>
***/
#include "asterisk.h"
@@ -2484,4 +2485,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Agent Proxy Channel",
.unload = unload_module,
.reload = reload,
.load_pri = AST_MODPRI_CHANNEL_DRIVER,
+ .nonoptreq = "res_monitor,chan_local",
);
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index df03a5805..364c85d04 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -38,7 +38,7 @@
*/
/*** MODULEINFO
- <depend>res_smdi</depend>
+ <use>res_smdi</use>
<depend>dahdi</depend>
<depend>tonezone</depend>
<use>pri</use>
@@ -2887,6 +2887,7 @@ static void my_pri_fixup_chans(void *chan_old, void *chan_new)
/* More stuff to transfer to the new channel. */
new_chan->law = old_chan->law;
+ strcpy(new_chan->dialstring, old_chan->dialstring);
}
#endif /* defined(HAVE_PRI) */
@@ -3111,7 +3112,7 @@ static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
if (pri->pvts[idx]->owner
#if defined(HAVE_PRI_SERVICE_MESSAGES)
/* Out-of-service B channels are "in-use". */
- && pri->pvts[idx]->service_status
+ || pri->pvts[idx]->service_status
#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
) {
++in_use;
@@ -13708,25 +13709,36 @@ static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_a
ast_cli(a->fd, "No PRI running on span %d\n", span);
return CLI_SUCCESS;
}
+
+ /* Set debug level in libpri */
for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
- if (pris[span-1].pri.dchans[x]) {
- if (level == 1) {
- pri_set_debug(pris[span-1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
- ast_cli(a->fd, "Enabled debugging on span %d\n", span);
- } else if (level == 0) {
- pri_set_debug(pris[span-1].pri.dchans[x], 0);
- /* close the file if it's set */
- ast_mutex_lock(&pridebugfdlock);
- close(pridebugfd);
- pridebugfd = -1;
- ast_cli(a->fd, "PRI debug output to file disabled\n");
- ast_mutex_unlock(&pridebugfdlock);
- } else {
- pri_set_debug(pris[span-1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
- ast_cli(a->fd, "Enabled debugging on span %d\n", span);
+ if (pris[span - 1].pri.dchans[x]) {
+ switch (level) {
+ case 0:
+ pri_set_debug(pris[span - 1].pri.dchans[x], 0);
+ break;
+ case 1:
+ pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
+ break;
+ default:
+ pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
+ break;
}
}
}
+ if (level == 0) {
+ /* Close the debugging file if it's set */
+ ast_mutex_lock(&pridebugfdlock);
+ if (0 <= pridebugfd) {
+ close(pridebugfd);
+ pridebugfd = -1;
+ ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
+ pridebugfilename);
+ }
+ ast_mutex_unlock(&pridebugfdlock);
+ }
+ pris[span - 1].pri.debug = (level) ? 1 : 0;
+ ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
return CLI_SUCCESS;
}
#endif /* defined(HAVE_PRI) */
@@ -13943,7 +13955,7 @@ static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_
int x;
int span;
int count=0;
- int debug=0;
+ int debug;
switch (cmd) {
case CLI_INIT:
@@ -13959,7 +13971,6 @@ static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_
for (span = 0; span < NUM_SPANS; span++) {
if (pris[span].pri.pri) {
for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
- debug = 0;
if (pris[span].pri.dchans[x]) {
debug = pri_get_debug(pris[span].pri.dchans[x]);
ast_cli(a->fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
@@ -13975,7 +13986,7 @@ static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_
ast_mutex_unlock(&pridebugfdlock);
if (!count)
- ast_cli(a->fd, "No debug set or no PRI running\n");
+ ast_cli(a->fd, "No PRI running\n");
return CLI_SUCCESS;
}
#endif /* defined(HAVE_PRI) */
@@ -17915,4 +17926,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
.unload = unload_module,
.reload = reload,
.load_pri = AST_MODPRI_CHANNEL_DRIVER,
+ .nonoptreq = "res_smdi",
);
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",
);
diff --git a/channels/chan_local.c b/channels/chan_local.c
index d1f66f8dd..aebca441a 100644
--- a/channels/chan_local.c
+++ b/channels/chan_local.c
@@ -409,6 +409,38 @@ static void check_bridge(struct local_pvt *p)
p->chan->audiohooks = p->owner->audiohooks;
p->owner->audiohooks = audiohooks_swapper;
}
+
+ /* If any Caller ID was set, preserve it after masquerade like above. We must check
+ * to see if Caller ID was set because otherwise we'll mistakingly copy info not
+ * set from the dialplan and will overwrite the real channel Caller ID. The reason
+ * for this whole preswapping action is because the Caller ID is set on the channel
+ * thread (which is the to be masqueraded away local channel) before both local
+ * channels are optimized away.
+ */
+ if (p->owner->caller.id.name.valid || p->owner->caller.id.number.valid
+ || p->owner->caller.id.subaddress.valid || p->owner->caller.ani.name.valid
+ || p->owner->caller.ani.number.valid || p->owner->caller.ani.subaddress.valid) {
+ struct ast_party_caller tmp;
+ tmp = p->owner->caller;
+ p->owner->caller = p->chan->_bridge->caller;
+ p->chan->_bridge->caller = tmp;
+ }
+ if (p->owner->redirecting.from.name.valid || p->owner->redirecting.from.number.valid
+ || p->owner->redirecting.from.subaddress.valid || p->owner->redirecting.to.name.valid
+ || p->owner->redirecting.to.number.valid || p->owner->redirecting.to.subaddress.valid) {
+ struct ast_party_redirecting tmp;
+ tmp = p->owner->redirecting;
+ p->owner->redirecting = p->chan->_bridge->redirecting;
+ p->chan->_bridge->redirecting = tmp;
+ }
+ if (p->owner->dialed.number.str || p->owner->dialed.subaddress.valid) {
+ struct ast_party_dialed tmp;
+ tmp = p->owner->dialed;
+ p->owner->dialed = p->chan->_bridge->dialed;
+ p->chan->_bridge->dialed = tmp;
+ }
+
+
ast_app_group_update(p->chan, p->owner);
ast_channel_masquerade(p->owner, p->chan->_bridge);
ast_set_flag(p, LOCAL_ALREADY_MASQED);
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index 485b39aad..2f953a9ae 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -30,7 +30,7 @@
*/
/*** MODULEINFO
- <depend>res_pktccops</depend>
+ <use>res_pktccops</use>
***/
#include "asterisk.h"
@@ -3580,7 +3580,7 @@ static int find_and_retrans(struct mgcp_subchannel *sub, struct mgcp_request *re
if (sscanf(req->identifier, "%30d", &seqno) != 1) {
seqno = 0;
}
- for (cur = sub->parent->parent->responses, next = cur->next; cur; cur = next, next = cur->next) {
+ for (cur = sub->parent->parent->responses, next = cur ? cur->next : NULL; cur; cur = next, next = cur ? cur->next : NULL) {
if (now - cur->whensent > RESPONSE_TIMEOUT) {
/* Delete this entry */
if (prev)
@@ -4915,4 +4915,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Media Gateway Control
.unload = unload_module,
.reload = reload,
.load_pri = AST_MODPRI_CHANNEL_DRIVER,
+ .nonoptreq = "res_pktccops",
);
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c
index 8b31ed23a..d326e1511 100644
--- a/channels/chan_misdn.c
+++ b/channels/chan_misdn.c
@@ -6011,7 +6011,7 @@ static int read_config(struct chan_list *ch)
* \param ast Current Asterisk channel
* \param id Party id information to send to the other side
* \param source Why are we sending this update
- * \param cid_tag Caller ID tag to set in the connected line
+ * \param cid_tag User tag to apply to the party id.
*
* \return Nothing
*/
@@ -6036,6 +6036,61 @@ static void misdn_queue_connected_line_update(struct ast_channel *ast, const str
/*!
* \internal
+ * \brief Update the caller id party on this channel.
+ *
+ * \param ast Current Asterisk channel
+ * \param id Remote party id information to update.
+ * \param cid_tag User tag to apply to the party id.
+ *
+ * \return Nothing
+ */
+static void misdn_update_caller_id(struct ast_channel *ast, const struct misdn_party_id *id, char *cid_tag)
+{
+ struct ast_party_caller caller;
+ struct ast_set_party_caller update_caller;
+
+ memset(&update_caller, 0, sizeof(update_caller));
+ update_caller.id.number = 1;
+ update_caller.ani.number = 1;
+
+ ast_channel_lock(ast);
+ ast_party_caller_set_init(&caller, &ast->caller);
+
+ caller.id.number.valid = 1;
+ caller.id.number.str = (char *) id->number;
+ caller.id.number.plan = misdn_to_ast_ton(id->number_type)
+ | misdn_to_ast_plan(id->number_plan);
+ caller.id.number.presentation = misdn_to_ast_pres(id->presentation)
+ | misdn_to_ast_screen(id->screening);
+
+ caller.ani.number = caller.id.number;
+
+ caller.id.tag = cid_tag;
+ caller.ani.tag = cid_tag;
+
+ ast_channel_set_caller_event(ast, &caller, &update_caller);
+ ast_channel_unlock(ast);
+}
+
+/*!
+ * \internal
+ * \brief Update the remote party id information.
+ *
+ * \param ast Current Asterisk channel
+ * \param id Remote party id information to update.
+ * \param source Why are we sending this update
+ * \param cid_tag User tag to apply to the party id.
+ *
+ * \return Nothing
+ */
+static void misdn_update_remote_party(struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source, char *cid_tag)
+{
+ misdn_update_caller_id(ast, id, cid_tag);
+ misdn_queue_connected_line_update(ast, id, source, cid_tag);
+}
+
+/*!
+ * \internal
* \brief Get the connected line information out of the Asterisk channel.
*
* \param ast Current Asterisk channel
@@ -7160,15 +7215,14 @@ static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame
static struct ast_frame *misdn_read(struct ast_channel *ast)
{
struct chan_list *tmp;
- fd_set rrfs;
- struct timeval tv = { 0, 20000 };
int len, t;
+ struct pollfd pfd = { .fd = -1, .events = POLLIN };
if (!ast) {
chan_misdn_log(1, 0, "misdn_read called without ast\n");
return NULL;
}
- if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
+ if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
return NULL;
}
@@ -7178,21 +7232,18 @@ static struct ast_frame *misdn_read(struct ast_channel *ast)
return NULL;
}
- FD_ZERO(&rrfs);
- FD_SET(tmp->pipe[0], &rrfs);
-
- t = select(FD_SETSIZE, &rrfs, NULL, NULL, &tv);
- if (!t) {
- chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
- len = 160;
- }
+ pfd.fd = tmp->pipe[0];
+ t = ast_poll(&pfd, 1, 20);
if (t < 0) {
- chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n", strerror(errno));
+ chan_misdn_log(-1, tmp->bc->port, "poll() error (err=%s)\n", strerror(errno));
return NULL;
}
- if (FD_ISSET(tmp->pipe[0], &rrfs)) {
+ if (!t) {
+ chan_misdn_log(3, tmp->bc->port, "poll() timed out\n");
+ len = 160;
+ } else if (pfd.revents & POLLIN) {
len = read(tmp->pipe[0], tmp->ast_rd_buf, sizeof(tmp->ast_rd_buf));
if (len <= 0) {
@@ -9161,7 +9212,7 @@ static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel
* The consequences if we wind up sending two updates is benign.
* The other end will think that it got transferred twice.
*/
- misdn_queue_connected_line_update(ch->ast, &party_id,
+ misdn_update_remote_party(ch->ast, &party_id,
(bc->fac_in.u.EctInform.Status == 0 /* alerting */)
? AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING
: AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER,
@@ -10233,7 +10284,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
misdn_add_number_prefix(bc->port, bc->connected.number_type, bc->connected.number, sizeof(bc->connected.number));
/* Update the connected line information on the other channel */
- misdn_queue_connected_line_update(ch->ast, &bc->connected, AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, bc->incoming_cid_tag);
+ misdn_update_remote_party(ch->ast, &bc->connected, AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, bc->incoming_cid_tag);
}
ch->l3id = bc->l3_id;
@@ -10456,25 +10507,21 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
ast_queue_frame(ch->ast, &frame);
}
} else {
- fd_set wrfs;
- struct timeval tv = { 0, 0 };
+ struct pollfd pfd = { .fd = ch->pipe[1], .events = POLLOUT };
int t;
- FD_ZERO(&wrfs);
- FD_SET(ch->pipe[1], &wrfs);
+ t = ast_poll(&pfd, 1, 0);
- t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv);
- if (!t) {
- chan_misdn_log(9, bc->port, "Select Timed out\n");
+ if (t < 0) {
+ chan_misdn_log(-1, bc->port, "poll() error (err=%s)\n", strerror(errno));
break;
}
-
- if (t < 0) {
- chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
+ if (!t) {
+ chan_misdn_log(9, bc->port, "poll() timed out\n");
break;
}
- if (FD_ISSET(ch->pipe[1], &wrfs)) {
+ if (pfd.revents & POLLOUT) {
chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
@@ -10636,7 +10683,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
if (bc->redirecting.to_changed) {
bc->redirecting.to_changed = 0;
if (ch && ch->ast) {
- misdn_queue_connected_line_update(ch->ast, &bc->redirecting.to,
+ misdn_update_remote_party(ch->ast, &bc->redirecting.to,
AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING, bc->incoming_cid_tag);
}
}
@@ -10645,7 +10692,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
if (bc->redirecting.to_changed) {
bc->redirecting.to_changed = 0;
if (ch && ch->ast) {
- misdn_queue_connected_line_update(ch->ast, &bc->redirecting.to,
+ misdn_update_remote_party(ch->ast, &bc->redirecting.to,
AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, bc->incoming_cid_tag);
}
}
diff --git a/channels/chan_multicast_rtp.c b/channels/chan_multicast_rtp.c
index e3414d2f3..93f46473f 100644
--- a/channels/chan_multicast_rtp.c
+++ b/channels/chan_multicast_rtp.c
@@ -126,11 +126,6 @@ static struct ast_channel *multicast_rtp_request(const char *type, format_t form
}
*destination++ = '\0';
- if (!ast_sockaddr_parse(&destination_address, destination,
- PARSE_PORT_REQUIRE)) {
- goto failure;
- }
-
if ((control = strchr(destination, '/'))) {
*control++ = '\0';
if (!ast_sockaddr_parse(&control_address, control,
@@ -139,6 +134,11 @@ static struct ast_channel *multicast_rtp_request(const char *type, format_t form
}
}
+ if (!ast_sockaddr_parse(&destination_address, destination,
+ PARSE_PORT_REQUIRE)) {
+ goto failure;
+ }
+
if (!(instance = ast_rtp_instance_new("multicast", NULL, &control_address, multicast_type))) {
goto failure;
}
diff --git a/channels/chan_phone.c b/channels/chan_phone.c
index 48da10fd6..531b95cb5 100644
--- a/channels/chan_phone.c
+++ b/channels/chan_phone.c
@@ -1017,12 +1017,12 @@ static void phone_check_exception(struct phone_pvt *i)
static void *do_monitor(void *data)
{
- fd_set rfds, efds;
- int n, res;
+ struct pollfd *fds = NULL;
+ int nfds = 0, inuse_fds = 0, res;
struct phone_pvt *i;
int tonepos = 0;
/* The tone we're playing this round */
- struct timeval wait = {0,0};
+ struct timeval tv = { 0, 0 };
int dotone;
/* This thread monitors all the frame relay interfaces which are not yet in use
(and thus do not have a separate thread) indefinitely */
@@ -1036,33 +1036,38 @@ static void *do_monitor(void *data)
}
/* Build the stuff we're going to select on, that is the socket of every
phone_pvt that does not have an associated owner channel */
- n = -1;
- FD_ZERO(&rfds);
- FD_ZERO(&efds);
i = iflist;
dotone = 0;
- while (i) {
- if (FD_ISSET(i->fd, &rfds))
- ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
+ inuse_fds = 0;
+ for (i = iflist; i; i = i->next) {
if (!i->owner) {
/* This needs to be watched, as it lacks an owner */
- FD_SET(i->fd, &rfds);
- FD_SET(i->fd, &efds);
- if (i->fd > n)
- n = i->fd;
+ if (inuse_fds == nfds) {
+ void *tmp = ast_realloc(fds, (nfds + 1) * sizeof(*fds));
+ if (!tmp) {
+ /* Avoid leaking */
+ continue;
+ }
+ fds = tmp;
+ nfds++;
+ }
+ fds[inuse_fds].fd = i->fd;
+ fds[inuse_fds].events = POLLIN | POLLERR;
+ fds[inuse_fds].revents = 0;
+ inuse_fds++;
+
if (i->dialtone && i->mode != MODE_SIGMA) {
/* Remember we're going to have to come back and play
more dialtones */
- if (ast_tvzero(wait)) {
+ if (ast_tvzero(tv)) {
/* If we're due for a dialtone, play one */
- if (write(i->fd, DialTone + tonepos, 240) != 240)
+ if (write(i->fd, DialTone + tonepos, 240) != 240) {
ast_log(LOG_WARNING, "Dial tone write error\n");
+ }
}
dotone++;
}
}
-
- i = i->next;
}
/* Okay, now that we know what to do, release the interface lock */
ast_mutex_unlock(&iflock);
@@ -1071,26 +1076,28 @@ static void *do_monitor(void *data)
if (dotone && i && i->mode != MODE_SIGMA) {
/* If we're ready to recycle the time, set it to 30 ms */
tonepos += 240;
- if (tonepos >= sizeof(DialTone))
- tonepos = 0;
- if (ast_tvzero(wait)) {
- wait = ast_tv(30000, 0);
+ if (tonepos >= sizeof(DialTone)) {
+ tonepos = 0;
}
- res = ast_select(n + 1, &rfds, NULL, &efds, &wait);
+ if (ast_tvzero(tv)) {
+ tv = ast_tv(0, 30000);
+ }
+ res = ast_poll2(fds, inuse_fds, &tv);
} else {
- res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
- wait = ast_tv(0,0);
+ res = ast_poll(fds, inuse_fds, -1);
+ tv = ast_tv(0, 0);
tonepos = 0;
}
/* Okay, select has finished. Let's see what happened. */
if (res < 0) {
- ast_debug(1, "select return %d: %s\n", res, strerror(errno));
+ ast_debug(1, "poll returned %d: %s\n", res, strerror(errno));
continue;
}
/* If there are no fd's changed, just continue, it's probably time
to play some more dialtones */
- if (!res)
+ if (!res) {
continue;
+ }
/* Alright, lock the interface list again, and let's look and see what has
happened */
if (ast_mutex_lock(&iflock)) {
@@ -1098,15 +1105,27 @@ static void *do_monitor(void *data)
continue;
}
- i = iflist;
- for(; i; i=i->next) {
- if (FD_ISSET(i->fd, &rfds)) {
+ for (i = iflist; i; i = i->next) {
+ int j;
+ /* Find the record */
+ for (j = 0; j < inuse_fds; j++) {
+ if (fds[j].fd == i->fd) {
+ break;
+ }
+ }
+
+ /* Not found? */
+ if (j == inuse_fds) {
+ continue;
+ }
+
+ if (fds[j].revents & POLLIN) {
if (i->owner) {
continue;
}
phone_mini_packet(i);
}
- if (FD_ISSET(i->fd, &efds)) {
+ if (fds[j].revents & POLLERR) {
if (i->owner) {
continue;
}
@@ -1116,7 +1135,6 @@ static void *do_monitor(void *data)
ast_mutex_unlock(&iflock);
}
return NULL;
-
}
static int restart_monitor()
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 47dc2610d..805b372ad 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -162,6 +162,7 @@
*/
/*** MODULEINFO
+ <depend>res_crypto</depend>
<depend>chan_local</depend>
***/
@@ -259,7 +260,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/translate.h"
#include "asterisk/ast_version.h"
#include "asterisk/event.h"
-#include "asterisk/stun.h"
#include "asterisk/cel.h"
#include "asterisk/data.h"
#include "asterisk/aoc.h"
@@ -762,6 +762,9 @@ static int regobjs = 0; /*!< Registry objects */
static struct ast_flags global_flags[3] = {{0}}; /*!< global SIP_ flags */
static int global_t38_maxdatagram; /*!< global T.38 FaxMaxDatagram override */
+static struct ast_event_sub *network_change_event_subscription; /*!< subscription id for network change events */
+static int network_change_event_sched_id = -1;
+
static char used_context[AST_MAX_CONTEXT]; /*!< name of automatically created context for unloading */
AST_MUTEX_DEFINE_STATIC(netlock);
@@ -1142,9 +1145,6 @@ static struct ast_sockaddr internip;
* hostname is stored in externhost, and the hostname->IP mapping
* is refreshed every 'externrefresh' seconds;
*
- * + with "stunaddr = host[:port]" we run queries every externrefresh seconds
- * to the specified server, and store the result in externaddr.
- *
* Other variables (externhost, externexpire, externrefresh) are used
* to support the above functions.
*/
@@ -1154,7 +1154,6 @@ static struct ast_sockaddr media_address; /*!< External RTP IP address if we are
static char externhost[MAXHOSTNAMELEN]; /*!< External host name */
static time_t externexpire; /*!< Expiration counter for re-resolving external host name in dynamic DNS */
static int externrefresh = 10; /*!< Refresh timer for DNS-based external address (dyndns) */
-static struct sockaddr_in stunaddr; /*!< stun server address */
static uint16_t externtcpport; /*!< external tcp port */
static uint16_t externtlsport; /*!< external tls port */
@@ -1334,6 +1333,7 @@ static int sip_poke_peer(struct sip_peer *peer, int force);
static void sip_poke_all_peers(void);
static void sip_peer_hold(struct sip_pvt *p, int hold);
static void mwi_event_cb(const struct ast_event *, void *);
+static void network_change_event_cb(const struct ast_event *, void *);
/*--- Applications, functions, CLI and manager command helpers */
static const char *sip_nat_mode(const struct sip_pvt *p);
@@ -1512,7 +1512,7 @@ static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req);
static int handle_request_message(struct sip_pvt *p, struct sip_request *req);
static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e);
static void handle_request_info(struct sip_pvt *p, struct sip_request *req);
-static int handle_request_options(struct sip_pvt *p, struct sip_request *req);
+static int handle_request_options(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e);
static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct ast_sockaddr *addr, int *nounlock);
static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int seqno, const char *e);
static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *current, struct sip_request *req, int seqno, int *nounlock);
@@ -2622,6 +2622,32 @@ cleanup:
return NULL;
}
+/* this func is used with ao2_callback to unlink/delete all marked
+ peers */
+static int peer_is_marked(void *peerobj, void *arg, int flags)
+{
+ struct sip_peer *peer = peerobj;
+ return peer->the_mark ? CMP_MATCH : 0;
+}
+
+
+/* \brief Unlink all marked peers from ao2 containers */
+static void unlink_marked_peers_from_tables(void)
+{
+ ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, NULL,
+ "initiating callback to remove marked peers");
+ ao2_t_callback(peers_by_ip, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, NULL,
+ "initiating callback to remove marked peers");
+}
+
+/* \brief Unlink single peer from all ao2 containers */
+static void unlink_peer_from_tables(struct sip_peer *peer)
+{
+ ao2_t_unlink(peers, peer, "ao2_unlink of peer from peers table");
+ if (!ast_sockaddr_isnull(&peer->addr)) {
+ ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table");
+ }
+}
/*!
* helper functions to unreference various types of objects.
@@ -3112,14 +3138,13 @@ static void build_via(struct sip_pvt *p)
static void ast_sip_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us, struct sip_pvt *p)
{
struct ast_sockaddr theirs;
- struct sockaddr_in externaddr_sin;
/* Set want_remap to non-zero if we want to remap 'us' to an externally
* reachable IP address and port. This is done if:
* 1. we have a localaddr list (containing 'internal' addresses marked
* as 'deny', so ast_apply_ha() will return AST_SENSE_DENY on them,
* and AST_SENSE_ALLOW on 'external' ones);
- * 2. either stunaddr or externaddr is set, so we know what to use as the
+ * 2. externaddr is set, so we know what to use as the
* externally visible address;
* 3. the remote address, 'them', is external;
* 4. the address returned by ast_ouraddrfor() is 'internal' (AST_SENSE_DENY
@@ -3141,22 +3166,16 @@ static void ast_sip_ouraddrfor(const struct ast_sockaddr *them, struct ast_socka
}
} else {
want_remap = localaddr &&
- !(ast_sockaddr_isnull(&externaddr) && stunaddr.sin_addr.s_addr) &&
+ !ast_sockaddr_isnull(&externaddr) &&
ast_apply_ha(localaddr, &theirs) == AST_SENSE_ALLOW ;
}
if (want_remap &&
(!sip_cfg.matchexternaddrlocally || !ast_apply_ha(localaddr, us)) ) {
- /* if we used externhost or stun, see if it is time to refresh the info */
+ /* if we used externhost, see if it is time to refresh the info */
if (externexpire && time(NULL) >= externexpire) {
- if (stunaddr.sin_addr.s_addr) {
- ast_sockaddr_to_sin(&externaddr, &externaddr_sin);
- ast_stun_request(sipsock, &stunaddr, NULL, &externaddr_sin);
- } else {
- if (ast_sockaddr_resolve_first(&externaddr, externhost, 0)) {
- ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost);
- }
- externexpire = time(NULL);
+ if (ast_sockaddr_resolve_first(&externaddr, externhost, 0)) {
+ ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost);
}
externexpire = time(NULL) + externrefresh;
}
@@ -3182,9 +3201,6 @@ static void ast_sip_ouraddrfor(const struct ast_sockaddr *them, struct ast_socka
break;
}
}
- else {
- ast_log(LOG_WARNING, "stun failed\n");
- }
ast_debug(1, "Target address %s is not local, substituting externaddr\n",
ast_sockaddr_stringify(them));
} else if (p) {
@@ -3341,7 +3357,6 @@ static int retrans_pkt(const void *data)
append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data->str);
xmitres = __sip_xmit(pkt->owner, pkt->data, pkt->packetlen);
- sip_pvt_unlock(pkt->owner);
/* If there was no error during the network transmission, schedule the next retransmission,
* but if the next retransmission is going to be beyond our timeout period, mark the packet's
@@ -3353,6 +3368,7 @@ static int retrans_pkt(const void *data)
pkt->retrans_stop = 1;
reschedule = diff;
}
+ sip_pvt_unlock(pkt->owner);
return reschedule;
}
}
@@ -3584,10 +3600,6 @@ static int __sip_autodestruct(const void *data)
}
}
- if (p->relatedpeer) {
- p->relatedpeer = unref_peer(p->relatedpeer, "__sip_autodestruct: unref peer p->relatedpeer"); /* Remove link to peer. If it's realtime, make sure it's gone from memory) */
- }
-
/* Reset schedule ID */
p->autokillid = -1;
@@ -4774,7 +4786,7 @@ static int dialog_initialize_rtp(struct sip_pvt *dialog)
ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
- ast_rtp_instance_set_qos(dialog->rtp, global_tos_audio, 0, "SIP RTP");
+ ast_rtp_instance_set_qos(dialog->rtp, global_tos_audio, global_cos_audio, "SIP RTP");
do_setnat(dialog);
@@ -5255,8 +5267,7 @@ void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist)
if (p->owner) {
if (lockowner)
ast_channel_lock(p->owner);
- if (option_debug)
- ast_log(LOG_DEBUG, "Detaching from %s\n", p->owner->name);
+ ast_debug(1, "Detaching from %s\n", p->owner->name);
p->owner->tech_pvt = NULL;
/* Make sure that the channel knows its backend is going away */
p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
@@ -5823,12 +5834,10 @@ static int sip_hangup(struct ast_channel *ast)
if (!p->alreadygone && p->initreq.data && !ast_strlen_zero(p->initreq.data->str)) {
if (needcancel) { /* Outgoing call, not up */
if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
- /* stop retransmitting an INVITE that has not received a response */
/* if we can't send right now, mark it pending */
if (p->invitestate == INV_CALLING) {
/* We can't send anything in CALLING state */
ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
- __sip_pretend_ack(p);
/* Do we need a timer here if we don't hear from them at all? Yes we do or else we will get hung dialogs and those are no fun. */
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
append_history(p, "DELAY", "Not sending cancel, waiting for timeout");
@@ -6416,7 +6425,7 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
* just says they are waiting to get AOC-E before completely tearing
* the call down. Since SIP does not support this at the moment go
* ahead and terminate the call here to avoid an unnecessary timeout. */
- ast_log(LOG_DEBUG, "AOC-E termination request received on %s. This is not yet supported on sip. Continue with hangup \n", p->owner->name);
+ ast_debug(1, "AOC-E termination request received on %s. This is not yet supported on sip. Continue with hangup \n", p->owner->name);
ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
}
break;
@@ -6882,8 +6891,7 @@ static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p
f = ast_dsp_process(p->owner, p->dsp, f);
if (f && f->frametype == AST_FRAME_DTMF) {
if (f->subclass.integer == 'f') {
- if (option_debug)
- ast_log(LOG_DEBUG, "Fax CNG detected on %s\n", ast->name);
+ ast_debug(1, "Fax CNG detected on %s\n", ast->name);
*faxdetect = 1;
/* If we only needed this DSP for fax detection purposes we can just drop it now */
if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) {
@@ -7046,6 +7054,7 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
char *sent_by, *branch;
const char *cseq = get_header(req, "Cseq");
unsigned int seqno;
+
/* get branch parameter from initial Request that started this dialog */
get_viabranch(ast_strdupa(get_header(req, "Via")), &sent_by, &branch);
/* only store the branch if it begins with the magic prefix "z9hG4bK", otherwise
@@ -7060,7 +7069,8 @@ struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
if (!ast_strlen_zero(cseq) && (sscanf(cseq, "%30u", &seqno) == 1)) {
p->init_icseq = seqno;
}
- set_socket_transport(&p->socket, req->socket.type); /* Later in ast_sip_ouraddrfor we need this to choose the right ip and port for the specific transport */
+ /* Later in ast_sip_ouraddrfor we need this to choose the right ip and port for the specific transport */
+ set_socket_transport(&p->socket, req->socket.type);
} else {
set_socket_transport(&p->socket, SIP_TRANSPORT_UDP);
}
@@ -7193,7 +7203,10 @@ enum match_req_res {
*/
static enum match_req_res match_req_to_dialog(struct sip_pvt *sip_pvt_ptr, struct match_req_args *arg)
{
- const char *init_ruri = REQ_OFFSET_TO_STR(&sip_pvt_ptr->initreq, rlPart2);
+ const char *init_ruri = NULL;
+ if (sip_pvt_ptr->initreq.headers) {
+ init_ruri = REQ_OFFSET_TO_STR(&sip_pvt_ptr->initreq, rlPart2);
+ }
/*
* Match Tags and call-id to Dialog
@@ -7252,8 +7265,8 @@ static enum match_req_res match_req_to_dialog(struct sip_pvt *sip_pvt_ptr, struc
if ((arg->method != SIP_RESPONSE) && /* must be a Request */
ast_strlen_zero(arg->totag) && /* must not have a totag */
(sip_pvt_ptr->init_icseq == arg->seqno) && /* the cseq must be the same as this dialogs initial cseq */
- !ast_strlen_zero(sip_pvt_ptr->initviabranch)) { /* The dialog must have started with a RFC3261 compliant branch tag */
-
+ !ast_strlen_zero(sip_pvt_ptr->initviabranch) && /* The dialog must have started with a RFC3261 compliant branch tag */
+ init_ruri) { /* the dialog must have an initial request uri associated with it */
/* This Request matches all the criteria required for Loop/Merge detection.
* Now we must go down the path of comparing VIA's and RURIs. */
if (ast_strlen_zero(arg->viabranch) ||
@@ -8106,8 +8119,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
break;
}
- if (option_debug > 2)
- ast_log(LOG_DEBUG, "Processing session-level SDP %c=%s... %s\n", type, value, (processed == TRUE)? "OK." : "UNSUPPORTED.");
+ ast_debug(3, "Processing session-level SDP %c=%s... %s\n", type, value, (processed == TRUE)? "OK." : "UNSUPPORTED.");
}
@@ -8291,11 +8303,10 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
break;
}
- if (option_debug > 2)
- ast_log(LOG_DEBUG, "Processing media-level (%s) SDP %c=%s... %s\n",
- (audio == TRUE)? "audio" : (video == TRUE)? "video" : "image",
- type, value,
- (processed == TRUE)? "OK." : "UNSUPPORTED.");
+ ast_debug(3, "Processing media-level (%s) SDP %c=%s... %s\n",
+ (audio == TRUE)? "audio" : (video == TRUE)? "video" : "image",
+ type, value,
+ (processed == TRUE)? "OK." : "UNSUPPORTED.");
}
}
@@ -8471,10 +8482,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
if (udptlportno > 0) {
if (ast_test_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP) && ast_test_flag(&p->flags[1], SIP_PAGE2_UDPTL_DESTINATION)) {
ast_rtp_instance_get_remote_address(p->rtp, isa);
- if (!ast_sockaddr_isnull(isa)) {
- if (debug) {
- ast_log(LOG_DEBUG, "Peer T.38 UDPTL is set behind NAT and with destination, destination address now %s\n", ast_sockaddr_stringify(isa));
- }
+ if (!ast_sockaddr_isnull(isa) && debug) {
+ ast_debug(1, "Peer T.38 UDPTL is set behind NAT and with destination, destination address now %s\n", ast_sockaddr_stringify(isa));
}
}
ast_sockaddr_set_port(isa, udptlportno);
@@ -8548,7 +8557,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
ast_set_write_format(p->owner, p->owner->writeformat);
}
- if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && !ast_sockaddr_isnull(sa) && (!sendonly || sendonly == -1)) {
+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && (!ast_sockaddr_isnull(sa) || !ast_sockaddr_isnull(vsa) || !ast_sockaddr_isnull(tsa) || !ast_sockaddr_isnull(isa)) && (!sendonly || sendonly == -1)) {
ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
/* Activate a re-invite */
ast_queue_frame(p->owner, &ast_null_frame);
@@ -8564,7 +8573,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
if (sip_cfg.notifyhold)
sip_peer_hold(p, FALSE);
ast_clear_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD); /* Clear both flags */
- } else if (ast_sockaddr_isnull(sa) || (sendonly && sendonly != -1)) {
+ } else if ((ast_sockaddr_isnull(sa) && ast_sockaddr_isnull(vsa) && ast_sockaddr_isnull(tsa) && ast_sockaddr_isnull(isa)) || (sendonly && sendonly != -1)) {
int already_on_hold = ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD);
ast_queue_control_data(p->owner, AST_CONTROL_HOLD,
S_OR(p->mohsuggest, NULL),
@@ -8750,8 +8759,7 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
struct ast_rtp_payload_type format = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(p->rtp), codec_n);
if (!format.asterisk_format || !format.code) /* non-codec or not found */
continue;
- if (option_debug)
- ast_log(LOG_DEBUG, "Setting framing for %s to %ld\n", ast_getformatname(format.code), framing);
+ ast_debug(1, "Setting framing for %s to %ld\n", ast_getformatname(format.code), framing);
ast_codec_pref_setsize(pref, format.code, framing);
}
ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, pref);
@@ -9003,6 +9011,20 @@ static int process_sdp_a_image(const char *a, struct sip_pvt *p)
return found;
}
+/*! \brief Add "Supported" header to sip message. Since some options may
+ * be disabled in the config, the sip_pvt must be inspected to determine what
+ * is supported for this dialog. */
+static int add_supported_header(struct sip_pvt *pvt, struct sip_request *req)
+{
+ int res;
+ if (st_get_mode(pvt) != SESSION_TIMER_MODE_REFUSE) {
+ res = add_header(req, "Supported", "replaces, timer");
+ } else {
+ res = add_header(req, "Supported", "replaces");
+ }
+ return res;
+}
+
/*! \brief Add header to SIP message */
static int add_header(struct sip_request *req, const char *var, const char *value)
{
@@ -9035,8 +9057,16 @@ static int add_header_max_forwards(struct sip_pvt *dialog, struct sip_request *r
char clen[10];
const char *max = NULL;
+ /* deadlock avoidance */
+ while (dialog->owner && ast_channel_trylock(dialog->owner)) {
+ sip_pvt_unlock(dialog);
+ usleep(1);
+ sip_pvt_lock(dialog);
+ }
+
if (dialog->owner) {
max = pbx_builtin_getvar_helper(dialog->owner, "SIP_MAX_FORWARDS");
+ ast_channel_unlock(dialog->owner);
}
/* The channel variable overrides the peer/channel value */
@@ -9436,14 +9466,13 @@ static int respprep(struct sip_request *resp, struct sip_pvt *p, const char *msg
if (!ast_strlen_zero(global_useragent))
add_header(resp, "Server", global_useragent);
add_header(resp, "Allow", ALLOWED_METHODS);
- add_header(resp, "Supported", SUPPORTED_EXTENSIONS);
+ add_supported_header(p, resp);
/* If this is an invite, add Session-Timers related headers if the feature is active for this session */
if (p->method == SIP_INVITE && p->stimer && p->stimer->st_active == TRUE && p->stimer->st_active_peer_ua == TRUE) {
char se_hdr[256];
snprintf(se_hdr, sizeof(se_hdr), "%d;refresher=%s", p->stimer->st_interval,
strefresher2str(p->stimer->st_ref));
- add_header(resp, "Require", "timer");
add_header(resp, "Session-Expires", se_hdr);
}
@@ -10259,6 +10288,8 @@ static void get_our_media_address(struct sip_pvt *p, int needvideo, int needtext
struct ast_sockaddr *taddr, struct ast_sockaddr *dest,
struct ast_sockaddr *vdest, struct ast_sockaddr *tdest)
{
+ int use_externip = 0;
+
/* First, get our address */
ast_rtp_instance_get_local_address(p->rtp, addr);
if (p->vrtp) {
@@ -10268,6 +10299,11 @@ static void get_our_media_address(struct sip_pvt *p, int needvideo, int needtext
ast_rtp_instance_get_local_address(p->trtp, taddr);
}
+ /* If our real IP differs from the local address returned by the RTP engine, use it. */
+ /* The premise is that if we are already using that IP to communicate with the client, */
+ /* we should be using it for RTP too. */
+ use_externip = ast_sockaddr_cmp_addr(&p->ourip, addr);
+
/* Now, try to figure out where we want them to send data */
/* Is this a re-invite to move the media out, then use the original offer from caller */
if (!ast_sockaddr_isnull(&p->redirip)) { /* If we have a redirection IP, use it */
@@ -10286,7 +10322,7 @@ static void get_our_media_address(struct sip_pvt *p, int needvideo, int needtext
*/
ast_sockaddr_copy(dest,
!ast_sockaddr_isnull(&media_address) ? &media_address :
- !ast_sockaddr_is_any(addr) ? addr :
+ !ast_sockaddr_is_any(addr) && !use_externip ? addr :
&p->ourip);
ast_sockaddr_set_port(dest, ast_sockaddr_port(addr));
}
@@ -10309,7 +10345,7 @@ static void get_our_media_address(struct sip_pvt *p, int needvideo, int needtext
*/
ast_sockaddr_copy(vdest,
!ast_sockaddr_isnull(&media_address) ? &media_address :
- !ast_sockaddr_is_any(vaddr) ? vaddr :
+ !ast_sockaddr_is_any(vaddr) && !use_externip ? vaddr :
&p->ourip);
ast_sockaddr_set_port(vdest, ast_sockaddr_port(vaddr));
}
@@ -10333,7 +10369,7 @@ static void get_our_media_address(struct sip_pvt *p, int needvideo, int needtext
*/
ast_sockaddr_copy(tdest,
!ast_sockaddr_isnull(&media_address) ? &media_address :
- !ast_sockaddr_is_any(taddr) ? taddr :
+ !ast_sockaddr_is_any(taddr) && !use_externip ? taddr :
&p->ourip);
ast_sockaddr_set_port(tdest, ast_sockaddr_port(taddr));
}
@@ -10909,7 +10945,7 @@ static int transmit_reinvite_with_sdp(struct sip_pvt *p, int t38version, int old
reqprep(&req, p, ast_test_flag(&p->flags[0], SIP_REINVITE_UPDATE) ? SIP_UPDATE : SIP_INVITE, 0, 1);
add_header(&req, "Allow", ALLOWED_METHODS);
- add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
+ add_supported_header(p, &req);
if (sipdebug) {
if (oldsdp == TRUE)
add_header(&req, "X-asterisk-Info", "SIP re-invite (Session-Timers)");
@@ -11305,7 +11341,7 @@ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init,
}
add_header(&req, "Allow", ALLOWED_METHODS);
- add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
+ add_supported_header(p, &req);
if (p->options && p->options->addsipheaders && p->owner) {
struct ast_channel *chan = p->owner; /* The owner channel */
@@ -11645,23 +11681,32 @@ static void state_notify_build_xml(int state, int full, const char *exten, const
ast_channel_unlock(caller);
caller = ast_channel_unref(caller);
}
+
+ /* We create a fake call-id which the phone will send back in an INVITE
+ Replaces header which we can grab and do some magic with. */
+ if (sip_cfg.pedanticsipchecking) {
+ ast_str_append(tmp, 0, "<dialog id=\"%s\" call-id=\"pickup-%s\" local-tag=\"%s\" remote-tag=\"%s\" direction=\"recipient\">\n",
+ exten, p->callid, p->theirtag, p->tag);
+ } else {
+ ast_str_append(tmp, 0, "<dialog id=\"%s\" call-id=\"pickup-%s\" direction=\"recipient\">\n",
+ exten, p->callid);
+ }
+ ast_str_append(tmp, 0,
+ "<remote>\n"
+ /* See the limitations of this above. Luckily the phone seems to still be
+ happy when these values are not correct. */
+ "<identity display=\"%s\">%s</identity>\n"
+ "<target uri=\"%s\"/>\n"
+ "</remote>\n"
+ "<local>\n"
+ "<identity>%s</identity>\n"
+ "<target uri=\"%s\"/>\n"
+ "</local>\n",
+ local_display, local_target, local_target, mto, mto);
+ } else {
+ ast_str_append(tmp, 0, "<dialog id=\"%s\" direction=\"recipient\">\n", exten);
}
- /* We create a fake call-id which the phone will send back in an INVITE
- Replaces header which we can grab and do some magic with. */
- ast_str_append(tmp, 0,
- "<dialog id=\"%s\" call-id=\"pickup-%s\" direction=\"recipient\">\n"
- "<remote>\n"
- /* See the limitations of this above. Luckily the phone seems to still be
- happy when these values are not correct. */
- "<identity display=\"%s\">%s</identity>\n"
- "<target uri=\"%s\"/>\n"
- "</remote>\n"
- "<local>\n"
- "<identity>%s</identity>\n"
- "<target uri=\"%s\"/>\n"
- "</local>\n",
- exten, p->callid, local_display, local_target, local_target, mto, mto);
} else {
ast_str_append(tmp, 0, "<dialog id=\"%s\">", exten);
}
@@ -11857,7 +11902,7 @@ static int transmit_notify_with_sipfrag(struct sip_pvt *p, int cseq, char *messa
add_header(&req, "Subscription-state", terminate ? "terminated;reason=noresource" : "active");
add_header(&req, "Content-Type", "message/sipfrag;version=2.0");
add_header(&req, "Allow", ALLOWED_METHODS);
- add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
+ add_supported_header(p, &req);
snprintf(tmp, sizeof(tmp), "SIP/2.0 %s\r\n", message);
add_content(&req, tmp);
@@ -11966,7 +12011,7 @@ static void update_connectedline(struct sip_pvt *p, const void *data, size_t dat
reqprep(&req, p, ast_test_flag(&p->flags[0], SIP_REINVITE_UPDATE) ? SIP_UPDATE : SIP_INVITE, 0, 1);
add_header(&req, "Allow", ALLOWED_METHODS);
- add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
+ add_supported_header(p, &req);
add_rpid(&req, p);
add_sdp(&req, p, FALSE, TRUE, FALSE);
@@ -11999,7 +12044,7 @@ static void update_connectedline(struct sip_pvt *p, const void *data, size_t dat
send_response(p, &resp, XMIT_UNRELIABLE, 0);
ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
} else {
- ast_log(LOG_DEBUG, "Unable able to send update to '%s' in state '%s'\n", p->owner->name, ast_state2str(p->owner->_state));
+ ast_debug(1, "Unable able to send update to '%s' in state '%s'\n", p->owner->name, ast_state2str(p->owner->_state));
}
} else {
ast_set_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND);
@@ -12456,7 +12501,7 @@ static int transmit_refer(struct sip_pvt *p, const char *dest)
add_header(&req, "Refer-To", referto);
add_header(&req, "Allow", ALLOWED_METHODS);
- add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
+ add_supported_header(p, &req);
if (!ast_strlen_zero(p->our_contact)) {
add_header(&req, "Referred-By", p->our_contact);
}
@@ -12652,7 +12697,6 @@ static int expire_register(const void *data)
peer->expire = -1;
peer->portinuri = 0;
- memset(&peer->addr, 0, sizeof(peer->addr));
destroy_association(peer); /* remove registration data from storage */
set_socket_transport(&peer->socket, peer->default_outbound_transport);
@@ -12675,12 +12719,13 @@ static int expire_register(const void *data)
if (peer->selfdestruct ||
ast_test_flag(&peer->flags[1], SIP_PAGE2_RTAUTOCLEAR)) {
- ao2_t_unlink(peers, peer, "ao2_unlink of peer from peers table");
- if (!ast_sockaddr_isnull(&peer->addr)) {
- ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table");
- }
+ unlink_peer_from_tables(peer);
}
+ /* Only clear the addr after we check for destruction. The addr must remain
+ * in order to unlink from the peers_by_ip container correctly */
+ memset(&peer->addr, 0, sizeof(peer->addr));
+
unref_peer(peer, "removing peer ref for expire_register");
return 0;
@@ -13411,6 +13456,39 @@ static void mwi_event_cb(const struct ast_event *event, void *userdata)
ao2_unlock(peer);
}
+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)
+{
+ network_change_event_sched_id = -1;
+ sip_send_all_registers();
+ sip_send_all_mwi_subscriptions();
+ return 0;
+}
+
+static void network_change_event_cb(const struct ast_event *event, void *userdata)
+{
+ ast_debug(1, "SIP, got a network change event, renewing all SIP registrations.\n");
+ if (network_change_event_sched_id == -1) {
+ network_change_event_sched_id = ast_sched_add(sched, 1000, network_change_event_sched_cb, NULL);
+ }
+}
+
/*! \brief Callback for the devicestate notification (SUBSCRIBE) support subsystem
\note If you add an "hint" priority to the extension in the dial plan,
you will get notifications on device state changes */
@@ -14623,7 +14701,7 @@ static int get_also_info(struct sip_pvt *p, struct sip_request *oreq)
* address and port in the SIP headers without the need for STUN.
* The address part is also reused for the media sessions.
* Note that ast_sip_ouraddrfor() still rewrites p->ourip
- * if you specify externaddr/seternaddr/stunaddr.
+ * if you specify externaddr/seternaddr/.
*/
static attribute_unused void check_via_response(struct sip_pvt *p, struct sip_request *req)
{
@@ -15790,14 +15868,6 @@ static int dialog_needdestroy(void *dialogobj, void *arg, int flags)
return 0;
}
-/* this func is used with ao2_callback to unlink/delete all marked
- peers */
-static int peer_is_marked(void *peerobj, void *arg, int flags)
-{
- struct sip_peer *peer = peerobj;
- return peer->the_mark ? CMP_MATCH : 0;
-}
-
/*! \brief Remove temporary realtime objects from memory (CLI) */
/*! \todo XXXX Propably needs an overhaul after removal of the devices */
static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -15900,8 +15970,7 @@ static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli
}
ao2_iterator_destroy(&i);
if (pruned) {
- ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, NULL,
- "initiating callback to remove marked peers");
+ unlink_marked_peers_from_tables();
ast_cli(a->fd, "%d peers pruned.\n", pruned);
} else
ast_cli(a->fd, "No peers found to prune.\n");
@@ -16740,6 +16809,10 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
ast_cli(a->fd, "\n\nGlobal Settings:\n");
ast_cli(a->fd, "----------------\n");
ast_cli(a->fd, " UDP Bindaddress: %s\n", ast_sockaddr_stringify(&bindaddr));
+ if (ast_sockaddr_is_ipv6(&bindaddr) && ast_sockaddr_is_any(&bindaddr)) {
+ ast_cli(a->fd, " ** Additional Info:\n");
+ ast_cli(a->fd, " [::] may include IPv4 in addition to IPv6, if such a feature is enabled in the OS.\n");
+ }
ast_cli(a->fd, " TCP SIP Bindaddress: %s\n",
sip_cfg.tcp_enabled != FALSE ?
ast_sockaddr_stringify(&sip_tcp_desc.local_address) :
@@ -16814,8 +16887,6 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
msg = "Disabled, no localnet list";
else if (ast_sockaddr_isnull(&externaddr))
msg = "Disabled";
- else if (stunaddr.sin_addr.s_addr != 0)
- msg = "Enabled using STUN";
else if (!ast_strlen_zero(externhost))
msg = "Enabled using externhost";
else
@@ -16835,8 +16906,6 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
ast_strdupa(ast_sockaddr_stringify_addr(&d->netmask)));
}
}
- ast_cli(a->fd, " STUN server: %s:%d\n", ast_inet_ntoa(stunaddr.sin_addr), ntohs(stunaddr.sin_port));
-
ast_cli(a->fd, "\nGlobal Signalling Settings:\n");
ast_cli(a->fd, "---------------------------\n");
ast_cli(a->fd, " Codecs: ");
@@ -18415,7 +18484,11 @@ static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char
}
}
-/*! \brief Check pending actions on SIP call */
+/*! \brief Check pending actions on SIP call
+ *
+ * \note both sip_pvt and sip_pvt's owner channel (if present)
+ * must be locked for this function.
+ */
static void check_pendings(struct sip_pvt *p)
{
if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
@@ -18430,6 +18503,9 @@ static void check_pendings(struct sip_pvt *p)
if (p->pendinginvite)
return;
+ if (p->owner) {
+ ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
+ }
/* Perhaps there is an SD change INVITE outstanding */
transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, TRUE);
}
@@ -18455,12 +18531,21 @@ static void check_pendings(struct sip_pvt *p)
static int sip_reinvite_retry(const void *data)
{
struct sip_pvt *p = (struct sip_pvt *) data;
+ struct ast_channel *owner;
sip_pvt_lock(p); /* called from schedule thread which requires a lock */
+ while ((owner = p->owner) && ast_channel_trylock(owner)) {
+ sip_pvt_unlock(p);
+ usleep(1);
+ sip_pvt_lock(p);
+ }
ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
p->waitid = -1;
check_pendings(p);
sip_pvt_unlock(p);
+ if (owner) {
+ ast_channel_unlock(owner);
+ }
dialog_unref(p, "unref the dialog ptr from sip_reinvite_retry, because it held a dialog ptr");
return 0;
}
@@ -18825,7 +18910,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
/* Check for Session-Timers related headers */
if (st_get_mode(p) != SESSION_TIMER_MODE_REFUSE && p->outgoing_call == TRUE && !reinvite) {
p_hdrval = (char*)get_header(req, "Session-Expires");
- if (!ast_strlen_zero(p_hdrval)) {
+ if (!ast_strlen_zero(p_hdrval)) {
/* UAS supports Session-Timers */
enum st_refresher tmp_st_ref = SESSION_TIMER_REFRESHER_AUTO;
int tmp_st_interval = 0;
@@ -19189,6 +19274,23 @@ static void handle_response_refer(struct sip_pvt *p, int resp, const char *rest,
ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
}
break;
+ default:
+ /* We should treat unrecognized 9xx as 900. 400 is actually
+ specified as a possible response, but any 4-6xx is
+ theoretically possible. */
+
+ if (resp < 299) { /* 1xx cases don't get here */
+ ast_log(LOG_WARNING, "SIP transfer to %s had unxpected 2xx response (%d), confusion is possible. \n", p->refer->refer_to, resp);
+ } else {
+ ast_log(LOG_WARNING, "SIP transfer to %s with response (%d). \n", p->refer->refer_to, resp);
+ }
+
+ p->refer->status = REFER_FAILED;
+ pvt_set_needdestroy(p, "received failure response");
+ if (p->owner) {
+ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
+ }
+ break;
}
}
@@ -19505,6 +19607,8 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
need to hang around for something more "definitive" */
if (resp != 100)
handle_response_peerpoke(p, resp, req);
+ } else if (sipmethod == SIP_REFER && resp >= 200) {
+ handle_response_refer(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_PUBLISH) {
/* SIP PUBLISH transcends this morass of doodoo and instead
* we just always call the response handler. Good gravy!
@@ -19541,18 +19645,12 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
}
break;
- case 202: /* Transfer accepted */
- if (sipmethod == SIP_REFER)
- handle_response_refer(p, resp, rest, req, seqno);
- break;
case 401: /* Not www-authorized on SIP method */
case 407: /* Proxy auth required */
if (sipmethod == SIP_INVITE)
handle_response_invite(p, resp, rest, req, seqno);
else if (sipmethod == SIP_NOTIFY)
handle_response_notify(p, resp, rest, req, seqno);
- else if (sipmethod == SIP_REFER)
- handle_response_refer(p, resp, rest, req, seqno);
else if (sipmethod == SIP_SUBSCRIBE)
handle_response_subscribe(p, resp, rest, req, seqno);
else if (p->registry && sipmethod == SIP_REGISTER)
@@ -19625,8 +19723,6 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
case 481: /* Call leg does not exist */
if (sipmethod == SIP_INVITE) {
handle_response_invite(p, resp, rest, req, seqno);
- } else if (sipmethod == SIP_REFER) {
- handle_response_refer(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_SUBSCRIBE) {
handle_response_subscribe(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_BYE) {
@@ -19668,16 +19764,9 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
}
if (sipmethod == SIP_INVITE)
handle_response_invite(p, resp, rest, req, seqno);
- else if (sipmethod == SIP_REFER)
- handle_response_refer(p, resp, rest, req, seqno);
else
ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n", ast_sockaddr_stringify(&p->sa), msg);
break;
- case 603: /* Declined transfer */
- if (sipmethod == SIP_REFER) {
- handle_response_refer(p, resp, rest, req, seqno);
- break;
- }
/* Fallthrough */
default:
if ((resp >= 300) && (resp < 700)) {
@@ -19720,10 +19809,7 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
case 410: /* Gone */
case 400: /* Bad Request */
case 500: /* Server error */
- if (sipmethod == SIP_REFER) {
- handle_response_refer(p, resp, rest, req, seqno);
- break;
- } else if (sipmethod == SIP_SUBSCRIBE) {
+ if (sipmethod == SIP_SUBSCRIBE) {
handle_response_subscribe(p, resp, rest, req, seqno);
break;
}
@@ -19821,15 +19907,9 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
;
}
break;
- case 202: /* Transfer accepted */
- if (sipmethod == SIP_REFER)
- handle_response_refer(p, resp, rest, req, seqno);
- break;
case 401: /* www-auth */
case 407:
- if (sipmethod == SIP_REFER)
- handle_response_refer(p, resp, rest, req, seqno);
- else if (sipmethod == SIP_INVITE)
+ if (sipmethod == SIP_INVITE)
handle_response_invite(p, resp, rest, req, seqno);
else if (sipmethod == SIP_BYE) {
if (p->authtries == MAX_AUTHTRIES || do_proxy_auth(p, req, resp, sipmethod, 0)) {
@@ -19851,15 +19931,7 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
case 501: /* Not Implemented */
if (sipmethod == SIP_INVITE)
handle_response_invite(p, resp, rest, req, seqno);
- else if (sipmethod == SIP_REFER)
- handle_response_refer(p, resp, rest, req, seqno);
break;
- case 603: /* Declined transfer */
- if (sipmethod == SIP_REFER) {
- handle_response_refer(p, resp, rest, req, seqno);
- break;
- }
- /* Fallthrough */
default: /* Errors without handlers */
if ((resp >= 100) && (resp < 200)) {
if (sipmethod == SIP_INVITE) { /* re-invite */
@@ -20307,18 +20379,8 @@ static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, str
*sep++ = '\0'; /* Response string */
respcode = atoi(code);
switch (respcode) {
- case 100: /* Trying: */
- case 101: /* dialog establishment */
- /* Don't do anything yet */
- success = -1; /* Wait */
- break;
- case 183: /* Ringing: */
- /* Don't do anything yet */
- success = -1; /* Wait */
- break;
case 200: /* OK: The new call is up, hangup this call */
/* Hangup the call that we are replacing */
- success = -1; /* Wait */
break;
case 301: /* Moved permenantly */
case 302: /* Moved temporarily */
@@ -20326,13 +20388,24 @@ static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, str
success = FALSE;
break;
case 503: /* Service Unavailable: The new call failed */
- /* Cancel transfer, continue the call */
+ case 603: /* Declined: Not accepted */
+ /* Cancel transfer, continue the current call */
success = FALSE;
break;
- case 603: /* Declined: Not accepted */
+ case 0: /* Parse error */
/* Cancel transfer, continue the current call */
+ ast_log(LOG_NOTICE, "Error parsing sipfrag in NOTIFY in response to REFER.\n");
success = FALSE;
break;
+ default:
+ if (respcode < 200) {
+ /* ignore provisional responses */
+ success = -1;
+ } else {
+ ast_log(LOG_NOTICE, "Got unknown code '%d' in NOTIFY in response to REFER.\n", respcode);
+ success = FALSE;
+ }
+ break;
}
if (success == FALSE) {
ast_log(LOG_NOTICE, "Transfer failed. Sorry. Nothing further to do with this call\n");
@@ -20398,26 +20471,39 @@ static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, str
/*! \brief Handle incoming OPTIONS request
An OPTIONS request should be answered like an INVITE from the same UA, including SDP
*/
-static int handle_request_options(struct sip_pvt *p, struct sip_request *req)
+static int handle_request_options(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
{
int res;
- /*! XXX get_destination assumes we're already authenticated. This means that a request from
- a known device (peer) will end up in the wrong context if this is out-of-dialog.
- However, we want to handle OPTIONS as light as possible, so we might want to have
- a configuration option whether we care or not. Some devices use this for testing
- capabilities, which means that we need to match device to answer with proper
- capabilities (including SDP).
- \todo Fix handle_request_options device handling with optional authentication
- (this needs to be fixed in 1.4 as well)
- */
-
if (p->lastinvite) {
/* if this is a request in an active dialog, just confirm that the dialog exists. */
transmit_response_with_allow(p, "200 OK", req, 0);
return 0;
}
+ if (sip_cfg.auth_options_requests) {
+ /* Do authentication if this OPTIONS request began the dialog */
+ copy_request(&p->initreq, req);
+ set_pvt_allowed_methods(p, req);
+ res = check_user(p, req, SIP_OPTIONS, e, XMIT_UNRELIABLE, addr);
+ if (res == AUTH_CHALLENGE_SENT) {
+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+ return 0;
+ }
+ if (res < 0) { /* Something failed in authentication */
+ if (res == AUTH_FAKE_AUTH) {
+ ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From"));
+ transmit_fake_auth_response(p, SIP_OPTIONS, req, XMIT_UNRELIABLE);
+ } else {
+ ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", get_header(req, "From"));
+ transmit_response(p, "403 Forbidden", req);
+ }
+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+ return 0;
+ }
+ }
+
+ /* must go through authentication before getting here */
res = (get_destination(p, req, NULL) == SIP_GET_DEST_EXTEN_FOUND ? 0 : -1);
build_contact(p);
@@ -20887,7 +20973,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
struct sip_pvt *subscription = NULL;
replace_id += 7; /* Worst case we are looking at \0 */
- if ((subscription = get_sip_pvt_byid_locked(replace_id, NULL, NULL)) == NULL) {
+ if ((subscription = get_sip_pvt_byid_locked(replace_id, totag, fromtag)) == NULL) {
ast_log(LOG_NOTICE, "Unable to find subscription with call-id: %s\n", replace_id);
transmit_response_reliable(p, "481 Call Leg Does Not Exist (Replaces)", req);
error = 1;
@@ -21192,10 +21278,10 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
}
/* Session-Timers */
- if (p->sipoptions & SIP_OPT_TIMER) {
+ if ((p->sipoptions & SIP_OPT_TIMER) && !ast_strlen_zero(get_header(req, "Session-Expires"))) {
/* The UAC has requested session-timers for this session. Negotiate
the session refresh interval and who will be the refresher */
- ast_debug(2, "Incoming INVITE with 'timer' option enabled\n");
+ ast_debug(2, "Incoming INVITE with 'timer' option supported and \"Session-Expires\" header.\n");
/* Allocate Session-Timers struct w/in the dialog */
if (!p->stimer)
@@ -21203,17 +21289,15 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
/* Parse the Session-Expires header */
p_uac_se_hdr = get_header(req, "Session-Expires");
- if (!ast_strlen_zero(p_uac_se_hdr)) {
- rtn = parse_session_expires(p_uac_se_hdr, &uac_max_se, &st_ref);
- if (rtn != 0) {
- transmit_response_reliable(p, "400 Session-Expires Invalid Syntax", req);
- p->invitestate = INV_COMPLETED;
- if (!p->lastinvite) {
- sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
- }
- res = -1;
- goto request_invite_cleanup;
+ rtn = parse_session_expires(p_uac_se_hdr, &uac_max_se, &st_ref);
+ if (rtn != 0) {
+ transmit_response_reliable(p, "400 Session-Expires Invalid Syntax", req);
+ p->invitestate = INV_COMPLETED;
+ if (!p->lastinvite) {
+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
}
+ res = -1;
+ goto request_invite_cleanup;
}
/* Parse the Min-SE header */
@@ -21650,7 +21734,7 @@ static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *
ast_do_masquerade(target.chan1);
- ast_channel_lock(transferer); /* the transferer pvt is expected to remain locked on return */
+ sip_pvt_lock(transferer); /* the transferer pvt is expected to remain locked on return */
ast_indicate(target.chan1, AST_CONTROL_UNHOLD);
@@ -22839,7 +22923,6 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
int firststate = AST_EXTENSION_REMOVED;
struct sip_peer *authpeer = NULL;
const char *eventheader = get_header(req, "Event"); /* Get Event package name */
- const char *acceptheader = get_header(req, "Accept");
int resubscribe = (p->subscribed != NONE);
char *temp, *event;
struct ao2_iterator i;
@@ -22970,51 +23053,93 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
if (!strcmp(event, "presence") || !strcmp(event, "dialog")) { /* Presence, RFC 3842 */
unsigned int pidf_xml;
+ const char *accept;
+ int start = 0;
+ enum subscriptiontype subscribed = NONE;
+ const char *unknown_acceptheader = NULL;
if (authpeer) /* We do not need the authpeer any more */
unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 2)");
/* Header from Xten Eye-beam Accept: multipart/related, application/rlmi+xml, application/pidf+xml, application/xpidf+xml */
+ accept = __get_header(req, "Accept", &start);
+ while ((subscribed == NONE) && !ast_strlen_zero(accept)) {
+ pidf_xml = strstr(accept, "application/pidf+xml") ? 1 : 0;
+
+ /* Older versions of Polycom firmware will claim pidf+xml, but really
+ * they only support xpidf+xml. */
+ if (pidf_xml && strstr(p->useragent, "Polycom")) {
+ subscribed = XPIDF_XML;
+ } else if (pidf_xml) {
+ subscribed = PIDF_XML; /* RFC 3863 format */
+ } else if (strstr(accept, "application/dialog-info+xml")) {
+ subscribed = DIALOG_INFO_XML;
+ /* IETF draft: draft-ietf-sipping-dialog-package-05.txt */
+ } else if (strstr(accept, "application/cpim-pidf+xml")) {
+ subscribed = CPIM_PIDF_XML; /* RFC 3863 format */
+ } else if (strstr(accept, "application/xpidf+xml")) {
+ subscribed = XPIDF_XML; /* Early pre-RFC 3863 format with MSN additions (Microsoft Messenger) */
+ } else {
+ unknown_acceptheader = accept;
+ }
+ /* check to see if there is another Accept header present */
+ accept = __get_header(req, "Accept", &start);
+ }
- pidf_xml = strstr(acceptheader, "application/pidf+xml") ? 1 : 0;
-
- /* Older versions of Polycom firmware will claim pidf+xml, but really
- * they only support xpidf+xml. */
- if (pidf_xml && strstr(p->useragent, "Polycom")) {
- p->subscribed = XPIDF_XML;
- } else if (pidf_xml) {
- p->subscribed = PIDF_XML; /* RFC 3863 format */
- } else if (strstr(acceptheader, "application/dialog-info+xml")) {
- p->subscribed = DIALOG_INFO_XML;
- /* IETF draft: draft-ietf-sipping-dialog-package-05.txt */
- } else if (strstr(acceptheader, "application/cpim-pidf+xml")) {
- p->subscribed = CPIM_PIDF_XML; /* RFC 3863 format */
- } else if (strstr(acceptheader, "application/xpidf+xml")) {
- p->subscribed = XPIDF_XML; /* Early pre-RFC 3863 format with MSN additions (Microsoft Messenger) */
- } else if (ast_strlen_zero(acceptheader)) {
+ if (!start) {
if (p->subscribed == NONE) { /* if the subscribed field is not already set, and there is no accept header... */
transmit_response(p, "489 Bad Event", req);
-
- ast_log(LOG_WARNING, "SUBSCRIBE failure: no Accept header: pvt: stateid: %d, laststate: %d, dialogver: %d, subscribecont: '%s', subscribeuri: '%s'\n",
- p->stateid, p->laststate, p->dialogver, p->subscribecontext, p->subscribeuri);
+ ast_log(LOG_WARNING,"SUBSCRIBE failure: no Accept header: pvt: "
+ "stateid: %d, laststate: %d, dialogver: %d, subscribecont: "
+ "'%s', subscribeuri: '%s'\n",
+ p->stateid,
+ p->laststate,
+ p->dialogver,
+ p->subscribecontext,
+ p->subscribeuri);
pvt_set_needdestroy(p, "no Accept header");
return 0;
}
/* if p->subscribed is non-zero, then accept is not obligatory; according to rfc 3265 section 3.1.3, at least.
so, we'll just let it ride, keeping the value from a previous subscription, and not abort the subscription */
- } else {
+ } else if (subscribed == NONE) {
/* Can't find a format for events that we know about */
char mybuf[200];
- snprintf(mybuf, sizeof(mybuf), "489 Bad Event (format %s)", acceptheader);
+ if (!ast_strlen_zero(unknown_acceptheader)) {
+ snprintf(mybuf, sizeof(mybuf), "489 Bad Event (format %s)", unknown_acceptheader);
+ } else {
+ snprintf(mybuf, sizeof(mybuf), "489 Bad Event");
+ }
transmit_response(p, mybuf, req);
-
- ast_log(LOG_WARNING, "SUBSCRIBE failure: unrecognized format: '%s' pvt: subscribed: %d, stateid: %d, laststate: %d, dialogver: %d, subscribecont: '%s', subscribeuri: '%s'\n",
- acceptheader, (int)p->subscribed, p->stateid, p->laststate, p->dialogver, p->subscribecontext, p->subscribeuri);
+ ast_log(LOG_WARNING,"SUBSCRIBE failure: unrecognized format:"
+ "'%s' pvt: subscribed: %d, stateid: %d, laststate: %d,"
+ "dialogver: %d, subscribecont: '%s', subscribeuri: '%s'\n",
+ unknown_acceptheader,
+ (int)p->subscribed,
+ p->stateid,
+ p->laststate,
+ p->dialogver,
+ p->subscribecontext,
+ p->subscribeuri);
pvt_set_needdestroy(p, "unrecognized format");
return 0;
+ } else {
+ p->subscribed = subscribed;
}
} else if (!strcmp(event, "message-summary")) {
- if (!ast_strlen_zero(acceptheader) && strcmp(acceptheader, "application/simple-message-summary")) {
+ int start = 0;
+ int found_supported = 0;
+ const char *acceptheader;
+
+ acceptheader = __get_header(req, "Accept", &start);
+ while (!found_supported && !ast_strlen_zero(acceptheader)) {
+ found_supported = strcmp(acceptheader, "application/simple-message-summary") ? 0 : 1;
+ if (!found_supported && (option_debug > 2)) {
+ ast_log(LOG_DEBUG, "Received SIP mailbox subscription for unknown format: %s\n", acceptheader);
+ }
+ acceptheader = __get_header(req, "Accept", &start);
+ }
+ if (start && !found_supported) {
/* Format requested that we do not support */
transmit_response(p, "406 Not Acceptable", req);
ast_debug(2, "Received SIP mailbox subscription for unknown format: %s\n", acceptheader);
@@ -23296,8 +23421,7 @@ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct as
return 0;
}
if (p->ocseq && (p->ocseq < seqno)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Ignoring out of order response %d (expecting %d)\n", seqno, p->ocseq);
+ ast_debug(1, "Ignoring out of order response %d (expecting %d)\n", seqno, p->ocseq);
return -1;
} else {
char causevar[256], causeval[256];
@@ -23404,7 +23528,7 @@ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct as
/* Handle various incoming SIP methods in requests */
switch (p->method) {
case SIP_OPTIONS:
- res = handle_request_options(p, req);
+ res = handle_request_options(p, req, addr, e);
break;
case SIP_INVITE:
res = handle_request_invite(p, req, debug, seqno, addr, recount, e, nounlock);
@@ -23489,9 +23613,7 @@ static void process_request_queue(struct sip_pvt *p, int *recount, int *nounlock
while ((req = AST_LIST_REMOVE_HEAD(&p->request_queue, next))) {
if (handle_incoming(p, req, &p->recv, recount, nounlock) == -1) {
/* Request failed */
- if (option_debug) {
- ast_log(LOG_DEBUG, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>");
- }
+ ast_debug(1, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>");
}
ast_free(req);
}
@@ -24478,7 +24600,7 @@ enum st_mode st_get_mode(struct sip_pvt *p)
static int sip_poke_noanswer(const void *data)
{
struct sip_peer *peer = (struct sip_peer *)data;
-
+
peer->pokeexpire = -1;
if (peer->lastms > -1) {
@@ -24497,9 +24619,12 @@ static int sip_poke_noanswer(const void *data)
peer->call = dialog_unref(peer->call, "unref dialog peer->call");
/* peer->call = sip_destroy(peer->call);*/
}
-
- peer->lastms = -1;
- ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name);
+
+ /* Don't send a devstate change if nothing changed. */
+ if (peer->lastms > -1) {
+ peer->lastms = -1;
+ ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name);
+ }
/* Try again quickly */
AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched,
@@ -25343,6 +25468,8 @@ static void set_peer_defaults(struct sip_peer *peer)
peer->timer_b = global_timer_b;
clear_peer_mailboxes(peer);
peer->disallowed_methods = sip_cfg.disallowed_methods;
+ peer->transports = default_transports;
+ peer->default_outbound_transport = default_primary_transport;
}
/*! \brief Create temporary peer (used in autocreatepeer mode) */
@@ -25497,6 +25624,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
/* If we have realm authentication information, remove them (reload) */
clear_realm_authentication(peer->auth);
peer->auth = NULL;
+ /* clear the transport information. We will detect if a default value is required after parsing the config */
peer->default_outbound_transport = 0;
peer->transports = 0;
@@ -26100,8 +26228,8 @@ static int reload_config(enum channelreloadreason reason)
int auto_sip_domains = FALSE;
struct ast_sockaddr old_bindaddr = bindaddr;
int registry_count = 0, peer_count = 0, timerb_set = 0, timert1_set = 0;
+ int subscribe_network_change = 1;
time_t run_start, run_end;
- struct sockaddr_in externaddr_sin;
int bindport = 0;
run_start = time(0);
@@ -26204,7 +26332,6 @@ static int reload_config(enum channelreloadreason reason)
/* Reset IP addresses */
ast_sockaddr_parse(&bindaddr, "0.0.0.0:0", 0);
- memset(&stunaddr, 0, sizeof(stunaddr));
memset(&internip, 0, sizeof(internip));
/* Free memory for local network address mask */
@@ -26245,6 +26372,7 @@ static int reload_config(enum channelreloadreason reason)
sip_cfg.notifyhold = FALSE; /*!< Keep track of hold status for a peer */
sip_cfg.directrtpsetup = FALSE; /* Experimental feature, disabled by default */
sip_cfg.alwaysauthreject = DEFAULT_ALWAYSAUTHREJECT;
+ sip_cfg.auth_options_requests = DEFAULT_AUTH_OPTIONS;
sip_cfg.allowsubscribe = FALSE;
sip_cfg.disallowed_methods = SIP_UNKNOWN;
sip_cfg.contact_ha = NULL; /* Reset the contact ACL */
@@ -26485,6 +26613,10 @@ static int reload_config(enum channelreloadreason reason)
}
} else if (!strcasecmp(v->name, "alwaysauthreject")) {
sip_cfg.alwaysauthreject = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "auth_options_requests")) {
+ if (ast_true(v->value)) {
+ sip_cfg.auth_options_requests = 1;
+ }
} else if (!strcasecmp(v->name, "mohinterpret")) {
ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret));
} else if (!strcasecmp(v->name, "mohsuggest")) {
@@ -26590,12 +26722,6 @@ static int reload_config(enum channelreloadreason reason)
}
} else if (!strcasecmp(v->name, "registerattempts")) {
global_regattempts_max = atoi(v->value);
- } else if (!strcasecmp(v->name, "stunaddr")) {
- stunaddr.sin_port = htons(3478);
- if (ast_parse_arg(v->value, PARSE_INADDR, &stunaddr)) {
- ast_log(LOG_WARNING, "Invalid STUN server address: %s\n", v->value);
- }
- externexpire = time(NULL);
} else if (!strcasecmp(v->name, "bindaddr") || !strcasecmp(v->name, "udpbindaddr")) {
if (ast_parse_arg(v->value, PARSE_ADDR, &bindaddr)) {
ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
@@ -26803,11 +26929,25 @@ static int reload_config(enum channelreloadreason reason)
ast_log(LOG_WARNING, "'%s' is not a valid maxforwards value at line %d. Using default.\n", v->value, v->lineno);
sip_cfg.default_max_forwards = DEFAULT_MAX_FORWARDS;
}
+ } 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, "snom_aoc_enabled")) {
ast_set2_flag(&global_flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC);
}
}
+ if (subscribe_network_change) {
+ network_change_event_subscribe();
+ } else {
+ network_change_event_unsubscribe();
+ }
+
if (global_t1 < global_t1min) {
ast_log(LOG_WARNING, "'t1min' (%d) cannot be greater than 't1timer' (%d). Resetting 't1timer' to the value of 't1min'\n", global_t1min, global_t1);
global_t1 = global_t1min;
@@ -26895,15 +27035,8 @@ static int reload_config(enum channelreloadreason reason)
ast_set_qos(sipsock, global_tos_sip, global_cos_sip, "SIP");
}
}
- }
- if (stunaddr.sin_addr.s_addr != 0) {
- ast_debug(1, "stun to %s:%d\n",
- ast_inet_ntoa(stunaddr.sin_addr) , ntohs(stunaddr.sin_port));
- ast_sockaddr_to_sin(&externaddr, &externaddr_sin);
- ast_stun_request(sipsock, &stunaddr,
- NULL, &externaddr_sin);
- ast_debug(1, "STUN sees us at %s\n",
- ast_sockaddr_stringify(&externaddr));
+ } else {
+ ast_set_qos(sipsock, global_tos_sip, global_cos_sip, "SIP");
}
ast_mutex_unlock(&netlock);
@@ -27060,10 +27193,10 @@ static int reload_config(enum channelreloadreason reason)
char temp[MAXHOSTNAMELEN];
/* First our default IP address */
- if (!ast_sockaddr_isnull(&bindaddr)) {
+ if (!ast_sockaddr_isnull(&bindaddr) && !ast_sockaddr_is_any(&bindaddr)) {
add_sip_domain(ast_sockaddr_stringify_addr(&bindaddr),
SIP_DOMAIN_AUTO, NULL);
- } else if (!ast_sockaddr_isnull(&internip)) {
+ } else if (!ast_sockaddr_isnull(&internip) && !ast_sockaddr_is_any(&internip)) {
/* Our internal IP address, if configured */
add_sip_domain(ast_sockaddr_stringify_addr(&internip),
SIP_DOMAIN_AUTO, NULL);
@@ -27490,7 +27623,7 @@ static int sip_removeheader(struct ast_channel *chan, const char *data)
if (strncasecmp(ast_var_name(newvariable), "SIPADDHEADER", strlen("SIPADDHEADER")) == 0) {
if (removeall || (!strncasecmp(ast_var_value(newvariable),inbuf,strlen(inbuf)))) {
if (sipdebug)
- ast_log(LOG_DEBUG,"removing SIP Header \"%s\" as %s\n",
+ ast_debug(1,"removing SIP Header \"%s\" as %s\n",
ast_var_value(newvariable),
ast_var_name(newvariable));
AST_LIST_REMOVE_CURRENT(entries);
@@ -27671,6 +27804,12 @@ static int process_crypto(struct sip_pvt *p, struct ast_rtp_instance *rtp, struc
}
}
+ /* For now, when we receive an INVITE just take the first successful crypto line */
+ if ((*srtp)->crypto && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+ ast_debug(3, "We've already processed a crypto attribute, skipping '%s'\n", a);
+ return FALSE;
+ }
+
if (!(*srtp)->crypto && !((*srtp)->crypto = sdp_crypto_setup())) {
return FALSE;
}
@@ -27694,9 +27833,8 @@ static int sip_do_reload(enum channelreloadreason reason)
start_poke = time(0);
/* Prune peers who still are supposed to be deleted */
- ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, NULL,
- "callback to remove marked peers");
-
+ unlink_marked_peers_from_tables();
+
ast_debug(4, "--------------- Done destroying pruned peers\n");
/* Send qualify (OPTIONS) to all peers */
@@ -27767,7 +27905,7 @@ static int ast_sockaddr_resolve_first_af(struct ast_sockaddr *addr,
return 1;
}
if (addrs_cnt > 1) {
- ast_log(LOG_DEBUG, "Multiple addresses, using the first one only\n");
+ ast_debug(1, "Multiple addresses, using the first one only\n");
}
ast_sockaddr_copy(addr, &addrs[0]);
@@ -28314,6 +28452,7 @@ static int load_module(void)
sip_register_tests();
+ network_change_event_subscribe();
return AST_MODULE_LOAD_SUCCESS;
}
@@ -28326,6 +28465,8 @@ static int unload_module(void)
struct ast_context *con;
struct ao2_iterator i;
+ network_change_event_unsubscribe();
+
ast_sched_dump(sched);
/* First, take us out of the channel type list */
@@ -28466,4 +28607,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Session Initiation Pr
.unload = unload_module,
.reload = reload,
.load_pri = AST_MODPRI_CHANNEL_DRIVER,
+ .nonoptreq = "res_crypto,chan_local",
);
diff --git a/channels/chan_usbradio.c b/channels/chan_usbradio.c
index b5867f5a4..eca7760ab 100644
--- a/channels/chan_usbradio.c
+++ b/channels/chan_usbradio.c
@@ -644,7 +644,7 @@ static struct chan_usbradio_pvt usbradio_default = {
/* DECLARE FUNCTION PROTOTYPES */
-static void store_txtoctype(struct chan_usbradio_pvt *o, char *s);
+static void store_txtoctype(struct chan_usbradio_pvt *o, const char *s);
static int hidhdwconfig(struct chan_usbradio_pvt *o);
static int set_txctcss_level(struct chan_usbradio_pvt *o);
static void pmrdump(struct chan_usbradio_pvt *o);
@@ -1119,8 +1119,7 @@ static void *hidthread(void *arg)
struct usb_device *usb_dev;
struct usb_dev_handle *usb_handle;
struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg;
- struct timeval to;
- fd_set rfds;
+ struct pollfd pfd = { .events = POLLIN };
usb_dev = hid_device_init(o->devstr);
if (usb_dev == NULL) {
@@ -1156,63 +1155,49 @@ static void *hidthread(void *arg)
traceusb1(("hidthread: Starting normally on %s!!\n",o->name));
lastrx = 0;
// popen
- while(!o->stophid)
- {
- to.tv_sec = 0;
- to.tv_usec = 50000; // maw sph
+ while (!o->stophid) {
+ pfd.fd = o->pttkick[0];
+ pfd.revents = 0;
- FD_ZERO(&rfds);
- FD_SET(o->pttkick[0],&rfds);
- /* ast_select emulates linux behaviour in terms of timeout handling */
- res = ast_select(o->pttkick[0] + 1, &rfds, NULL, NULL, &to);
+ res = ast_poll(&pfd, 1, 50);
if (res < 0) {
- ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
+ ast_log(LOG_WARNING, "poll() failed: %s\n", strerror(errno));
usleep(10000);
continue;
}
- if (FD_ISSET(o->pttkick[0],&rfds))
- {
+ if (pfd.revents & POLLIN) {
char c;
- if (read(o->pttkick[0],&c,1) < 0) {
+ if (read(o->pttkick[0], &c, 1) < 0) {
ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
}
}
- if(o->wanteeprom)
- {
+ if (o->wanteeprom) {
ast_mutex_lock(&o->eepromlock);
- if (o->eepromctl == 1) /* to read */
- {
+ if (o->eepromctl == 1) { /* to read */
/* if CS okay */
- if (!get_eeprom(usb_handle,o->eeprom))
- {
- if (o->eeprom[EEPROM_MAGIC_ADDR] != EEPROM_MAGIC)
- {
- ast_log(LOG_NOTICE,"UNSUCCESSFUL: EEPROM MAGIC NUMBER BAD on channel %s\n",o->name);
- }
- else
- {
+ if (!get_eeprom(usb_handle, o->eeprom)) {
+ if (o->eeprom[EEPROM_MAGIC_ADDR] != EEPROM_MAGIC) {
+ ast_log(LOG_NOTICE, "UNSUCCESSFUL: EEPROM MAGIC NUMBER BAD on channel %s\n", o->name);
+ } else {
o->rxmixerset = o->eeprom[EEPROM_RXMIXERSET];
- o->txmixaset = o->eeprom[EEPROM_TXMIXASET];
+ o->txmixaset = o->eeprom[EEPROM_TXMIXASET];
o->txmixbset = o->eeprom[EEPROM_TXMIXBSET];
- memcpy(&o->rxvoiceadj,&o->eeprom[EEPROM_RXVOICEADJ],sizeof(float));
- memcpy(&o->rxctcssadj,&o->eeprom[EEPROM_RXCTCSSADJ],sizeof(float));
+ memcpy(&o->rxvoiceadj, &o->eeprom[EEPROM_RXVOICEADJ], sizeof(float));
+ memcpy(&o->rxctcssadj, &o->eeprom[EEPROM_RXCTCSSADJ], sizeof(float));
o->txctcssadj = o->eeprom[EEPROM_TXCTCSSADJ];
o->rxsquelchadj = o->eeprom[EEPROM_RXSQUELCHADJ];
ast_log(LOG_NOTICE,"EEPROM Loaded on channel %s\n",o->name);
}
- }
- else
- {
- ast_log(LOG_NOTICE,"USB Adapter has no EEPROM installed or Checksum BAD on channel %s\n",o->name);
+ } else {
+ ast_log(LOG_NOTICE, "USB Adapter has no EEPROM installed or Checksum BAD on channel %s\n", o->name);
}
hid_set_outputs(usb_handle,bufsave);
- }
- if (o->eepromctl == 2) /* to write */
- {
+ }
+ if (o->eepromctl == 2) { /* to write */
put_eeprom(usb_handle,o->eeprom);
hid_set_outputs(usb_handle,bufsave);
- ast_log(LOG_NOTICE,"USB Parameters written to EEPROM on %s\n",o->name);
+ ast_log(LOG_NOTICE, "USB Parameters written to EEPROM on %s\n", o->name);
}
o->eepromctl = 0;
ast_mutex_unlock(&o->eepromlock);
@@ -1220,38 +1205,43 @@ static void *hidthread(void *arg)
buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
hid_get_inputs(usb_handle,buf);
keyed = !(buf[o->hid_io_cor_loc] & o->hid_io_cor);
- if (keyed != o->rxhidsq)
- {
- if(o->debuglevel)printf("chan_usbradio() hidthread: update rxhidsq = %d\n",keyed);
+ if (keyed != o->rxhidsq) {
+ if (o->debuglevel) {
+ printf("chan_usbradio() hidthread: update rxhidsq = %d\n", keyed);
+ }
o->rxhidsq=keyed;
}
/* if change in tx state as controlled by xpmr */
- txtmp=o->pmrChan->txPttOut;
-
- if (o->lasttx != txtmp)
- {
- o->pmrChan->txPttHid=o->lasttx = txtmp;
- if(o->debuglevel)printf("hidthread: tx set to %d\n",txtmp);
- buf[o->hid_gpio_loc] = 0;
- if (!o->invertptt)
- {
- if (txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
+ txtmp = o->pmrChan->txPttOut;
+
+ if (o->lasttx != txtmp) {
+ o->pmrChan->txPttHid = o->lasttx = txtmp;
+ if (o->debuglevel) {
+ ast_debug(0, "hidthread: tx set to %d\n", txtmp);
}
- else
- {
- if (!txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
+ buf[o->hid_gpio_loc] = 0;
+ if (!o->invertptt) {
+ if (txtmp) {
+ buf[o->hid_gpio_loc] = o->hid_io_ptt;
+ }
+ } else {
+ if (!txtmp) {
+ buf[o->hid_gpio_loc] = o->hid_io_ptt;
+ }
}
buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
- memcpy(bufsave,buf,sizeof(buf));
- hid_set_outputs(usb_handle,buf);
+ memcpy(bufsave, buf, sizeof(buf));
+ hid_set_outputs(usb_handle, buf);
}
time(&o->lasthidtime);
}
buf[o->hid_gpio_loc] = 0;
- if (o->invertptt) buf[o->hid_gpio_loc] = o->hid_io_ptt;
+ if (o->invertptt) {
+ buf[o->hid_gpio_loc] = o->hid_io_ptt;
+ }
buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
- hid_set_outputs(usb_handle,buf);
+ hid_set_outputs(usb_handle, buf);
pthread_exit(0);
}
@@ -1452,37 +1442,29 @@ static void *sound_thread(void *arg)
*/
read(o->sounddev, ign, sizeof(ign));
for (;;) {
- fd_set rfds, wfds;
- int maxfd, res;
-
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- FD_SET(o->sndcmd[0], &rfds);
- maxfd = o->sndcmd[0]; /* pipe from the main process */
- if (o->cursound > -1 && o->sounddev < 0)
+ struct pollfd pfd[2] = { { .fd = o->sndcmd[0], .events = POLLIN }, { .fd = o->sounddev } };
+ int res;
+
+ if (o->cursound > -1 && o->sounddev < 0) {
setformat(o, O_RDWR); /* need the channel, try to reopen */
- else if (o->cursound == -1 && o->owner == NULL)
- {
+ } else if (o->cursound == -1 && o->owner == NULL) {
setformat(o, O_CLOSE); /* can close */
}
if (o->sounddev > -1) {
if (!o->owner) { /* no one owns the audio, so we must drain it */
- FD_SET(o->sounddev, &rfds);
- maxfd = MAX(o->sounddev, maxfd);
+ pfd[1].events = POLLIN;
}
if (o->cursound > -1) {
- FD_SET(o->sounddev, &wfds);
- maxfd = MAX(o->sounddev, maxfd);
+ pfd[1].events |= POLLOUT;
}
}
- /* ast_select emulates linux behaviour in terms of timeout handling */
- res = ast_select(maxfd + 1, &rfds, &wfds, NULL, NULL);
+ res = ast_poll(pfd, o->sounddev > -1 ? 2 : 1, -1);
if (res < 1) {
- ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
+ ast_log(LOG_WARNING, "poll failed: %s\n", strerror(errno));
sleep(1);
continue;
}
- if (FD_ISSET(o->sndcmd[0], &rfds)) {
+ if (pfd[0].revents & POLLIN) {
/* read which sound to play from the pipe */
int i, what = -1;
@@ -1495,14 +1477,17 @@ static void *sound_thread(void *arg)
break;
}
}
- if (sounds[i].ind == -1)
+ if (sounds[i].ind == -1) {
ast_log(LOG_WARNING, "invalid sound index: %d\n", what);
+ }
}
if (o->sounddev > -1) {
- if (FD_ISSET(o->sounddev, &rfds)) /* read and ignore errors */
+ if (pfd[1].revents & POLLIN) { /* read and ignore errors */
read(o->sounddev, ign, sizeof(ign));
- if (FD_ISSET(o->sounddev, &wfds))
+ }
+ if (pfd[1].revents & POLLOUT) {
send_sound(o);
+ }
}
}
return NULL; /* Never reached */
@@ -2697,7 +2682,7 @@ static void store_callerid(struct chan_usbradio_pvt *o, char *s)
}
#endif
-static void store_rxdemod(struct chan_usbradio_pvt *o, char *s)
+static void store_rxdemod(struct chan_usbradio_pvt *o, const char *s)
{
if (!strcasecmp(s,"no")){
o->rxdemod = RX_AUDIO_NONE;
@@ -2716,7 +2701,7 @@ static void store_rxdemod(struct chan_usbradio_pvt *o, char *s)
}
-static void store_txmixa(struct chan_usbradio_pvt *o, char *s)
+static void store_txmixa(struct chan_usbradio_pvt *o, const char *s)
{
if (!strcasecmp(s,"no")){
o->txmixa = TX_OUT_OFF;
@@ -2740,7 +2725,7 @@ static void store_txmixa(struct chan_usbradio_pvt *o, char *s)
//ast_log(LOG_WARNING, "set txmixa = %s\n", s);
}
-static void store_txmixb(struct chan_usbradio_pvt *o, char *s)
+static void store_txmixb(struct chan_usbradio_pvt *o, const char *s)
{
if (!strcasecmp(s,"no")){
o->txmixb = TX_OUT_OFF;
@@ -2765,7 +2750,7 @@ static void store_txmixb(struct chan_usbradio_pvt *o, char *s)
}
/*
*/
-static void store_rxcdtype(struct chan_usbradio_pvt *o, char *s)
+static void store_rxcdtype(struct chan_usbradio_pvt *o, const char *s)
{
if (!strcasecmp(s,"no")){
o->rxcdtype = CD_IGNORE;
@@ -2790,7 +2775,7 @@ static void store_rxcdtype(struct chan_usbradio_pvt *o, char *s)
}
/*
*/
-static void store_rxsdtype(struct chan_usbradio_pvt *o, char *s)
+static void store_rxsdtype(struct chan_usbradio_pvt *o, const char *s)
{
if (!strcasecmp(s,"no") || !strcasecmp(s,"SD_IGNORE")){
o->rxsdtype = SD_IGNORE;
@@ -2812,7 +2797,7 @@ static void store_rxsdtype(struct chan_usbradio_pvt *o, char *s)
}
/*
*/
-static void store_rxgain(struct chan_usbradio_pvt *o, char *s)
+static void store_rxgain(struct chan_usbradio_pvt *o, const char *s)
{
float f;
sscanf(s, "%30f", &f);
@@ -2821,7 +2806,7 @@ static void store_rxgain(struct chan_usbradio_pvt *o, char *s)
}
/*
*/
-static void store_rxvoiceadj(struct chan_usbradio_pvt *o, char *s)
+static void store_rxvoiceadj(struct chan_usbradio_pvt *o, const char *s)
{
float f;
sscanf(s, "%30f", &f);
@@ -2830,7 +2815,7 @@ static void store_rxvoiceadj(struct chan_usbradio_pvt *o, char *s)
}
/*
*/
-static void store_rxctcssadj(struct chan_usbradio_pvt *o, char *s)
+static void store_rxctcssadj(struct chan_usbradio_pvt *o, const char *s)
{
float f;
sscanf(s, "%30f", &f);
@@ -2839,7 +2824,7 @@ static void store_rxctcssadj(struct chan_usbradio_pvt *o, char *s)
}
/*
*/
-static void store_txtoctype(struct chan_usbradio_pvt *o, char *s)
+static void store_txtoctype(struct chan_usbradio_pvt *o, const char *s)
{
if (!strcasecmp(s,"no") || !strcasecmp(s,"TOC_NONE")){
o->txtoctype = TOC_NONE;
diff --git a/channels/console_video.c b/channels/console_video.c
index 88bf807d5..c26ac983f 100644
--- a/channels/console_video.c
+++ b/channels/console_video.c
@@ -234,34 +234,34 @@ struct video_out_desc {
* and contain all configurtion info.
*/
struct video_desc {
- char codec_name[64]; /* the codec we use */
+ char codec_name[64]; /* the codec we use */
- int stayopen; /* set if gui starts manually */
- pthread_t vthread; /* video thread */
- ast_mutex_t dec_lock; /* sync decoder and video thread */
- int shutdown; /* set to shutdown vthread */
- struct ast_channel *owner; /* owner channel */
+ int stayopen; /* set if gui starts manually */
+ pthread_t vthread; /* video thread */
+ ast_mutex_t dec_lock; /* sync decoder and video thread */
+ int shutdown; /* set to shutdown vthread */
+ struct ast_channel *owner; /* owner channel */
- struct fbuf_t enc_in; /* encoder input buffer, allocated in video_out_init() */
+ struct fbuf_t enc_in; /* encoder input buffer, allocated in video_out_init() */
- char keypad_file[256]; /* image for the keypad */
- char keypad_font[256]; /* font for the keypad */
+ char keypad_file[256]; /* image for the keypad */
+ char keypad_font[256]; /* font for the keypad */
- char sdl_videodriver[256];
+ char sdl_videodriver[256];
- struct fbuf_t rem_dpy; /* display remote video, no buffer (it is in win[WIN_REMOTE].bmp) */
- struct fbuf_t loc_dpy; /* display local source, no buffer (managed by SDL in bmp[1]) */
+ struct fbuf_t rem_dpy; /* display remote video, no buffer (it is in win[WIN_REMOTE].bmp) */
+ struct fbuf_t loc_dpy; /* display local source, no buffer (managed by SDL in bmp[1]) */
/* geometry of the thumbnails for all video sources. */
- struct fbuf_t src_dpy[MAX_VIDEO_SOURCES]; /* no buffer allocated here */
+ struct fbuf_t src_dpy[MAX_VIDEO_SOURCES]; /* no buffer allocated here */
- int frame_freeze; /* flag to freeze the incoming frame */
+ int frame_freeze; /* flag to freeze the incoming frame */
/* local information for grabbers, codecs, gui */
- struct gui_info *gui;
- struct video_dec_desc *in; /* remote video descriptor */
- struct video_out_desc out; /* local video descriptor */
+ struct gui_info *gui;
+ struct video_dec_desc *in; /* remote video descriptor */
+ struct video_out_desc out; /* local video descriptor */
};
static AVPicture *fill_pict(struct fbuf_t *b, AVPicture *p);
@@ -387,8 +387,9 @@ static struct fbuf_t *grabber_read(struct video_device *dev, int fps)
*/
static void grabber_move(struct video_device *dev, int dx, int dy)
{
- if (dev->grabber && dev->grabber->move)
- dev->grabber->move(dev->grabber_data, dx, dy);
+ if (dev->grabber && dev->grabber->move) {
+ dev->grabber->move(dev->grabber_data, dx, dy);
+ }
}
/*
@@ -508,33 +509,32 @@ static int video_out_init(struct video_desc *env)
/* now setup the parameters for the encoder.
* XXX should be codec-specific
*/
- {
- AVCodecContext *enc_ctx = avcodec_alloc_context();
- v->enc_ctx = enc_ctx;
- enc_ctx->pix_fmt = enc_in->pix_fmt;
- enc_ctx->width = enc_in->w;
- enc_ctx->height = enc_in->h;
- /* XXX rtp_callback ?
- * rtp_mode so ffmpeg inserts as many start codes as possible.
- */
- enc_ctx->rtp_mode = 1;
- enc_ctx->rtp_payload_size = v->mtu / 2; // mtu/2
- enc_ctx->bit_rate = v->bitrate;
- enc_ctx->bit_rate_tolerance = enc_ctx->bit_rate/2;
- enc_ctx->qmin = v->qmin; /* should be configured */
- enc_ctx->time_base = (AVRational){1, v->fps};
- enc_ctx->gop_size = v->fps*5; // emit I frame every 5 seconds
-
- v->enc->enc_init(v->enc_ctx);
-
- if (avcodec_open(enc_ctx, v->codec) < 0) {
- ast_log(LOG_WARNING, "Unable to initialize the encoder %d\n",
- codec);
- av_free(enc_ctx);
- v->enc_ctx = NULL;
- return video_out_uninit(env);
+ {
+ AVCodecContext *enc_ctx = avcodec_alloc_context();
+ v->enc_ctx = enc_ctx;
+ enc_ctx->pix_fmt = enc_in->pix_fmt;
+ enc_ctx->width = enc_in->w;
+ enc_ctx->height = enc_in->h;
+ /* XXX rtp_callback ?
+ * rtp_mode so ffmpeg inserts as many start codes as possible.
+ */
+ enc_ctx->rtp_mode = 1;
+ enc_ctx->rtp_payload_size = v->mtu / 2; // mtu/2
+ enc_ctx->bit_rate = v->bitrate;
+ enc_ctx->bit_rate_tolerance = enc_ctx->bit_rate/2;
+ enc_ctx->qmin = v->qmin; /* should be configured */
+ enc_ctx->time_base = (AVRational){1, v->fps};
+ enc_ctx->gop_size = v->fps*5; // emit I frame every 5 seconds
+
+ v->enc->enc_init(v->enc_ctx);
+
+ if (avcodec_open(enc_ctx, v->codec) < 0) {
+ ast_log(LOG_WARNING, "Unable to initialize the encoder %d\n", codec);
+ av_free(enc_ctx);
+ v->enc_ctx = NULL;
+ return video_out_uninit(env);
+ }
}
- }
/*
* Allocate enough for the encoded bitstream. As we are compressing,
* we hope that the output is never larger than the input size.
@@ -637,9 +637,9 @@ static void my_scale(struct fbuf_t *in, AVPicture *p_in,
p_in = fill_pict(in, &my_p_in);
if (p_out == NULL)
p_out = fill_pict(out, &my_p_out);
-
- /*if win_w is different from zero then we must change
- the size of the scaled buffer (the position is already
+
+ /*if win_w is different from zero then we must change
+ the size of the scaled buffer (the position is already
encoded into the out parameter)*/
if (out->win_w) { /* picture in picture enabled */
eff_w=out->win_w;
@@ -650,26 +650,26 @@ static void my_scale(struct fbuf_t *in, AVPicture *p_in,
img_convert(p_out, out->pix_fmt,
p_in, in->pix_fmt, in->w, in->h);
#else /* XXX replacement */
- {
- struct SwsContext *convert_ctx;
-
- convert_ctx = sws_getContext(in->w, in->h, in->pix_fmt,
- eff_w, eff_h, out->pix_fmt,
- SWS_BICUBIC, NULL, NULL, NULL);
- if (convert_ctx == NULL) {
- ast_log(LOG_ERROR, "FFMPEG::convert_cmodel : swscale context initialization failed");
- return;
+ {
+ struct SwsContext *convert_ctx;
+
+ convert_ctx = sws_getContext(in->w, in->h, in->pix_fmt,
+ eff_w, eff_h, out->pix_fmt,
+ SWS_BICUBIC, NULL, NULL, NULL);
+ if (convert_ctx == NULL) {
+ ast_log(LOG_ERROR, "FFMPEG::convert_cmodel : swscale context initialization failed");
+ return;
+ }
+ if (0)
+ ast_log(LOG_WARNING, "in %d %dx%d out %d %dx%d\n",
+ in->pix_fmt, in->w, in->h, out->pix_fmt, eff_w, eff_h);
+ sws_scale(convert_ctx,
+ p_in->data, p_in->linesize,
+ in->w, in->h, /* src slice */
+ p_out->data, p_out->linesize);
+
+ sws_freeContext(convert_ctx);
}
- if (0)
- ast_log(LOG_WARNING, "in %d %dx%d out %d %dx%d\n",
- in->pix_fmt, in->w, in->h, out->pix_fmt, eff_w, eff_h);
- sws_scale(convert_ctx,
- p_in->data, p_in->linesize,
- in->w, in->h, /* src slice */
- p_out->data, p_out->linesize);
-
- sws_freeContext(convert_ctx);
- }
#endif /* XXX replacement */
}
@@ -873,18 +873,20 @@ static void *video_thread(void *arg)
}
}
sdl_setup(env);
- if (!ast_strlen_zero(save_display))
+ if (!ast_strlen_zero(save_display)) {
setenv("DISPLAY", save_display, 1);
+ }
ast_mutex_init(&env->dec_lock); /* used to sync decoder and renderer */
if (grabber_open(&env->out)) {
ast_log(LOG_WARNING, "cannot open local video source\n");
- }
+ }
- if (env->out.device_num)
+ if (env->out.device_num) {
env->out.devices[env->out.device_primary].status_index |= IS_PRIMARY | IS_SECONDARY;
-
+ }
+
/* even if no device is connected, we must call video_out_init,
* as some of the data structures it initializes are
* used in get_video_frames()
@@ -893,14 +895,14 @@ static void *video_thread(void *arg)
/* Writes intial status of the sources. */
if (env->gui) {
- for (i = 0; i < env->out.device_num; i++) {
- print_message(env->gui->thumb_bd_array[i].board,
- src_msgs[env->out.devices[i].status_index]);
- }
+ for (i = 0; i < env->out.device_num; i++) {
+ print_message(env->gui->thumb_bd_array[i].board,
+ src_msgs[env->out.devices[i].status_index]);
+ }
}
for (;;) {
- struct timeval t = { 0, 50000 }; /* XXX 20 times/sec */
+ struct timespec t = { 0, 50000000 }; /* XXX 20 times/sec */
struct ast_frame *p, *f;
struct ast_channel *chan;
int fd;
@@ -908,13 +910,14 @@ static void *video_thread(void *arg)
/* determine if video format changed */
if (count++ % 10 == 0) {
- if (env->out.sendvideo && env->out.devices)
- sprintf(buf, "%s %s %dx%d @@ %dfps %dkbps",
+ if (env->out.sendvideo && env->out.devices) {
+ snprintf(buf, sizeof(buf), "%s %s %dx%d @@ %dfps %dkbps",
env->out.devices[env->out.device_primary].name, env->codec_name,
env->enc_in.w, env->enc_in.h,
- env->out.fps, env->out.bitrate/1000);
- else
- sprintf(buf, "hold");
+ env->out.fps, env->out.bitrate / 1000);
+ } else {
+ sprintf(buf, "hold");
+ }
caption = buf;
}
@@ -923,36 +926,36 @@ static void *video_thread(void *arg)
* otherwise the drag will not work */
if (env->gui)
eventhandler(env, caption);
-
+
/* sleep for a while */
- ast_select(0, NULL, NULL, NULL, &t);
+ nanosleep(&t, NULL);
if (env->in) {
- struct video_dec_desc *v = env->in;
-
- /*
- * While there is something to display, call the decoder and free
- * the buffer, possibly enabling the receiver to store new data.
- */
- while (v->dec_in_dpy) {
- struct fbuf_t *tmp = v->dec_in_dpy; /* store current pointer */
-
- /* decode the frame, but show it only if not frozen */
- if (v->d_callbacks->dec_run(v, tmp) && !env->frame_freeze)
- show_frame(env, WIN_REMOTE);
- tmp->used = 0; /* mark buffer as free */
- tmp->ebit = 0;
- ast_mutex_lock(&env->dec_lock);
- if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN]) /* advance to next, circular */
- v->dec_in_dpy = &v->dec_in[0];
-
- if (v->dec_in_cur == NULL) /* receiver was idle, enable it... */
- v->dec_in_cur = tmp; /* using the slot just freed */
- else if (v->dec_in_dpy == v->dec_in_cur) /* this was the last slot */
- v->dec_in_dpy = NULL; /* nothing more to display */
- ast_mutex_unlock(&env->dec_lock);
+ struct video_dec_desc *v = env->in;
+
+ /*
+ * While there is something to display, call the decoder and free
+ * the buffer, possibly enabling the receiver to store new data.
+ */
+ while (v->dec_in_dpy) {
+ struct fbuf_t *tmp = v->dec_in_dpy; /* store current pointer */
+
+ /* decode the frame, but show it only if not frozen */
+ if (v->d_callbacks->dec_run(v, tmp) && !env->frame_freeze)
+ show_frame(env, WIN_REMOTE);
+ tmp->used = 0; /* mark buffer as free */
+ tmp->ebit = 0;
+ ast_mutex_lock(&env->dec_lock);
+ if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN]) /* advance to next, circular */
+ v->dec_in_dpy = &v->dec_in[0];
+
+ if (v->dec_in_cur == NULL) /* receiver was idle, enable it... */
+ v->dec_in_cur = tmp; /* using the slot just freed */
+ else if (v->dec_in_dpy == v->dec_in_cur) /* this was the last slot */
+ v->dec_in_dpy = NULL; /* nothing more to display */
+ ast_mutex_unlock(&env->dec_lock);
+ }
}
- }
if (env->shutdown)
break;
@@ -988,7 +991,7 @@ static void *video_thread(void *arg)
for (p = f; p; p = AST_LIST_NEXT(p, frame_list)) {
if (write(fd, &blah, l) != l)
ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d: %s!\n",
- chan->name, f->frametype, f->subclass, strerror(errno));
+ chan->name, f->frametype, f->subclass, strerror(errno));
}
}
ast_channel_unlock(chan);
@@ -1194,13 +1197,13 @@ int console_video_cli(struct video_desc *env, const char *var, int fd)
if (env == NULL)
return 1; /* unrecognised */
- if (!strcasecmp(var, "videodevice")) {
+ if (!strcasecmp(var, "videodevice")) {
ast_cli(fd, "videodevice is [%s]\n", env->out.devices[env->out.device_primary].name);
- } else if (!strcasecmp(var, "videocodec")) {
+ } else if (!strcasecmp(var, "videocodec")) {
ast_cli(fd, "videocodec is [%s]\n", env->codec_name);
- } else if (!strcasecmp(var, "sendvideo")) {
+ } else if (!strcasecmp(var, "sendvideo")) {
ast_cli(fd, "sendvideo is [%s]\n", env->out.sendvideo ? "on" : "off");
- } else if (!strcasecmp(var, "video_size")) {
+ } else if (!strcasecmp(var, "video_size")) {
int in_w = 0, in_h = 0;
if (env->in) {
in_w = env->in->dec_out.w;
@@ -1212,22 +1215,22 @@ int console_video_cli(struct video_desc *env, const char *var, int fd)
env->loc_dpy.w, env->loc_dpy.h,
env->rem_dpy.w, env->rem_dpy.h,
in_w, in_h);
- } else if (!strcasecmp(var, "bitrate")) {
+ } else if (!strcasecmp(var, "bitrate")) {
ast_cli(fd, "bitrate is [%d]\n", env->out.bitrate);
- } else if (!strcasecmp(var, "qmin")) {
+ } else if (!strcasecmp(var, "qmin")) {
ast_cli(fd, "qmin is [%d]\n", env->out.qmin);
- } else if (!strcasecmp(var, "fps")) {
+ } else if (!strcasecmp(var, "fps")) {
ast_cli(fd, "fps is [%d]\n", env->out.fps);
- } else if (!strcasecmp(var, "startgui")) {
+ } else if (!strcasecmp(var, "startgui")) {
env->stayopen = 1;
console_video_start(env, NULL);
- } else if (!strcasecmp(var, "stopgui") && env->stayopen != 0) {
+ } else if (!strcasecmp(var, "stopgui") && env->stayopen != 0) {
env->stayopen = 0;
if (env->gui && env->owner)
ast_cli_command(-1, "console hangup");
else /* not in a call */
console_video_uninit(env);
- } else {
+ } else {
return 1; /* unrecognised */
}
return 0; /* recognised */
diff --git a/channels/sig_analog.c b/channels/sig_analog.c
index 762169f87..90e8628e8 100644
--- a/channels/sig_analog.c
+++ b/channels/sig_analog.c
@@ -2471,7 +2471,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", analog_event2str(res), res, p->channel, index);
if (res & (ANALOG_EVENT_PULSEDIGIT | ANALOG_EVENT_DTMFUP)) {
- analog_set_pulsedial(p, (res & ANALOG_EVENT_PULSEDIGIT));
+ analog_set_pulsedial(p, (res & ANALOG_EVENT_PULSEDIGIT) ? 1 : 0);
ast_debug(1, "Detected %sdigit '%c'\n", (res & ANALOG_EVENT_PULSEDIGIT) ? "pulse ": "", res & 0xff);
analog_confmute(p, 0);
p->subs[index].f.frametype = AST_FRAME_DTMF_END;
@@ -3581,11 +3581,9 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
}
break;
case ANALOG_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
- ast_log(LOG_NOTICE,
- "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
- i->channel);
- return i->chan_pvt;
- break;
+ ast_log(LOG_NOTICE, "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
+ i->channel);
+ return i->chan_pvt;
case ANALOG_EVENT_NEONMWI_ACTIVE:
analog_handle_notify_message(NULL, i, -1, ANALOG_EVENT_NEONMWI_ACTIVE);
break;
diff --git a/channels/sig_analog.h b/channels/sig_analog.h
index ff62ed52d..d88e622e7 100644
--- a/channels/sig_analog.h
+++ b/channels/sig_analog.h
@@ -271,6 +271,7 @@ struct analog_pvt {
unsigned int transfer:1;
unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */
unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */
+ unsigned int callwaitingcallerid:1;
const struct ast_channel_tech *chan_tech;
/*!
* \brief TRUE if distinctive rings are to be detected.
@@ -287,7 +288,6 @@ struct analog_pvt {
int polarityonanswerdelay;
int stripmsd;
enum analog_cid_start cid_start;
- int callwaitingcallerid;
char mohsuggest[MAX_MUSICCLASS];
char cid_num[AST_MAX_EXTENSION];
char cid_name[AST_MAX_EXTENSION];
diff --git a/channels/sig_pri.c b/channels/sig_pri.c
index 6878d81e8..c75badd66 100644
--- a/channels/sig_pri.c
+++ b/channels/sig_pri.c
@@ -4176,36 +4176,36 @@ static void *pri_dchannel(void *vpri)
}
}
/* Start with reasonable max */
- lowest = ast_tv(60, 0);
+ if (doidling || pri->resetting) {
+ /*
+ * Make sure we stop at least once per second if we're
+ * monitoring idle channels
+ */
+ lowest = ast_tv(1, 0);
+ } else {
+ /* Don't poll for more than 60 seconds */
+ lowest = ast_tv(60, 0);
+ }
for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
- /* Find lowest available d-channel */
- if (!pri->dchans[i])
+ if (!pri->dchans[i]) {
+ /* We scanned all D channels on this span. */
break;
- if ((next = pri_schedule_next(pri->dchans[i]))) {
+ }
+ next = pri_schedule_next(pri->dchans[i]);
+ if (next) {
/* We need relative time here */
tv = ast_tvsub(*next, ast_tvnow());
if (tv.tv_sec < 0) {
- tv = ast_tv(0,0);
+ /*
+ * A timer has already expired.
+ * By definition zero time is the lowest so we can quit early.
+ */
+ lowest = ast_tv(0, 0);
+ break;
}
- if (doidling || pri->resetting) {
- if (tv.tv_sec > 1) {
- tv = ast_tv(1, 0);
- }
- } else {
- if (tv.tv_sec > 60) {
- tv = ast_tv(60, 0);
- }
+ if (ast_tvcmp(tv, lowest) < 0) {
+ lowest = tv;
}
- } else if (doidling || pri->resetting) {
- /* Make sure we stop at least once per second if we're
- monitoring idle channels */
- tv = ast_tv(1,0);
- } else {
- /* Don't poll for more than 60 seconds */
- tv = ast_tv(60, 0);
- }
- if (!i || ast_tvcmp(tv, lowest) < 0) {
- lowest = tv;
}
}
ast_mutex_unlock(&pri->lock);
@@ -4243,8 +4243,10 @@ static void *pri_dchannel(void *vpri)
ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
if (e) {
- if (pri->debug)
- pri_dump_event(pri->dchans[which], e);
+ if (pri->debug) {
+ ast_verbose("Span: %d Processing event: %s\n",
+ pri->span, pri_event2str(e->e));
+ }
if (e->e != PRI_EVENT_DCHAN_DOWN) {
if (!(pri->dchanavail[which] & DCHAN_UP)) {
@@ -5917,7 +5919,20 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
l = NULL;
n = NULL;
if (!p->hidecallerid) {
- l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
+ if (ast->connected.id.number.valid) {
+ /* If we get to the end of this loop without breaking, there's no
+ * calleridnum. This is done instead of testing for "unknown" or
+ * the thousands of other ways that the calleridnum could be
+ * invalid. */
+ for (l = ast->connected.id.number.str; l && *l; l++) {
+ if (strchr("0123456789", *l)) {
+ l = ast->connected.id.number.str;
+ break;
+ }
+ }
+ } else {
+ l = NULL;
+ }
if (!p->hidecalleridname) {
n = ast->connected.id.name.valid ? ast->connected.id.name.str : NULL;
}
@@ -6316,7 +6331,7 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi
case AST_CONTROL_PROGRESS:
ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
sig_pri_set_digital(p, 0); /* Digital-only calls isn't allowing any inband progress messages */
- if (!p->progress && p->pri && !p->outgoing && !p->no_b_channel) {
+ if (!p->progress && !p->alerting && p->pri && !p->outgoing && !p->no_b_channel) {
if (p->pri->pri) {
if (!pri_grab(p, p->pri)) {
#ifdef HAVE_PRI_PROG_W_CAUSE
diff --git a/channels/sig_pri.h b/channels/sig_pri.h
index f57d8f700..98b05b9ca 100644
--- a/channels/sig_pri.h
+++ b/channels/sig_pri.h
@@ -295,8 +295,8 @@ struct sig_pri_span {
int fds[SIG_PRI_NUM_DCHANS]; /*!< FD's for d-channels */
#if defined(HAVE_PRI_AOC_EVENTS)
- int aoc_passthrough_flag; /*!< Represents what AOC messages (S,D,E) are allowed to pass-through */
- int aoce_delayhangup:1; /*!< defines whether the aoce_delayhangup option is enabled or not */
+ int aoc_passthrough_flag; /*!< Represents what AOC messages (S,D,E) are allowed to pass-through */
+ unsigned int aoce_delayhangup:1; /*!< defines whether the aoce_delayhangup option is enabled or not */
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
#if defined(HAVE_PRI_SERVICE_MESSAGES)
@@ -389,7 +389,7 @@ struct sig_pri_span {
int num_call_waiting_calls;
#endif /* defined(HAVE_PRI_CALL_WAITING) */
int dchanavail[SIG_PRI_NUM_DCHANS]; /*!< Whether each channel is available */
- int debug; /*!< set to true if to dump PRI event info (tested but never set) */
+ int debug; /*!< set to true if to dump PRI event info */
int span; /*!< span number put into user output messages */
int resetting; /*!< true if span is being reset/restarted */
int resetpos; /*!< current position during a reset (-1 if not started) */
diff --git a/channels/sip/config_parser.c b/channels/sip/config_parser.c
index 659e8cecc..0ab9ed769 100644
--- a/channels/sip/config_parser.c
+++ b/channels/sip/config_parser.c
@@ -661,16 +661,18 @@ int sip_parse_host(char *line, int lineno, char **hostname, int *portnum, enum s
else
line = *hostname;
- if ((port = strrchr(line, ':'))) {
- *port++ = '\0';
+ if (ast_sockaddr_split_hostport(line, hostname, &port, 0) == 0) {
+ ast_log(LOG_WARNING, "Cannot parse host '%s' on line %d of sip.conf.\n",
+ line, lineno);
+ return -1;
+ }
+ if (port) {
if (!sscanf(port, "%5u", portnum)) {
ast_log(LOG_NOTICE, "'%s' is not a valid port number on line %d of sip.conf. using default.\n", port, lineno);
port = NULL;
}
- }
-
- if (!port) {
+ } else {
if (*transport & SIP_TRANSPORT_TLS) {
*portnum = STANDARD_TLS_PORT;
} else {
diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h
index 0e207ca23..2bd1bc75f 100644
--- a/channels/sip/include/sip.h
+++ b/channels/sip/include/sip.h
@@ -154,14 +154,6 @@
*/
#define ALLOWED_METHODS "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH"
-/*! \brief SIP Extensions we support
- * \note This should be generated based on the previous array
- * in combination with settings.
- *
- * \todo We should not have "timer" if it's disabled in the configuration file.
- */
-#define SUPPORTED_EXTENSIONS "replaces, timer"
-
/*! \brief Standard SIP unsecure port for UDP and TCP from RFC 3261. DO NOT CHANGE THIS */
#define STANDARD_SIP_PORT 5060
/*! \brief Standard SIP TLS port from RFC 3261. DO NOT CHANGE THIS */
@@ -209,12 +201,13 @@
#define DEFAULT_DOMAINSASREALM FALSE /*!< Use the domain option to guess the realm for registration and invite requests */
#define DEFAULT_NOTIFYRINGING TRUE /*!< Notify devicestate system on ringing state */
#define DEFAULT_NOTIFYCID DISABLED /*!< Include CID with ringing notifications */
-#define DEFAULT_PEDANTIC FALSE /*!< Avoid following SIP standards for dialog matching */
+#define DEFAULT_PEDANTIC TRUE /*!< Follow SIP standards for dialog matching */
#define DEFAULT_AUTOCREATEPEER FALSE /*!< Don't create peers automagically */
#define DEFAULT_MATCHEXTERNADDRLOCALLY FALSE /*!< Match extern IP locally default setting */
#define DEFAULT_QUALIFY FALSE /*!< Don't monitor devices */
#define DEFAULT_CALLEVENTS FALSE /*!< Extra manager SIP call events */
-#define DEFAULT_ALWAYSAUTHREJECT FALSE /*!< Don't reject authentication requests always */
+#define DEFAULT_ALWAYSAUTHREJECT TRUE /*!< Don't reject authentication requests always */
+#define DEFAULT_AUTH_OPTIONS FALSE
#define DEFAULT_REGEXTENONQUALIFY FALSE
#define DEFAULT_T1MIN 100 /*!< 100 MS for minimal roundtrip time */
#define DEFAULT_MAX_CALL_BITRATE (384) /*!< Max bitrate for video */
@@ -682,6 +675,7 @@ struct sip_settings {
int srvlookup; /*!< SRV Lookup on or off. Default is on */
int allowguest; /*!< allow unauthenticated peers to connect? */
int alwaysauthreject; /*!< Send 401 Unauthorized for all failing requests */
+ int auth_options_requests; /*!< Authenticate OPTIONS requests */
int compactheaders; /*!< send compact sip headers */
int allow_external_domains; /*!< Accept calls to external SIP domains? */
int callevents; /*!< Whether we send manager events or not */