[svn-commits] oej: branch group/pinana-publish-1.4 r297165 - /team/group/pinana-publish-1.4...
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Wed Dec 1 15:38:12 CST 2010
Author: oej
Date: Wed Dec 1 15:38:07 2010
New Revision: 297165
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=297165
Log:
We now do not send new PUBLISH requests while we have an open transaction.
This should propably be corrected in trunk for call completion code.
However, I fail to send a queued statechange the way I thought would be correct.
I need help from Marquis Watkins :-)
Modified:
team/group/pinana-publish-1.4/channels/chan_sip.c
Modified: team/group/pinana-publish-1.4/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/group/pinana-publish-1.4/channels/chan_sip.c?view=diff&rev=297165&r1=297164&r2=297165
==============================================================================
--- team/group/pinana-publish-1.4/channels/chan_sip.c (original)
+++ team/group/pinana-publish-1.4/channels/chan_sip.c Wed Dec 1 15:38:07 2010
@@ -1191,6 +1191,14 @@
char dev[0];
};
+/*! \brief PUBLISH transaction states */
+enum publish_state {
+ INITIATED, /*!< New state initiated */
+ REQUEST_SENT, /*!< Packet composed, request to transmit done */
+ TERMINATED, /*!< Transaction completed */
+};
+
+
/*! Structure for publish bodies */
struct sip_epa_entry {
/*!
@@ -1229,6 +1237,12 @@
* require its own instance-specific data.
*/
void *instance_data;
+ /*!
+ * According to the RFC, we can only have ONE outstanding
+ * request at a time. We need to know if we have an outstanding
+ * PVT that's waiting for 200 OK.
+ */
+ enum publish_state epa_state;
};
/*! Structure that we have one per device for keeping control of PUBLISH states */
@@ -1236,6 +1250,7 @@
char name[AST_MAX_EXTENSION]; /*!< Device name for entry */
char pubname[AST_MAX_EXTENSION]; /*!< Publisher name */
int laststate; /*!< Last known state */
+ int nextstate; /*!< Next known state */
struct sip_epa_entry *epa; /*!< EPA Entry for this entry */
};
@@ -8205,6 +8220,9 @@
if (!p->initreq.headers || init > 2)
initialize_initreq(p, &req);
p->lastinvite = p->ocseq;
+ if (sipmethod == SIP_PUBLISH && p->epa_entry) {
+ p->epa_entry->epa_state = REQUEST_SENT;
+ }
return send_request(p, &req, init ? XMIT_CRITICAL : XMIT_RELIABLE, p->ocseq);
}
@@ -9899,26 +9917,49 @@
return 0;
}
+
+/*! \brief If there's a state change DURING a PUBLISH transaction, we need to send a new PUBLISH as
+ soon as the previous one is completed. The RFC states only one PUBLISh transaction at a time
+ from one EPA to the same URI.
+*/
+static void dlginfo_check_nextstatus(struct sip_epa_entry *epa_entry)
+{
+ struct sip_published_device *device = (struct sip_published_device *) epa_entry->instance_data;
+ if (device->nextstate != -1) {
+ /* Add to the device change thread queue */
+ if (option_debug > 2) {
+ ast_log(LOG_DEBUG, "Device %s have nextstate, adding to queue\n", device->name);
+ }
+ //XXX OEJ PINANA _ This is disabled as it generates strange segfaults
+ //sip_devicestate_cb(device->name, device->nextstate, NULL);
+ device->nextstate = -1; /* Reset next state change */
+ }
+}
+
+
/*! \brief Handle errors when publishing dialog-info stuff */
static void dlginfo_handle_publish_error(struct sip_pvt *pvt, const int resp, struct sip_request *req, struct sip_epa_entry *epa_entry)
{
/* Do we really care of errors here? */
ast_log(LOG_DEBUG, "-- %s : PUBLISH error response code %d\n", pvt->callid, resp);
+ dlginfo_check_nextstatus(epa_entry);
return;
}
/*! \brief Handle a 200 OK to a published dialog-info */
static void dlginfo_handle_publish_ok(struct sip_pvt *pvt, struct sip_request *req, struct sip_epa_entry *epa_entry)
{
- char *etag = get_header(req, "SIP-ETag");
+ const char *etag = get_header(req, "SIP-ETag");
ast_copy_string(epa_entry->entity_tag, etag, sizeof(epa_entry->entity_tag));
+ dlginfo_check_nextstatus(epa_entry);
return;
}
static void dlginfo_epa_destructor(void *data)
{
/* PINANA XXX needs fixing???? */
- //struct sip_epa_entry *epa_entry = data;
+ struct sip_epa_entry *epa_entry = data;
+ ast_log(LOG_DEBUG, "*** Destroying EPA entry \n");
//struct dlginfo_epa_entry *dlginfo_entry = epa_entry->instance_data;
//ast_free(dlginfo_entry);
}
@@ -9955,7 +9996,7 @@
i = ao2_iterator_init(pub_dev, 0);
while ((device = ao2_iterator_next(&i))) {
ast_log(LOG_DEBUG, " PUBLISH: Comparing %s and device %s\n", device->name, sc->dev);
- if (!strcasecmp(device->pubname, pres_server->name) && !strcasecmp(device->name, sc->dev)) {
+ if (!found && !strcasecmp(device->pubname, pres_server->name) && !strcasecmp(device->name, sc->dev)) {
//Most or all of this code duplication will go away when we start using libxml2
char uri[SIPBUFSIZE];
char body[SIPBUFSIZE * 2];
@@ -9965,15 +10006,26 @@
found = TRUE;
ast_log(LOG_DEBUG, "*** Found our friend %s in the existing list \n", device->name);
- if (device->laststate == sc->state) {
+ if (device->epa && device->epa->epa_state != TERMINATED) {
+ /* We already have a PUBLISH transaction. Let's skip this or put it on the queue */
+ if (device->laststate != sc->state) {
+ ast_log(LOG_DEBUG, "--- We have an outstanding request for %s. Setting nextstate and kipping.\n", device->name);
+ device->nextstate = sc->state;
+ }
+ } else if (device->laststate == sc->state) {
ast_log(LOG_DEBUG, "--- No change, skipping PUBLISH for %s\n", device->name);
} else {
+ device->laststate = sc->state;
+ device->nextstate = -1;
generate_random_string(dlg_id, sizeof(dlg_id));
- ast_log(LOG_WARNING, "Device state is %d, %s\n", sc->state, ast_devstate_str(sc->state));
+ if (option_debug > 2) {
+ ast_log(LOG_DEBUG, "New device state for %s is %d, %s\n", device->name, sc->state, ast_devstate_str(sc->state));
+ }
snprintf(uri, sizeof(uri), "sip:%s@%s", sc->dev, pres_server->domain);
presence_build_dialoginfo_xml(body, &maxbytes, 1, ast_devstate_str(sc->state), dlg_id, 1, uri, 0);
ast_copy_string(device->epa->body, body, sizeof(device->epa->body));
publish_type = SIP_PUBLISH_MODIFY;
+ device->epa->epa_state = INITIATED;
transmit_publish(device->epa, publish_type, uri);
/* Do stuff here */
}
@@ -10003,6 +10055,7 @@
ast_log(LOG_ERROR, "Cannot allocate sip_epa_entry!\n");
return -1;
}
+ device->epa->instance_data = (void *) device;
ast_copy_string(device->name, sc->dev, sizeof(device->name));
ast_copy_string(device->pubname, pres_server->name, sizeof(device->pubname));
/* Initiate stuff */
@@ -10015,6 +10068,7 @@
device->epa->publish_type = publish_type;
ast_copy_string(device->epa->entity_tag, create_new_etag(), sizeof(device->epa->entity_tag));
ast_log(LOG_DEBUG, "*** Created new publish device for %s with URI %s\n", sc->dev, uri);
+ device->epa->epa_state = INITIATED;
transmit_publish(device->epa, publish_type, uri);
ast_log(LOG_DEBUG, "*** Published update for device %s\n", sc->dev);
/* ----------------------------- Current state:
@@ -10122,7 +10176,9 @@
static int sip_devicestate_cb(const char *dev, int state, void *ign)
{
struct statechange *sc;
- ast_log(LOG_DEBUG, "---PUBLISH: Got state change for %s - do we care? Really? Oh, I did not know. \n", dev);
+ if (option_debug > 2) {
+ ast_log(LOG_DEBUG, "---PUBLISH: Got state change for %s - Queing up\n", dev);
+ }
if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1))) {
return 0;
@@ -19559,7 +19615,9 @@
return 0;
}
-/*! \brief Handle responses from PUBLISH request */
+/*! \brief Handle responses from PUBLISH request
+ Todo: We should handle 503 and 491 gracefully and retry after a while unless we have a nextstate (dialoginfo)
+*/
static void handle_response_publish(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno)
{
struct sip_epa_entry *epa_entry = p->epa_entry;
@@ -19570,6 +19628,11 @@
if (resp < 200 ) { /* Provisional responses */
return;
}
+
+ if (!epa_entry) {
+ ast_log(LOG_ERROR, "No epa_entry on a PUBLISH? Something's broken...\n");
+ }
+ epa_entry->epa_state = TERMINATED; /* Transaction is over and gone */
if (resp == 401 || resp == 407) {
ast_string_field_set(p, theirtag, NULL);
@@ -19607,6 +19670,8 @@
if (epa_entry->static_data->handle_ok) {
epa_entry->static_data->handle_ok(p, req, epa_entry);
}
+ /*XXX maybe Check if we have another state change waiting */
+ needdestroy = TRUE;
} else {
/* Rather than try to make individual callbacks for each error
* type, there is just a single error callback. The callback
@@ -19615,10 +19680,12 @@
if (epa_entry->static_data->handle_error) {
epa_entry->static_data->handle_error(p, resp, req, epa_entry);
}
+ needdestroy = TRUE;
}
if (needdestroy) {
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
}
+
}
/* \brief Handle SIP response in SUBSCRIBE transaction */
More information about the svn-commits
mailing list