WPS: Convert struct subscription to use struct dl_list
This commit is contained in:
parent
f98b440c47
commit
ec32c29471
5 changed files with 50 additions and 107 deletions
|
@ -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, ®->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 */
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue