WPS: Send SSDP byebye notifications when stopping UPnP advertisements

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.
This commit is contained in:
Jouni Malinen 2009-11-15 00:46:58 +02:00
parent 9b61515c26
commit 44577e4c2e
3 changed files with 36 additions and 5 deletions

View file

@ -964,8 +964,7 @@ void upnp_wps_device_stop(struct upnp_wps_device_sm *sm)
subscription_destroy(s); subscription_destroy(s);
} }
advertisement_state_machine_stop(sm); advertisement_state_machine_stop(sm, 1);
/* TODO: send byebye notifications */
event_send_stop_all(sm); event_send_stop_all(sm);
os_free(sm->wlanevent); os_free(sm->wlanevent);

View file

@ -159,7 +159,8 @@ int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text,
/* wps_upnp_ssdp.c */ /* wps_upnp_ssdp.c */
void msearchreply_state_machine_stop(struct advertisement_state_machine *a); void msearchreply_state_machine_stop(struct advertisement_state_machine *a);
int advertisement_state_machine_start(struct upnp_wps_device_sm *sm); 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); void ssdp_listener_stop(struct upnp_wps_device_sm *sm);
int ssdp_listener_start(struct upnp_wps_device_sm *sm); int ssdp_listener_start(struct upnp_wps_device_sm *sm);
int ssdp_listener_open(void); int ssdp_listener_open(void);

View file

@ -228,10 +228,41 @@ static void advertisement_state_machine_handler(void *eloop_data,
/** /**
* advertisement_state_machine_stop - Stop SSDP advertisements * advertisement_state_machine_stop - Stop SSDP advertisements
* @sm: WPS UPnP state machine from upnp_wps_device_init() * @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); 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; struct advertisement_state_machine *a = &sm->advertisement;
int next_timeout_msec; int next_timeout_msec;
advertisement_state_machine_stop(sm); advertisement_state_machine_stop(sm, 0);
/* /*
* Start out advertising down, this automatically switches * Start out advertising down, this automatically switches