[svn-commits] wedhorn: branch wedhorn/skinny-subs r189201 - /team/wedhorn/skinny-subs/chann...
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Fri Apr 17 18:17:57 CDT 2009
Author: wedhorn
Date: Fri Apr 17 18:17:53 2009
New Revision: 189201
URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=189201
Log:
Initial commit of changes to skinny subchannel handling and locking.
Modified:
team/wedhorn/skinny-subs/channels/chan_skinny.c
Modified: team/wedhorn/skinny-subs/channels/chan_skinny.c
URL: http://svn.digium.com/svn-view/asterisk/team/wedhorn/skinny-subs/channels/chan_skinny.c?view=diff&rev=189201&r1=189200&r2=189201
==============================================================================
--- team/wedhorn/skinny-subs/channels/chan_skinny.c (original)
+++ team/wedhorn/skinny-subs/channels/chan_skinny.c Fri Apr 17 18:17:53 2009
@@ -71,13 +71,6 @@
#include "asterisk/indications.h"
#include "asterisk/linkedlists.h"
-#ifdef SKINNY_DEVMODE
-#define SKINNY_DEVONLY(code) \
- code
-#else
-#define SKINNY_DEVONLY(code)
-#endif
-
/*************************************
* Skinny/Asterisk Protocol Settings *
*************************************/
@@ -96,6 +89,21 @@
SKINNY_CODEC_H261 = 100,
SKINNY_CODEC_H263 = 101
};
+#define DEBUG_OFF 0
+#define DEBUG_SIMPLE (1 << 0)
+#define DEBUG_SUB (1 << 1)
+#define DEBUG_RTP (1 << 2)
+#define DEBUG_PACKET (1 << 3)
+#define DEBUG_CORE (1 << 4)
+#define DEBUG_DEVICE (1 << 5)
+#define DEBUG_THREAD (1 << 6)
+#define DEBUG_LOCK (1 << 7)
+#define DEBUG_UNSET (1 << 16)
+
+#define SKINNY_DEBUG(debug_type, code) \
+ if (skinnydebug & (debug_type)) { \
+ code; \
+ }
#define DEFAULT_SKINNY_PORT 2000
#define DEFAULT_SKINNY_BACKLOG 2
@@ -167,16 +175,26 @@
};
static struct ast_jb_conf global_jbconf;
-#ifdef SKINNY_DEVMODE
-AST_THREADSTORAGE(message2str_threadbuf);
-#define MESSAGE2STR_BUFSIZE 35
-#endif
+//AST_THREADSTORAGE(message2str_threadbuf);
+//#define MESSAGE2STR_BUFSIZE 35
+
+AST_THREADSTORAGE(stimulus2str_threadbuf);
+#define STIMULUS2STR_BUFSIZE 35
+
+AST_THREADSTORAGE(softkey2str_threadbuf);
+#define SOFTKEY2STR_BUFSIZE 35
AST_THREADSTORAGE(device2str_threadbuf);
#define DEVICE2STR_BUFSIZE 15
AST_THREADSTORAGE(control2str_threadbuf);
#define CONTROL2STR_BUFSIZE 100
+
+AST_THREADSTORAGE(substate2str_threadbuf);
+#define SUBSTATE2STR_BUFSIZE 25
+
+AST_THREADSTORAGE(skinnystate2str_threadbuf);
+#define SKINNYSTATE2STR_BUFSIZE 25
/*********************
* Protocol Messages *
@@ -388,6 +406,11 @@
uint32_t space[3];
};
+struct call_info_message2 {
+ char str1[40];
+ char str2[24];
+};
+
#define FORWARD_STAT_MESSAGE 0x0090
struct forward_stat_message {
uint32_t activeforward;
@@ -496,6 +519,11 @@
#define DISPLAYTEXT_MESSAGE 0x0099
struct displaytext_message {
char text[40];
+};
+
+struct displaytext_message_old {
+ char line1[20];
+ char line2[12];
};
#define CLEAR_NOTIFY_MESSAGE 0x0115
@@ -724,7 +752,7 @@
\155: Default Router 3
\156: Default Router 4
\157: Default Router 5
- \160: DNS Server 1
+ \160: DNS Server 1rec
\161: DNS Server 2
\162: DNS Server 3
\163: DNS Server 4
@@ -916,6 +944,7 @@
struct version_res_message version;
struct button_template_res_message buttontemplate;
struct displaytext_message displaytext;
+ struct displaytext_message_old displaytextold;
struct display_prompt_status_message displaypromptstatus;
struct clear_prompt_message clearpromptstatus;
struct definetimedate_message definetimedate;
@@ -1043,12 +1072,47 @@
#define SKINNY_CALLREMOTEMULTILINE 13
#define SKINNY_INVALID 14
+/* The following sub states are unique to chan_skinny.
+ Do not send to core or skinny devices.
+ They relate to set_sub_state() */
+#define SUBSTATE_NEW 101
+#define SUBSTATE_OFFHOOK 102
+#define SUBSTATE_DIAL 103
+#define SUBSTATE_PROGRESS 104
+#define SUBSTATE_RINGOUT 105
+#define SUBSTATE_BUSY 106
+#define SUBSTATE_CONGESTION 107
+#define SUBSTATE_RINGIN 108
+#define SUBSTATE_CALLWAIT 109
+#define SUBSTATE_CONNECTED 110
+#define SUBSTATE_HOLD 111
+#define SUBSTATE_TRANSFER 112
+#define SUBSTATE_AUTOANS 113
+#define SUBSTATE_HANGUP 114
+#define SUBSTATE_ONHOOK 115
+#define SUBSTATE_DIE 116
+#define SUBSTATE_CALLREMOTEMULTILINE 117
+#define SUBSTATE_CALLPARK 118
+#define SUBSTATE_INVALID 121
+#define SUBSTATE_DESTROY 122
+#define SUBSTATE_DIALING 123
+#define SUBSTATE_REORDER 131
+#define SUBSTATE_ANNOYTONE 132
+#define SUBSTATE_INBOUNDCALL 133
+#define SUBSTATE_DUMPSUB 134
+#define SUBSTATE_ENDCALL 135
+
#define SKINNY_SILENCE 0x00
-#define SKINNY_DIALTONE 0x21
+#define SKINNY_INSIDEDIALTONE 0x21
+#define SKINNY_OUTSIDEDIALTONE 0x22
#define SKINNY_BUSYTONE 0x23
-#define SKINNY_ALERT 0x24
-#define SKINNY_REORDER 0x25
+#define SKINNY_ALERTTONE 0x24
+#define SKINNY_REORDERTONE 0x25
#define SKINNY_CALLWAITTONE 0x2D
+#define SKINNY_ZIPZIP 0x31
+#define SKINNY_ZIP 0x32
+#define SKINNY_BEEPBONK 0x33
+#define SKINNY_HOLDTONE 0x35
#define SKINNY_NOTONE 0x7F
#define SKINNY_LAMP_OFF 1
@@ -1061,6 +1125,8 @@
#define SKINNY_RING_INSIDE 2
#define SKINNY_RING_OUTSIDE 3
#define SKINNY_RING_FEATURE 4
+#define SKINNY_RING_FLASHONLY 5
+#define SKINNY_RING_PRECEDENCE 6
#define SKINNY_CFWD_ALL (1 << 0)
#define SKINNY_CFWD_BUSY (1 << 1)
@@ -1109,7 +1175,6 @@
static int matchdigittimeout = 3000;
struct skinny_subchannel {
- ast_mutex_t lock;
struct ast_channel *owner;
struct ast_rtp_instance *rtp;
struct ast_rtp_instance *vrtp;
@@ -1125,9 +1190,35 @@
int alreadygone;
int blindxfer;
int xferor;
-
-
- AST_LIST_ENTRY(skinny_subchannel) list;
+ int substate;
+ int devstate;
+ pthread_t thread;
+ int thread_die;
+ char reference;
+ int killdialingthread;
+ int killendcallthread;
+ int ringermode;
+ int autoans;
+ int autoans_time;
+ int autoans_tone;
+ int autohangup;
+ int dialing;
+ int hangingup;
+ int endcalltonetime;
+ char label[42];
+ pthread_t dialingthread;
+ char exten[AST_MAX_EXTENSION];
+ int calltype;
+ int locks;
+ char callingname[AST_MAX_EXTENSION];
+ char callingnum[AST_MAX_EXTENSION];
+ char calledname[AST_MAX_EXTENSION];
+ char callednum[AST_MAX_EXTENSION];
+ char oldcallingname[20];
+ char oldcallingnum[12];
+
+ AST_LIST_ENTRY(skinny_subchannel) llist;
+ AST_LIST_ENTRY(skinny_subchannel) dlist;
struct skinny_subchannel *related;
struct skinny_line *parent;
};
@@ -1180,17 +1271,16 @@
int onhooktime; \
int msgstate; \
int immediate; \
- int hookstate; \
int nat; \
int canreinvite; \
int prune;
struct skinny_line {
SKINNY_LINE_OPTIONS
- ast_mutex_t lock;
struct ast_event_sub *mwi_event_sub; /* Event based MWI */
struct skinny_subchannel *activesub;
- AST_LIST_HEAD(, skinny_subchannel) sub;
+ struct skinny_subchannel *startfortraverse;
+ AST_LIST_HEAD(, skinny_subchannel) subs;
AST_LIST_ENTRY(skinny_line) list;
AST_LIST_ENTRY(skinny_line) all;
struct skinny_device *device;
@@ -1215,14 +1305,12 @@
.getforward = 0,
.needdestroy = 0,
.prune = 0,
- .hookstate = SKINNY_ONHOOK,
};
struct skinny_line_options *default_line = &default_line_struct;
static AST_LIST_HEAD_STATIC(lines, skinny_line);
struct skinny_speeddial {
- ast_mutex_t lock;
char label[42];
char context[AST_MAX_CONTEXT];
char exten[AST_MAX_EXTENSION];
@@ -1236,7 +1324,6 @@
};
struct skinny_addon {
- ast_mutex_t lock;
char type[10];
AST_LIST_ENTRY(skinny_addon) list;
struct skinny_device *parent;
@@ -1259,8 +1346,15 @@
int transfer; \
int callwaiting; \
int mwiblink; \
+ int hookstate; \
int dnd; \
- int prune;
+ int prune; \
+ int autohangup; \
+ int ringermode; \
+ int ringermodetone; \
+ int devicetone; \
+ int locks; \
+ int rtptone;
struct skinny_device {
SKINNY_DEVICE_OPTIONS
@@ -1272,6 +1366,9 @@
struct ast_ha *ha;
struct skinnysession *session;
struct skinny_line *activeline;
+ struct skinny_subchannel *activesub;
+// struct skinny_subchannel *workingsub;
+ AST_LIST_HEAD(, skinny_subchannel) subs;
AST_LIST_HEAD(, skinny_line) lines;
AST_LIST_HEAD(, skinny_speeddial) speeddials;
AST_LIST_HEAD(, skinny_addon) addons;
@@ -1287,9 +1384,16 @@
.mwiblink = 0,
.dnd = 0,
.confcapability = AST_FORMAT_ULAW | AST_FORMAT_ALAW,
- .capability = 0,
+ .capability = 0,
.prune = 0,
-};
+ .hookstate = SKINNY_ONHOOK,
+ .autohangup = 0,
+ .ringermode = SKINNY_RING_OFF,
+ .devicetone = SKINNY_SILENCE,
+ .rtptone = SKINNY_SILENCE,
+ .locks = 0,
+};
+
struct skinny_device_options *default_device = &default_device_struct;
static AST_LIST_HEAD_STATIC(devices, skinny_device);
@@ -1305,7 +1409,7 @@
struct skinnysession {
pthread_t t;
- ast_mutex_t lock;
+// ast_mutex_t lock;
struct sockaddr_in sin;
int fd;
char inbuf[SKINNY_MAX_PACKET];
@@ -1327,9 +1431,12 @@
static int skinny_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
static int skinny_senddigit_begin(struct ast_channel *ast, char digit);
static int skinny_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
-static int handle_time_date_req_message(struct skinny_req *req, struct skinnysession *s);
+//static int handle_time_date_req_message(struct skinny_req *req, struct skinnysession *s);
static void mwi_event_cb(const struct ast_event *event, void *userdata);
static int skinny_reload(void);
+static struct skinny_subchannel *set_sub_state(struct skinny_subchannel *sub, int state);
+//static struct skinny_subchannel *set_workingsub_state(struct skinny_device *d, int state);
+static void destroy_sub(struct skinny_subchannel *sub);
static const struct ast_channel_tech skinny_tech = {
.type = "Skinny",
@@ -1353,563 +1460,11 @@
static int skinny_extensionstate_cb(char *context, char* exten, int state, void *data);
static int skinny_transfer(struct skinny_subchannel *sub);
-static void *get_button_template(struct skinnysession *s, struct button_definition_template *btn)
-{
- struct skinny_device *d = s->device;
- struct skinny_addon *a;
- int i;
-
- switch (d->type) {
- case SKINNY_DEVICE_30SPPLUS:
- case SKINNY_DEVICE_30VIP:
- /* 13 rows, 2 columns */
- for (i = 0; i < 4; i++)
- (btn++)->buttonDefinition = BT_CUST_LINE;
- (btn++)->buttonDefinition = BT_REDIAL;
- (btn++)->buttonDefinition = BT_VOICEMAIL;
- (btn++)->buttonDefinition = BT_CALLPARK;
- (btn++)->buttonDefinition = BT_FORWARDALL;
- (btn++)->buttonDefinition = BT_CONFERENCE;
- for (i = 0; i < 4; i++)
- (btn++)->buttonDefinition = BT_NONE;
- for (i = 0; i < 13; i++)
- (btn++)->buttonDefinition = BT_SPEEDDIAL;
-
- break;
- case SKINNY_DEVICE_12SPPLUS:
- case SKINNY_DEVICE_12SP:
- case SKINNY_DEVICE_12:
- /* 6 rows, 2 columns */
- for (i = 0; i < 2; i++)
- (btn++)->buttonDefinition = BT_CUST_LINE;
- for (i = 0; i < 4; i++)
- (btn++)->buttonDefinition = BT_SPEEDDIAL;
- (btn++)->buttonDefinition = BT_HOLD;
- (btn++)->buttonDefinition = BT_REDIAL;
- (btn++)->buttonDefinition = BT_TRANSFER;
- (btn++)->buttonDefinition = BT_FORWARDALL;
- (btn++)->buttonDefinition = BT_CALLPARK;
- (btn++)->buttonDefinition = BT_VOICEMAIL;
- break;
- case SKINNY_DEVICE_7910:
- (btn++)->buttonDefinition = BT_LINE;
- (btn++)->buttonDefinition = BT_HOLD;
- (btn++)->buttonDefinition = BT_TRANSFER;
- (btn++)->buttonDefinition = BT_DISPLAY;
- (btn++)->buttonDefinition = BT_VOICEMAIL;
- (btn++)->buttonDefinition = BT_CONFERENCE;
- (btn++)->buttonDefinition = BT_FORWARDALL;
- for (i = 0; i < 2; i++)
- (btn++)->buttonDefinition = BT_SPEEDDIAL;
- (btn++)->buttonDefinition = BT_REDIAL;
- break;
- case SKINNY_DEVICE_7960:
- case SKINNY_DEVICE_7961:
- case SKINNY_DEVICE_7961GE:
- case SKINNY_DEVICE_7962:
- case SKINNY_DEVICE_7965:
- for (i = 0; i < 6; i++)
- (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
- break;
- case SKINNY_DEVICE_7940:
- case SKINNY_DEVICE_7941:
- case SKINNY_DEVICE_7941GE:
- case SKINNY_DEVICE_7942:
- case SKINNY_DEVICE_7945:
- for (i = 0; i < 2; i++)
- (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
- break;
- case SKINNY_DEVICE_7935:
- case SKINNY_DEVICE_7936:
- for (i = 0; i < 2; i++)
- (btn++)->buttonDefinition = BT_LINE;
- break;
- case SKINNY_DEVICE_ATA186:
- (btn++)->buttonDefinition = BT_LINE;
- break;
- case SKINNY_DEVICE_7970:
- case SKINNY_DEVICE_7971:
- case SKINNY_DEVICE_7975:
- case SKINNY_DEVICE_CIPC:
- for (i = 0; i < 8; i++)
- (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
- break;
- case SKINNY_DEVICE_7985:
- /* XXX I have no idea what the buttons look like on these. */
- ast_log(LOG_WARNING, "Unsupported device type '%d (7985)' found.\n", d->type);
- break;
- case SKINNY_DEVICE_7912:
- case SKINNY_DEVICE_7911:
- case SKINNY_DEVICE_7905:
- (btn++)->buttonDefinition = BT_LINE;
- (btn++)->buttonDefinition = BT_HOLD;
- break;
- case SKINNY_DEVICE_7920:
- /* XXX I don't know if this is right. */
- for (i = 0; i < 4; i++)
- (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
- break;
- case SKINNY_DEVICE_7921:
- for (i = 0; i < 6; i++)
- (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
- break;
- case SKINNY_DEVICE_7902:
- ast_log(LOG_WARNING, "Unsupported device type '%d (7902)' found.\n", d->type);
- break;
- case SKINNY_DEVICE_7906:
- ast_log(LOG_WARNING, "Unsupported device type '%d (7906)' found.\n", d->type);
- break;
- case SKINNY_DEVICE_7931:
- ast_log(LOG_WARNING, "Unsupported device type '%d (7931)' found.\n", d->type);
- break;
- case SKINNY_DEVICE_7937:
- ast_log(LOG_WARNING, "Unsupported device type '%d (7937)' found.\n", d->type);
- break;
- case SKINNY_DEVICE_7914:
- ast_log(LOG_WARNING, "Unsupported device type '%d (7914)' found. Expansion module registered by itself?\n", d->type);
- break;
- case SKINNY_DEVICE_SCCPGATEWAY_AN:
- case SKINNY_DEVICE_SCCPGATEWAY_BRI:
- ast_log(LOG_WARNING, "Unsupported device type '%d (SCCP gateway)' found.\n", d->type);
- break;
- default:
- ast_log(LOG_WARNING, "Unknown device type '%d' found.\n", d->type);
- break;
- }
-
- AST_LIST_LOCK(&d->addons);
- AST_LIST_TRAVERSE(&d->addons, a, list) {
- if (!strcasecmp(a->type, "7914")) {
- for (i = 0; i < 14; i++)
- (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
- } else {
- ast_log(LOG_WARNING, "Unknown addon type '%s' found. Skipping.\n", a->type);
- }
- }
- AST_LIST_UNLOCK(&d->addons);
-
- return btn;
-}
-
-static struct skinny_req *req_alloc(size_t size, int response_message)
-{
- struct skinny_req *req;
-
- if (!(req = ast_calloc(1, skinny_header_size + size + 4)))
- return NULL;
-
- req->len = htolel(size+4);
- req->e = htolel(response_message);
-
- return req;
-}
-
-static struct skinny_line *find_line_by_instance(struct skinny_device *d, int instance)
-{
- struct skinny_line *l;
-
- /*Dialing from on hook or on a 7920 uses instance 0 in requests
- but we need to start looking at instance 1 */
-
- if (!instance)
- instance = 1;
-
- AST_LIST_TRAVERSE(&d->lines, l, list){
- if (l->instance == instance)
- break;
- }
-
- if (!l) {
- ast_log(LOG_WARNING, "Could not find line with instance '%d' on device '%s'\n", instance, d->name);
- }
- return l;
-}
-
-static struct skinny_line *find_line_by_name(const char *dest)
-{
- struct skinny_line *l;
- struct skinny_line *tmpl = NULL;
- struct skinny_device *d;
- char line[256];
- char *at;
- char *device;
- int checkdevice = 0;
-
- ast_copy_string(line, dest, sizeof(line));
- at = strchr(line, '@');
- if (at)
- *at++ = '\0';
- device = at;
-
- if (!ast_strlen_zero(device))
- checkdevice = 1;
-
- AST_LIST_LOCK(&devices);
- AST_LIST_TRAVERSE(&devices, d, list){
- if (checkdevice && tmpl)
- break;
- else if (!checkdevice) {
- /* This is a match, since we're checking for line on every device. */
- } else if (!strcasecmp(d->name, device)) {
- if (skinnydebug)
- ast_verb(2, "Found device: %s\n", d->name);
- } else
- continue;
-
- /* Found the device (or we don't care which device) */
- AST_LIST_TRAVERSE(&d->lines, l, list){
- /* Search for the right line */
- if (!strcasecmp(l->name, line)) {
- if (tmpl) {
- ast_verb(2, "Ambiguous line name: %s\n", line);
- AST_LIST_UNLOCK(&devices);
- return NULL;
- } else
- tmpl = l;
- }
- }
- }
- AST_LIST_UNLOCK(&devices);
- return tmpl;
-}
-
-/*!
- * implement the setvar config line
- */
-static struct ast_variable *add_var(const char *buf, struct ast_variable *list)
-{
- struct ast_variable *tmpvar = NULL;
- char *varname = ast_strdupa(buf), *varval = NULL;
-
- if ((varval = strchr(varname,'='))) {
- *varval++ = '\0';
- if ((tmpvar = ast_variable_new(varname, varval, ""))) {
- tmpvar->next = list;
- list = tmpvar;
- }
- }
- return list;
-}
-
-/* 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;
- }
-
- /* 7920 phones set call reference to 0, so use the first
- sub-channel on the list.
- This MIGHT need more love to be right */
- if (!reference)
- sub = AST_LIST_FIRST(&l->sub);
- else {
- AST_LIST_TRAVERSE(&l->sub, sub, list) {
- 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_LIST_TRAVERSE(&d->lines, l, list){
- AST_LIST_TRAVERSE(&l->sub, sub, list){
- 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, int isHint)
-{
- struct skinny_speeddial *sd;
-
- AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
- if (sd->isHint == isHint && sd->instance == instance)
- break;
- }
-
- if (!sd) {
- ast_log(LOG_WARNING, "Could not find speeddial with instance '%d' on device '%s'\n", instance, d->name);
- }
- return sd;
-}
-
-static int codec_skinny2ast(enum skinny_codecs skinnycodec)
-{
- switch (skinnycodec) {
- case SKINNY_CODEC_ALAW:
- return AST_FORMAT_ALAW;
- case SKINNY_CODEC_ULAW:
- return AST_FORMAT_ULAW;
- case SKINNY_CODEC_G723_1:
- return AST_FORMAT_G723_1;
- case SKINNY_CODEC_G729A:
- return AST_FORMAT_G729A;
- case SKINNY_CODEC_G726_32:
- return AST_FORMAT_G726_AAL2; /* XXX Is this right? */
- case SKINNY_CODEC_H261:
- return AST_FORMAT_H261;
- case SKINNY_CODEC_H263:
- return AST_FORMAT_H263;
- default:
- return 0;
- }
-}
-
-static int codec_ast2skinny(int astcodec)
-{
- switch (astcodec) {
- case AST_FORMAT_ALAW:
- return SKINNY_CODEC_ALAW;
- case AST_FORMAT_ULAW:
- return SKINNY_CODEC_ULAW;
- case AST_FORMAT_G723_1:
- return SKINNY_CODEC_G723_1;
- case AST_FORMAT_G729A:
- return SKINNY_CODEC_G729A;
- case AST_FORMAT_G726_AAL2: /* XXX Is this right? */
- return SKINNY_CODEC_G726_32;
- case AST_FORMAT_H261:
- return SKINNY_CODEC_H261;
- case AST_FORMAT_H263:
- return SKINNY_CODEC_H263;
- default:
- return 0;
- }
-}
-
-static int set_callforwards(struct skinny_line *l, const char *cfwd, int cfwdtype)
-{
- if (!l)
- return 0;
-
- if (!ast_strlen_zero(cfwd)) {
- if (cfwdtype & SKINNY_CFWD_ALL) {
- l->cfwdtype |= SKINNY_CFWD_ALL;
- ast_copy_string(l->call_forward_all, cfwd, sizeof(l->call_forward_all));
- }
- if (cfwdtype & SKINNY_CFWD_BUSY) {
- l->cfwdtype |= SKINNY_CFWD_BUSY;
- ast_copy_string(l->call_forward_busy, cfwd, sizeof(l->call_forward_busy));
- }
- if (cfwdtype & SKINNY_CFWD_NOANSWER) {
- l->cfwdtype |= SKINNY_CFWD_NOANSWER;
- ast_copy_string(l->call_forward_noanswer, cfwd, sizeof(l->call_forward_noanswer));
- }
- } else {
- if (cfwdtype & SKINNY_CFWD_ALL) {
- l->cfwdtype &= ~SKINNY_CFWD_ALL;
- memset(l->call_forward_all, 0, sizeof(l->call_forward_all));
- }
- if (cfwdtype & SKINNY_CFWD_BUSY) {
- l->cfwdtype &= ~SKINNY_CFWD_BUSY;
- memset(l->call_forward_busy, 0, sizeof(l->call_forward_busy));
- }
- if (cfwdtype & SKINNY_CFWD_NOANSWER) {
- l->cfwdtype &= ~SKINNY_CFWD_NOANSWER;
- memset(l->call_forward_noanswer, 0, sizeof(l->call_forward_noanswer));
- }
- }
- return l->cfwdtype;
-}
-
-static void cleanup_stale_contexts(char *new, char *old)
-{
- char *oldcontext, *newcontext, *stalecontext, *stringp, newlist[AST_MAX_CONTEXT];
-
- while ((oldcontext = strsep(&old, "&"))) {
- stalecontext = '\0';
- ast_copy_string(newlist, new, sizeof(newlist));
- stringp = newlist;
- while ((newcontext = strsep(&stringp, "&"))) {
- if (strcmp(newcontext, oldcontext) == 0) {
- /* This is not the context you're looking for */
- stalecontext = '\0';
- break;
- } else if (strcmp(newcontext, oldcontext)) {
- stalecontext = oldcontext;
- }
-
- }
- if (stalecontext)
- ast_context_destroy(ast_context_find(stalecontext), "Skinny");
- }
-}
-
-static void register_exten(struct skinny_line *l)
-{
- char multi[256];
- char *stringp, *ext, *context;
-
- if (ast_strlen_zero(regcontext))
- return;
-
- ast_copy_string(multi, S_OR(l->regexten, l->name), sizeof(multi));
- stringp = multi;
- while ((ext = strsep(&stringp, "&"))) {
- if ((context = strchr(ext, '@'))) {
- *context++ = '\0'; /* split ext at context */
- if (!ast_context_find(context)) {
- ast_log(LOG_WARNING, "Context %s must exist in regcontext= in skinny.conf!\n", context);
- continue;
- }
- } else {
- context = regcontext;
- }
- ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop",
- ast_strdup(l->name), ast_free_ptr, "Skinny");
- }
-}
-
-static void unregister_exten(struct skinny_line *l)
-{
- char multi[256];
- char *stringp, *ext, *context;
-
- if (ast_strlen_zero(regcontext))
- return;
-
- ast_copy_string(multi, S_OR(l->regexten, l->name), sizeof(multi));
- stringp = multi;
- while ((ext = strsep(&stringp, "&"))) {
- if ((context = strchr(ext, '@'))) {
- *context++ = '\0'; /* split ext at context */
- if (!ast_context_find(context)) {
- ast_log(LOG_WARNING, "Context %s must exist in regcontext= in skinny.conf!\n", context);
- continue;
- }
- } else {
- context = regcontext;
- }
- ast_context_remove_extension(context, ext, 1, NULL);
- }
-}
-
-static int skinny_register(struct skinny_req *req, struct skinnysession *s)
-{
- struct skinny_device *d;
- struct skinny_line *l;
- struct skinny_speeddial *sd;
- struct sockaddr_in sin;
- socklen_t slen;
- int instance;
-
- AST_LIST_LOCK(&devices);
- AST_LIST_TRAVERSE(&devices, d, list){
- if (!strcasecmp(req->data.reg.name, d->id)
- && ast_apply_ha(d->ha, &(s->sin))) {
- s->device = d;
- d->type = letohl(req->data.reg.type);
- if (ast_strlen_zero(d->version_id)) {
- ast_copy_string(d->version_id, version_id, sizeof(d->version_id));
- }
- d->registered = 1;
- d->session = s;
-
- slen = sizeof(sin);
- if (getsockname(s->fd, (struct sockaddr *)&sin, &slen)) {
- ast_log(LOG_WARNING, "Cannot get socket name\n");
- sin.sin_addr = __ourip;
- }
- 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);
- }
- instance = 0;
- AST_LIST_TRAVERSE(&d->lines, l, list) {
- instance++;
- }
- AST_LIST_TRAVERSE(&d->lines, l, list) {
- /* FIXME: All sorts of issues will occur if this line is already connected to a device */
- if (l->device) {
- ast_verb(1, "Line %s already connected to %s. Not connecting to %s.\n", l->name, l->device->name, d->name);
- } else {
- l->device = d;
- l->capability = l->confcapability & d->capability;
- l->prefs = l->confprefs;
- if (!l->prefs.order[0]) {
- l->prefs = d->confprefs;
- }
- /* l->capability = d->capability;
- l->prefs = d->prefs; */
- l->instance = instance;
- l->newmsgs = ast_app_has_voicemail(l->mailbox, NULL);
- set_callforwards(l, NULL, 0);
- register_exten(l);
- /* initialize MWI on line and device */
- mwi_event_cb(0, l);
- ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
- }
- --instance;
- }
- break;
- }
- }
- AST_LIST_UNLOCK(&devices);
- if (!d) {
- return 0;
- }
- return 1;
-}
-
-static int skinny_unregister(struct skinny_req *req, struct skinnysession *s)
-{
- struct skinny_device *d;
- struct skinny_line *l;
- struct skinny_speeddial *sd;
-
- d = s->device;
-
- if (d) {
- d->session = NULL;
- d->registered = 0;
-
- AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
- if (sd->stateid > -1)
- ast_extension_state_del(sd->stateid, NULL);
- }
- AST_LIST_TRAVERSE(&d->lines, l, list) {
- if (l->device == d) {
- l->device = NULL;
- l->capability = 0;
- ast_parse_allow_disallow(&l->prefs, &l->capability, "all", 0);
- l->instance = 0;
- unregister_exten(l);
- ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Skinny/%s@%s", l->name, d->name);
- }
- }
- }
-
- return -1; /* main loop will destroy the session */
-}
-
-#ifdef SKINNY_DEVMODE
-static char *message2str(int type)
+/* --------------------------------------------------------------------------------------------------------------------------------------------------------------
+ * STRING HANDLING FUNCTIONS
+ * -------------------------------------------------------------------------------------------------------------------------------------------------------------- */
+
+/*static char *message2str(int type)
{
char *tmp;
@@ -2036,841 +1591,104 @@
snprintf(tmp, MESSAGE2STR_BUFSIZE, "UNKNOWN_MESSAGE-%d", type);
return tmp;
}
-}
-#endif
-
-static int transmit_response(struct skinny_device *d, struct skinny_req *req)
-{
- struct skinnysession *s = d->session;
- int res = 0;
-
- if (!s) {
- ast_log(LOG_WARNING, "Asked to transmit to a non-existent session!\n");
- return -1;
- }
-
- ast_mutex_lock(&s->lock);
-
- SKINNY_DEVONLY(if (skinnydebug>1) ast_verb(4, "Transmitting %s to %s\n", message2str(req->e), d->name);)
-
- if (letohl(req->len > SKINNY_MAX_PACKET) || letohl(req->len < 0)) {
- ast_log(LOG_WARNING, "transmit_response: the length of the request is out of bounds\n");
- ast_mutex_unlock(&s->lock);
- return -1;
- }
-
- memset(s->outbuf, 0, sizeof(s->outbuf));
- memcpy(s->outbuf, req, skinny_header_size);
- memcpy(s->outbuf+skinny_header_size, &req->data, letohl(req->len));
-
- res = write(s->fd, s->outbuf, letohl(req->len)+8);
-
- if (res != letohl(req->len)+8) {
- ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, letohl(req->len)+8, strerror(errno));
- if (res == -1) {
- if (skinnydebug)
- ast_log(LOG_WARNING, "Transmit: Skinny Client was lost, unregistering\n");
- skinny_unregister(NULL, s);
- }
-
- }
-
- ast_free(req);
- ast_mutex_unlock(&s->lock);
- return 1;
-}
-
-static void transmit_speaker_mode(struct skinny_device *d, int mode)
-{
- struct skinny_req *req;
-
- if (!(req = req_alloc(sizeof(struct set_speaker_message), SET_SPEAKER_MESSAGE)))
- return;
-
- req->data.setspeaker.mode = htolel(mode);
- transmit_response(d, req);
-}
-/*
-static void transmit_microphone_mode(struct skinny_device *d, int mode)
-{
- struct skinny_req *req;
-
- if (!(req = req_alloc(sizeof(struct set_microphone_message), SET_MICROPHONE_MESSAGE)))
- return;
-
- req->data.setmicrophone.mode = htolel(mode);
- transmit_response(d, req);
-}
-*/
-
-static void transmit_callinfo(struct skinny_device *d, const char *fromname, const char *fromnum, const char *toname, const char *tonum, int instance, int callid, int calltype)
-{
- struct skinny_req *req;
-
- /* We should not be able to get here without a device */
- if (!d)
- return;
-
- 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) on %s(%d)\n", fromname, fromnum, toname, tonum, d->name, instance);
-
- if (fromname) {
- ast_copy_string(req->data.callinfo.callingPartyName, fromname, sizeof(req->data.callinfo.callingPartyName));
- }
- if (fromnum) {
- ast_copy_string(req->data.callinfo.callingParty, fromnum, sizeof(req->data.callinfo.callingParty));
- }
- if (toname) {
- ast_copy_string(req->data.callinfo.calledPartyName, toname, sizeof(req->data.callinfo.calledPartyName));
- }
- if (tonum) {
- 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(calltype);
- transmit_response(d, req);
-}
-
-static void transmit_connect(struct skinny_device *d, struct skinny_subchannel *sub)
-{
- struct skinny_req *req;
- struct skinny_line *l = sub->parent;
- struct ast_format_list fmt;
-
- if (!(req = req_alloc(sizeof(struct open_receive_channel_message), OPEN_RECEIVE_CHANNEL_MESSAGE)))
- return;
-
- fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
-
- req->data.openreceivechannel.conferenceId = htolel(sub->callid);
- req->data.openreceivechannel.partyId = htolel(sub->callid);
- req->data.openreceivechannel.packets = htolel(fmt.cur_ms);
- req->data.openreceivechannel.capability = htolel(codec_ast2skinny(fmt.bits));
- req->data.openreceivechannel.echo = htolel(0);
- req->data.openreceivechannel.bitrate = htolel(0);
- transmit_response(d, req);
-}
-
-static void transmit_tone(struct skinny_device *d, int tone, int instance, int reference)
-{
- struct skinny_req *req;
-
- if (tone == SKINNY_NOTONE) {
- /* This is bad, mmm'kay? */
- return;
- }
-
- if (tone > 0) {
- if (!(req = req_alloc(sizeof(struct start_tone_message), START_TONE_MESSAGE)))
- return;
- req->data.starttone.tone = htolel(tone);
- req->data.starttone.instance = htolel(instance);
- req->data.starttone.reference = htolel(reference);
- } else {
- if (!(req = req_alloc(sizeof(struct stop_tone_message), STOP_TONE_MESSAGE)))
- return;
- req->data.stoptone.instance = htolel(instance);
- req->data.stoptone.reference = htolel(reference);
- }
-
- //Bad, tone is already set so this is redundant and a change to the if above
- //may lead to issues where we try to set a tone to a stop_tone_message
- //if (tone > 0) {
- // req->data.starttone.tone = htolel(tone);
- //}
- transmit_response(d, req);
-}
-
-static void transmit_selectsoftkeys(struct skinny_device *d, int instance, int callid, int softkey)
-{
- struct skinny_req *req;
-
- if (!(req = req_alloc(sizeof(struct select_soft_keys_message), SELECT_SOFT_KEYS_MESSAGE)))
- return;
-
- req->data.selectsoftkey.instance = htolel(instance);
- req->data.selectsoftkey.reference = htolel(callid);
- req->data.selectsoftkey.softKeySetIndex = htolel(softkey);
- req->data.selectsoftkey.validKeyMask = htolel(0xFFFFFFFF);
- transmit_response(d, req);
-}
-
-static void transmit_lamp_indication(struct skinny_device *d, int stimulus, int instance, int indication)
-{
- struct skinny_req *req;
-
- if (!(req = req_alloc(sizeof(struct set_lamp_message), SET_LAMP_MESSAGE)))
- return;
-
- req->data.setlamp.stimulus = htolel(stimulus);
- req->data.setlamp.stimulusInstance = htolel(instance);
- req->data.setlamp.deviceStimulus = htolel(indication);
- transmit_response(d, req);
-}
-
-static void transmit_ringer_mode(struct skinny_device *d, int mode)
-{
- struct skinny_req *req;
-
- if (skinnydebug)
- ast_verb(1, "Setting ringer mode to '%d'.\n", mode);
-
- if (!(req = req_alloc(sizeof(struct set_ringer_message), SET_RINGER_MESSAGE)))
- return;
-
- 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(d, req);
-}
-
-static void transmit_displaymessage(struct skinny_device *d, const char *text, int instance, int reference)
-{
- struct skinny_req *req;
-
- if (text == 0) {
- if (!(req = req_alloc(0, CLEAR_DISPLAY_MESSAGE)))
- return;
-
- //what do we want hear CLEAR_DISPLAY_MESSAGE or CLEAR_PROMPT_STATUS???
- //if we are clearing the display, it appears there is no instance and refernece info (size 0)
- //req->data.clearpromptstatus.lineInstance = instance;
- //req->data.clearpromptstatus.callReference = reference;
-
- /* send datetime message. We have to do it here because it will clear the display on the phone if we do it elsewhere */
- handle_time_date_req_message(NULL, d->session);
-
- if (skinnydebug)
- ast_verb(1, "Clearing Display\n");
- } else {
- if (!(req = req_alloc(sizeof(struct displaytext_message), DISPLAYTEXT_MESSAGE)))
- return;
-
- ast_copy_string(req->data.displaytext.text, text, sizeof(req->data.displaytext.text));
- if (skinnydebug)
- ast_verb(1, "Displaying message '%s'\n", req->data.displaytext.text);
- }
-
- transmit_response(d, req);
-}
-
-static void transmit_displaynotify(struct skinny_device *d, const char *text, int t)
-{
- struct skinny_req *req;
-
- if (!(req = req_alloc(sizeof(struct display_notify_message), DISPLAY_NOTIFY_MESSAGE)))
- return;
-
- ast_copy_string(req->data.displaynotify.displayMessage, text, sizeof(req->data.displaynotify.displayMessage));
- req->data.displaynotify.displayTimeout = htolel(t);
-
- if (skinnydebug)
- ast_verb(1, "Displaying notify '%s'\n", text);
-
- transmit_response(d, req);
-}
-
-static void transmit_displaypromptstatus(struct skinny_device *d, const char *text, int t, int instance, int callid)
-{
- struct skinny_req *req;
-
- if (text == 0) {
- if (!(req = req_alloc(sizeof(struct clear_prompt_message), CLEAR_PROMPT_MESSAGE)))
- return;
-
- req->data.clearpromptstatus.lineInstance = htolel(instance);
- req->data.clearpromptstatus.callReference = htolel(callid);
-
- if (skinnydebug)
- ast_verb(1, "Clearing Prompt\n");
- } else {
- if (!(req = req_alloc(sizeof(struct display_prompt_status_message), DISPLAY_PROMPT_STATUS_MESSAGE)))
- return;
-
- ast_copy_string(req->data.displaypromptstatus.promptMessage, text, sizeof(req->data.displaypromptstatus.promptMessage));
- req->data.displaypromptstatus.messageTimeout = htolel(t);
- req->data.displaypromptstatus.lineInstance = htolel(instance);
- req->data.displaypromptstatus.callReference = htolel(callid);
-
- if (skinnydebug)
- ast_verb(1, "Displaying Prompt Status '%s'\n", text);
- }
-
- transmit_response(d, req);
-}
-
-static void transmit_dialednumber(struct skinny_device *d, const char *text, int instance, int callid)
-{
- struct skinny_req *req;
-
- if (!(req = req_alloc(sizeof(struct dialed_number_message), DIALED_NUMBER_MESSAGE)))
- return;
-
- ast_copy_string(req->data.dialednumber.dialedNumber, text, sizeof(req->data.dialednumber.dialedNumber));
- req->data.dialednumber.lineInstance = htolel(instance);
- req->data.dialednumber.callReference = htolel(callid);
-
- transmit_response(d, req);
-}
-
-static void transmit_closereceivechannel(struct skinny_device *d, struct skinny_subchannel *sub)
-{
- struct skinny_req *req;
-
- if (!(req = req_alloc(sizeof(struct close_receive_channel_message), CLOSE_RECEIVE_CHANNEL_MESSAGE)))
- return;
-
- req->data.closereceivechannel.conferenceId = htolel(0);
- req->data.closereceivechannel.partyId = htolel(sub->callid);
- transmit_response(d, req);
-}
-
-static void transmit_stopmediatransmission(struct skinny_device *d, struct skinny_subchannel *sub)
-{
- struct skinny_req *req;
-
- if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
- return;
-
- req->data.stopmedia.conferenceId = htolel(0);
- req->data.stopmedia.passThruPartyId = htolel(sub->callid);
- transmit_response(d, req);
-}
-
-static void transmit_activatecallplane(struct skinny_device *d, struct skinny_line *l)
-{
- struct skinny_req *req;
-
- if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
- return;
-
- req->data.activatecallplane.lineInstance = htolel(l->instance);
- transmit_response(d, req);
-}
-
-static void transmit_callstateonly(struct skinny_device *d, struct skinny_subchannel *sub, int state)
-{
- struct skinny_req *req;
-
- if (!(req = req_alloc(sizeof(struct call_state_message), CALL_STATE_MESSAGE)))
- return;
-
- req->data.callstate.callState = htolel(state);
- req->data.callstate.lineInstance = htolel(sub->parent->instance);
- req->data.callstate.callReference = htolel(sub->callid);
- transmit_response(d, req);
-}
-
-static void transmit_callstate(struct skinny_device *d, int instance, int state, unsigned callid)
-{
- struct skinny_req *req;
-
- if (state == SKINNY_ONHOOK) {
- if (!(req = req_alloc(sizeof(struct close_receive_channel_message), CLOSE_RECEIVE_CHANNEL_MESSAGE)))
- return;
-
- req->data.closereceivechannel.conferenceId = htolel(callid);
- req->data.closereceivechannel.partyId = htolel(callid);
- transmit_response(d, req);
-
- if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
- return;
-
- req->data.stopmedia.conferenceId = htolel(callid);
- req->data.stopmedia.passThruPartyId = htolel(callid);
- transmit_response(d, req);
-
- transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
-
- transmit_displaypromptstatus(d, NULL, 0, instance, callid);
- }
-
- if (!(req = req_alloc(sizeof(struct call_state_message), CALL_STATE_MESSAGE)))
- return;
-
- req->data.callstate.callState = htolel(state);
- req->data.callstate.lineInstance = htolel(instance);
- req->data.callstate.callReference = htolel(callid);
- transmit_response(d, req);
-
- if (state == SKINNY_ONHOOK) {
- transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
- }
-
- if (state == SKINNY_OFFHOOK || state == SKINNY_ONHOOK) {
- if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
- return;
-
- req->data.activatecallplane.lineInstance = htolel(instance);
- transmit_response(d, req);
- }
-}
-
-
-static void transmit_cfwdstate(struct skinny_device *d, struct skinny_line *l)
-{
- struct skinny_req *req;
- int anyon = 0;
-
- if (!(req = req_alloc(sizeof(struct forward_stat_message), FORWARD_STAT_MESSAGE)))
- return;
-
- if (l->cfwdtype & SKINNY_CFWD_ALL) {
- if (!ast_strlen_zero(l->call_forward_all)) {
- ast_copy_string(req->data.forwardstat.fwdallnum, l->call_forward_all, sizeof(req->data.forwardstat.fwdallnum));
- req->data.forwardstat.fwdall = htolel(1);
- anyon++;
- } else {
- req->data.forwardstat.fwdall = htolel(0);
- }
- }
- if (l->cfwdtype & SKINNY_CFWD_BUSY) {
- if (!ast_strlen_zero(l->call_forward_busy)) {
- ast_copy_string(req->data.forwardstat.fwdbusynum, l->call_forward_busy, sizeof(req->data.forwardstat.fwdbusynum));
- req->data.forwardstat.fwdbusy = htolel(1);
- anyon++;
- } else {
- req->data.forwardstat.fwdbusy = htolel(0);
- }
- }
- if (l->cfwdtype & SKINNY_CFWD_NOANSWER) {
- if (!ast_strlen_zero(l->call_forward_noanswer)) {
- ast_copy_string(req->data.forwardstat.fwdnoanswernum, l->call_forward_noanswer, sizeof(req->data.forwardstat.fwdnoanswernum));
- req->data.forwardstat.fwdnoanswer = htolel(1);
[... 7696 lines stripped ...]
More information about the svn-commits
mailing list