WPS: Convert struct subscription to use struct dl_list

This commit is contained in:
Jouni Malinen 2009-12-19 14:15:43 +02:00
parent f98b440c47
commit ec32c29471
5 changed files with 50 additions and 107 deletions

View file

@ -2762,8 +2762,8 @@ static void wps_registrar_sel_reg_union(struct wps_registrar *reg)
if (reg->wps->wps_upnp == NULL) if (reg->wps->wps_upnp == NULL)
return; return;
s = reg->wps->wps_upnp->subscriptions; dl_list_for_each(s, &reg->wps->wps_upnp->subscriptions,
while (s) { struct subscription, list) {
struct subscr_addr *sa; struct subscr_addr *sa;
sa = dl_list_first(&s->addr_list, struct subscr_addr, list); sa = dl_list_first(&s->addr_list, struct subscr_addr, list);
if (sa) { if (sa) {
@ -2776,10 +2776,6 @@ static void wps_registrar_sel_reg_union(struct wps_registrar *reg)
else else
wpa_printf(MSG_DEBUG, "WPS: External Registrar not " wpa_printf(MSG_DEBUG, "WPS: External Registrar not "
"selected"); "selected");
s = s->next;
if (s == reg->wps->wps_upnp->subscriptions)
break;
} }
#endif /* CONFIG_WPS_UPNP */ #endif /* CONFIG_WPS_UPNP */
} }

View file

