aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_agent.c1
-rw-r--r--channels/chan_alsa.c1
-rw-r--r--channels/chan_bridge.c4
-rw-r--r--channels/chan_console.c1
-rw-r--r--channels/chan_dahdi.c22
-rw-r--r--channels/chan_gtalk.c10
-rw-r--r--channels/chan_h323.c4
-rw-r--r--channels/chan_iax2.c1
-rw-r--r--channels/chan_jingle.c2
-rw-r--r--channels/chan_local.c4
-rw-r--r--channels/chan_mgcp.c1
-rw-r--r--channels/chan_misdn.c1
-rw-r--r--channels/chan_multicast_rtp.c4
-rw-r--r--channels/chan_nbs.c1
-rw-r--r--channels/chan_oss.c1
-rw-r--r--channels/chan_phone.c1
-rw-r--r--channels/chan_sip.c104
-rw-r--r--channels/chan_skinny.c755
-rw-r--r--channels/chan_unistim.c4
-rw-r--r--channels/chan_usbradio.c1
-rw-r--r--channels/chan_vpb.cc2
-rw-r--r--channels/sig_pri.c46
22 files changed, 764 insertions, 207 deletions
diff --git a/channels/chan_agent.c b/channels/chan_agent.c
index 0dc930f9d..044524669 100644
--- a/channels/chan_agent.c
+++ b/channels/chan_agent.c
@@ -33,6 +33,7 @@
/*** MODULEINFO
<depend>chan_local</depend>
<depend>res_monitor</depend>
+ <support_level>core</support_level>
***/
#include "asterisk.h"
diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c
index b1e7c30e5..b51c942af 100644
--- a/channels/chan_alsa.c
+++ b/channels/chan_alsa.c
@@ -29,6 +29,7 @@
/*** MODULEINFO
<depend>alsa</depend>
+ <support_level>extended</support_level>
***/
#include "asterisk.h"
diff --git a/channels/chan_bridge.c b/channels/chan_bridge.c
index 7b01909ae..36f23a500 100644
--- a/channels/chan_bridge.c
+++ b/channels/chan_bridge.c
@@ -25,6 +25,10 @@
* \ingroup channel_drivers
*/
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
diff --git a/channels/chan_console.c b/channels/chan_console.c
index a5f22be2d..a0eddbeae 100644
--- a/channels/chan_console.c
+++ b/channels/chan_console.c
@@ -49,6 +49,7 @@
/*** MODULEINFO
<depend>portaudio</depend>
+ <support_level>extended</support_level>
***/
#include "asterisk.h"
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 321be6625..b80b1b1e8 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -44,6 +44,7 @@
<use type="external">pri</use>
<use type="external">ss7</use>
<use type="external">openr2</use>
+ <support_level>core</support_level>
***/
#include "asterisk.h"
@@ -409,8 +410,6 @@ static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
static char defaultcic[64] = "";
static char defaultozz[64] = "";
-static char parkinglot[AST_MAX_EXTENSION] = ""; /*!< Default parking lot for this channel */
-
/*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
static char mwimonitornotify[PATH_MAX] = "";
#ifndef HAVE_DAHDI_LINEREVERSE_VMWI
@@ -3072,9 +3071,9 @@ static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
#if defined(HAVE_PRI)
static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
{
- int x, res;
+ int x;
- res = ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
+ ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
if (x) {
ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span);
}
@@ -11075,7 +11074,7 @@ quit_no_clean:
*/
static int mwi_send_init(struct dahdi_pvt * pvt)
{
- int x, res;
+ int x;
struct ast_format tmpfmt;
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
@@ -11112,7 +11111,7 @@ static int mwi_send_init(struct dahdi_pvt * pvt)
return -1;
}
x = DAHDI_FLUSH_BOTH;
- res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
+ ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
x = 3000;
ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
#ifdef HAVE_DAHDI_LINEREVERSE_VMWI
@@ -16799,7 +16798,7 @@ static void process_echocancel(struct dahdi_chan_conf *confp, const char *data,
/*!
* \internal
* \brief Determine the configured display text options.
- * \since 1.10
+ * \since 10.0
*
* \param value Configuration value string.
*
@@ -16846,7 +16845,7 @@ static unsigned long dahdi_display_text_option(const char *value)
/*!
* \internal
* \brief Determine the configured date/time send policy option.
- * \since 1.10
+ * \since 10.0
*
* \param value Configuration value string.
*
@@ -16926,11 +16925,6 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
continue;
- /* must have parkinglot in confp before build_channels is called */
- if (!strcasecmp(v->name, "parkinglot")) {
- ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
- }
-
/* Create the interface list */
if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
if (options & PROC_DAHDI_OPT_NOCHAN) {
@@ -17094,7 +17088,7 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
} else if (!strcasecmp(v->name, "mohsuggest")) {
ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
} else if (!strcasecmp(v->name, "parkinglot")) {
- ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
+ ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
} else if (!strcasecmp(v->name, "stripmsd")) {
ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
confp->chan.stripmsd = atoi(v->value);
diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c
index 3b08d8ce4..a15fca975 100644
--- a/channels/chan_gtalk.c
+++ b/channels/chan_gtalk.c
@@ -35,6 +35,7 @@
<depend>iksemel</depend>
<depend>res_jabber</depend>
<use type="external">openssl</use>
+ <support_level>extended</support_level>
***/
#include "asterisk.h"
@@ -1336,7 +1337,7 @@ static int gtalk_newcall(struct gtalk *client, ikspak *pak)
ast_copy_string(p->sid, sid, sizeof(p->sid));
/* codec points to the first <payload-type/> tag */
- codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x)));
+ codec = iks_first_tag(iks_first_tag(pak->query));
while (codec) {
char *codec_id = iks_find_attrib(codec, "id");
@@ -2049,6 +2050,12 @@ static int gtalk_parser(void *data, ikspak *pak)
{
struct gtalk *client = ASTOBJ_REF((struct gtalk *) data);
int res;
+ iks *tmp;
+
+ if (!strcasecmp(iks_name(pak->query), "jin:jingle") && (tmp = iks_next(pak->query)) && !strcasecmp(iks_name(tmp), "ses:session")) {
+ ast_debug(1, "New method detected. Skipping jingle offer and using old gtalk method.\n");
+ pak->query = tmp;
+ }
if (!strcmp(S_OR(iks_find_attrib(pak->x, "type"), ""), "error")) {
ast_log(LOG_NOTICE, "Remote peer reported an error, trying to establish the call anyway\n");
@@ -2233,6 +2240,7 @@ static int gtalk_load_config(void)
ASTOBJ_WRLOCK(member);
member->connection = NULL;
iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, GOOGLE_NS, IKS_RULE_DONE);
+ iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, GOOGLE_JINGLE_NS, IKS_RULE_DONE);
iks_filter_add_rule(iterator->f, gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS, "http://jabber.org/protocol/gtalk", IKS_RULE_DONE);
ASTOBJ_UNLOCK(member);
ASTOBJ_UNLOCK(iterator);
diff --git a/channels/chan_h323.c b/channels/chan_h323.c
index 07646652f..e90bee18c 100644
--- a/channels/chan_h323.c
+++ b/channels/chan_h323.c
@@ -36,7 +36,9 @@
/*** MODULEINFO
<depend>openh323</depend>
- <defaultenabled>yes</defaultenabled>
+ <defaultenabled>no</defaultenabled>
+ <support_level>deprecated</support_level>
+ <replacement>chan_ooh323</replacement>
***/
#ifdef __cplusplus
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 9f5f32deb..dff1bfda2 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -33,6 +33,7 @@
/*** MODULEINFO
<use type="external">crypto</use>
+ <support_level>core</support_level>
***/
#include "asterisk.h"
diff --git a/channels/chan_jingle.c b/channels/chan_jingle.c
index 53b1a85e4..86a6410db 100644
--- a/channels/chan_jingle.c
+++ b/channels/chan_jingle.c
@@ -31,6 +31,8 @@
<depend>iksemel</depend>
<depend>res_jabber</depend>
<use type="external">openssl</use>
+ <defaultenabled>no</defaultenabled>
+ <support_level>extended</support_level>
***/
#include "asterisk.h"
diff --git a/channels/chan_local.c b/channels/chan_local.c
index 3c16fc51a..937ede4c2 100644
--- a/channels/chan_local.c
+++ b/channels/chan_local.c
@@ -25,6 +25,10 @@
* \ingroup channel_drivers
*/
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index bd92fe9b0..dfd5a310f 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -31,6 +31,7 @@
/*** MODULEINFO
<use type="module">res_pktccops</use>
+ <support_level>extended</support_level>
***/
#include "asterisk.h"
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c
index d6e10aebe..e9fa80010 100644
--- a/channels/chan_misdn.c
+++ b/channels/chan_misdn.c
@@ -53,6 +53,7 @@
<depend>isdnnet</depend>
<depend>misdn</depend>
<depend>suppserv</depend>
+ <support_level>extended</support_level>
***/
#include "asterisk.h"
diff --git a/channels/chan_multicast_rtp.c b/channels/chan_multicast_rtp.c
index b398abb21..929525ffb 100644
--- a/channels/chan_multicast_rtp.c
+++ b/channels/chan_multicast_rtp.c
@@ -27,6 +27,10 @@
* \ingroup channel_drivers
*/
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
diff --git a/channels/chan_nbs.c b/channels/chan_nbs.c
index fdfbd8eb3..3ff97dde7 100644
--- a/channels/chan_nbs.c
+++ b/channels/chan_nbs.c
@@ -27,6 +27,7 @@
/*** MODULEINFO
<depend>nbs</depend>
+ <support_level>extended</support_level>
***/
#include "asterisk.h"
diff --git a/channels/chan_oss.c b/channels/chan_oss.c
index 67c55c592..a8ca79a3e 100644
--- a/channels/chan_oss.c
+++ b/channels/chan_oss.c
@@ -35,6 +35,7 @@
/*** MODULEINFO
<depend>oss</depend>
+ <support_level>extended</support_level>
***/
#include "asterisk.h"
diff --git a/channels/chan_phone.c b/channels/chan_phone.c
index 4b7ec9721..6acb7a184 100644
--- a/channels/chan_phone.c
+++ b/channels/chan_phone.c
@@ -27,6 +27,7 @@
/*** MODULEINFO
<depend>ixjuser</depend>
+ <support_level>extended</support_level>
***/
#include "asterisk.h"
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 18eba2371..a0b9cb037 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -164,6 +164,7 @@
/*** MODULEINFO
<use type="module">res_crypto</use>
<depend>chan_local</depend>
+ <support_level>core</support_level>
***/
/*! \page sip_session_timers SIP Session Timers in Asterisk Chan_sip
@@ -1350,7 +1351,7 @@ static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target
static int do_magic_pickup(struct ast_channel *channel, const char *extension, const char *context);
/*--- Device monitoring and Device/extension state/event handling */
-static int cb_extensionstate(char *context, char* exten, int state, void *data);
+static int cb_extensionstate(const char *context, const char *exten, enum ast_extension_states state, void *data);
static int sip_devicestate(void *data);
static int sip_poke_noanswer(const void *data);
static int sip_poke_peer(struct sip_peer *peer, int force);
@@ -4227,10 +4228,11 @@ static void enable_dsp_detect(struct sip_pvt *p)
}
if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) ||
- (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
- if (!p->rtp || ast_rtp_instance_dtmf_mode_set(p->rtp, AST_RTP_DTMF_MODE_INBAND)) {
- features |= DSP_FEATURE_DIGIT_DETECT;
- }
+ (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
+ if (p->rtp) {
+ ast_rtp_instance_dtmf_mode_set(p->rtp, AST_RTP_DTMF_MODE_INBAND);
+ }
+ features |= DSP_FEATURE_DIGIT_DETECT;
}
if (ast_test_flag(&p->flags[1], SIP_PAGE2_FAX_DETECT_CNG)) {
@@ -4265,6 +4267,11 @@ static int sip_setoption(struct ast_channel *chan, int option, void *data, int d
int res = -1;
struct sip_pvt *p = chan->tech_pvt;
+ if (!p) {
+ ast_log(LOG_ERROR, "Attempt to Ref a null pointer. sip private structure is gone!\n");
+ return -1;
+ }
+
sip_pvt_lock(p);
switch (option) {
@@ -6529,11 +6536,7 @@ static int sip_senddigit_begin(struct ast_channel *ast, char digit)
sip_pvt_lock(p);
switch (ast_test_flag(&p->flags[0], SIP_DTMF)) {
case SIP_DTMF_INBAND:
- if (p->rtp && ast_rtp_instance_dtmf_mode_get(p->rtp) == AST_RTP_DTMF_MODE_INBAND) {
- ast_rtp_instance_dtmf_begin(p->rtp, digit);
- } else {
- res = -1; /* Tell Asterisk to generate inband indications */
- }
+ res = -1; /* Tell Asterisk to generate inband indications */
break;
case SIP_DTMF_RFC2833:
if (p->rtp)
@@ -6565,11 +6568,7 @@ static int sip_senddigit_end(struct ast_channel *ast, char digit, unsigned int d
ast_rtp_instance_dtmf_end_with_duration(p->rtp, digit, duration);
break;
case SIP_DTMF_INBAND:
- if (p->rtp && ast_rtp_instance_dtmf_mode_get(p->rtp) == AST_RTP_DTMF_MODE_INBAND) {
- ast_rtp_instance_dtmf_end(p->rtp, digit);
- } else {
- res = -1; /* Tell Asterisk to stop inband indications */
- }
+ res = -1; /* Tell Asterisk to stop inband indications */
break;
}
sip_pvt_unlock(p);
@@ -6926,8 +6925,8 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
if ((ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) ||
(ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
- if (!i->rtp || ast_rtp_instance_dtmf_mode_set(i->rtp, AST_RTP_DTMF_MODE_INBAND)) {
- enable_dsp_detect(i);
+ if (i->rtp) {
+ ast_rtp_instance_dtmf_mode_set(i->rtp, AST_RTP_DTMF_MODE_INBAND);
}
} else if (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) {
if (i->rtp) {
@@ -9468,6 +9467,7 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
if ((format = ast_rtp_codecs_get_payload_format(newaudiortp, codec))) {
unsigned int bit_rate;
+ int val = 0;
switch ((int) format->id) {
case AST_FORMAT_SIREN7:
@@ -9500,20 +9500,21 @@ static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_
}
}
break;
+ case AST_FORMAT_CELT:
+ if (sscanf(fmtp_string, "framesize=%30u", &val) == 1) {
+ ast_format_append(format, CELT_ATTR_KEY_FRAME_SIZE, val, AST_FORMAT_ATTR_END);
+ }
case AST_FORMAT_SILK:
- {
- int val = 0;
- if (sscanf(fmtp_string, "maxaveragebitrate=%30u", &val) == 1) {
- ast_format_append(format, SILK_ATTR_KEY_MAX_BITRATE, val, AST_FORMAT_ATTR_END);
- }
- if (sscanf(fmtp_string, "usedtx=%30u", &val) == 1) {
- ast_format_append(format, SILK_ATTR_KEY_DTX, val ? 1 : 0, AST_FORMAT_ATTR_END);
- }
- if (sscanf(fmtp_string, "useinbandfec=%30u", &val) == 1) {
- ast_format_append(format, SILK_ATTR_KEY_FEC, val ? 1 : 0, AST_FORMAT_ATTR_END);
- }
- break;
+ if (sscanf(fmtp_string, "maxaveragebitrate=%30u", &val) == 1) {
+ ast_format_append(format, SILK_ATTR_KEY_MAX_BITRATE, val, AST_FORMAT_ATTR_END);
+ }
+ if (sscanf(fmtp_string, "usedtx=%30u", &val) == 1) {
+ ast_format_append(format, SILK_ATTR_KEY_DTX, val ? 1 : 0, AST_FORMAT_ATTR_END);
}
+ if (sscanf(fmtp_string, "useinbandfec=%30u", &val) == 1) {
+ ast_format_append(format, SILK_ATTR_KEY_FEC, val ? 1 : 0, AST_FORMAT_ATTR_END);
+ }
+ break;
}
}
}
@@ -10829,7 +10830,7 @@ static void add_codec_to_sdp(const struct sip_pvt *p,
{
int rtp_code;
struct ast_format_list fmt;
-
+ int val = 0;
if (debug)
ast_verbose("Adding codec %d (%s) to SDP\n", format->id, ast_getformatname(format));
@@ -10872,20 +10873,22 @@ static void add_codec_to_sdp(const struct sip_pvt *p,
/* Indicate that we only expect 64Kbps */
ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=64000\r\n", rtp_code);
break;
+ case AST_FORMAT_CELT:
+ if (!ast_format_get_value(format, CELT_ATTR_KEY_FRAME_SIZE, &val) && val > 0) {
+ ast_str_append(a_buf, 0, "a=fmtp:%d framesize=%u\r\n", rtp_code, val);
+ }
+ break;
case AST_FORMAT_SILK:
- {
- int val = 0;
- if (!ast_format_get_value(format, SILK_ATTR_KEY_MAX_BITRATE, &val) && val > 5000 && val < 40000) {
- ast_str_append(a_buf, 0, "a=fmtp:%d maxaveragebitrate=%u\r\n", rtp_code, val);
- }
- if (!ast_format_get_value(format, SILK_ATTR_KEY_DTX, &val)) {
- ast_str_append(a_buf, 0, "a=fmtp:%d usedtx=%u\r\n", rtp_code, val ? 1 : 0);
- }
- if (!ast_format_get_value(format, SILK_ATTR_KEY_FEC, &val)) {
- ast_str_append(a_buf, 0, "a=fmtp:%d useinbandfec=%u\r\n", rtp_code, val ? 1 : 0);
- }
- break;
+ if (!ast_format_get_value(format, SILK_ATTR_KEY_MAX_BITRATE, &val) && val > 5000 && val < 40000) {
+ ast_str_append(a_buf, 0, "a=fmtp:%d maxaveragebitrate=%u\r\n", rtp_code, val);
+ }
+ if (!ast_format_get_value(format, SILK_ATTR_KEY_DTX, &val)) {
+ ast_str_append(a_buf, 0, "a=fmtp:%d usedtx=%u\r\n", rtp_code, val ? 1 : 0);
+ }
+ if (!ast_format_get_value(format, SILK_ATTR_KEY_FEC, &val)) {
+ ast_str_append(a_buf, 0, "a=fmtp:%d useinbandfec=%u\r\n", rtp_code, val ? 1 : 0);
}
+ break;
}
if (fmt.cur_ms && (fmt.cur_ms < *min_packet_size))
@@ -14341,7 +14344,7 @@ static void network_change_event_cb(const struct ast_event *event, void *userdat
/*! \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 */
-static int cb_extensionstate(char *context, char* exten, int state, void *data)
+static int cb_extensionstate(const char *context, const char *exten, enum ast_extension_states state, void *data)
{
struct sip_pvt *p = data;
@@ -16079,7 +16082,11 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req, struct a
return;
}
- if (get_msg_text2(&buf, req, FALSE)) {
+ /* If this is an out of dialog msg, add back newlines, otherwise strip the new lines.
+ * In dialog msg's newlines are stripped to preserve the behavior of how Asterisk has worked
+ * in the past. If it is found later that new lines can be added into in dialog msgs as well,
+ * then change this. */
+ if (get_msg_text2(&buf, req, p->owner ? FALSE : TRUE)) {
ast_log(LOG_WARNING, "Unable to retrieve text from %s\n", p->callid);
transmit_response(p, "202 Accepted", req);
if (!p->owner)
@@ -19133,11 +19140,11 @@ static int build_reply_digest(struct sip_pvt *p, int method, char* digest, int d
struct sip_auth_container *credentials;
if (!ast_strlen_zero(p->domain))
- ast_copy_string(uri, p->domain, sizeof(uri));
+ snprintf(uri, sizeof(uri), "%s:%s", p->socket.type == SIP_TRANSPORT_TLS ? "sips" : "sip", p->domain);
else if (!ast_strlen_zero(p->uri))
ast_copy_string(uri, p->uri, sizeof(uri));
else
- snprintf(uri, sizeof(uri), "sip:%s@%s", p->username, ast_sockaddr_stringify_host_remote(&p->sa));
+ snprintf(uri, sizeof(uri), "%s:%s@%s", p->socket.type == SIP_TRANSPORT_TLS ? "sips" : "sip", p->username, ast_sockaddr_stringify_host_remote(&p->sa));
snprintf(cnonce, sizeof(cnonce), "%08lx", ast_random());
@@ -22515,7 +22522,6 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
}
p->invitestate = INV_COMPLETED;
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
- ast_string_field_set(p, theirtag, NULL);
res = 0;
goto request_invite_cleanup;
}
@@ -29067,7 +29073,9 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
if ((instance || vinstance || tinstance) &&
!ast_bridged_channel(chan) &&
!sip_cfg.directrtpsetup) {
- return 0;
+ sip_pvt_unlock(p);
+ ast_channel_unlock(chan);
+ return 0;
}
if (p->alreadygone) {
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index ea7d16c9e..dad151ea1 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -25,6 +25,9 @@
* \ingroup channel_drivers
*/
+/*** MODULEINFO
+ <support_level>extended</support_level>
+ ***/
#include "asterisk.h"
@@ -252,6 +255,9 @@ AST_THREADSTORAGE(control2str_threadbuf);
AST_THREADSTORAGE(substate2str_threadbuf);
#define SUBSTATE2STR_BUFSIZE 15
+AST_THREADSTORAGE(callstate2str_threadbuf);
+#define CALLSTATE2STR_BUFSIZE 15
+
/*********************
* Protocol Messages *
*********************/
@@ -636,6 +642,8 @@ struct soft_key_template_definition {
#define KEYDEF_RINGOUT 8
#define KEYDEF_OFFHOOKWITHFEAT 9
#define KEYDEF_UNKNOWN 10
+#define KEYDEF_SLAHOLD 11
+#define KEYDEF_SLACONNECTEDNOTACTIVE 12
#define SOFTKEY_NONE 0x00
#define SOFTKEY_REDIAL 0x01
@@ -895,6 +903,18 @@ static const uint8_t soft_key_default_unknown[] = {
SOFTKEY_NONE,
};
+static const uint8_t soft_key_default_SLAhold[] = {
+ SOFTKEY_REDIAL,
+ SOFTKEY_NEWCALL,
+ SOFTKEY_RESUME,
+};
+
+static const uint8_t soft_key_default_SLAconnectednotactive[] = {
+ SOFTKEY_REDIAL,
+ SOFTKEY_NEWCALL,
+ SOFTKEY_JOIN,
+};
+
static const struct soft_key_definitions soft_key_default_definitions[] = {
{KEYDEF_ONHOOK, soft_key_default_onhook, sizeof(soft_key_default_onhook) / sizeof(uint8_t)},
{KEYDEF_CONNECTED, soft_key_default_connected, sizeof(soft_key_default_connected) / sizeof(uint8_t)},
@@ -906,7 +926,9 @@ static const struct soft_key_definitions soft_key_default_definitions[] = {
{KEYDEF_CONNWITHCONF, soft_key_default_connwithconf, sizeof(soft_key_default_connwithconf) / sizeof(uint8_t)},
{KEYDEF_RINGOUT, soft_key_default_ringout, sizeof(soft_key_default_ringout) / sizeof(uint8_t)},
{KEYDEF_OFFHOOKWITHFEAT, soft_key_default_offhookwithfeat, sizeof(soft_key_default_offhookwithfeat) / sizeof(uint8_t)},
- {KEYDEF_UNKNOWN, soft_key_default_unknown, sizeof(soft_key_default_unknown) / sizeof(uint8_t)}
+ {KEYDEF_UNKNOWN, soft_key_default_unknown, sizeof(soft_key_default_unknown) / sizeof(uint8_t)},
+ {KEYDEF_SLAHOLD, soft_key_default_SLAhold, sizeof(soft_key_default_SLAhold) / sizeof(uint8_t)},
+ {KEYDEF_SLACONNECTEDNOTACTIVE, soft_key_default_SLAconnectednotactive, sizeof(soft_key_default_SLAconnectednotactive) / sizeof(uint8_t)}
};
struct soft_key_template_res_message {
@@ -1218,6 +1240,7 @@ struct skinny_subchannel {
AST_LIST_ENTRY(skinny_subchannel) list;
struct skinny_subchannel *related;
struct skinny_line *line;
+ struct skinny_subline *subline;
};
#define SKINNY_LINE_OPTIONS \
@@ -1242,6 +1265,8 @@ struct skinny_subchannel {
char mohinterpret[MAX_MUSICCLASS]; \
char mohsuggest[MAX_MUSICCLASS]; \
char lastnumberdialed[AST_MAX_EXTENSION]; \
+ char dialoutexten[AST_MAX_EXTENSION]; \
+ char dialoutcontext[AST_MAX_CONTEXT]; \
ast_group_t callgroup; \
ast_group_t pickupgroup; \
int callwaiting; \
@@ -1268,9 +1293,11 @@ struct skinny_subchannel {
struct skinny_line {
SKINNY_LINE_OPTIONS
ast_mutex_t lock;
+ struct skinny_container *container;
struct ast_event_sub *mwi_event_sub; /* Event based MWI */
struct skinny_subchannel *activesub;
AST_LIST_HEAD(, skinny_subchannel) sub;
+ AST_LIST_HEAD(, skinny_subline) sublines;
AST_LIST_ENTRY(skinny_line) list;
AST_LIST_ENTRY(skinny_line) all;
struct skinny_device *device;
@@ -1297,8 +1324,29 @@ static struct skinny_line_options *default_line = &default_line_struct;
static AST_LIST_HEAD_STATIC(lines, skinny_line);
+struct skinny_subline {
+ struct skinny_container *container;
+ struct skinny_line *line;
+ struct skinny_subchannel *sub;
+ AST_LIST_ENTRY(skinny_subline) list;
+ char name[80];
+ char context[AST_MAX_CONTEXT];
+ char exten[AST_MAX_EXTENSION];
+ char stname[AST_MAX_EXTENSION];
+ char lnname[AST_MAX_EXTENSION];
+ char ourName[40];
+ char ourNum[24];
+ char theirName[40];
+ char theirNum[24];
+ int calldirection;
+ int substate;
+ int extenstate;
+ unsigned int callid;
+};
+
struct skinny_speeddial {
ast_mutex_t lock;
+ struct skinny_container *container;
char label[42];
char context[AST_MAX_CONTEXT];
char exten[AST_MAX_EXTENSION];
@@ -1311,6 +1359,16 @@ struct skinny_speeddial {
struct skinny_device *parent;
};
+#define SKINNY_DEVICECONTAINER 1
+#define SKINNY_LINECONTAINER 2
+#define SKINNY_SUBLINECONTAINER 3
+#define SKINNY_SDCONTAINER 4
+
+struct skinny_container {
+ int type;
+ void *data;
+};
+
struct skinny_addon {
ast_mutex_t lock;
char type[10];
@@ -1420,7 +1478,7 @@ static struct ast_channel_tech skinny_tech = {
.bridge = ast_rtp_instance_bridge,
};
-static int skinny_extensionstate_cb(char *context, char* exten, int state, void *data);
+static int skinny_extensionstate_cb(const char *context, const char *exten, enum ast_extension_states state, void *data);
static int skinny_transfer(struct skinny_subchannel *sub);
static struct skinny_line *skinny_line_alloc(void)
@@ -1444,6 +1502,7 @@ static struct skinny_line *skinny_line_destroy(struct skinny_line *l)
{
l->cap = ast_format_cap_destroy(l->cap);
l->confcap = ast_format_cap_destroy(l->confcap);
+ ast_free(l->container);
ast_free(l);
return NULL;
}
@@ -1692,6 +1751,47 @@ static struct skinny_line *find_line_by_name(const char *dest)
return tmpl;
}
+static struct skinny_subline *find_subline_by_name(const char *dest)
+{
+ struct skinny_line *l;
+ struct skinny_subline *subline;
+ struct skinny_subline *tmpsubline = NULL;
+ struct skinny_device *d;
+
+ AST_LIST_LOCK(&devices);
+ AST_LIST_TRAVERSE(&devices, d, list){
+ AST_LIST_TRAVERSE(&d->lines, l, list){
+ AST_LIST_TRAVERSE(&l->sublines, subline, list){
+ if (!strcasecmp(subline->name, dest)) {
+ if (tmpsubline) {
+ ast_verb(2, "Ambiguous subline name: %s\n", dest);
+ AST_LIST_UNLOCK(&devices);
+ return NULL;
+ } else
+ tmpsubline = subline;
+ }
+ }
+ }
+ }
+ AST_LIST_UNLOCK(&devices);
+ return tmpsubline;
+}
+
+static struct skinny_subline *find_subline_by_callid(struct skinny_device *d, int callid)
+{
+ struct skinny_subline *subline;
+ struct skinny_line *l;
+
+ AST_LIST_TRAVERSE(&d->lines, l, list){
+ AST_LIST_TRAVERSE(&l->sublines, subline, list){
+ if (subline->callid == callid) {
+ return subline;
+ }
+ }
+ }
+ return NULL;
+}
+
/*!
* implement the setvar config line
*/
@@ -1943,6 +2043,7 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s)
{
struct skinny_device *d;
struct skinny_line *l;
+ struct skinny_subline *subline;
struct skinny_speeddial *sd;
struct sockaddr_in sin;
socklen_t slen;
@@ -1970,7 +2071,7 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s)
d->ourip = sin.sin_addr;
AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
- sd->stateid = ast_extension_state_add(sd->context, sd->exten, skinny_extensionstate_cb, sd);
+ sd->stateid = ast_extension_state_add(sd->context, sd->exten, skinny_extensionstate_cb, sd->container);
}
instance = 0;
AST_LIST_TRAVERSE(&d->lines, l, list) {
@@ -1997,6 +2098,9 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s)
register_exten(l);
/* initialize MWI on line and device */
mwi_event_cb(0, l);
+ AST_LIST_TRAVERSE(&l->sublines, subline, list) {
+ ast_extension_state_add(subline->context, subline->exten, skinny_extensionstate_cb, subline->container);
+ }
ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s", l->name);
}
--instance;
@@ -2172,6 +2276,40 @@ static char *message2str(int type)
return tmp;
}
}
+
+static char *callstate2str(int ind)
+{
+ char *tmp;
+
+ switch (ind) {
+ case SUBSTATE_OFFHOOK:
+ return "SKINNY_OFFHOOK";
+ case SKINNY_ONHOOK:
+ return "SKINNY_ONHOOK";
+ case SKINNY_RINGOUT:
+ return "SKINNY_RINGOUT";
+ case SKINNY_RINGIN:
+ return "SKINNY_RINGIN";
+ case SKINNY_CONNECTED:
+ return "SKINNY_CONNECTED";
+ case SKINNY_BUSY:
+ return "SKINNY_BUSY";
+ case SKINNY_CONGESTION:
+ return "SKINNY_CONGESTION";
+ case SKINNY_PROGRESS:
+ return "SKINNY_PROGRESS";
+ case SKINNY_HOLD:
+ return "SKINNY_HOLD";
+ case SKINNY_CALLWAIT:
+ return "SKINNY_CALLWAIT";
+ default:
+ if (!(tmp = ast_threadstorage_get(&callstate2str_threadbuf, CALLSTATE2STR_BUFSIZE)))
+ return "Unknown";
+ snprintf(tmp, CALLSTATE2STR_BUFSIZE, "UNKNOWN-%d", ind);
+ return tmp;
+ }
+}
+
#endif
static int transmit_response_bysession(struct skinnysession *s, struct skinny_req *req)
@@ -2255,24 +2393,46 @@ static void transmit_microphone_mode(struct skinny_device *d, int mode)
transmit_response(d, req);
}
-static void transmit_callinfo(struct skinny_subchannel *sub)
+//static void transmit_callinfo(struct skinny_subchannel *sub)
+static void transmit_callinfo(struct skinny_device *d, int instance, int callid, char *fromname, char *fromnum, char *toname, char *tonum, int calldirection)
{
- struct skinny_device *d;
- struct skinny_line *l;
struct skinny_req *req;
+
+ if (!(req = req_alloc(sizeof(struct call_info_message), CALL_INFO_MESSAGE)))
+ return;
+
+ if (skinnydebug) {
+ ast_verb(1, "Setting Callinfo to %s(%s) from %s(%s) (dir=%d) on %s(%d)\n", toname, tonum, fromname, fromnum, calldirection, d->name, instance);
+ }
+
+ ast_copy_string(req->data.callinfo.callingPartyName, fromname, sizeof(req->data.callinfo.callingPartyName));
+ ast_copy_string(req->data.callinfo.callingParty, fromnum, sizeof(req->data.callinfo.callingParty));
+ ast_copy_string(req->data.callinfo.calledPartyName, toname, sizeof(req->data.callinfo.calledPartyName));
+ ast_copy_string(req->data.callinfo.calledParty, tonum, sizeof(req->data.callinfo.calledParty));
+ req->data.callinfo.instance = htolel(instance);
+ req->data.callinfo.reference = htolel(callid);
+ req->data.callinfo.type = htolel(calldirection);
+ transmit_response(d, req);
+}
+
+static void send_callinfo(struct skinny_subchannel *sub)
+{
struct ast_channel *ast;
+ struct skinny_device *d;
+ struct skinny_line *l;
char *fromname;
char *fromnum;
char *toname;
char *tonum;
- if (!sub || !(l=sub->line) || !(d=l->device) || !(ast=sub->owner)) {
+ if (!sub || !sub->owner || !sub->line || !sub->line->device) {
return;
}
-
- if (!(req = req_alloc(sizeof(struct call_info_message), CALL_INFO_MESSAGE)))
- return;
-
+
+ ast = sub->owner;
+ l = sub->line;
+ d = l->device;
+
if (sub->calldirection == SKINNY_INCOMING) {
fromname = S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, "");
fromnum = S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, "");
@@ -2287,19 +2447,42 @@ static void transmit_callinfo(struct skinny_subchannel *sub)
ast_verb(1, "Error sending Callinfo to %s(%d) - No call direction in sub\n", d->name, l->instance);
return;
}
+ transmit_callinfo(d, l->instance, sub->callid, fromname, fromnum, toname, tonum, sub->calldirection);
+}
- if (skinnydebug) {
- ast_verb(1, "Setting Callinfo to %s(%s) from %s(%s) (dir=%d) on %s(%d)\n", toname, tonum, fromname, fromnum, sub->calldirection, d->name, l->instance);
+static void push_callinfo(struct skinny_subline *subline, struct skinny_subchannel *sub)
+{
+ struct ast_channel *ast;
+ struct skinny_device *d;
+ struct skinny_line *l;
+ char *fromname;
+ char *fromnum;
+ char *toname;
+ char *tonum;
+
+ if (!sub || !sub->owner || !sub->line || !sub->line->device) {
+ return;
}
- ast_copy_string(req->data.callinfo.callingPartyName, fromname, sizeof(req->data.callinfo.callingPartyName));
- ast_copy_string(req->data.callinfo.callingParty, fromnum, sizeof(req->data.callinfo.callingParty));
- ast_copy_string(req->data.callinfo.calledPartyName, toname, sizeof(req->data.callinfo.calledPartyName));
- ast_copy_string(req->data.callinfo.calledParty, tonum, sizeof(req->data.callinfo.calledParty));
- req->data.callinfo.instance = htolel(l->instance);
- req->data.callinfo.reference = htolel(sub->callid);
- req->data.callinfo.type = htolel(sub->calldirection);
- transmit_response(d, req);
+ ast = sub->owner;
+ l = sub->line;
+ d = l->device;
+
+ if (sub->calldirection == SKINNY_INCOMING) {
+ fromname = S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, "");
+ fromnum = S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, "");
+ toname = S_COR(ast->caller.id.name.valid, ast->caller.id.name.str, "");
+ tonum = S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, "");
+ } else if (sub->calldirection == SKINNY_OUTGOING) {
+ fromname = S_COR(ast->caller.id.name.valid, ast->caller.id.name.str, "");
+ fromnum = S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, "");
+ toname = S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, l->lastnumberdialed);
+ tonum = S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, l->lastnumberdialed);
+ } else {
+ ast_verb(1, "Error sending Callinfo to %s(%d) - No call direction in sub\n", d->name, l->instance);
+ return;
+ }
+ transmit_callinfo(subline->line->device, subline->line->instance, subline->callid, fromname, fromnum, toname, tonum, sub->calldirection);
}
static void transmit_connect(struct skinny_device *d, struct skinny_subchannel *sub)
@@ -2556,6 +2739,12 @@ static void transmit_callstate(struct skinny_device *d, int buttonInstance, unsi
if (!(req = req_alloc(sizeof(struct call_state_message), CALL_STATE_MESSAGE)))
return;
+
+#ifdef SKINNY_DEVMODE
+ if (skinnydebug) {
+ ast_verb(3, "Transmitting CALL_STATE_MESSAGE to %s - line %d, callid %d, state %s\n", d->name, buttonInstance, callid, callstate2str(state));
+ }
+#endif
req->data.callstate.callState = htolel(state);
req->data.callstate.lineInstance = htolel(buttonInstance);
@@ -2700,8 +2889,8 @@ static void transmit_softkeysetres(struct skinny_device *d)
return;
req->data.softkeysets.softKeySetOffset = htolel(0);
- req->data.softkeysets.softKeySetCount = htolel(11);
- req->data.softkeysets.totalSoftKeySetCount = htolel(11);
+ req->data.softkeysets.softKeySetCount = htolel(13);
+ req->data.softkeysets.totalSoftKeySetCount = htolel(13);
for (x = 0; x < sizeof(soft_key_default_definitions) / sizeof(struct soft_key_definitions); x++) {
const uint8_t *defaults = softkeymode->defaults;
/* XXX I wanted to get the size of the array dynamically, but that wasn't wanting to work.
@@ -2793,51 +2982,111 @@ static void transmit_capabilitiesreq(struct skinny_device *d)
transmit_response(d, req);
}
-static int skinny_extensionstate_cb(char *context, char *exten, int state, void *data)
+static int skinny_extensionstate_cb(const char *context, const char *exten, enum ast_extension_states state, void *data)
{
- struct skinny_speeddial *sd = data;
- struct skinny_device *d = sd->parent;
+ struct skinny_container *container = data;
+ struct skinny_device *d = NULL;
char hint[AST_MAX_EXTENSION];
- if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, sd->context, sd->exten)) {
- /* If they are not registered, we will override notification and show no availability */
- if (ast_device_state(hint) == AST_DEVICE_UNAVAILABLE) {
- transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_FLASH);
- transmit_callstate(d, sd->instance, 0, SKINNY_ONHOOK);
+ if (container->type == SKINNY_SDCONTAINER) {
+ struct skinny_speeddial *sd = container->data;
+ d = sd->parent;
+
+ if (skinnydebug) {
+ ast_verb(2, "Got hint %s on speeddial %s\n", ast_extension_state2str(state), sd->label);
+ }
+
+ if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, sd->context, sd->exten)) {
+ /* If they are not registered, we will override notification and show no availability */
+ if (ast_device_state(hint) == AST_DEVICE_UNAVAILABLE) {
+ transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_FLASH);
+ transmit_callstate(d, sd->instance, 0, SKINNY_ONHOOK);
+ return 0;
+ }
+ switch (state) {
+ case AST_EXTENSION_DEACTIVATED: /* Retry after a while */
+ case AST_EXTENSION_REMOVED: /* Extension is gone */
+ ast_verb(2, "Extension state: Watcher for hint %s %s. Notify Device %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", d->name);
+ sd->stateid = -1;
+ transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_OFF);
+ transmit_callstate(d, sd->instance, 0, SKINNY_ONHOOK);
+ break;
+ case AST_EXTENSION_RINGING:
+ case AST_EXTENSION_UNAVAILABLE:
+ transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_BLINK);
+ transmit_callstate(d, sd->instance, 0, SKINNY_RINGIN);
+ break;
+ case AST_EXTENSION_BUSY: /* callstate = SKINNY_BUSY wasn't wanting to work - I'll settle for this */
+ case AST_EXTENSION_INUSE:
+ transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_ON);
+ transmit_callstate(d, sd->instance, 0, SKINNY_CALLREMOTEMULTILINE);
+ break;
+ case AST_EXTENSION_ONHOLD:
+ transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_WINK);
+ transmit_callstate(d, sd->instance, 0, SKINNY_HOLD);
+ break;
+ case AST_EXTENSION_NOT_INUSE:
+ default:
+ transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_OFF);
+ transmit_callstate(d, sd->instance, 0, SKINNY_ONHOOK);
+ break;
+ }
+ }
+ sd->laststate = state;
+ } else if (container->type == SKINNY_SUBLINECONTAINER) {
+ struct skinny_subline *subline = container->data;
+ struct skinny_line *l = subline->line;
+ d = l->device;
+
+ if (skinnydebug) {
+ ast_verb(2, "Got hint %s on subline %s (%s@%s)\n", ast_extension_state2str(state), subline->name, exten, context);
+ }
+
+ subline->extenstate = state;
+
+ if (subline->callid == 0) {
return 0;
}
+
switch (state) {
- case AST_EXTENSION_DEACTIVATED: /* Retry after a while */
- case AST_EXTENSION_REMOVED: /* Extension is gone */
- ast_verb(2, "Extension state: Watcher for hint %s %s. Notify Device %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", d->name);
- sd->stateid = -1;
- transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_OFF);
- transmit_callstate(d, sd->instance, 0, SKINNY_ONHOOK);
- break;
- case AST_EXTENSION_RINGING:
- case AST_EXTENSION_UNAVAILABLE:
- transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_BLINK);
- transmit_callstate(d, sd->instance, 0, SKINNY_RINGIN);
+ case AST_EXTENSION_RINGING: /* Handled by normal ringin */
break;
- case AST_EXTENSION_BUSY: /* callstate = SKINNY_BUSY wasn't wanting to work - I'll settle for this */
case AST_EXTENSION_INUSE:
- transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_ON);
- transmit_callstate(d, sd->instance, 0, SKINNY_CALLREMOTEMULTILINE);
+ if (subline->sub && (subline->sub->substate == SKINNY_CONNECTED)) { /* Device has a real call */
+ transmit_callstate(d, l->instance, subline->callid, SKINNY_CONNECTED);
+ transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_CONNECTED);
+ transmit_displaypromptstatus(d, "Connected", 0, l->instance, subline->callid);
+ } else { /* Some other device has active call */
+ transmit_callstate(d, l->instance, subline->callid, SKINNY_CALLREMOTEMULTILINE);
+ transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE);
+ transmit_displaypromptstatus(d, "In Use", 0, l->instance, subline->callid);
+ }
+ transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
+ transmit_ringer_mode(d, SKINNY_RING_OFF);
+ transmit_activatecallplane(d, l);
break;
case AST_EXTENSION_ONHOLD:
- transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_WINK);
- transmit_callstate(d, sd->instance, 0, SKINNY_HOLD);
+ transmit_callstate(d, l->instance, subline->callid, SKINNY_HOLD);
+ transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLAHOLD);
+ transmit_displaypromptstatus(d, "Hold", 0, l->instance, subline->callid);
+ transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
+ transmit_activatecallplane(d, l);
break;
case AST_EXTENSION_NOT_INUSE:
- default:
- transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_OFF);
- transmit_callstate(d, sd->instance, 0, SKINNY_ONHOOK);
+ transmit_callstate(d, l->instance, subline->callid, SKINNY_ONHOOK);
+ transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_ONHOOK);
+ transmit_clearpromptmessage(d, l->instance, subline->callid);
+ transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
+ transmit_activatecallplane(d, l);
+ subline->callid = 0;
break;
+ default:
+ ast_log(LOG_WARNING, "AST_EXTENSION_STATE %s not configured\n", ast_extension_state2str(state));
}
+ } else {
+ ast_log(LOG_WARNING, "Invalid data supplied to skinny_extensionstate_cb\n");
}
- sd->laststate = state;
-
return 0;
}
@@ -2857,7 +3106,7 @@ static void update_connectedline(struct skinny_subchannel *sub, const void *data
ast_verb(3,"Sub %d - Updating\n", sub->callid);
}
- transmit_callinfo(sub);
+ send_callinfo(sub);
if (sub->owner->_state == AST_STATE_UP) {
transmit_callstate(d, l->instance, sub->callid, SKINNY_CONNECTED);
transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
@@ -3654,6 +3903,7 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str
{
struct skinny_device *d;
struct skinny_line *l;
+ struct skinny_subline *subline;
struct ast_codec_pref *pref;
int x = 0;
char codec_buf[512];
@@ -3724,6 +3974,12 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str
ast_cli(fd, "Codec Order: (");
print_codec_to_cli(fd, &l->prefs);
ast_cli(fd, ")\n");
+ if (AST_LIST_FIRST(&l->sublines)) {
+ ast_cli(fd, "Sublines:\n");
+ AST_LIST_TRAVERSE(&l->sublines, subline, list) {
+ ast_cli(fd, " %s, %s@%s\n", subline->name, subline->exten, subline->context);
+ }
+ }
ast_cli(fd, "\n");
} else { /* manager */
astman_append(s, "Channeltype: SKINNY\r\n");
@@ -3924,7 +4180,6 @@ static void *skinny_newcall(void *data)
struct skinny_device *d = l->device;
int res = 0;
- ast_copy_string(l->lastnumberdialed, c->exten, sizeof(l->lastnumberdialed));
ast_set_callerid(c,
l->hidecallerid ? "" : l->cid_num,
l->hidecallerid ? "" : l->cid_name,
@@ -3941,6 +4196,7 @@ static void *skinny_newcall(void *data)
if (!sub->rtp) {
start_rtp(sub);
}
+ ast_verb(3, "Sub %d - Calling %s@%s\n", sub->callid, c->exten, c->context);
res = ast_pbx_run(c);
if (res) {
ast_log(LOG_WARNING, "PBX exited non-zero\n");
@@ -4520,7 +4776,7 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s
return 0;
}
-static struct ast_channel *skinny_new(struct skinny_line *l, int state, const char *linkedid, int direction)
+static struct ast_channel *skinny_new(struct skinny_line *l, struct skinny_subline *subline, int state, const char *linkedid, int direction)
{
struct ast_channel *tmp;
struct skinny_subchannel *sub;
@@ -4557,6 +4813,13 @@ static struct ast_channel *skinny_new(struct skinny_line *l, int state, const ch
sub->related = NULL;
sub->calldirection = direction;
+ if (subline) {
+ sub->subline = subline;
+ subline->sub = sub;
+ } else {
+ sub->subline = NULL;
+ }
+
AST_LIST_INSERT_HEAD(&l->sub, sub, list);
//l->activesub = sub;
}
@@ -4607,7 +4870,11 @@ static struct ast_channel *skinny_new(struct skinny_line *l, int state, const ch
}
}
- ast_copy_string(tmp->context, l->context, sizeof(tmp->context));
+ if (subline) {
+ ast_copy_string(tmp->context, subline->context, sizeof(tmp->context));
+ } else {
+ ast_copy_string(tmp->context, l->context, sizeof(tmp->context));
+ }
ast_copy_string(tmp->exten, l->exten, sizeof(tmp->exten));
/* Don't use ast_set_callerid() here because it will
@@ -4676,6 +4943,7 @@ static char *substate2str(int ind) {
static void setsubstate(struct skinny_subchannel *sub, int state)
{
struct skinny_line *l = sub->line;
+ struct skinny_subline *subline = sub->subline;
struct skinny_device *d = l->device;
struct ast_channel *c = sub->owner;
pthread_t t;
@@ -4695,7 +4963,118 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
if ((state == SUBSTATE_RINGIN) && ((d->hookstate == SKINNY_OFFHOOK) || (AST_LIST_NEXT(AST_LIST_FIRST(&l->sub), list)))) {
actualstate = SUBSTATE_CALLWAIT;
}
-
+
+ if ((state == SUBSTATE_CONNECTED) && (!subline) && (AST_LIST_FIRST(&l->sublines))) {
+ const char *slastation;
+ struct skinny_subline *tmpsubline;
+ slastation = pbx_builtin_getvar_helper(c, "SLASTATION");
+ ast_verb(3, "Connecting %s to subline\n", slastation);
+ if (slastation) {
+ AST_LIST_TRAVERSE(&l->sublines, tmpsubline, list) {
+ if (!strcasecmp(tmpsubline->stname, slastation)) {
+ subline = tmpsubline;
+ break;
+ }
+ }
+ if (subline) {
+ struct skinny_line *tmpline;
+ subline->sub = sub;
+ sub->subline = subline;
+ subline->callid = sub->callid;
+ send_callinfo(sub);
+ AST_LIST_TRAVERSE(&lines, tmpline, all) {
+ AST_LIST_TRAVERSE(&tmpline->sublines, tmpsubline, list) {
+ if (!(subline == tmpsubline)) {
+ if (!strcasecmp(subline->lnname, tmpsubline->lnname)) {
+ tmpsubline->callid = callnums++;
+ transmit_callstate(tmpsubline->line->device, tmpsubline->line->instance, tmpsubline->callid, SKINNY_OFFHOOK);
+ push_callinfo(tmpsubline, sub);
+ skinny_extensionstate_cb(NULL, NULL, tmpsubline->extenstate, tmpsubline->container);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (subline) { /* Different handling for subs under a subline, indications come through hints */
+ switch (actualstate) {
+ case SUBSTATE_ONHOOK:
+ AST_LIST_REMOVE(&l->sub, sub, list);
+ if (sub->related) {
+ sub->related->related = NULL;
+ }
+
+ if (sub == l->activesub) {
+ l->activesub = NULL;
+ transmit_closereceivechannel(d, sub);
+ transmit_stopmediatransmission(d, sub);
+ }
+
+ if (subline->callid) {
+ transmit_stop_tone(d, l->instance, sub->callid);
+ transmit_callstate(d, l->instance, subline->callid, SKINNY_CALLREMOTEMULTILINE);
+ transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE);
+ transmit_displaypromptstatus(d, "In Use", 0, l->instance, subline->callid);
+ }
+
+ sub->cxmode = SKINNY_CX_RECVONLY;
+ sub->substate = SUBSTATE_ONHOOK;
+ if (sub->rtp) {
+ ast_rtp_instance_destroy(sub->rtp);
+ sub->rtp = NULL;
+ }
+ sub->substate = SUBSTATE_ONHOOK;
+ if (sub->owner) {
+ ast_queue_hangup(sub->owner);
+ }
+ return;
+ case SUBSTATE_CONNECTED:
+ transmit_activatecallplane(d, l);
+ transmit_stop_tone(d, l->instance, sub->callid);
+ transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_CONNECTED);
+ transmit_callstate(d, l->instance, subline->callid, SKINNY_CONNECTED);
+ if (!sub->rtp) {
+ start_rtp(sub);
+ }
+ if (sub->substate == SUBSTATE_RINGIN || sub->substate == SUBSTATE_CALLWAIT) {
+ ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
+ }
+ if (sub->substate == SUBSTATE_DIALING || sub->substate == SUBSTATE_RINGOUT) {
+ transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
+ }
+ if (sub->owner->_state != AST_STATE_UP) {
+ ast_setstate(sub->owner, AST_STATE_UP);
+ }
+ sub->substate = SUBSTATE_CONNECTED;
+ l->activesub = sub;
+ return;
+ case SUBSTATE_HOLD:
+ if (sub->substate != SUBSTATE_CONNECTED) {
+ ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_HOLD from %s (on call-%d)\n", substate2str(sub->substate), sub->callid);
+ return;
+ }
+ transmit_activatecallplane(d, l);
+ transmit_closereceivechannel(d, sub);
+ transmit_stopmediatransmission(d, sub);
+
+ transmit_callstate(d, l->instance, subline->callid, SKINNY_CALLREMOTEMULTILINE);
+ transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE);
+ transmit_displaypromptstatus(d, "In Use", 0, l->instance, subline->callid);
+
+ sub->substate = SUBSTATE_HOLD;
+
+ ast_queue_control_data(sub->owner, AST_CONTROL_HOLD,
+ S_OR(l->mohsuggest, NULL),
+ !ast_strlen_zero(l->mohsuggest) ? strlen(l->mohsuggest) + 1 : 0);
+
+ return;
+ default:
+ ast_log(LOG_WARNING, "Substate handling under subline for state %d not implemented on Sub-%d\n", state, sub->callid);
+ }
+ }
+
if ((d->hookstate == SKINNY_ONHOOK) && ((actualstate == SUBSTATE_OFFHOOK) || (actualstate == SUBSTATE_DIALING)
|| (actualstate == SUBSTATE_RINGOUT) || (actualstate == SUBSTATE_CONNECTED) || (actualstate == SUBSTATE_BUSY)
|| (actualstate == SUBSTATE_CONGESTION) || (actualstate == SUBSTATE_PROGRESS))) {
@@ -4708,7 +5087,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
}
if (actualstate == sub->substate) {
- transmit_callinfo(sub);
+ send_callinfo(sub);
transmit_callstate(d, l->instance, sub->callid, SKINNY_HOLD);
return;
}
@@ -4766,24 +5145,40 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
break;
case SUBSTATE_DIALING:
if (ast_strlen_zero(sub->exten) || !ast_exists_extension(c, c->context, sub->exten, 1, l->cid_num)) {
- ast_log(LOG_WARNING, "Exten (%s) does not exist, unable to set substate DIALING on sub %d\n", sub->exten, sub->callid);
+ ast_log(LOG_WARNING, "Exten (%s)@(%s) does not exist, unable to set substate DIALING on sub %d\n", sub->exten, c->context, sub->callid);
return;
}
if (d->hookstate == SKINNY_ONHOOK) {
d->hookstate = SKINNY_OFFHOOK;
transmit_speaker_mode(d, SKINNY_SPEAKERON);
- transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
transmit_activatecallplane(d, l);
}
- transmit_stop_tone(d, l->instance, sub->callid);
- transmit_clear_display_message(d, l->instance, sub->callid);
- transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
- transmit_displaypromptstatus(d, "Dialing", 0, l->instance, sub->callid);
- ast_copy_string(c->exten, sub->exten, sizeof(c->exten));
- ast_copy_string(l->lastnumberdialed, sub->exten, sizeof(l->lastnumberdialed));
+ if (!sub->subline) {
+ transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+ transmit_stop_tone(d, l->instance, sub->callid);
+ transmit_clear_display_message(d, l->instance, sub->callid);
+ transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
+ transmit_displaypromptstatus(d, "Dialing", 0, l->instance, sub->callid);
+ }
+ if (AST_LIST_FIRST(&l->sublines)) {
+ if (subline) {
+ ast_copy_string(c->exten, subline->exten, sizeof(c->exten));
+ ast_copy_string(c->context, "sla_stations", sizeof(c->context));
+ } else {
+ pbx_builtin_setvar_helper(c, "_DESTEXTEN", sub->exten);
+ pbx_builtin_setvar_helper(c, "_DESTCONTEXT", c->context);
+ ast_copy_string(c->exten, l->dialoutexten, sizeof(c->exten));
+ ast_copy_string(c->context, l->dialoutcontext, sizeof(c->context));
+ ast_copy_string(l->lastnumberdialed, sub->exten, sizeof(l->lastnumberdialed));
+ }
+ } else {
+ ast_copy_string(c->exten, sub->exten, sizeof(c->exten));
+ ast_copy_string(l->lastnumberdialed, sub->exten, sizeof(l->lastnumberdialed));
+ }
+
sub->substate = SUBSTATE_DIALING;
if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
@@ -4803,14 +5198,14 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGOUT);
transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
transmit_displaypromptstatus(d, "Ring Out", 0, l->instance, sub->callid);
- transmit_callinfo(sub);
+ send_callinfo(sub);
sub->substate = SUBSTATE_RINGOUT;
break;
case SUBSTATE_RINGIN:
transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGIN);
transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN);
transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
- transmit_callinfo(sub);
+ send_callinfo(sub);
transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
transmit_ringer_mode(d, SKINNY_RING_INSIDE);
transmit_activatecallplane(d, l);
@@ -4830,7 +5225,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
transmit_callstate(d, l->instance, sub->callid, SKINNY_CALLWAIT);
transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN);
transmit_displaypromptstatus(d, "Callwaiting", 0, l->instance, sub->callid);
- transmit_callinfo(sub);
+ send_callinfo(sub);
transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
transmit_start_tone(d, SKINNY_CALLWAITTONE, l->instance, sub->callid);
@@ -4846,7 +5241,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
transmit_ringer_mode(d, SKINNY_RING_OFF);
transmit_activatecallplane(d, l);
transmit_stop_tone(d, l->instance, sub->callid);
- transmit_callinfo(sub);
+ send_callinfo(sub);
transmit_callstate(d, l->instance, sub->callid, SKINNY_CONNECTED);
transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
@@ -4880,7 +5275,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
if (!d->earlyrtp) {
transmit_start_tone(d, SKINNY_BUSYTONE, l->instance, sub->callid);
}
- transmit_callinfo(sub);
+ send_callinfo(sub);
transmit_callstate(d, l->instance, sub->callid, SKINNY_BUSY);
transmit_displaypromptstatus(d, "Busy", 0, l->instance, sub->callid);
sub->substate = SUBSTATE_BUSY;
@@ -4894,7 +5289,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
if (!d->earlyrtp) {
transmit_start_tone(d, SKINNY_REORDER, l->instance, sub->callid);
}
- transmit_callinfo(sub);
+ send_callinfo(sub);
transmit_callstate(d, l->instance, sub->callid, SKINNY_CONGESTION);
transmit_displaypromptstatus(d, "Congestion", 0, l->instance, sub->callid);
sub->substate = SUBSTATE_CONGESTION;
@@ -4908,7 +5303,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
if (!d->earlyrtp) {
transmit_start_tone(d, SKINNY_ALERT, l->instance, sub->callid);
}
- transmit_callinfo(sub);
+ send_callinfo(sub);
transmit_callstate(d, l->instance, sub->callid, SKINNY_PROGRESS);
transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
sub->substate = SUBSTATE_PROGRESS;
@@ -5060,7 +5455,7 @@ static int handle_transfer_button(struct skinny_subchannel *sub)
if (!(sub->substate == SUBSTATE_HOLD)) {
setsubstate(sub, SUBSTATE_HOLD);
}
- c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
if (c) {
newsub = c->tech_pvt;
/* point the sub and newsub at each other so we know they are related */
@@ -5248,7 +5643,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession
break;
}
- c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
if (!c) {
ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
} else {
@@ -5268,7 +5663,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession
}
if (!sub || !sub->owner)
- c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
else
c = sub->owner;
@@ -5304,7 +5699,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession
}
if (!sub || !sub->owner) {
- c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
} else {
c = sub->owner;
}
@@ -5366,7 +5761,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession
ast_verb(1, "Received Stimulus: Forward All(%d/%d)\n", instance, callreference);
if (!sub || !sub->owner) {
- c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
} else {
c = sub->owner;
}
@@ -5383,7 +5778,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession
ast_verb(1, "Received Stimulus: Forward Busy (%d/%d)\n", instance, callreference);
if (!sub || !sub->owner) {
- c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
} else {
c = sub->owner;
}
@@ -5401,7 +5796,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession
#if 0 /* Not sure how to handle this yet */
if (!sub || !sub->owner) {
- c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
} else {
c = sub->owner;
}
@@ -5444,7 +5839,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession
if (sub && sub->owner) {
ast_debug(1, "Current subchannel [%s] already has owner\n", sub->owner->name);
} else {
- c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
if (c) {
setsubstate(c->tech_pvt, SUBSTATE_OFFHOOK);
} else {
@@ -5517,7 +5912,7 @@ static int handle_offhook_message(struct skinny_req *req, struct skinnysession *
if (sub && sub->owner) {
ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
} else {
- c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
if (c) {
setsubstate(c->tech_pvt, SUBSTATE_OFFHOOK);
} else {
@@ -5851,7 +6246,7 @@ static int handle_enbloc_call_message(struct skinny_req *req, struct skinnysessi
l = sub->line;
}
- c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
if(!c) {
ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
@@ -5914,7 +6309,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
}
if (!sub || !sub->owner) {
- c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
} else {
c = sub->owner;
}
@@ -5931,9 +6326,9 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
ast_verb(1, "Received Softkey Event: New Call(%d/%d)\n", instance, callreference);
/* New Call ALWAYS gets a new sub-channel */
- c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
sub = c->tech_pvt;
-
+
if (!c) {
ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
} else {
@@ -5943,7 +6338,16 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
case SOFTKEY_HOLD:
if (skinnydebug)
ast_verb(1, "Received Softkey Event: Hold(%d/%d)\n", instance, callreference);
- setsubstate(sub, SUBSTATE_HOLD);
+
+ if (sub) {
+ setsubstate(sub, SUBSTATE_HOLD);
+ } else { /* No sub, maybe an SLA call */
+ struct skinny_subline *subline;
+ if ((subline = find_subline_by_callid(d, callreference))) {
+ setsubstate(subline->sub, SUBSTATE_HOLD);
+ }
+ }
+
break;
case SOFTKEY_TRNSFER:
if (skinnydebug)
@@ -5976,7 +6380,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
ast_verb(1, "Received Softkey Event: Forward All(%d/%d)\n", instance, callreference);
if (!sub || !sub->owner) {
- c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
} else {
c = sub->owner;
}
@@ -5994,7 +6398,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
ast_verb(1, "Received Softkey Event: Forward Busy (%d/%d)\n", instance, callreference);
if (!sub || !sub->owner) {
- c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
} else {
c = sub->owner;
}
@@ -6013,7 +6417,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
#if 0 /* Not sure how to handle this yet */
if (!sub || !sub->owner) {
- c = skinny_new(l, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
} else {
c = sub->owner;
}
@@ -6042,7 +6446,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
return 0;
}
- if (l->transfer && sub->xferor && sub->owner->_state >= AST_STATE_RING) {
+ if (l->transfer && sub && sub->xferor && sub->owner->_state >= AST_STATE_RING) {
/* We're allowed to transfer, we have two active calls and
we made at least one of the calls. Let's try and transfer */
handle_transfer_button(sub);
@@ -6051,7 +6455,14 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s", l->name);
- dumpsub(sub, 1);
+ if (sub) {
+ dumpsub(sub, 1);
+ } else { /* No sub, maybe an SLA call */
+ struct skinny_subline *subline;
+ if ((subline = find_subline_by_callid(d, callreference))) {
+ dumpsub(subline->sub, 1);
+ }
+ }
d->hookstate = SKINNY_ONHOOK;
@@ -6062,8 +6473,20 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
case SOFTKEY_RESUME:
if (skinnydebug)
ast_verb(1, "Received Softkey Event: Resume(%d/%d)\n", instance, callreference);
-
- activatesub(sub, SUBSTATE_CONNECTED);
+
+ if (sub) {
+ activatesub(sub, SUBSTATE_CONNECTED);
+ } else { /* No sub, maybe an inactive SLA call */
+ struct skinny_subline *subline;
+ subline = find_subline_by_callid(d, callreference);
+ c = skinny_new(l, subline, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ if (!c) {
+ ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
+ } else {
+ sub = c->tech_pvt;
+ dialandactivatesub(sub, subline->exten);
+ }
+ }
break;
case SOFTKEY_ANSWER:
if (skinnydebug)
@@ -6117,6 +6540,18 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
case SOFTKEY_JOIN:
if (skinnydebug)
ast_verb(1, "Received Softkey Event: Join(%d/%d)\n", instance, callreference);
+ /* this is SLA territory, should not get here unless there is a meetme at subline */
+ {
+ struct skinny_subline *subline;
+ subline = find_subline_by_callid(d, callreference);
+ c = skinny_new(l, subline, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
+ if (!c) {
+ ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
+ } else {
+ sub = c->tech_pvt;
+ dialandactivatesub(sub, subline->exten);
+ }
+ }
break;
case SOFTKEY_MEETME:
/* XXX How is this different from CONFRN? */
@@ -6575,6 +7010,7 @@ static int skinny_devicestate(void *data)
static struct ast_channel *skinny_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause)
{
struct skinny_line *l;
+ struct skinny_subline *subline = NULL;
struct ast_channel *tmpc = NULL;
char tmp[256];
char *dest = data;
@@ -6591,13 +7027,24 @@ static struct ast_channel *skinny_request(const char *type, struct ast_format_ca
}
l = find_line_by_name(tmp);
if (!l) {
- ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
- return NULL;
+ subline = find_subline_by_name(tmp);
+ if (!subline) {
+ ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
+ return NULL;
+ }
+ l = subline->line;
}
ast_verb(3, "skinny_request(%s)\n", tmp);
- tmpc = skinny_new(l, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL, SKINNY_INCOMING);
+ tmpc = skinny_new(l, subline, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL, SKINNY_INCOMING);
if (!tmpc) {
ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
+ } else if (subline) {
+ struct skinny_subchannel *sub = tmpc->tech_pvt;
+ subline->sub = sub;
+ subline->calldirection = SKINNY_INCOMING;
+ subline->substate = SUBSTATE_UNSET;
+ subline->callid = sub->callid;
+ sub->subline = subline;
}
return tmpc;
}
@@ -6947,36 +7394,92 @@ static struct ast_channel *skinny_request(const char *type, struct ast_format_ca
}
continue;
}
+ } else if (!strcasecmp(v->name, "subline")) {
+ if (type & (TYPE_LINE)) {
+ struct skinny_subline *subline;
+ struct skinny_container *container;
+ char buf[256];
+ char *stringp = buf, *exten, *stname, *context;
+
+ if (!(subline = ast_calloc(1, sizeof(*subline)))) {
+ ast_log(LOG_WARNING, "Unable to allocate memory for subline %s. Ignoring subline.\n", v->value);
+ continue;
+ }
+ if (!(container = ast_calloc(1, sizeof(*container)))) {
+ ast_log(LOG_WARNING, "Unable to allocate memory for subline %s container. Ignoring subline.\n", v->value);
+ ast_free(subline);
+ continue;
+ }
+
+ ast_copy_string(buf, v->value, sizeof(buf));
+ exten = strsep(&stringp, "@");
+ ast_copy_string(subline->exten, ast_strip(exten), sizeof(subline->exten));
+ stname = strsep(&exten, "_");
+ ast_copy_string(subline->stname, ast_strip(stname), sizeof(subline->stname));
+ ast_copy_string(subline->lnname, ast_strip(exten), sizeof(subline->lnname));
+ context = strsep(&stringp, ",");
+ ast_copy_string(subline->name, ast_strip(stringp), sizeof(subline->name));
+ ast_copy_string(subline->context, ast_strip(context), sizeof(subline->context));
+
+ subline->line = CLINE;
+ subline->sub = NULL;
+
+ container->type = SKINNY_SUBLINECONTAINER;
+ container->data = subline;
+ subline->container = container;
+ AST_LIST_INSERT_HEAD(&CLINE->sublines, subline, list);
+ continue;
+ }
+ } else if (!strcasecmp(v->name, "dialoutcontext")) {
+ if (type & (TYPE_LINE)) {
+ ast_copy_string(CLINE_OPTS->dialoutcontext, v->value, sizeof(CLINE_OPTS->dialoutcontext));
+ continue;
+ }
+ } else if (!strcasecmp(v->name, "dialoutexten")) {
+ if (type & (TYPE_LINE)) {
+ ast_copy_string(CLINE_OPTS->dialoutexten, v->value, sizeof(CLINE_OPTS->dialoutexten));
+ continue;
+ }
} else if (!strcasecmp(v->name, "speeddial")) {
if (type & (TYPE_DEVICE)) {
struct skinny_speeddial *sd;
+ struct skinny_container *container;
+ char buf[256];
+ char *stringp = buf, *exten, *context, *label;
+
if (!(sd = ast_calloc(1, sizeof(*sd)))) {
ast_log(LOG_WARNING, "Unable to allocate memory for speeddial %s. Ignoring speeddial.\n", v->name);
continue;
- } else {
- char buf[256];
- char *stringp = buf, *exten, *context, *label;
- ast_copy_string(buf, v->value, sizeof(buf));
- exten = strsep(&stringp, ",");
- if ((context = strchr(exten, '@'))) {
- *context++ = '\0';
- }
- label = stringp;
- ast_mutex_init(&sd->lock);
- ast_copy_string(sd->exten, exten, sizeof(sd->exten));
- if (!ast_strlen_zero(context)) {
- sd->isHint = 1;
- sd->instance = lineInstance++;
- ast_copy_string(sd->context, context, sizeof(sd->context));
- } else {
- sd->isHint = 0;
- sd->instance = speeddialInstance++;
- sd->context[0] = '\0';
- }
- ast_copy_string(sd->label, S_OR(label, exten), sizeof(sd->label));
- sd->parent = CDEV;
- AST_LIST_INSERT_HEAD(&CDEV->speeddials, sd, list);
}
+ if (!(container = ast_calloc(1, sizeof(*container)))) {
+ ast_log(LOG_WARNING, "Unable to allocate memory for speeddial %s container. Ignoring speeddial.\n", v->name);
+ ast_free(sd);
+ continue;
+ }
+
+ ast_copy_string(buf, v->value, sizeof(buf));
+ exten = strsep(&stringp, ",");
+ if ((context = strchr(exten, '@'))) {
+ *context++ = '\0';
+ }
+ label = stringp;
+ ast_mutex_init(&sd->lock);
+ ast_copy_string(sd->exten, exten, sizeof(sd->exten));
+ if (!ast_strlen_zero(context)) {
+ sd->isHint = 1;
+ sd->instance = lineInstance++;
+ ast_copy_string(sd->context, context, sizeof(sd->context));
+ } else {
+ sd->isHint = 0;
+ sd->instance = speeddialInstance++;
+ sd->context[0] = '\0';
+ }
+ ast_copy_string(sd->label, S_OR(label, exten), sizeof(sd->label));
+ sd->parent = CDEV;
+ container->type = SKINNY_SDCONTAINER;
+ container->data = sd;
+ sd->container = container;
+ AST_LIST_INSERT_HEAD(&CDEV->speeddials, sd, list);
continue;
}
} else if (!strcasecmp(v->name, "addon")) {
@@ -7005,6 +7508,7 @@ static struct ast_channel *skinny_request(const char *type, struct ast_format_ca
{
struct skinny_line *l, *temp;
int update = 0;
+ struct skinny_container *container;
ast_log(LOG_NOTICE, "Configuring skinny line %s.\n", lname);
@@ -7023,7 +7527,17 @@ static struct ast_channel *skinny_request(const char *type, struct ast_format_ca
AST_LIST_UNLOCK(&lines);
return NULL;
}
+ if (!(container = ast_calloc(1, sizeof(*container)))) {
+ ast_log(LOG_WARNING, "Unable to allocate memory for line %s container.\n", lname);
+ skinny_line_destroy(l);
+ AST_LIST_UNLOCK(&lines);
+ return NULL;
+ }
+ container->type = SKINNY_LINECONTAINER;
+ container->data = l;
+ l->container = container;
+
memcpy(l, default_line, sizeof(*default_line));
ast_mutex_init(&l->lock);
ast_copy_string(l->name, lname, sizeof(l->name));
@@ -7281,6 +7795,7 @@ static void delete_devices(void)
}
/* Delete all speeddials for this device */
while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) {
+ free(sd->container);
free(sd);
}
/* Delete all addons for this device */
diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c
index f4b92330e..8f0cfa59e 100644
--- a/channels/chan_unistim.c
+++ b/channels/chan_unistim.c
@@ -32,6 +32,10 @@
* \ingroup channel_drivers
*/
+/*** MODULEINFO
+ <support_level>extended</support_level>
+ ***/
+
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
diff --git a/channels/chan_usbradio.c b/channels/chan_usbradio.c
index 925629f85..62a26de7f 100644
--- a/channels/chan_usbradio.c
+++ b/channels/chan_usbradio.c
@@ -38,6 +38,7 @@
<depend>alsa</depend>
<depend>usb</depend>
<defaultenabled>no</defaultenabled>
+ <support_level>extended</support_level>
***/
/*** MAKEOPTS
diff --git a/channels/chan_vpb.cc b/channels/chan_vpb.cc
index 0215ab82f..b4e9858ee 100644
--- a/channels/chan_vpb.cc
+++ b/channels/chan_vpb.cc
@@ -31,6 +31,8 @@
/*** MODULEINFO
<depend>vpb</depend>
+ <defaultenabled>no</defaultenabled>
+ <support_level>extended</support_level>
***/
#include <vpbapi.h>
diff --git a/channels/sig_pri.c b/channels/sig_pri.c
index 0204f054a..28ff16ff7 100644
--- a/channels/sig_pri.c
+++ b/channels/sig_pri.c
@@ -1191,7 +1191,7 @@ static void pri_queue_control(struct sig_pri_span *pri, int chanpos, int subclas
/*!
* \internal
* \brief Find the channel associated with the libpri call.
- * \since 1.10
+ * \since 10.0
*
* \param pri PRI span control structure.
* \param call LibPRI opaque call pointer to find.
@@ -1221,7 +1221,7 @@ static int pri_find_principle_by_call(struct sig_pri_span *pri, q931_call *call)
/*!
* \internal
* \brief Kill the call.
- * \since 1.10
+ * \since 10.0
*
* \param pri PRI span control structure.
* \param call LibPRI opaque call pointer to find.
@@ -4358,7 +4358,7 @@ static void sig_pri_handle_subcmds(struct sig_pri_span *pri, int chanpos, int ev
/*!
* \internal
* \brief Convert the MOH state to string.
- * \since 1.10
+ * \since 10.0
*
* \param state MOH state to process.
*
@@ -4409,7 +4409,7 @@ static const char *sig_pri_moh_state_str(enum sig_pri_moh_state state)
/*!
* \internal
* \brief Convert the MOH event to string.
- * \since 1.10
+ * \since 10.0
*
* \param event MOH event to process.
*
@@ -4458,7 +4458,7 @@ static const char *sig_pri_moh_event_str(enum sig_pri_moh_event event)
/*!
* \internal
* \brief Retrieve a call that was placed on hold by the HOLD message.
- * \since 1.10
+ * \since 10.0
*
* \param pvt Channel private control structure.
*
@@ -4500,7 +4500,7 @@ static enum sig_pri_moh_state sig_pri_moh_retrieve_call(struct sig_pri_chan *pvt
/*!
* \internal
* \brief MOH FSM state idle.
- * \since 1.10
+ * \since 10.0
*
* \param chan Channel to post event to (Usually pvt->owner)
* \param pvt Channel private control structure.
@@ -4564,7 +4564,7 @@ static enum sig_pri_moh_state sig_pri_moh_fsm_idle(struct ast_channel *chan, str
/*!
* \internal
* \brief MOH FSM state notify remote party.
- * \since 1.10
+ * \since 10.0
*
* \param chan Channel to post event to (Usually pvt->owner)
* \param pvt Channel private control structure.
@@ -4598,7 +4598,7 @@ static enum sig_pri_moh_state sig_pri_moh_fsm_notify(struct ast_channel *chan, s
/*!
* \internal
* \brief MOH FSM state generate moh.
- * \since 1.10
+ * \since 10.0
*
* \param chan Channel to post event to (Usually pvt->owner)
* \param pvt Channel private control structure.
@@ -4631,7 +4631,7 @@ static enum sig_pri_moh_state sig_pri_moh_fsm_moh(struct ast_channel *chan, stru
/*!
* \internal
* \brief MOH FSM state hold requested.
- * \since 1.10
+ * \since 10.0
*
* \param chan Channel to post event to (Usually pvt->owner)
* \param pvt Channel private control structure.
@@ -4676,7 +4676,7 @@ static enum sig_pri_moh_state sig_pri_moh_fsm_hold_req(struct ast_channel *chan,
/*!
* \internal
* \brief MOH FSM state hold requested with pending unhold.
- * \since 1.10
+ * \since 10.0
*
* \param chan Channel to post event to (Usually pvt->owner)
* \param pvt Channel private control structure.
@@ -4717,7 +4717,7 @@ static enum sig_pri_moh_state sig_pri_moh_fsm_pend_unhold(struct ast_channel *ch
/*!
* \internal
* \brief MOH FSM state hold.
- * \since 1.10
+ * \since 10.0
*
* \param chan Channel to post event to (Usually pvt->owner)
* \param pvt Channel private control structure.
@@ -4759,7 +4759,7 @@ static enum sig_pri_moh_state sig_pri_moh_fsm_hold(struct ast_channel *chan, str
/*!
* \internal
* \brief MOH FSM state retrieve requested.
- * \since 1.10
+ * \since 10.0
*
* \param chan Channel to post event to (Usually pvt->owner)
* \param pvt Channel private control structure.
@@ -4801,7 +4801,7 @@ static enum sig_pri_moh_state sig_pri_moh_fsm_retrieve_req(struct ast_channel *c
/*!
* \internal
* \brief MOH FSM state retrieve requested with pending hold.
- * \since 1.10
+ * \since 10.0
*
* \param chan Channel to post event to (Usually pvt->owner)
* \param pvt Channel private control structure.
@@ -4879,7 +4879,7 @@ static enum sig_pri_moh_state sig_pri_moh_fsm_pend_hold(struct ast_channel *chan
/*!
* \internal
* \brief MOH FSM state retrieve failed.
- * \since 1.10
+ * \since 10.0
*
* \param chan Channel to post event to (Usually pvt->owner)
* \param pvt Channel private control structure.
@@ -4919,7 +4919,7 @@ static enum sig_pri_moh_state sig_pri_moh_fsm_retrieve_fail(struct ast_channel *
/*!
* \internal
* \brief MOH FSM state function type.
- * \since 1.10
+ * \since 10.0
*
* \param chan Channel to post event to (Usually pvt->owner)
* \param pvt Channel private control structure.
@@ -4952,7 +4952,7 @@ static const sig_pri_moh_fsm_state sig_pri_moh_fsm[SIG_PRI_MOH_STATE_NUM] = {
/*!
* \internal
* \brief Send an event to the MOH FSM.
- * \since 1.10
+ * \since 10.0
*
* \param chan Channel to post event to (Usually pvt->owner)
* \param pvt Channel private control structure.
@@ -4994,7 +4994,7 @@ static void sig_pri_moh_fsm_event(struct ast_channel *chan, struct sig_pri_chan
/*!
* \internal
* \brief Post an AMI hold event.
- * \since 1.10
+ * \since 10.0
*
* \param chan Channel to post event to
* \param is_held TRUE if the call was placed on hold.
@@ -5093,7 +5093,7 @@ done_with_private:;
/*!
* \internal
* \brief Handle the hold acknowledge event from libpri.
- * \since 1.10
+ * \since 10.0
*
* \param pri PRI span control structure.
* \param ev Hold acknowledge event received.
@@ -5139,7 +5139,7 @@ static void sig_pri_handle_hold_ack(struct sig_pri_span *pri, pri_event *ev)
/*!
* \internal
* \brief Handle the hold reject event from libpri.
- * \since 1.10
+ * \since 10.0
*
* \param pri PRI span control structure.
* \param ev Hold reject event received.
@@ -5254,7 +5254,7 @@ static void sig_pri_handle_retrieve(struct sig_pri_span *pri, pri_event *ev)
/*!
* \internal
* \brief Handle the retrieve acknowledge event from libpri.
- * \since 1.10
+ * \since 10.0
*
* \param pri PRI span control structure.
* \param ev Retrieve acknowledge event received.
@@ -5287,7 +5287,7 @@ static void sig_pri_handle_retrieve_ack(struct sig_pri_span *pri, pri_event *ev)
/*!
* \internal
* \brief Handle the retrieve reject event from libpri.
- * \since 1.10
+ * \since 10.0
*
* \param pri PRI span control structure.
* \param ev Retrieve reject event received.
@@ -7055,7 +7055,7 @@ static void *pri_dchannel(void *vpri)
/*!
* \brief Output AMI show spans response events for the given PRI span.
- * \since 1.10
+ * \since 10.0
*
* \param show_cmd AMI command name
* \param s AMI session to output span information.
@@ -8844,7 +8844,7 @@ void sig_pri_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, str
#if defined(HAVE_PRI_DISPLAY_TEXT)
/*!
* \brief Send display text.
- * \since 1.10
+ * \since 10.0
*
* \param p Channel to send text over
* \param text Text to send.