WPS: Send SSDP byebye notifications when stopping UPnP advertisements
authorJouni Malinen <j@w1.fi>
Sat, 14 Nov 2009 22:46:58 +0000 (00:46 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 14 Nov 2009 22:46:58 +0000 (00:46 +0200)
This will notify control points of the services going away and allows
them to notice this without having to wait timeout on the
initial advertisements.

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

index 07b5bce..eaadd27 100644 (file)
@@ -964,8 +964,7 @@ void upnp_wps_device_stop(struct upnp_wps_device_sm *sm)
                subscription_destroy(s);
        }
 
-       advertisement_state_machine_stop(sm);
-       /* TODO: send byebye notifications */
+       advertisement_state_machine_stop(sm, 1);
 
        event_send_stop_all(sm);
        os_free(sm->wlanevent);
index ac8a710..63e6506 100644 (file)
@@ -159,7 +159,8 @@ int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text,
 /* wps_upnp_ssdp.c */
 void msearchreply_state_machine_stop(struct advertisement_state_machine *a);
 int advertisement_state_machine_start(struct upnp_wps_device_sm *sm);
-void advertisement_state_machine_stop(struct upnp_wps_device_sm *sm);
+void advertisement_state_machine_stop(struct upnp_wps_device_sm *sm,
+                                     int send_byebye);
 void ssdp_listener_stop(struct upnp_wps_device_sm *sm);
 int ssdp_listener_start(struct upnp_wps_device_sm *sm);
 int ssdp_listener_open(void);
index 3ffff09..93706ea 100644 (file)
@@ -228,10 +228,41 @@ static void advertisement_state_machine_handler(void *eloop_data,
 /**
  * advertisement_state_machine_stop - Stop SSDP advertisements
  * @sm: WPS UPnP state machine from upnp_wps_device_init()
+ * @send_byebye: Send byebye advertisement messages immediately
  */
-void advertisement_state_machine_stop(struct upnp_wps_device_sm *sm)
+void advertisement_state_machine_stop(struct upnp_wps_device_sm *sm,
+                                     int send_byebye)
 {
+       struct advertisement_state_machine *a = &sm->advertisement;
+       int islast = 0;
+       struct wpabuf *msg;
+       struct sockaddr_in dest;
+
        eloop_cancel_timeout(advertisement_state_machine_handler, NULL, sm);
+       if (!send_byebye)
+               return;
+
+       a->type = ADVERTISE_DOWN;
+       a->state = 0;
+       a->sm = sm;
+
+       os_memset(&dest, 0, sizeof(dest));
+       dest.sin_family = AF_INET;
+       dest.sin_addr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS);
+       dest.sin_port = htons(UPNP_MULTICAST_PORT);
+
+       while (!islast) {
+               msg = next_advertisement(a, &islast);
+               if (msg == NULL)
+                       break;
+               if (sendto(sm->multicast_sd, wpabuf_head(msg), wpabuf_len(msg),
+                          0, (struct sockaddr *) &dest, sizeof(dest)) < 0) {
+                       wpa_printf(MSG_INFO, "WPS UPnP: Advertisement sendto "
+                                  "failed: %d (%s)", errno, strerror(errno));
+               }
+               wpabuf_free(msg);
+               a->state++;
+       }
 }
 
 
@@ -317,7 +348,7 @@ int advertisement_state_machine_start(struct upnp_wps_device_sm *sm)
        struct advertisement_state_machine *a = &sm->advertisement;
        int next_timeout_msec;
 
-       advertisement_state_machine_stop(sm);
+       advertisement_state_machine_stop(sm, 0);
 
        /*
         * Start out advertising down, this automatically switches