* Copyright (c) 2000-2003 Intel Corporation
* Copyright (c) 2006-2007 Sony Corporation
* Copyright (c) 2008-2009 Atheros Communications
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
*
* See wps_upnp.c for more details on licensing and code history.
*/
*/
#define MAX_EVENTS_QUEUED 20 /* How far behind queued events */
-#define EVENT_TIMEOUT_SEC 30 /* Drop sending event after timeout */
/* How long to wait before sending event */
#define EVENT_DELAY_SECONDS 0
* TODO: As an optimization we could share data between subscribers.
*/
struct wps_event_ {
- struct wps_event_ *next;
- struct wps_event_ *prev; /* double linked list */
+ struct dl_list list;
struct subscription *s; /* parent */
unsigned subscriber_sequence; /* which event for this subscription*/
unsigned int retry; /* which retry */
*/
static void event_delete(struct wps_event_ *e)
{
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Delete event %p", e);
event_clean(e);
wpabuf_free(e->data);
os_free(e);
*/
static struct wps_event_ *event_dequeue(struct subscription *s)
{
- struct wps_event_ **event_head = &s->event_queue;
- struct wps_event_ *e = *event_head;
- if (e == NULL)
- return NULL;
- e->next->prev = e->prev;
- e->prev->next = e->next;
- if (*event_head == e) {
- if (e == e->next) {
- /* last in queue */
- *event_head = NULL;
- } else {
- *event_head = e->next;
- }
+ struct wps_event_ *e;
+ e = dl_list_first(&s->event_queue, struct wps_event_, list);
+ if (e) {
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Dequeue event %p for "
+ "subscription %p", e, s);
+ dl_list_del(&e->list);
}
- s->n_queue--;
- e->next = e->prev = NULL;
- /* but parent "s" is still valid */
return e;
}
-/* event_enqueue_at_end -- add event to end of queue */
-static void event_enqueue_at_end(struct subscription *s, struct wps_event_ *e)
-{
- struct wps_event_ **event_head = &s->event_queue;
- if (*event_head == NULL) {
- *event_head = e->next = e->prev = e;
- } else {
- e->next = *event_head;
- e->prev = e->next->prev;
- e->prev->next = e;
- e->next->prev = e;
- }
- s->n_queue++;
-}
-
-
-/* event_enqueue_at_begin -- add event to begin of queue
- * (appropriate for retrying event only)
- */
-static void event_enqueue_at_begin(struct subscription *s,
- struct wps_event_ *e)
-{
- struct wps_event_ **event_head = &s->event_queue;
- if (*event_head == NULL) {
- *event_head = e->next = e->prev = e;
- } else {
- e->prev = *event_head;
- e->next = e->prev->next;
- e->prev->next = e;
- e->next->prev = e;
- *event_head = e;
- }
- s->n_queue++;
-}
-
-
/* event_delete_all -- delete entire event queue and current event */
void event_delete_all(struct subscription *s)
{
struct subscription *s = e->s;
struct upnp_wps_device_sm *sm = s->sm;
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Retry event %p for subscription %p",
+ e, s);
event_clean(e);
/* will set: s->current_event = NULL; */
- if (do_next_address)
+ if (do_next_address) {
e->retry++;
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Try address %d", e->retry);
+ }
if (e->retry >= dl_list_len(&s->addr_list)) {
wpa_printf(MSG_DEBUG, "WPS UPnP: Giving up on sending event "
"for %s", e->addr->domain_and_port);
+ event_delete(e);
return;
}
- event_enqueue_at_begin(s, e);
+ dl_list_add(&s->event_queue, &e->list);
event_send_all_later(sm);
}
struct wps_event_ *e = ctx;
struct subscription *s = e->s;
+ wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP client callback: e=%p c=%p "
+ "event=%d", e, c, event);
switch (event) {
case HTTP_CLIENT_OK:
wpa_printf(MSG_DEBUG,
- "WPS UPnP: Got event reply OK from "
- "%s", e->addr->domain_and_port);
+ "WPS UPnP: Got event %p reply OK from %s",
+ e, e->addr->domain_and_port);
event_delete(e);
/* Schedule sending more if there is more to send */
- if (s->event_queue)
+ if (!dl_list_empty(&s->event_queue))
event_send_all_later(s->sm);
break;
case HTTP_CLIENT_FAILED:
* Assume we are called ONLY with no current event and ONLY with
* nonempty event queue and ONLY with at least one address to send to.
*/
- assert(!dl_list_empty(&s->addr_list));
- assert(s->current_event == NULL);
- assert(s->event_queue != NULL);
+ if (dl_list_empty(&s->addr_list))
+ return -1;
+ if (s->current_event)
+ return -1;
+ if (dl_list_empty(&s->event_queue))
+ return -1;
s->current_event = e = event_dequeue(s);
subscription_destroy(s);
} else {
if (s->current_event == NULL /* not busy */ &&
- s->event_queue != NULL /* more to do */) {
+ !dl_list_empty(&s->event_queue) /* more to do */) {
if (event_send_start(s))
nerrors++;
}
int event_add(struct subscription *s, const struct wpabuf *data)
{
struct wps_event_ *e;
+ unsigned int len;
- if (s->n_queue >= MAX_EVENTS_QUEUED) {
+ len = dl_list_len(&s->event_queue);
+ if (len >= MAX_EVENTS_QUEUED) {
wpa_printf(MSG_DEBUG, "WPS UPnP: Too many events queued for "
- "subscriber");
+ "subscriber %p", s);
return 1;
}
e = os_zalloc(sizeof(*e));
if (e == NULL)
return 1;
+ dl_list_init(&e->list);
e->s = s;
e->data = wpabuf_dup(data);
if (e->data == NULL) {
e->subscriber_sequence = s->next_subscriber_sequence++;
if (s->next_subscriber_sequence == 0)
s->next_subscriber_sequence++;
- event_enqueue_at_end(s, e);
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Queue event %p for subscriber %p "
+ "(queue len %u)", e, s, len + 1);
+ dl_list_add_tail(&s->event_queue, &e->list);
event_send_all_later(s->sm);
return 0;
}