WPS: Limit Probe Request event queuing if subscriber may have left
authorJouni Malinen <j@w1.fi>
Sun, 17 Oct 2010 17:58:58 +0000 (20:58 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 17 Oct 2010 17:58:58 +0000 (20:58 +0300)
Instead of queuing all events for a subscriber, only queue more
important events if delivery of event notifications starts failing.
This allows more time for the subscriber to recover since the maximum
queue length if not reached because of Probe Request frames only.

src/wps/wps_upnp.c
src/wps/wps_upnp_event.c
src/wps/wps_upnp_i.h

index 4c0a5c1..410df46 100644 (file)
@@ -499,7 +499,8 @@ static void upnp_wps_device_send_event(struct upnp_wps_device_sm *sm)
 
        dl_list_for_each_safe(s, tmp, &sm->subscriptions, struct subscription,
                              list) {
 
        dl_list_for_each_safe(s, tmp, &sm->subscriptions, struct subscription,
                              list) {
-               if (event_add(s, buf) == 1) {
+               if (event_add(s, buf, sm->wlanevent_type ==
+                             UPNP_WPS_WLANEVENT_TYPE_PROBE) == 1) {
                        wpa_printf(MSG_INFO, "WPS UPnP: Dropping "
                                   "subscriber %p due to event backlog", s);
                        dl_list_del(&s->list);
                        wpa_printf(MSG_INFO, "WPS UPnP: Dropping "
                                   "subscriber %p due to event backlog", s);
                        dl_list_del(&s->list);
@@ -650,7 +651,7 @@ static int subscription_first_event(struct subscription *s)
                wpabuf_put_property(buf, "WLANEvent", wlan_event);
        wpabuf_put_str(buf, tail);
 
                wpabuf_put_property(buf, "WLANEvent", wlan_event);
        wpabuf_put_str(buf, tail);
 
-       ret = event_add(s, buf);
+       ret = event_add(s, buf, 0);
        if (ret) {
                wpabuf_free(buf);
                return ret;
        if (ret) {
                wpabuf_free(buf);
                return ret;
@@ -798,6 +799,7 @@ int upnp_wps_device_send_wlan_event(struct upnp_wps_device_sm *sm,
 
        os_free(sm->wlanevent);
        sm->wlanevent = val;
 
        os_free(sm->wlanevent);
        sm->wlanevent = val;
+       sm->wlanevent_type = ev_type;
        upnp_wps_device_send_event(sm);
 
        ret = 0;
        upnp_wps_device_send_event(sm);
 
        ret = 0;
index 6555f9e..8c3ded8 100644 (file)
@@ -132,6 +132,7 @@ static void event_retry(struct wps_event_ *e, int do_next_address)
                wpa_printf(MSG_DEBUG, "WPS UPnP: Giving up on sending event "
                           "for %s", e->addr->domain_and_port);
                event_delete(e);
                wpa_printf(MSG_DEBUG, "WPS UPnP: Giving up on sending event "
                           "for %s", e->addr->domain_and_port);
                event_delete(e);
+               s->last_event_failed = 1;
                if (!dl_list_empty(&s->event_queue))
                        event_send_all_later(s->sm);
                return;
                if (!dl_list_empty(&s->event_queue))
                        event_send_all_later(s->sm);
                return;
@@ -222,6 +223,7 @@ static void event_http_cb(void *ctx, struct http_client *c,
                           "WPS UPnP: Got event %p reply OK from %s",
                           e, e->addr->domain_and_port);
                e->addr->num_failures = 0;
                           "WPS UPnP: Got event %p reply OK from %s",
                           e, e->addr->domain_and_port);
                e->addr->num_failures = 0;
+               s->last_event_failed = 0;
                event_delete(e);
 
                /* Schedule sending more if there is more to send */
                event_delete(e);
 
                /* Schedule sending more if there is more to send */
@@ -367,9 +369,10 @@ void event_send_stop_all(struct upnp_wps_device_sm *sm)
  * event_add - Add a new event to a queue
  * @s: Subscription
  * @data: Event data (is copied; caller retains ownership)
  * event_add - Add a new event to a queue
  * @s: Subscription
  * @data: Event data (is copied; caller retains ownership)
+ * @probereq: Whether this is a Probe Request event
  * Returns: 0 on success, -1 on error, 1 on max event queue limit reached
  */
  * Returns: 0 on success, -1 on error, 1 on max event queue limit reached
  */
-int event_add(struct subscription *s, const struct wpabuf *data)
+int event_add(struct subscription *s, const struct wpabuf *data, int probereq)
 {
        struct wps_event_ *e;
        unsigned int len;
 {
        struct wps_event_ *e;
        unsigned int len;
@@ -381,6 +384,17 @@ int event_add(struct subscription *s, const struct wpabuf *data)
                return 1;
        }
 
                return 1;
        }
 
+       if (s->last_event_failed && probereq && len > 0) {
+               /*
+                * Avoid queuing frames for subscribers that may have left
+                * without unsubscribing.
+                */
+               wpa_printf(MSG_DEBUG, "WPS UPnP: Do not queue more Probe "
+                          "Request frames for subscription %p since last "
+                          "delivery failed", s);
+               return -1;
+       }
+
        e = os_zalloc(sizeof(*e));
        if (e == NULL)
                return -1;
        e = os_zalloc(sizeof(*e));
        if (e == NULL)
                return -1;
index 68782c0..4143eca 100644 (file)
@@ -92,6 +92,7 @@ struct subscription {
        struct dl_list event_queue; /* Queued event messages. */
        struct wps_event_ *current_event; /* non-NULL if being sent (not in q)
                                           */
        struct dl_list event_queue; /* Queued event messages. */
        struct wps_event_ *current_event; /* non-NULL if being sent (not in q)
                                           */
+       int last_event_failed; /* Whether delivery of last event failed */
 
        /* Information from SetSelectedRegistrar action */
        u8 selected_registrar;
 
        /* Information from SetSelectedRegistrar action */
        u8 selected_registrar;
@@ -132,6 +133,7 @@ struct upnp_wps_device_sm {
                                    */
 
        char *wlanevent; /* the last WLANEvent data */
                                    */
 
        char *wlanevent; /* the last WLANEvent data */
+       enum upnp_wps_wlanevent_type wlanevent_type;
 
        /* FIX: maintain separate structures for each UPnP peer */
        struct upnp_wps_peer peer;
 
        /* FIX: maintain separate structures for each UPnP peer */
        struct upnp_wps_peer peer;
@@ -168,7 +170,7 @@ int web_listener_start(struct upnp_wps_device_sm *sm);
 void web_listener_stop(struct upnp_wps_device_sm *sm);
 
 /* wps_upnp_event.c */
 void web_listener_stop(struct upnp_wps_device_sm *sm);
 
 /* wps_upnp_event.c */
-int event_add(struct subscription *s, const struct wpabuf *data);
+int event_add(struct subscription *s, const struct wpabuf *data, int probereq);
 void event_delete_all(struct subscription *s);
 void event_send_all_later(struct upnp_wps_device_sm *sm);
 void event_send_stop_all(struct upnp_wps_device_sm *sm);
 void event_delete_all(struct subscription *s);
 void event_send_all_later(struct upnp_wps_device_sm *sm);
 void event_send_stop_all(struct upnp_wps_device_sm *sm);