[svn-commits] branch north/chan_skinny-fixup r33517 - in
/team/north/chan_skinny-fixup: cha...
svn-commits at lists.digium.com
svn-commits at lists.digium.com
Sun Jun 11 13:58:00 MST 2006
Author: north
Date: Sun Jun 11 15:57:59 2006
New Revision: 33517
URL: http://svn.digium.com/view/asterisk?rev=33517&view=rev
Log:
config file updates
many many changes..
re-added support for subchannels
general restructuring
new items in some of the structs
added "skinny reset <device>" support
a bunch more that I've since forgot
Modified:
team/north/chan_skinny-fixup/channels/chan_skinny.c
team/north/chan_skinny-fixup/configs/skinny.conf.sample
Modified: team/north/chan_skinny-fixup/channels/chan_skinny.c
URL: http://svn.digium.com/view/asterisk/team/north/chan_skinny-fixup/channels/chan_skinny.c?rev=33517&r1=33516&r2=33517&view=diff
==============================================================================
--- team/north/chan_skinny-fixup/channels/chan_skinny.c (original)
+++ team/north/chan_skinny-fixup/channels/chan_skinny.c Sun Jun 11 15:57:59 2006
@@ -70,6 +70,7 @@
#include "asterisk/utils.h"
#include "asterisk/dsp.h"
#include "asterisk/stringfields.h"
+#include "asterisk/astobj.h"
#include "asterisk/abstract_jb.h"
/*************************************
@@ -145,16 +146,28 @@
#define KEYPAD_BUTTON_MESSAGE 0x0003
typedef struct keypad_button_message {
int button;
+ int lineInstance;
+ int callReference;
} keypad_button_message;
#define STIMULUS_MESSAGE 0x0005
typedef struct stimulus_message {
int stimulus;
int stimulusInstance;
+ int unknown1;
} stimulus_message;
#define OFFHOOK_MESSAGE 0x0006
+typedef struct offhook_message {
+ int unknown1;
+ int unknown2;
+} offhook_message;
+
#define ONHOOK_MESSAGE 0x0007
+typedef struct onhook_message {
+ int unknown1;
+ int unknown2;
+} onhook_message;
#define CAPABILITIES_RES_MESSAGE 0x0010
typedef struct station_capabilities {
@@ -187,8 +200,6 @@
#define SERVER_REQUEST_MESSAGE 0x0012
#define ALARM_MESSAGE 0x0020
-/* XXX We never actually use this. Maybe in the future we can.
- I only added it for testing. */
typedef struct alarm_message {
uint32_t alarmSeverity;
char displayMessage[80];
@@ -237,6 +248,8 @@
#define SET_RINGER_MESSAGE 0x0085
typedef struct set_ringer_message {
int ringerMode;
+ int unknown1; /* See notes in transmit_ringer_mode */
+ int unknown2;
} set_ringer_message;
#define SET_LAMP_MESSAGE 0x0086
@@ -408,6 +421,11 @@
int serverListenPort[5];
int serverIpAddr[5];
} server_res_message;
+
+#define RESET_MESSAGE 0x009F
+typedef struct reset_message {
+ uint32_t resetType;
+} reset_message;
#define KEEP_ALIVE_ACK_MESSAGE 0x0100
@@ -661,6 +679,7 @@
soft_key_set_res_message softkeysets;
soft_key_template_res_message softkeytemplate;
server_res_message serverres;
+ reset_message reset;
set_lamp_message setlamp;
set_ringer_message setringer;
call_state_message callstate;
@@ -668,6 +687,8 @@
select_soft_keys_message selectsoftkey;
activate_call_plane_message activatecallplane;
stimulus_message stimulus;
+ offhook_message offhook;
+ onhook_message onhook;
set_speaker_message setspeaker;
call_info_message callinfo;
start_media_transmission_message startmedia;
@@ -852,6 +873,25 @@
/* How long to wait for an extra digit, if there is an ambiguous match */
static int matchdigittimeout = 3000;
+
+struct skinny_subchannel {
+ ast_mutex_t lock;
+ struct ast_channel *owner;
+ struct ast_rtp *rtp;
+ struct ast_rtp *vrtp;
+ unsigned int callid;
+ /* time_t lastouttime; */ /* Unused */
+ int progress;
+ int ringing;
+ /* int lastout; */ /* Unused */
+ int cxmode;
+ int nat;
+ int outgoing;
+ int alreadygone;
+
+ struct skinny_subchannel *next;
+ struct skinny_line *parent;
+};
struct skinny_line {
ast_mutex_t lock;
@@ -888,21 +928,12 @@
int capability;
int nonCodecCapability;
int onhooktime;
- int msgstate; /* voicemail message state */
+ int msgstate; /* voicemail message state */
int immediate;
int hookstate;
- int progress;
- unsigned int callid;
- struct ast_channel *owner;
- struct ast_rtp *rtp;
- time_t lastouttime;
- int ringing;
- int lastout;
- int cxmode;
int nat;
- int outgoing;
- int alreadygone;
-
+
+ struct skinny_subchannel *sub;
struct skinny_line *next;
struct skinny_device *parent;
};
@@ -932,7 +963,8 @@
char version_id[16];
int type;
int registered;
-// char model[10];
+ int lastlineinstance;
+ int lastcallreference;
struct sockaddr_in addr;
struct in_addr ourip;
struct skinny_line *lines;
@@ -1170,6 +1202,54 @@
return NULL;
}
+/* It's quicker/easier to find the subchannel when we know the instance number too */
+static struct skinny_subchannel *find_subchannel_by_instance_reference(struct skinny_device *d, int instance, int reference)
+{
+ struct skinny_line *l = find_line_by_instance(d, instance);
+ struct skinny_subchannel *sub;
+
+ if (!l) {
+ return NULL;
+ }
+
+ for (sub = l->sub; sub; sub = sub->next) {
+ if (sub->callid == reference)
+ break;
+ }
+
+ if (!sub) {
+ ast_log(LOG_WARNING, "Could not find subchannel with reference '%d' on '%s'\n", reference, d->name);
+ }
+ return sub;
+}
+
+/* Find the subchannel when we only have the callid - this shouldn't happen often */
+static struct skinny_subchannel *find_subchannel_by_reference(struct skinny_device *d, int reference)
+{
+ struct skinny_line *l;
+ struct skinny_subchannel *sub = NULL;
+
+ ast_log(LOG_WARNING, "find_subchannel_by_reference: %d\n", reference);
+
+ for (l = d->lines; l; l = l->next) {
+ for (sub = l->sub; sub; sub = sub->next) {
+ if (sub->callid == reference)
+ break;
+ }
+ if (sub)
+ break;
+ }
+
+ if (!l) {
+ ast_log(LOG_WARNING, "Could not find any lines that contained a subchannel with reference '%d' on device '%s'\n", reference, d->name);
+ } else {
+ if (!sub) {
+ ast_log(LOG_WARNING, "Could not find subchannel with reference '%d' on '%s@%s'\n", reference, l->name, d->name);
+ }
+ }
+ return sub;
+}
+
static struct skinny_speeddial *find_speeddial_by_instance(struct skinny_device *d, int instance)
{
struct skinny_speeddial *sd;
@@ -1249,21 +1329,21 @@
if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
return;
- req->data.activatecallplane.lineInstance = 0;
+ req->data.activatecallplane.lineInstance = htolel(instance);
transmit_response(s, req);
if (!(req = req_alloc(sizeof(struct close_receive_channel_message), CLOSE_RECEIVE_CHANNEL_MESSAGE)))
return;
req->data.closereceivechannel.conferenceId = 0;
- req->data.closereceivechannel.partyId = 0;
+ req->data.closereceivechannel.partyId = htolel(callid);
transmit_response(s, req);
if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
return;
req->data.stopmedia.conferenceId = 0;
- req->data.stopmedia.passThruPartyId = 0;
+ req->data.stopmedia.passThruPartyId = htolel(callid);
transmit_response(s, req);
}
}
@@ -1293,16 +1373,16 @@
transmit_response(s, req);
}
-static void transmit_connect(struct skinnysession *s)
+static void transmit_connect(struct skinnysession *s, struct skinny_subchannel *sub)
{
skinny_req *req;
- struct skinny_line *l = s->device->lines;
+ struct skinny_line *l = sub->parent;
if (!(req = req_alloc(sizeof(struct open_receive_channel_message), OPEN_RECEIVE_CHANNEL_MESSAGE)))
return;
req->data.openreceivechannel.conferenceId = 0;
- req->data.openreceivechannel.partyId = 0;
+ req->data.openreceivechannel.partyId = htolel(sub->callid);
req->data.openreceivechannel.packets = htolel(20);
req->data.openreceivechannel.capability = htolel(convert_cap(l->capability));
req->data.openreceivechannel.echo = 0;
@@ -1313,10 +1393,10 @@
static void transmit_tone(struct skinnysession *s, int tone)
{
skinny_req *req;
+ struct skinny_device *d = s->device;
if (tone == SKINNY_NOTONE) {
- if (skinnydebug)
- ast_verbose("I almost sent a SKINNY_NOTONE to device '%s'. I think this causes some devices to reset.\n", s->device->name);
+ /* This is bad, mmm'kay? */
return;
}
@@ -1330,8 +1410,6 @@
if (tone > 0) {
req->data.starttone.tone = htolel(tone);
- } else {
-// req->len = htolel(4);
}
transmit_response(s, req);
}
@@ -1373,10 +1451,18 @@
if (!(req = req_alloc(sizeof(struct set_ringer_message), SET_RINGER_MESSAGE)))
return;
- /* XXX I don't know why, but my phone reboots unless I set this. */
- req->len = htolel(0);
-
req->data.setringer.ringerMode = htolel(mode);
+ /* XXX okay, I don't quite know what this is, but here's what happens (on a 7960).
+ Note: The phone will always show as ringing on the display.
+
+ 1: phone will audibly ring over and over
+ 2: phone will audibly ring only once
+ any other value, will NOT cause the phone to audibly ring
+ */
+ req->data.setringer.unknown1 = htolel(1);
+ /* XXX the value here doesn't seem to change anything. Must be higher than 0.
+ Perhaps a packet capture can shed some light on this. */
+ req->data.setringer.unknown2 = htolel(1);
transmit_response(s, req);
}
@@ -1459,7 +1545,8 @@
{
int new;
int old;
- struct skinny_line *l = s->device->lines;
+ struct skinny_device *d = s->device;
+ struct skinny_line *l = d->lines;
transmit_displaymessage(s, NULL);
@@ -1467,10 +1554,10 @@
while (l) {
if (has_voicemail(l)) {
if (skinnydebug)
- ast_verbose("Checking for voicemail Skinny %s@%s\n", l->name, l->parent->name);
+ ast_verbose("Checking for voicemail Skinny %s@%s\n", l->name, d->name);
ast_app_inboxcount(l->mailbox, &new, &old);
if (skinnydebug)
- ast_verbose("Skinny %s@%s has voicemail!\n", l->name, l->parent->name);
+ ast_verbose("Skinny %s@%s has voicemail!\n", l->name, d->name);
transmit_lamp_indication(s, STIMULUS_VOICEMAIL, l->instance, l->mwiblink?SKINNY_LAMP_BLINK:SKINNY_LAMP_ON);
} else {
transmit_lamp_indication(s, STIMULUS_VOICEMAIL, l->instance, SKINNY_LAMP_OFF);
@@ -1485,25 +1572,30 @@
/* Yes, it can. Currently 7985 and Cisco VT Advantage do video. */
static struct ast_rtp *skinny_get_vrtp_peer(struct ast_channel *chan)
{
+ struct skinny_subchannel *sub;
+ sub = chan->tech_pvt;
+ if (sub && sub->vrtp) {
+ return sub->vrtp;
+ }
return NULL;
}
static struct ast_rtp *skinny_get_rtp_peer(struct ast_channel *chan)
{
- struct skinny_line *l;
- l = chan->tech_pvt;
- if (l && l->rtp) {
- return l->rtp;
+ struct skinny_subchannel *sub;
+ sub = chan->tech_pvt;
+ if (sub && sub->rtp) {
+ return sub->rtp;
}
return NULL;
}
static int skinny_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
{
- struct skinny_line *l;
- l = chan->tech_pvt;
- if (l) {
- /* transmit_modify_with_sdp(l, rtp); @@FIXME@@ if needed */
+ struct skinny_subchannel *sub;
+ sub = chan->tech_pvt;
+ if (sub) {
+ /* transmit_modify_with_sdp(sub, rtp); @@FIXME@@ if needed */
return 0;
}
return -1;
@@ -1533,6 +1625,60 @@
}
skinnydebug = 0;
ast_cli(fd, "Skinny Debugging Disabled\n");
+ return RESULT_SUCCESS;
+}
+
+static char *complete_skinny_reset(const char *line, const char *word, int pos, int state)
+{
+ struct skinny_device *d;
+
+ char *result = NULL;
+ int wordlen = strlen(word);
+ int which = 0;
+
+ if (pos == 2) {
+ for (d = devices; d && !result; d = d->next) {
+ if (!strncasecmp(word, d->id, wordlen) && ++which > state)
+ result = ast_strdup(d->id);
+ }
+ }
+
+ return result;
+}
+
+static int skinny_reset_device(int fd, int argc, char *argv[])
+{
+ struct skinny_device *d;
+ skinny_req *req;
+
+ if (argc < 3 || argc > 4) {
+ return RESULT_SHOWUSAGE;
+ }
+ ast_mutex_lock(&devicelock);
+
+ for (d = devices; d; d = d->next) {
+ int fullrestart = 0;
+ if (!strcasecmp(argv[2], d->id) || !strcasecmp(argv[2], "all")) {
+ if (!(d->session))
+ continue;
+
+ if (!(req = req_alloc(sizeof(struct reset_message), RESET_MESSAGE)))
+ continue;
+
+ if (argc == 4 && !strcasecmp(argv[3], "restart"))
+ fullrestart = 1;
+
+ if (fullrestart)
+ req->data.reset.resetType = 2;
+ else
+ req->data.reset.resetType = 1;
+
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "%s device %s.\n", (fullrestart) ? "Restarting" : "Resetting", d->id);
+ transmit_response(d->session, req);
+ }
+ }
+ ast_mutex_unlock(&devicelock);
return RESULT_SUCCESS;
}
@@ -1581,22 +1727,40 @@
ast_mutex_lock(&devicelock);
d = devices;
+#if 0
ast_cli(fd, "Device Name Instance Name Label O R\n");
ast_cli(fd, "-------------------- -------- -------------------- -------------------- - -\n");
while(d) {
l = d->lines;
while (l) {
ast_cli(fd, "%-20s %8d %-20s %-20s %c %c\n",
- l->parent->name,
+ d->name,
l->instance,
l->name,
l->label,
- l->owner?'Y':'N',
- l->rtp?'Y':'N');
+ sub->owner?'Y':'N',
+ sub->rtp?'Y':'N');
l = l->next;
}
d = d->next;
}
+#else
+ ast_cli(fd, "Device Name Instance Name Label \n");
+ ast_cli(fd, "-------------------- -------- -------------------- --------------------\n");
+ while(d) {
+ l = d->lines;
+ while (l) {
+ ast_cli(fd, "%-20s %8d %-20s %-20s\n",
+ d->name,
+ l->instance,
+ l->name,
+ l->label);
+ l = l->next;
+ }
+ d = d->next;
+ }
+#endif
+
ast_mutex_unlock(&devicelock);
return RESULT_SUCCESS;
}
@@ -1617,6 +1781,10 @@
"Usage: skinny no debug\n"
" Disables dumping of Skinny packets for debugging purposes\n";
+static char reset_usage[] =
+"Usage: skinny reset <DeviceId|all> [restart]\n"
+" Causes a Skinny device to reset itself, optionally with a full restart\n";
+
static struct ast_cli_entry cli_show_devices =
{ { "skinny", "show", "devices", NULL }, skinny_show_devices, "Show defined Skinny devices", show_devices_usage };
@@ -1628,6 +1796,9 @@
static struct ast_cli_entry cli_no_debug =
{ { "skinny", "no", "debug", NULL }, skinny_no_debug, "Disable Skinny debugging", no_debug_usage };
+
+static struct ast_cli_entry cli_reset_device =
+ { { "skinny", "reset", NULL }, skinny_reset_device, "Reset Skinny device(s)", reset_usage, complete_skinny_reset };
#if 0
static struct skinny_paging_device *build_paging_device(char *cat, struct ast_variable *v)
@@ -1644,12 +1815,14 @@
struct skinny_addon *a;
int lineInstance = 1;
int speeddialInstance = 1;
- int y=0;
-
- d = malloc(sizeof(struct skinny_device));
- if (d) {
- memset(d, 0, sizeof(struct skinny_device));
+ int y = 0;
+
+ d = ast_calloc(1, sizeof(struct skinny_device));
+ if (!d) {
+ return NULL;
+ } else {
ast_copy_string(d->name, cat, sizeof(d->name));
+ d->lastlineinstance = 1;
while(v) {
if (!strcasecmp(v->name, "host")) {
if (ast_get_ip(&d->addr, v->value)) {
@@ -1668,8 +1841,6 @@
ast_copy_string(d->version_id, v->value, sizeof(d->version_id));
} else if (!strcasecmp(v->name, "nat")) {
nat = ast_true(v->value);
-// } else if (!strcasecmp(v->name, "model")) {
-// ast_copy_string(d->model, v->value, sizeof(d->model));
} else if (!strcasecmp(v->name, "callerid")) {
if (!strcasecmp(v->value, "asreceived")) {
cid_num[0] = '\0';
@@ -1715,9 +1886,17 @@
} else if (!strcasecmp(v->name, "speeddial")) {
sd = malloc(sizeof(struct skinny_speeddial));
if (sd) {
+ char *stringp, *exten, *label;
+ stringp = v->value;
+ exten = strsep(&stringp, ",");
+ label = strsep(&stringp, ",");
memset(sd, 0, sizeof(struct skinny_speeddial));
ast_mutex_init(&sd->lock);
- ast_copy_string(sd->exten, v->value, sizeof(sd->exten));
+ ast_copy_string(sd->exten, exten, sizeof(sd->exten));
+ if (label)
+ ast_copy_string(sd->label, label, sizeof(sd->label));
+ else
+ ast_copy_string(sd->label, exten, sizeof(sd->label));
sd->instance = speeddialInstance++;
sd->next = d->speeddials;
@@ -1782,10 +1961,6 @@
l->instance = lineInstance++;
/* ASSUME we're onhook at this point */
l->hookstate = SKINNY_ONHOOK;
- /* Make a call*ID */
- l->callid = callnums;
- callnums++;
- l->cxmode = SKINNY_CX_INACTIVE;
l->nat = nat;
l->next = d->lines;
@@ -1844,27 +2019,45 @@
return 1;
}
-static void start_rtp(struct skinny_line *l)
-{
- ast_mutex_lock(&l->lock);
+static int skinny_unregister(skinny_req *req, struct skinnysession *s)
+{
+ struct skinny_device *d;
+
+ d = s->device;
+
+ if (d) {
+ d->session = NULL;
+ d->registered = 0;
+ }
+
+ return -1; /* main loop will destroy the session */
+}
+
+static void start_rtp(struct skinny_subchannel *sub)
+{
+ struct skinny_line *l = sub->parent;
+ struct skinny_device *d = l->parent;
+ ast_mutex_lock(&sub->lock);
/* Allocate the RTP */
- l->rtp = ast_rtp_new(sched, io, 1, 0);
- if (l->rtp && l->owner) {
- l->owner->fds[0] = ast_rtp_fd(l->rtp);
- }
- if (l->rtp) {
- ast_rtp_setnat(l->rtp, l->nat);
+ sub->rtp = ast_rtp_new(sched, io, 1, 0);
+ if (sub->rtp && sub->owner) {
+ sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
+ }
+ if (sub->rtp) {
+ ast_rtp_setnat(sub->rtp, l->nat);
}
/* Create the RTP connection */
- transmit_connect(l->parent->session);
- ast_mutex_unlock(&l->lock);
+ transmit_connect(d->session, sub);
+ ast_mutex_unlock(&sub->lock);
}
static void *skinny_ss(void *data)
{
struct ast_channel *chan = data;
- struct skinny_line *l = chan->tech_pvt;
- struct skinnysession *s = l->parent->session;
+ struct skinny_subchannel *sub = chan->tech_pvt;
+ struct skinny_line *l = sub->parent;
+ struct skinny_device *d = l->parent;
+ struct skinnysession *s = d->session;
char exten[AST_MAX_EXTENSION] = "";
int len = 0;
int timeout = firstdigittimeout;
@@ -1872,13 +2065,13 @@
int getforward=0;
if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s@%s'\n", l->name, l->parent->name);
+ ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s@%s'\n", l->name, d->name);
while (len < AST_MAX_EXTENSION-1) {
res = ast_waitfordigit(chan, timeout);
timeout = 0;
if (res < 0) {
if (skinnydebug)
- ast_verbose("Skinny(%s@%s): waitfordigit returned < 0\n", l->name, l->parent->name);
+ ast_verbose("Skinny(%s@%s): waitfordigit returned < 0\n", l->name, d->name);
ast_indicate(chan, -1);
ast_hangup(chan);
return NULL;
@@ -1935,122 +2128,6 @@
transmit_tone(s, SKINNY_REORDER);
ast_hangup(chan);
return NULL;
- } else if (!strcmp(exten,ast_pickup_ext())) {
- /* Scan all channels and see if any there
- * ringing channels with that have call groups
- * that equal this channels pickup group
- */
- if (ast_pickup_call(chan)) {
- ast_log(LOG_WARNING, "No call pickup possible...\n");
- transmit_tone(s, SKINNY_REORDER);
- }
- ast_hangup(chan);
- return NULL;
- } else if (!strcmp(exten, ast_parking_ext()) &&
- l->next && l->next->owner &&
- ast_bridged_channel(l->next->owner)) {
- /* This is a three way call, the main call being a real channel,
- and we're parking the first call. */
- ast_masq_park_call(ast_bridged_channel(l->next->owner), chan, 0, NULL);
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
- break;
- } else if (!ast_strlen_zero(l->lastcallerid) && !strcmp(exten, "*60")) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", l->lastcallerid);
- res = ast_db_put("blacklist", l->lastcallerid, "1");
- if (!res) {
- transmit_tone(s, SKINNY_DIALTONE);
- memset(exten, 0, sizeof(exten));
- len = 0;
- }
- } else if (!l->hidecallerid && !strcmp(exten, "*67")) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
- /* Disable Caller*ID if enabled */
- l->hidecallerid = 1;
- if (chan->cid.cid_num) {
- free(chan->cid.cid_num);
- }
- chan->cid.cid_num = NULL;
- if (chan->cid.cid_name) {
- free(chan->cid.cid_name);
- }
- chan->cid.cid_name = NULL;
- transmit_tone(s, SKINNY_DIALTONE);
- len = 0;
- memset(exten, 0, sizeof(exten));
- timeout = firstdigittimeout;
- } else if (l->callreturn && !strcmp(exten, "*69")) {
- res = 0;
- if (!ast_strlen_zero(l->lastcallerid)) {
- res = ast_say_digit_str(chan, l->lastcallerid, "", chan->language);
- }
- if (!res) {
- transmit_tone(s, SKINNY_DIALTONE);
- }
- break;
- } else if (l->callwaiting && !strcmp(exten, "*70")) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
- /* Disable call waiting if enabled */
- l->callwaiting = 0;
- transmit_tone(s, SKINNY_DIALTONE);
- len = 0;
- memset(exten, 0, sizeof(exten));
- timeout = firstdigittimeout;
- } else if (l->cancallforward && !strcmp(exten, "*72")) {
- transmit_tone(s, SKINNY_DIALTONE);
- getforward = 1;
- memset(exten, 0, sizeof(exten));
- len = 0;
- } else if (l->cancallforward && !strcmp(exten, "*73")) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %s\n", chan->name);
- transmit_tone(s, SKINNY_DIALTONE);
- memset(l->call_forward, 0, sizeof(l->call_forward));
- getforward = 0;
- memset(exten, 0, sizeof(exten));
- len = 0;
- } else if (!strcmp(exten, "*78")) {
- /* Do not disturb */
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %s\n", chan->name);
- transmit_tone(s, SKINNY_DIALTONE);
- l->dnd = 1;
- getforward = 0;
- memset(exten, 0, sizeof(exten));
- len = 0;
- } else if (!strcmp(exten, "*79")) {
- /* Do not disturb */
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %s\n", chan->name);
- transmit_tone(s, SKINNY_DIALTONE);
- l->dnd = 0;
- getforward = 0;
- memset(exten, 0, sizeof(exten));
- len = 0;
- } else if (l->hidecallerid && !strcmp(exten, "*82")) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
- /* Enable Caller*ID if enabled */
- l->hidecallerid = 0;
- if (chan->cid.cid_num) {
- free(chan->cid.cid_num);
- }
- if (!ast_strlen_zero(l->cid_num)) {
- chan->cid.cid_num = strdup(l->cid_num);
- }
- if (chan->cid.cid_name) {
- free(chan->cid.cid_name);
- }
- if (!ast_strlen_zero(l->cid_name)) {
- chan->cid.cid_name = strdup(l->cid_name);
- }
- transmit_tone(s, SKINNY_DIALTONE);
- len = 0;
- memset(exten, 0, sizeof(exten));
- timeout = firstdigittimeout;
} else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
((exten[0] != '*') || (!ast_strlen_zero(exten) > 2))) {
ast_log(LOG_WARNING, "Can't match [%s] from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
@@ -2076,13 +2153,12 @@
{
int res = 0;
int tone = 0;
- struct skinny_line *l;
- struct skinnysession *session;
-
- l = ast->tech_pvt;
- session = l->parent->session;
-
- if (!l->parent->registered) {
+ struct skinny_subchannel *sub = ast->tech_pvt;
+ struct skinny_line *l = sub->parent;
+ struct skinny_device *d = l->parent;
+ struct skinnysession *session = d->session;
+
+ if (!d->registered) {
ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
return -1;
}
@@ -2116,37 +2192,42 @@
transmit_ringer_mode(session, SKINNY_RING_INSIDE);
transmit_tone(session, tone);
- transmit_callstate(session, l->instance, SKINNY_RINGIN, l->callid);
- transmit_displaypromptstatus(session, "Ring-In", 0, l->instance, l->callid);
- transmit_callinfo(session, ast->cid.cid_name, ast->cid.cid_num, l->cid_name, l->cid_num, l->instance, l->callid, 1);
- transmit_selectsoftkeys(session, l->instance, l->callid, KEYDEF_RINGIN);
+ transmit_callstate(session, l->instance, SKINNY_RINGIN, sub->callid);
+ transmit_displaypromptstatus(session, "Ring-In", 0, l->instance, sub->callid);
+ transmit_callinfo(session, ast->cid.cid_name, ast->cid.cid_num, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
+ transmit_selectsoftkeys(session, l->instance, sub->callid, KEYDEF_RINGIN);
ast_setstate(ast, AST_STATE_RINGING);
ast_queue_control(ast, AST_CONTROL_RINGING);
- l->outgoing = 1;
+ sub->outgoing = 1;
return res;
}
static int skinny_hangup(struct ast_channel *ast)
{
- struct skinny_line *l = ast->tech_pvt;
- struct skinnysession *s = l->parent->session;
-
- if (skinnydebug)
- ast_verbose("skinny_hangup(%s) on %s@%s\n", ast->name, l->name, l->parent->name);
- if (!ast->tech_pvt) {
+ struct skinny_subchannel *sub = ast->tech_pvt;
+ struct skinny_line *l;
+ struct skinny_device *d;
+ struct skinnysession *s;
+
+ if (!sub) {
ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
return 0;
}
-
- if (l->parent->registered) {
+ l = sub->parent;
+ d = l->parent;
+ s = d->session;
+ if (skinnydebug)
+ ast_verbose("skinny_hangup(%s) on %s@%s\n", ast->name, l->name, d->name);
+
+ if (d->registered) {
if ((l->type = TYPE_LINE) && (l->hookstate == SKINNY_OFFHOOK)) {
l->hookstate = SKINNY_ONHOOK;
- transmit_callstate(s, l->instance, SKINNY_ONHOOK, l->callid);
+ transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid);
transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
} else if ((l->type = TYPE_LINE) && (l->hookstate == SKINNY_ONHOOK)) {
- transmit_callstate(s, l->instance, SKINNY_ONHOOK, l->callid);
+ transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid);
transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
transmit_ringer_mode(s, SKINNY_RING_OFF);
transmit_tone(s, SKINNY_SILENCE);
@@ -2154,53 +2235,57 @@
do_housekeeping(s);
}
}
- ast_mutex_lock(&l->lock);
- l->owner = NULL;
+ ast_mutex_lock(&sub->lock);
+ sub->owner = NULL;
ast->tech_pvt = NULL;
- l->alreadygone = 0;
- l->outgoing = 0;
- if (l->rtp) {
- ast_rtp_destroy(l->rtp);
- l->rtp = NULL;
- }
- ast_mutex_unlock(&l->lock);
+ sub->alreadygone = 0;
+ sub->outgoing = 0;
+ if (sub->rtp) {
+ ast_rtp_destroy(sub->rtp);
+ sub->rtp = NULL;
+ }
+ ast_mutex_unlock(&sub->lock);
return 0;
}
static int skinny_answer(struct ast_channel *ast)
{
int res = 0;
- struct skinny_line *l = ast->tech_pvt;
- struct skinnysession *s = l->parent->session;
-
- l->cxmode = SKINNY_CX_SENDRECV;
- if (!l->rtp) {
- start_rtp(l);
+ struct skinny_subchannel *sub = ast->tech_pvt;
+ struct skinny_line *l = sub->parent;
+ struct skinny_device *d = l->parent;
+ struct skinnysession *s = d->session;
+
+ sub->cxmode = SKINNY_CX_SENDRECV;
+ if (!sub->rtp) {
+ start_rtp(sub);
}
if (skinnydebug)
- ast_verbose("skinny_answer(%s) on %s@%s-%d\n", ast->name, l->name, l->parent->name, l->callid);
+ ast_verbose("skinny_answer(%s) on %s@%s-%d\n", ast->name, l->name, d->name, sub->callid);
if (ast->_state != AST_STATE_UP) {
ast_setstate(ast, AST_STATE_UP);
}
transmit_tone(s, SKINNY_NOTONE);
- transmit_callstate(s, l->instance, SKINNY_CONNECTED, l->callid);
- transmit_displaypromptstatus(s, "Connected", 0, l->instance, l->callid);
+ transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid);
+ transmit_displaypromptstatus(s, "Connected", 0, l->instance, sub->callid);
return res;
}
-static struct ast_frame *skinny_rtp_read(struct skinny_line *l)
-{
- /* Retrieve audio/etc from channel. Assumes l->lock is already held. */
+/* Retrieve audio/etc from channel. Assumes sub->lock is already held. */
+static struct ast_frame *skinny_rtp_read(struct skinny_subchannel *sub)
+{
+ struct ast_channel *ast = sub->owner;
struct ast_frame *f;
- f = ast_rtp_read(l->rtp);
- if (l->owner) {
+
+ f = ast_rtp_read(sub->rtp);
+ if (ast) {
/* We already hold the channel lock */
if (f->frametype == AST_FRAME_VOICE) {
- if (f->subclass != l->owner->nativeformats) {
+ if (f->subclass != ast->nativeformats) {
ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
- l->owner->nativeformats = f->subclass;
- ast_set_read_format(l->owner, l->owner->readformat);
- ast_set_write_format(l->owner, l->owner->writeformat);
+ ast->nativeformats = f->subclass;
+ ast_set_read_format(ast, ast->readformat);
+ ast_set_write_format(ast, ast->writeformat);
}
}
}
@@ -2210,16 +2295,16 @@
static struct ast_frame *skinny_read(struct ast_channel *ast)
{
struct ast_frame *fr;
- struct skinny_line *l = ast->tech_pvt;
- ast_mutex_lock(&l->lock);
- fr = skinny_rtp_read(l);
- ast_mutex_unlock(&l->lock);
+ struct skinny_subchannel *sub = ast->tech_pvt;
+ ast_mutex_lock(&sub->lock);
+ fr = skinny_rtp_read(sub);
+ ast_mutex_unlock(&sub->lock);
return fr;
}
static int skinny_write(struct ast_channel *ast, struct ast_frame *frame)
{
- struct skinny_line *l = ast->tech_pvt;
+ struct skinny_subchannel *sub = ast->tech_pvt;
int res = 0;
if (frame->frametype != AST_FRAME_VOICE) {
if (frame->frametype == AST_FRAME_IMAGE) {
@@ -2235,36 +2320,38 @@
return -1;
}
}
- if (l) {
- ast_mutex_lock(&l->lock);
- if (l->rtp) {
- res = ast_rtp_write(l->rtp, frame);
- }
- ast_mutex_unlock(&l->lock);
+ if (sub) {
+ ast_mutex_lock(&sub->lock);
+ if (sub->rtp) {
+ res = ast_rtp_write(sub->rtp, frame);
+ }
+ ast_mutex_unlock(&sub->lock);
}
return res;
}
static int skinny_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
{
- struct skinny_line *l = newchan->tech_pvt;
+ struct skinny_subchannel *sub = newchan->tech_pvt;
ast_log(LOG_NOTICE, "skinny_fixup(%s, %s)\n", oldchan->name, newchan->name);
- if (l->owner != oldchan) {
- ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, l->owner);
+ if (sub->owner != oldchan) {
+ ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
return -1;
}
- l->owner = newchan;
+ sub->owner = newchan;
return 0;
}
static int skinny_senddigit(struct ast_channel *ast, char digit)
{
#if 0
- struct skinny_line *l = ast->tech_pvt;
+ struct skinny_subchannel *sub = ast->tech_pvt;
+ struct skinny_line *l = sub->parent;
+ struct skinny_device *d = l->parent;
int tmp;
/* not right */
sprintf(tmp, "%d", digit);
- transmit_tone(l->parent->session, digit);
+ transmit_tone(d->session, digit);
#endif
return -1;
}
@@ -2317,21 +2404,23 @@
static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen)
{
- struct skinny_line *l = ast->tech_pvt;
- struct skinnysession *s = l->parent->session;
+ struct skinny_subchannel *sub = ast->tech_pvt;
+ struct skinny_line *l = sub->parent;
+ struct skinny_device *d = l->parent;
+ struct skinnysession *s = d->session;
if (skinnydebug)
ast_verbose(VERBOSE_PREFIX_3 "Asked to indicate '%s' condition on channel %s\n", control2str(ind), ast->name);
switch(ind) {
case AST_CONTROL_RINGING:
if (ast->_state != AST_STATE_UP) {
- if (!l->progress) {
+ if (!sub->progress) {
transmit_tone(s, SKINNY_ALERT);
- transmit_callstate(s, l->instance, SKINNY_RINGOUT, l->callid);
- transmit_dialednumber(s, ast->exten, l->instance, l->callid);
- transmit_displaypromptstatus(s, "Ring Out", 0, l->instance, l->callid);
- transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, ast->exten, ast->exten, l->instance, l->callid, 2); /* 2 = outgoing from phone */
- l->ringing = 1;
+ transmit_callstate(s, l->instance, SKINNY_RINGOUT, sub->callid);
+ transmit_dialednumber(s, ast->exten, l->instance, sub->callid);
+ transmit_displaypromptstatus(s, "Ring Out", 0, l->instance, sub->callid);
+ transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, ast->exten, ast->exten, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
+ sub->ringing = 1;
break;
}
}
@@ -2339,8 +2428,8 @@
case AST_CONTROL_BUSY:
if (ast->_state != AST_STATE_UP) {
transmit_tone(s, SKINNY_BUSYTONE);
- transmit_callstate(s, l->instance, SKINNY_BUSY, l->callid);
- l->alreadygone = 1;
+ transmit_callstate(s, l->instance, SKINNY_BUSY, sub->callid);
+ sub->alreadygone = 1;
ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
break;
}
@@ -2348,19 +2437,19 @@
case AST_CONTROL_CONGESTION:
if (ast->_state != AST_STATE_UP) {
transmit_tone(s, SKINNY_REORDER);
- transmit_callstate(s, l->instance, SKINNY_CONGESTION, l->callid);
- l->alreadygone = 1;
+ transmit_callstate(s, l->instance, SKINNY_CONGESTION, sub->callid);
+ sub->alreadygone = 1;
ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
break;
}
return -1;
case AST_CONTROL_PROGRESS:
- if ((ast->_state != AST_STATE_UP) && !l->progress && !l->outgoing) {
+ if ((ast->_state != AST_STATE_UP) && !sub->progress && !sub->outgoing) {
transmit_tone(s, SKINNY_ALERT);
- transmit_callstate(s, l->instance, SKINNY_PROGRESS, l->callid);
- transmit_displaypromptstatus(s, "Call Progress", 0, l->instance, l->callid);
- transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, ast->exten, ast->exten, l->instance, l->callid, 2); /* 2 = outgoing from phone */
- l->progress = 1;
+ transmit_callstate(s, l->instance, SKINNY_PROGRESS, sub->callid);
+ transmit_displaypromptstatus(s, "Call Progress", 0, l->instance, sub->callid);
+ transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, ast->exten, ast->exten, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
+ sub->progress = 1;
break;
}
return -1;
@@ -2379,19 +2468,44 @@
static struct ast_channel *skinny_new(struct skinny_line *l, int state)
{
struct ast_channel *tmp;
+ struct skinny_subchannel *sub;
+ struct skinny_device *d = l->parent;
int fmt;
+
tmp = ast_channel_alloc(1);
- if (tmp) {
+ if (!tmp) {
+ ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
+ return NULL;
+ } else {
+ sub = ast_calloc(1, sizeof(struct skinny_subchannel));
+ if (!sub) {
+ ast_log(LOG_WARNING, "Unable to allocate Skinny subchannel\n");
+ return NULL;
+ } else {
+ ast_mutex_init(&sub->lock);
+
+ sub->owner = tmp;
+ sub->callid = callnums++;
+ d->lastlineinstance = l->instance;
+ d->lastcallreference = sub->callid;
+ sub->cxmode = SKINNY_CX_INACTIVE;
+ sub->nat = l->nat;
+ sub->parent = l;
+
+ sub->next = l->sub;
+ l->sub = sub;
+ }
tmp->tech = &skinny_tech;
+ tmp->tech_pvt = sub;
tmp->nativeformats = l->capability;
if (!tmp->nativeformats)
tmp->nativeformats = capability;
fmt = ast_best_codec(tmp->nativeformats);
if (skinnydebug)
ast_verbose("skinny_new: tmp->nativeformats=%d fmt=%d\n", tmp->nativeformats, fmt);
- ast_string_field_build(tmp, name, "Skinny/%s@%s-%d", l->name, l->parent->name, l->callid);
- if (l->rtp) {
- tmp->fds[0] = ast_rtp_fd(l->rtp);
+ ast_string_field_build(tmp, name, "Skinny/%s@%s-%d", l->name, d->name, sub->callid);
+ if (sub->rtp) {
+ tmp->fds[0] = ast_rtp_fd(sub->rtp);
}
ast_setstate(tmp, state);
if (state == AST_STATE_RING) {
@@ -2401,14 +2515,13 @@
tmp->rawwriteformat = fmt;
tmp->readformat = fmt;
tmp->rawreadformat = fmt;
- tmp->tech_pvt = l;
if (!ast_strlen_zero(l->language))
ast_string_field_set(tmp, language, l->language);
if (!ast_strlen_zero(l->accountcode))
ast_string_field_set(tmp, accountcode, l->accountcode);
if (l->amaflags)
tmp->amaflags = l->amaflags;
- l->owner = tmp;
+
ast_mutex_lock(&usecnt_lock);
usecnt++;
ast_mutex_unlock(&usecnt_lock);
@@ -2417,7 +2530,7 @@
tmp->pickupgroup = l->pickupgroup;
ast_string_field_set(tmp, call_forward, l->call_forward);
ast_copy_string(tmp->context, l->context, sizeof(tmp->context));
- ast_copy_string(tmp->exten,l->exten, sizeof(tmp->exten));
+ ast_copy_string(tmp->exten, l->exten, sizeof(tmp->exten));
tmp->cid.cid_num = ast_strdup(l->cid_num);
tmp->cid.cid_name = ast_strdup(l->cid_name);
tmp->priority = 1;
@@ -2432,10 +2545,8 @@
}
/* Configure the new channel jb */
- if (tmp && l && l->rtp)
+ if (tmp && sub->rtp)
ast_jb_configure(tmp, &global_jbconf);
- } else {
- ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
}
return tmp;
}
@@ -2455,10 +2566,11 @@
char name[16];
int res;
+ memcpy(&name, req->data.reg.name, sizeof(name));
+
res = skinny_register(req, s);
if (!res) {
- ast_log(LOG_ERROR, "Rejecting Device %s: Device not found\n", req->data.reg.name);
- memcpy(&name, req->data.reg.name, sizeof(req->data.reg.name));
+ ast_log(LOG_ERROR, "Rejecting Device %s: Device not found\n", name);
if (!(req = req_alloc(sizeof(register_rej_message), REGISTER_REJ_MESSAGE)))
return -1;
@@ -2467,7 +2579,7 @@
return 0;
}
if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Device '%s' successfully registered\n", s->device->name);
+ ast_verbose(VERBOSE_PREFIX_3 "Device '%s' successfully registered\n", name);
if (!(req = req_alloc(sizeof(register_ack_message), REGISTER_ACK_MESSAGE)))
return -1;
@@ -2499,12 +2611,17 @@
static int handle_keypad_button_message(skinny_req *req, struct skinnysession *s)
{
+ struct skinny_subchannel *sub = NULL;
struct skinny_line *l;
struct ast_frame f = { 0, };
char d;
int digit;
+ int lineInstance;
+ int callReference;
digit = letohl(req->data.keypad.button);
+ lineInstance = letohl(req->data.keypad.lineInstance);
+ callReference = letohl(req->data.keypad.callReference);
f.frametype = AST_FRAME_DTMF;
if (digit == 14) {
d = '*';
@@ -2525,12 +2642,20 @@
}
f.subclass = d;
f.src = "skinny";
- l = s->device->lines;
- if (l->owner) {
+
+ if (lineInstance && callReference)
+ sub = find_subchannel_by_instance_reference(s->device, lineInstance, callReference);
+
+ if (!sub)
+ return 0;
+
+ l = sub->parent;
+ if (sub->owner) {
/* XXX MUST queue this frame to all lines in threeway call if threeway call is active */
- ast_queue_frame(l->owner, &f);
- if (l->next && l->owner) {
- ast_queue_frame(l->owner, &f);
+ ast_queue_frame(sub->owner, &f);
+ /* XXX This seriously needs to be fixed */
+ if (sub->next && sub->next->owner) {
+ ast_queue_frame(sub->next->owner, &f);
}
} else {
if (skinnydebug)
@@ -2541,16 +2666,33 @@
static int handle_stimulus_message(skinny_req *req, struct skinnysession *s)
{
+ struct skinny_device *d = s->device;
struct skinny_line *l;
+ struct skinny_subchannel *sub;
struct skinny_speeddial *sd;
struct ast_channel *c;
pthread_t t;
int event;
int instance;
+ int unknown1;
int res = 0;
event = letohl(req->data.stimulus.stimulus);
instance = letohl(req->data.stimulus.stimulusInstance);
+ unknown1 = letohl(req->data.stimulus.unknown1); /* No clue.. */
+ if (skinnydebug)
+ ast_verbose("unknown1 in handle_stimulus_message is '%d'\n", unknown1);
+
+ sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
+
+ if (!sub) {
+ l = find_line_by_instance(d, d->lastlineinstance);
+ if (!l) {
+ return 0;
+ }
+ } else {
+ l = sub->parent;
+ }
switch(event) {
case STIMULUS_REDIAL:
@@ -2560,16 +2702,17 @@
if (skinnydebug)
ast_verbose("Received Stimulus: Redial(%d)\n", instance);
- l = s->device->lines;
-
- transmit_callstate(s, l->instance, SKINNY_OFFHOOK, l->callid);
- if (skinnydebug)
- ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, s->device->name);
- transmit_displaymessage(s, NULL); /* clear display */
- transmit_tone(s, SKINNY_DIALTONE);
-
+#if 0
c = skinny_new(l, AST_STATE_DOWN);
if(c) {
+ sub = c->tech_pvt;
+ l = sub->parent;
+ transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
+ if (skinnydebug)
+ ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
+ transmit_displaymessage(s, NULL); /* clear display */
+ transmit_tone(s, SKINNY_DIALTONE);
+
if (ast_strlen_zero(l->lastnumberdialed)) {
ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found.\n");
return 0;
@@ -2596,27 +2739,29 @@
}
}
} else {
- ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, s->device->name);
- }
[... 817 lines stripped ...]
More information about the svn-commits
mailing list