@ -467,14 +467,14 @@ static void upnp_wps_device_send_event(struct upnp_wps_device_sm *sm)
/* Enqueue event message for all subscribers */ /* Enqueue event message for all subscribers */
struct wpabuf *buf; /* holds event message */ struct wpabuf *buf; /* holds event message */
int buf_size = 0; int buf_size = 0;
struct subscription *s; struct subscription *s, *tmp;
/* Actually, utf-8 is the default, but it doesn't hurt to specify it */ /* Actually, utf-8 is the default, but it doesn't hurt to specify it */
const char *format_head = const char *format_head =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">\n"; "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">\n";
const char *format_tail = "</e:propertyset>\n"; const char *format_tail = "</e:propertyset>\n";
if (sm->subscriptions == NULL) { if (dl_list_empty(&sm->subscriptions)) {
/* optimize */ /* optimize */
return; return;
} }
@ -496,19 +496,15 @@ static void upnp_wps_device_send_event(struct upnp_wps_device_sm *sm)
wpa_printf(MSG_MSGDUMP, "WPS UPnP: WLANEvent message:\n%s", wpa_printf(MSG_MSGDUMP, "WPS UPnP: WLANEvent message:\n%s",
(char *) wpabuf_head(buf)); (char *) wpabuf_head(buf));
s = sm->subscriptions; dl_list_for_each_safe(s, tmp, &sm->subscriptions, struct subscription,
do { list) {
if (event_add(s, buf)) { if (event_add(s, buf)) {
struct subscription *s_old = s;
wpa_printf(MSG_INFO, "WPS UPnP: Dropping " wpa_printf(MSG_INFO, "WPS UPnP: Dropping "
"subscriber due to event backlog"); "subscriber due to event backlog");
s = s_old->next; dl_list_del(&s->list);
subscription_unlink(s_old); subscription_destroy(s);
subscription_destroy(s_old);
} else {
s = s->next;
} }
} while (s != sm->subscriptions); }
wpabuf_free(buf); wpabuf_free(buf);
} }
@ -520,43 +516,6 @@ static void upnp_wps_device_send_event(struct upnp_wps_device_sm *sm)
* This is the result of an incoming HTTP over TCP SUBSCRIBE request. * This is the result of an incoming HTTP over TCP SUBSCRIBE request.
*/ */
/* subscription_unlink -- remove from the active list */
void subscription_unlink(struct subscription *s)
{
struct upnp_wps_device_sm *sm = s->sm;
if (s->next == s) {
/* only one? */
sm->subscriptions = NULL;
} else {
if (sm->subscriptions == s)
sm->subscriptions = s->next;
s->next->prev = s->prev;
s->prev->next = s->next;
}
sm->n_subscriptions--;
}
/* subscription_link_to_end -- link to end of active list
* (should have high expiry time!)
*/
static void subscription_link_to_end(struct subscription *s)
{
struct upnp_wps_device_sm *sm = s->sm;
if (sm->subscriptions) {
s->next = sm->subscriptions;
s->prev = s->next->prev;
s->prev->next = s;
s->next->prev = s;
} else {
sm->subscriptions = s->next = s->prev = s;
}
sm->n_subscriptions++;
}
/* subscription_destroy -- destroy an unlinked subscription /* subscription_destroy -- destroy an unlinked subscription
* Be sure to unlink first if necessary. * Be sure to unlink first if necessary.
*/ */
@ -573,10 +532,13 @@ void subscription_destroy(struct subscription *s)
/* subscription_list_age -- remove expired subscriptions */ /* subscription_list_age -- remove expired subscriptions */
static void subscription_list_age(struct upnp_wps_device_sm *sm, time_t now) static void subscription_list_age(struct upnp_wps_device_sm *sm, time_t now)
{ {
struct subscription *s; struct subscription *s, *tmp;
while ((s = sm->subscriptions) != NULL && s->timeout_time < now) { dl_list_for_each_safe(s, tmp, &sm->subscriptions,
struct subscription, list) {
if (s->timeout_time > now)
break;
wpa_printf(MSG_DEBUG, "WPS UPnP: Removing aged subscription"); wpa_printf(MSG_DEBUG, "WPS UPnP: Removing aged subscription");
subscription_unlink(s); dl_list_del(&s->list);
subscription_destroy(s); subscription_destroy(s);
} }
} }
@ -588,17 +550,11 @@ static void subscription_list_age(struct upnp_wps_device_sm *sm, time_t now)
struct subscription * subscription_find(struct upnp_wps_device_sm *sm, struct subscription * subscription_find(struct upnp_wps_device_sm *sm,
const u8 uuid[UUID_LEN]) const u8 uuid[UUID_LEN])
{ {
struct subscription *s0 = sm->subscriptions; struct subscription *s;
struct subscription *s = s0; dl_list_for_each(s, &sm->subscriptions, struct subscription, list) {
if (s0 == NULL)
return NULL;
do {
if (os_memcmp(s->uuid, uuid, UUID_LEN) == 0) if (os_memcmp(s->uuid, uuid, UUID_LEN) == 0)
return s; /* Found match */ return s; /* Found match */
s = s->next; }
} while (s != s0);
return NULL; return NULL;
} }
@ -715,11 +671,12 @@ struct subscription * subscription_start(struct upnp_wps_device_sm *sm,
subscription_list_age(sm, now); subscription_list_age(sm, now);
/* If too many subscriptions, remove oldest */ /* If too many subscriptions, remove oldest */
if (sm->n_subscriptions >= MAX_SUBSCRIPTIONS) { if (dl_list_len(&sm->subscriptions) >= MAX_SUBSCRIPTIONS) {
s = sm->subscriptions; s = dl_list_first(&sm->subscriptions, struct subscription,
list);
wpa_printf(MSG_INFO, "WPS UPnP: Too many subscriptions, " wpa_printf(MSG_INFO, "WPS UPnP: Too many subscriptions, "
"trashing oldest"); "trashing oldest");
subscription_unlink(s); dl_list_del(&s->list);
subscription_destroy(s); subscription_destroy(s);
} }
@ -733,14 +690,14 @@ struct subscription * subscription_start(struct upnp_wps_device_sm *sm,
uuid_make(s->uuid); uuid_make(s->uuid);
subscr_addr_list_create(s, callback_urls); subscr_addr_list_create(s, callback_urls);
/* Add to end of list, since it has the highest expiration time */ /* Add to end of list, since it has the highest expiration time */
subscription_link_to_end(s); dl_list_add_tail(&sm->subscriptions, &s->list);
/* Queue up immediate event message (our last event) /* Queue up immediate event message (our last event)
* as required by UPnP spec. * as required by UPnP spec.
*/ */
if (subscription_first_event(s)) { if (subscription_first_event(s)) {
wpa_printf(MSG_INFO, "WPS UPnP: Dropping subscriber due to " wpa_printf(MSG_INFO, "WPS UPnP: Dropping subscriber due to "
"event backlog"); "event backlog");
subscription_unlink(s); dl_list_del(&s->list);
subscription_destroy(s); subscription_destroy(s);
return NULL; return NULL;
} }
@ -762,10 +719,10 @@ struct subscription * subscription_renew(struct upnp_wps_device_sm *sm,
if (s == NULL) if (s == NULL)
return NULL; return NULL;
wpa_printf(MSG_DEBUG, "WPS UPnP: Subscription renewed"); wpa_printf(MSG_DEBUG, "WPS UPnP: Subscription renewed");
subscription_unlink(s); dl_list_del(&s->list);
s->timeout_time = expire; s->timeout_time = expire;
/* add back to end of list, since it now has highest expiry */ /* add back to end of list, since it now has highest expiry */
subscription_link_to_end(s); dl_list_add_tail(&sm->subscriptions, &s->list);
return s; return s;
} }
@ -950,6 +907,16 @@ fail:
} }
static void upnp_wps_free_subscriptions(struct dl_list *head)
{
struct subscription *s, *tmp;
dl_list_for_each_safe(s, tmp, head, struct subscription, list) {
dl_list_del(&s->list);
subscription_destroy(s);
}
}
/** /**
* upnp_wps_device_stop - Stop WPS UPnP operations on an interface * upnp_wps_device_stop - Stop WPS UPnP operations on an interface
* @sm: WPS UPnP state machine from upnp_wps_device_init() * @sm: WPS UPnP state machine from upnp_wps_device_init()
@ -963,11 +930,7 @@ void upnp_wps_device_stop(struct upnp_wps_device_sm *sm)
web_listener_stop(sm); web_listener_stop(sm);
while (sm->msearch_replies) while (sm->msearch_replies)
msearchreply_state_machine_stop(sm->msearch_replies); msearchreply_state_machine_stop(sm->msearch_replies);
while (sm->subscriptions) { upnp_wps_free_subscriptions(&sm->subscriptions);
struct subscription *s = sm->subscriptions;
subscription_unlink(s);
subscription_destroy(s);
}
advertisement_state_machine_stop(sm, 1); advertisement_state_machine_stop(sm, 1);
@ -1095,6 +1058,7 @@ upnp_wps_device_init(struct upnp_wps_device_ctx *ctx, struct wps_context *wps,
sm->ctx = ctx; sm->ctx = ctx;
sm->wps = wps; sm->wps = wps;
sm->priv = priv; sm->priv = priv;
dl_list_init(&sm->subscriptions);
return sm; return sm;
} }
@ -1107,5 +1071,5 @@ upnp_wps_device_init(struct upnp_wps_device_ctx *ctx, struct wps_context *wps,
*/ */
int upnp_wps_subscribers(struct upnp_wps_device_sm *sm) int upnp_wps_subscribers(struct upnp_wps_device_sm *sm)
{ {
return sm->subscriptions != NULL; return !dl_list_empty(&sm->subscriptions);
} }

