[svn-commits] mmichelson: branch 10-digiumphones r361261 - in /branches/10-digiumphones/cha...
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Wed Apr 4 15:50:59 CDT 2012
Author: mmichelson
Date: Wed Apr 4 15:50:55 2012
New Revision: 361261
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=361261
Log:
Changes to the channels directory for Digium phone support.
Next step: Get this poopoo compiling!
Modified:
branches/10-digiumphones/channels/chan_sip.c
branches/10-digiumphones/channels/chan_skinny.c
branches/10-digiumphones/channels/sip/include/sip.h
Modified: branches/10-digiumphones/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/branches/10-digiumphones/channels/chan_sip.c?view=diff&rev=361261&r1=361260&r2=361261
==============================================================================
--- branches/10-digiumphones/channels/chan_sip.c (original)
+++ branches/10-digiumphones/channels/chan_sip.c Wed Apr 4 15:50:55 2012
@@ -264,6 +264,7 @@
#include "asterisk/cel.h"
#include "asterisk/data.h"
#include "asterisk/aoc.h"
+#include "asterisk/custom_control_frame.h"
#include "asterisk/message.h"
#include "sip/include/sip.h"
#include "sip/include/globals.h"
@@ -1086,6 +1087,13 @@
}
}
+struct state_notify_data {
+ int state;
+ int presence_state;
+ const char *presence_subtype;
+ const char *presence_message;
+};
+
/*!
* \details
* Here we implement the container for dialogs which are in the
@@ -1369,7 +1377,8 @@
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(const char *context, const char *exten, enum ast_extension_states state, void *data);
+static int extensionstate_update(char *context, char *exten, struct state_notify_data *data, struct sip_pvt *p);
+static int cb_extensionstate(char *context, char *exten, struct ast_state_cb_info *info, 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);
@@ -1500,7 +1509,7 @@
static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason);
static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_request *oreq, int *cc_recall_core_id);
static int get_msg_text(char *buf, int len, struct sip_request *req);
-static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout);
+static int transmit_state_notify(struct sip_pvt *p, struct state_notify_data *data, int full, int timeout);
static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen);
static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen);
static int get_domain(const char *str, char *domain, int len);
@@ -3858,7 +3867,10 @@
/* If this is a subscription, tell the phone that we got a timeout */
if (p->subscribed && p->subscribed != MWI_NOTIFICATION && p->subscribed != CALL_COMPLETION) {
- transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, TRUE); /* Send last notification */
+ struct state_notify_data data = { 0, };
+ data.state = AST_EXTENSION_DEACTIVATED;
+
+ transmit_state_notify(p, &data, 1, TRUE); /* Send last notification */
p->subscribed = NONE;
append_history(p, "Subscribestatus", "timeout");
ast_debug(3, "Re-scheduled destruction of SIP subscription %s\n", p->callid ? p->callid : "<unknown>");
@@ -6866,6 +6878,54 @@
return 0;
}
+/*!
+ * \brief Sends AST_CUSTOM_FRAME of type sip info.
+ *
+ * \note pvt is expected to be locked before entering this function.
+ */
+static int sip_handle_custom_info(struct sip_pvt *pvt, struct ast_custom_payload *pl)
+{
+ struct ast_variable *headers = NULL;
+ char *content_type = NULL;
+ char *content = NULL;
+ char *useragent_filter = NULL;
+ struct ast_variable *var;
+ struct sip_request req;
+ int res = -1;
+
+ if (ast_custom_payload_sipinfo_decode(pl, &headers, &content_type, &content, &useragent_filter)) {
+ goto custom_info_cleanup;
+ }
+
+ if (!(ast_strlen_zero(useragent_filter))) {
+ int match = (strstr(pvt->useragent, useragent_filter)) ? 1 : 0;
+ if (!match) {
+ goto custom_info_cleanup;
+ }
+ }
+
+ reqprep(&req, pvt, SIP_INFO, 0, 1);
+ for (var = headers; var; var = var->next) {
+ add_header(&req, var->name, var->value);
+ }
+ if (!ast_strlen_zero(content) && !ast_strlen_zero(content_type)) {
+ add_header(&req, "Content-Type", content_type);
+ add_content(&req, content);
+ }
+
+ res = send_request(pvt, &req, XMIT_RELIABLE, pvt->ocseq);
+
+custom_info_cleanup:
+
+ ast_free(content);
+ ast_free(content_type);
+ ast_free(useragent_filter);
+ ast_variables_destroy(headers);
+
+ return res;
+}
+
+
/*! \brief Play indication to user
* With SIP a lot of indications is sent as messages, letting the device play
the indication - busy signal, congestion etc
@@ -6994,6 +7054,11 @@
break;
case AST_CONTROL_REDIRECTING:
update_redirecting(p, data, datalen);
+ break;
+ case AST_CONTROL_CUSTOM:
+ if (datalen && ast_custom_payload_type((struct ast_custom_payload *) data) == AST_CUSTOM_SIP_INFO) {
+ sip_handle_custom_info(p, (struct ast_custom_payload *) data);
+ }
break;
case AST_CONTROL_AOC:
{
@@ -12875,8 +12940,13 @@
return res ? CMP_MATCH | CMP_STOP : 0;
}
+static int allow_notify_user_presence(struct sip_pvt *p)
+{
+ return (strstr(p->useragent, "Digium")) ? 1 : 0;
+}
+
/*! \brief Builds XML portion of NOTIFY messages for presence or dialog updates */
-static void state_notify_build_xml(int state, int full, const char *exten, const char *context, struct ast_str **tmp, struct sip_pvt *p, int subscribed, const char *mfrom, const char *mto)
+static void state_notify_build_xml(struct state_notify_data *data, int full, const char *exten, const char *context, struct ast_str **tmp, struct sip_pvt *p, int subscribed, const char *mfrom, const char *mto)
{
enum state { NOTIFY_OPEN, NOTIFY_INUSE, NOTIFY_CLOSED } local_state = NOTIFY_OPEN;
const char *statestring = "terminated";
@@ -12884,7 +12954,7 @@
const char *pidfnote= "Ready";
char hint[AST_MAX_EXTENSION];
- switch (state) {
+ switch (data->state) {
case (AST_EXTENSION_RINGING | AST_EXTENSION_INUSE):
statestring = (sip_cfg.notifyringing) ? "early" : "confirmed";
local_state = NOTIFY_INUSE;
@@ -12929,8 +12999,15 @@
/* Check which device/devices we are watching and if they are registered */
if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten)) {
- char *hint2 = hint, *individual_hint = NULL;
+ char *hint2;
+ char *individual_hint = NULL;
int hint_count = 0, unavailable_count = 0;
+
+ /* strip off any possible PRESENCE providers from hint */
+ if ((hint2 = strrchr(hint, ','))) {
+ *hint2 = '\0';
+ }
+ hint2 = hint;
while ((individual_hint = strsep(&hint2, "&"))) {
hint_count++;
@@ -12979,12 +13056,24 @@
ast_str_append(tmp, 0, "<status><basic>open</basic></status>\n");
else
ast_str_append(tmp, 0, "<status><basic>%s</basic></status>\n", (local_state != NOTIFY_CLOSED) ? "open" : "closed");
+
+ if (allow_notify_user_presence(p) && (data->presence_state > 0)) {
+ ast_str_append(tmp, 0, "</tuple>\n");
+ ast_str_append(tmp, 0, "<tuple id=\"digium-presence\">\n");
+ ast_str_append(tmp, 0, "<status>\n");
+ ast_str_append(tmp, 0, "<digium_presence type=\"%s\" subtype=\"%s\">%s</digium_presence>\n",
+ ast_presence_state2str(data->presence_state),
+ S_OR(data->presence_subtype, ""),
+ S_OR(data->presence_message, ""));
+ ast_str_append(tmp, 0, "</status>\n");
+ }
+
ast_str_append(tmp, 0, "</tuple>\n</presence>\n");
break;
case DIALOG_INFO_XML: /* SNOM subscribes in this format */
ast_str_append(tmp, 0, "<?xml version=\"1.0\"?>\n");
ast_str_append(tmp, 0, "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"%u\" state=\"%s\" entity=\"%s\">\n", p->dialogver, full ? "full" : "partial", mto);
- if ((state & AST_EXTENSION_RINGING) && sip_cfg.notifyringing) {
+ if ((data->state & AST_EXTENSION_RINGING) && sip_cfg.notifyringing) {
const char *local_display = exten;
char *local_target = ast_strdupa(mto);
const char *remote_display = exten;
@@ -13053,7 +13142,7 @@
ast_str_append(tmp, 0, "<dialog id=\"%s\">\n", exten);
}
ast_str_append(tmp, 0, "<state>%s</state>\n", statestring);
- if (state == AST_EXTENSION_ONHOLD) {
+ if (data->state == AST_EXTENSION_ONHOLD) {
ast_str_append(tmp, 0, "<local>\n<target uri=\"%s\">\n"
"<param pname=\"+sip.rendering\" pvalue=\"no\"/>\n"
"</target>\n</local>\n", mto);
@@ -13097,7 +13186,7 @@
}
/*! \brief Used in the SUBSCRIBE notification subsystem (RFC3265) */
-static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout)
+static int transmit_state_notify(struct sip_pvt *p, struct state_notify_data *data, int full, int timeout)
{
struct ast_str *tmp = ast_str_alloca(4000);
char from[256], to[256];
@@ -13129,7 +13218,7 @@
reqprep(&req, p, SIP_NOTIFY, 0, 1);
- switch(state) {
+ switch (data->state) {
case AST_EXTENSION_DEACTIVATED:
if (timeout)
add_header(&req, "Subscription-State", "terminated;reason=timeout");
@@ -13152,19 +13241,19 @@
case XPIDF_XML:
case CPIM_PIDF_XML:
add_header(&req, "Event", subscriptiontype->event);
- state_notify_build_xml(state, full, p->exten, p->context, &tmp, p, p->subscribed, mfrom, mto);
+ state_notify_build_xml(data, full, p->exten, p->context, &tmp, p, p->subscribed, mfrom, mto);
add_header(&req, "Content-Type", subscriptiontype->mediatype);
p->dialogver++;
break;
case PIDF_XML: /* Eyebeam supports this format */
add_header(&req, "Event", subscriptiontype->event);
- state_notify_build_xml(state, full, p->exten, p->context, &tmp, p, p->subscribed, mfrom, mto);
+ state_notify_build_xml(data, full, p->exten, p->context, &tmp, p, p->subscribed, mfrom, mto);
add_header(&req, "Content-Type", subscriptiontype->mediatype);
p->dialogver++;
break;
case DIALOG_INFO_XML: /* SNOM subscribes in this format */
add_header(&req, "Event", subscriptiontype->event);
- state_notify_build_xml(state, full, p->exten, p->context, &tmp, p, p->subscribed, mfrom, mto);
+ state_notify_build_xml(data, full, p->exten, p->context, &tmp, p, p->subscribed, mfrom, mto);
add_header(&req, "Content-Type", subscriptiontype->mediatype);
p->dialogver++;
break;
@@ -14946,42 +15035,61 @@
dialog_unref(p, "the extensionstate containing this dialog ptr was destroyed");
}
-/*! \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(const char *context, const char *exten, enum ast_extension_states state, void *data)
-{
- struct sip_pvt *p = data;
-
+static int extensionstate_update(char *context, char *exten, struct state_notify_data *data, struct sip_pvt *p)
+{
sip_pvt_lock(p);
- switch(state) {
+ switch (data->state) {
case AST_EXTENSION_DEACTIVATED: /* Retry after a while */
case AST_EXTENSION_REMOVED: /* Extension is gone */
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); /* Delete subscription in 32 secs */
- ast_verb(2, "Extension state: Watcher for hint %s %s. Notify User %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", p->username);
+ ast_verb(2, "Extension state: Watcher for hint %s %s. Notify User %s\n", exten, data->state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", p->username);
p->subscribed = NONE;
- append_history(p, "Subscribestatus", "%s", state == AST_EXTENSION_REMOVED ? "HintRemoved" : "Deactivated");
+ append_history(p, "Subscribestatus", "%s", data->state == AST_EXTENSION_REMOVED ? "HintRemoved" : "Deactivated");
break;
default: /* Tell user */
- p->laststate = state;
+ p->laststate = data->state;
+ p->last_presence_state = data->presence_state;
+ ast_string_field_set(p, last_presence_subtype, S_OR(data->presence_subtype, ""));
+ ast_string_field_set(p, last_presence_message, S_OR(data->presence_message, ""));
break;
}
if (p->subscribed != NONE) { /* Only send state NOTIFY if we know the format */
if (!p->pendinginvite) {
- transmit_state_notify(p, state, 1, FALSE);
+ transmit_state_notify(p, data, 1, FALSE);
} else {
/* We already have a NOTIFY sent that is not answered. Queue the state up.
if many state changes happen meanwhile, we will only send a notification of the last one */
ast_set_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE);
}
}
- ast_verb(2, "Extension Changed %s[%s] new state %s for Notify User %s %s\n", exten, context, ast_extension_state2str(state), p->username,
+ ast_verb(2, "Extension Changed %s[%s] new state %s for Notify User %s %s\n", exten, context, ast_extension_state2str(data->state), p->username,
ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE) ? "(queued)" : "");
sip_pvt_unlock(p);
return 0;
+}
+
+/*! \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, struct ast_state_cb_info *info, void *data)
+{
+ struct sip_pvt *p = data;
+ struct state_notify_data notify_data = {
+ .state = info->exten_state,
+ .presence_state = info->presence_state,
+ .presence_subtype = info->presence_subtype,
+ .presence_message = info->presence_message,
+ };
+
+ if ((info->reason == AST_HINT_UPDATE_PRESENCE) && !(allow_notify_user_presence(p))) {
+ /* ignore a presence triggered update if we know the useragent doesn't care */
+ return 0;
+ }
+
+ return extensionstate_update(context, exten, ¬ify_data, p);
}
/*! \brief Send a fake 401 Unauthorized response when the administrator
@@ -21022,9 +21130,15 @@
pvt_set_needdestroy(p, "received 200 response");
}
if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) {
+ struct state_notify_data data = {
+ .state = p->laststate,
+ .presence_state = p->last_presence_state,
+ .presence_subtype = p->last_presence_subtype,
+ .presence_message = p->last_presence_message,
+ };
/* Ready to send the next state we have on queue */
ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE);
- cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p);
+ extensionstate_update((char *)p->context, (char *)p->exten, &data, (void *) p);
}
}
break;
@@ -25714,8 +25828,10 @@
sip_unref_peer(peer, "release a peer ref now that MWI is sent");
}
} else if (p->subscribed != CALL_COMPLETION) {
-
- if ((firststate = ast_extension_state(NULL, p->context, p->exten)) < 0) {
+ struct state_notify_data data = { 0, };
+ char *subtype = NULL;
+ char *message = NULL;
+ if ((data.state = ast_extension_state(NULL, p->context, p->exten)) < 0) {
ast_log(LOG_NOTICE, "Got SUBSCRIBE for extension %s@%s from %s, but there is no hint for that extension.\n", p->exten, p->context, ast_sockaddr_stringify(&p->sa));
transmit_response(p, "404 Not found", req);
@@ -25725,14 +25841,21 @@
}
return 0;
}
+ if (allow_notify_user_presence(p)) {
+ data.presence_state = ast_hint_presence_state(NULL, p->context, p->exten, &subtype, &message);
+ data.presence_subtype = subtype;
+ data.presence_message = message;
+ }
ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
transmit_response(p, "200 OK", req);
- transmit_state_notify(p, firststate, 1, FALSE); /* Send first notification */
- append_history(p, "Subscribestatus", "%s", ast_extension_state2str(firststate));
+ transmit_state_notify(p, &data, 1, FALSE); /* Send first notification */
+ append_history(p, "Subscribestatus", "%s", ast_extension_state2str(data.state));
/* hide the 'complete' exten/context in the refer_to field for later display */
ast_string_field_build(p, subscribeuri, "%s@%s", p->exten, p->context);
/* Deleted the slow iteration of all sip dialogs to find old subscribes from this peer for exten at context */
+ ast_free(subtype);
+ ast_free(message);
}
if (!p->expiry) {
pvt_set_needdestroy(p, "forcing expiration");
Modified: branches/10-digiumphones/channels/chan_skinny.c
URL: http://svnview.digium.com/svn/asterisk/branches/10-digiumphones/channels/chan_skinny.c?view=diff&rev=361261&r1=361260&r2=361261
==============================================================================
--- branches/10-digiumphones/channels/chan_skinny.c (original)
+++ branches/10-digiumphones/channels/chan_skinny.c Wed Apr 4 15:50:55 2012
@@ -1481,7 +1481,7 @@
.bridge = ast_rtp_instance_bridge,
};
-static int skinny_extensionstate_cb(const char *context, const char *exten, enum ast_extension_states state, void *data);
+static int skinny_extensionstate_cb(char *context, char* id, struct ast_state_cb_info *info, void *data);
static int skinny_transfer(struct skinny_subchannel *sub);
static struct skinny_line *skinny_line_alloc(void)
@@ -2990,11 +2990,17 @@
transmit_response(d, req);
}
-static int skinny_extensionstate_cb(const char *context, const char *exten, enum ast_extension_states state, void *data)
+static int skinny_extensionstate_cb(char *context, char *exten, struct ast_state_cb_info *info, void *data)
{
struct skinny_container *container = data;
struct skinny_device *d = NULL;
char hint[AST_MAX_EXTENSION];
+ int state = info->exten_state;
+
+ /* only interested in device state here */
+ if (info->reason != AST_HINT_UPDATE_DEVICE) {
+ return 0;
+ }
if (container->type == SKINNY_SDCONTAINER) {
struct skinny_speeddial *sd = container->data;
Modified: branches/10-digiumphones/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/branches/10-digiumphones/channels/sip/include/sip.h?view=diff&rev=361261&r1=361260&r2=361261
==============================================================================
--- branches/10-digiumphones/channels/sip/include/sip.h (original)
+++ branches/10-digiumphones/channels/sip/include/sip.h Wed Apr 4 15:50:55 2012
@@ -1019,6 +1019,8 @@
AST_STRING_FIELD(parkinglot); /*!< Parkinglot */
AST_STRING_FIELD(engine); /*!< RTP engine to use */
AST_STRING_FIELD(dialstring); /*!< The dialstring used to call this SIP endpoint */
+ AST_STRING_FIELD(last_presence_subtype); /*!< The last presence subtype sent for a subscription. */
+ AST_STRING_FIELD(last_presence_message); /*!< The last presence message for a subscription */
AST_STRING_FIELD(msg_body); /*!< Text for a MESSAGE body */
);
char via[128]; /*!< Via: header */
@@ -1117,6 +1119,7 @@
enum subscriptiontype subscribed; /*!< SUBSCRIBE: Is this dialog a subscription? */
int stateid; /*!< SUBSCRIBE: ID for devicestate subscriptions */
int laststate; /*!< SUBSCRIBE: Last known extension state */
+ int last_presence_state; /*!< SUBSCRIBE: Last known presence state */
uint32_t dialogver; /*!< SUBSCRIBE: Version for subscription dialog-info */
struct ast_dsp *dsp; /*!< Inband DTMF or Fax CNG tone Detection dsp */
More information about the svn-commits
mailing list