View file

@ -238,7 +238,7 @@ static void event_http_cb(void *ctx, struct http_client *c,
*/ */
wpa_printf(MSG_DEBUG, "WPS UPnP: Deleting subscription due to " wpa_printf(MSG_DEBUG, "WPS UPnP: Deleting subscription due to "
"errors"); "errors");
subscription_unlink(s); dl_list_del(&s->list);
subscription_destroy(s); subscription_destroy(s);
break; break;
case HTTP_CLIENT_TIMEOUT: case HTTP_CLIENT_TIMEOUT:
@ -314,32 +314,26 @@ static int event_send_start(struct subscription *s)
static void event_send_all_later_handler(void *eloop_data, void *user_ctx) static void event_send_all_later_handler(void *eloop_data, void *user_ctx)
{ {
struct upnp_wps_device_sm *sm = user_ctx; struct upnp_wps_device_sm *sm = user_ctx;
struct subscription *s; struct subscription *s, *tmp;
struct subscription *s_old;
int nerrors = 0; int nerrors = 0;
sm->event_send_all_queued = 0; sm->event_send_all_queued = 0;
s = sm->subscriptions; dl_list_for_each_safe(s, tmp, &sm->subscriptions, struct subscription,
if (s == NULL) list) {
return;
do {
if (dl_list_empty(&s->addr_list)) { if (dl_list_empty(&s->addr_list)) {
/* if we've given up on all addresses */ /* if we've given up on all addresses */
wpa_printf(MSG_DEBUG, "WPS UPnP: Removing " wpa_printf(MSG_DEBUG, "WPS UPnP: Removing "
"subscription with no addresses"); "subscription with no addresses");
s_old = s; dl_list_del(&s->list);
s = s_old->next; subscription_destroy(s);
subscription_unlink(s_old);
subscription_destroy(s_old);
} else { } else {
if (s->current_event == NULL /* not busy */ && if (s->current_event == NULL /* not busy */ &&
s->event_queue != NULL /* more to do */) { s->event_queue != NULL /* more to do */) {
if (event_send_start(s)) if (event_send_start(s))
nerrors++; nerrors++;
} }
s = s->next;
} }
} while (sm->subscriptions != NULL && s != sm->subscriptions); }
if (nerrors) { if (nerrors) {
/* Try again later */ /* Try again later */

View file

@ -81,9 +81,7 @@ struct subscr_addr {
* also have to age out subscribers unless they renew. * also have to age out subscribers unless they renew.
*/ */
struct subscription { struct subscription {
/* double linked list */ struct dl_list list;
struct subscription *next;
struct subscription *prev;
struct upnp_wps_device_sm *sm; /* parent */ struct upnp_wps_device_sm *sm; /* parent */
time_t timeout_time; /* when to age out the subscription */ time_t timeout_time; /* when to age out the subscription */
unsigned next_subscriber_sequence; /* number our messages */ unsigned next_subscriber_sequence; /* number our messages */
@ -136,8 +134,7 @@ struct upnp_wps_device_sm {
int web_port; /* our port that others get xml files from */ int web_port; /* our port that others get xml files from */
struct http_server *web_srv; struct http_server *web_srv;
/* Note: subscriptions are kept in expiry order */ /* Note: subscriptions are kept in expiry order */
struct subscription *subscriptions; /* linked list */ struct dl_list subscriptions;
int n_subscriptions; /* no of current subscriptions */
int event_send_all_queued; /* if we are scheduled to send events soon int event_send_all_queued; /* if we are scheduled to send events soon
*/ */
@ -153,7 +150,6 @@ struct subscription * subscription_start(struct upnp_wps_device_sm *sm,
const char *callback_urls); const char *callback_urls);
struct subscription * subscription_renew(struct upnp_wps_device_sm *sm, struct subscription * subscription_renew(struct upnp_wps_device_sm *sm,
const u8 uuid[UUID_LEN]); const u8 uuid[UUID_LEN]);
void subscription_unlink(struct subscription *s);
void subscription_destroy(struct subscription *s); void subscription_destroy(struct subscription *s);
struct subscription * subscription_find(struct upnp_wps_device_sm *sm, struct subscription * subscription_find(struct upnp_wps_device_sm *sm,
const u8 uuid[UUID_LEN]); const u8 uuid[UUID_LEN]);

View file

@ -553,16 +553,9 @@ static struct subscription * find_er(struct upnp_wps_device_sm *sm,
struct sockaddr_in *cli) struct sockaddr_in *cli)
{ {
struct subscription *s; struct subscription *s;
dl_list_for_each(s, &sm->subscriptions, struct subscription, list)
s = sm->subscriptions;
while (s) {
if (find_er_addr(s, cli)) if (find_er_addr(s, cli))
return s; return s;
s = s->next;
if (s == sm->subscriptions)
break;
}
return NULL; return NULL;
} }
@ -1136,7 +1129,7 @@ static void web_connection_parse_unsubscribe(struct upnp_wps_device_sm *sm,
wpa_printf(MSG_DEBUG, "WPS UPnP: Unsubscribing %p %s", wpa_printf(MSG_DEBUG, "WPS UPnP: Unsubscribing %p %s",
s, (sa && sa->domain_and_port) ? s, (sa && sa->domain_and_port) ?
sa->domain_and_port : "-null-"); sa->domain_and_port : "-null-");
subscription_unlink(s); dl_list_del(&s->list);
subscription_destroy(s); subscription_destroy(s);
} }
} else { } else {