Browse Source

WPS ER: Delay wpa_supplicant termination to allow unsubscription

Instead of forcefully deinitializing ER immediately, give it some
time to complete unsubscription and call eloop_terminate() only once
ER code has completed its work.
Jouni Malinen 15 years ago
parent
commit
1a1bf008cb

+ 1 - 1
src/wps/wps.h

@@ -674,7 +674,7 @@ int wps_attr_text(struct wpabuf *data, char *buf, char *end);
 
 struct wps_er * wps_er_init(struct wps_context *wps, const char *ifname);
 void wps_er_refresh(struct wps_er *er);
-void wps_er_deinit(struct wps_er *er);
+void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx);
 void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id,
 			u16 sel_reg_config_methods);
 int wps_er_pbc(struct wps_er *er, const u8 *uuid);

+ 17 - 5
src/wps/wps_er.c

@@ -1161,19 +1161,19 @@ wps_er_init(struct wps_context *wps, const char *ifname)
 			   er->mac_addr, &er->mac_addr_text)) {
 		wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address "
 			   "for %s. Does it have IP address?", ifname);
-		wps_er_deinit(er);
+		wps_er_deinit(er, NULL, NULL);
 		return NULL;
 	}
 
 	if (wps_er_ssdp_init(er) < 0) {
-		wps_er_deinit(er);
+		wps_er_deinit(er, NULL, NULL);
 		return NULL;
 	}
 
 	addr.s_addr = er->ip_addr;
 	er->http_srv = http_server_init(&addr, -1, wps_er_http_req, er);
 	if (er->http_srv == NULL) {
-		wps_er_deinit(er);
+		wps_er_deinit(er, NULL, NULL);
 		return NULL;
 	}
 	er->http_port = http_server_get_port(er->http_srv);
@@ -1204,23 +1204,35 @@ void wps_er_refresh(struct wps_er *er)
 static void wps_er_deinit_finish(void *eloop_data, void *user_ctx)
 {
 	struct wps_er *er = eloop_data;
+	void (*deinit_done_cb)(void *ctx);
+	void *deinit_done_ctx;
+
 	wpa_printf(MSG_DEBUG, "WPS ER: Finishing deinit");
+
+	deinit_done_cb = er->deinit_done_cb;
+	deinit_done_ctx = er->deinit_done_ctx;
 	os_free(er->ip_addr_text);
 	os_free(er->mac_addr_text);
 	os_free(er);
+
+	if (deinit_done_cb)
+		deinit_done_cb(deinit_done_ctx);
 }
 
 
-void wps_er_deinit(struct wps_er *er)
+void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx)
 {
 	if (er == NULL)
 		return;
 	http_server_deinit(er->http_srv);
 	wps_er_ap_remove_all(er);
 	wps_er_ssdp_deinit(er);
-	eloop_register_timeout(5, 0, wps_er_deinit_finish, er, NULL);
+	eloop_register_timeout(dl_list_empty(&er->ap_unsubscribing) ? 0 : 5, 0,
+			       wps_er_deinit_finish, er, NULL);
 	wpa_printf(MSG_DEBUG, "WPS ER: Finish deinit from timeout");
 	er->deinitializing = 1;
+	er->deinit_done_cb = cb;
+	er->deinit_done_ctx = ctx;
 }
 
 

+ 2 - 0
src/wps/wps_er.h

@@ -88,6 +88,8 @@ struct wps_er {
 	unsigned int next_ap_id;
 	unsigned int event_id;
 	int deinitializing;
+	void (*deinit_done_cb)(void *ctx);
+	void *deinit_done_ctx;
 };
 
 

+ 2 - 2
wpa_supplicant/ctrl_iface.c

@@ -1714,7 +1714,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 		if (wpa_supplicant_reload_configuration(wpa_s))
 			reply_len = -1;
 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
-		eloop_terminate();
+		wpa_supplicant_terminate_proc(wpa_s->global);
 	} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
 		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
 			reply_len = -1;
@@ -2007,7 +2007,7 @@ char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
 		reply_len = wpa_supplicant_global_iface_interfaces(
 			global, reply, reply_size);
 	} else if (os_strcmp(buf, "TERMINATE") == 0) {
-		eloop_terminate();
+		wpa_supplicant_terminate_proc(global);
 	} else {
 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 		reply_len = 16;

+ 19 - 2
wpa_supplicant/wpa_supplicant.c

@@ -546,6 +546,23 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_states state)
 }
 
 
+void wpa_supplicant_terminate_proc(struct wpa_global *global)
+{
+	int pending = 0;
+#ifdef CONFIG_WPS
+	struct wpa_supplicant *wpa_s = global->ifaces;
+	while (wpa_s) {
+		if (wpas_wps_terminate_pending(wpa_s) == 1)
+			pending = 1;
+		wpa_s = wpa_s->next;
+	}
+#endif /* CONFIG_WPS */
+	if (pending)
+		return;
+	eloop_terminate();
+}
+
+
 static void wpa_supplicant_terminate(int sig, void *signal_ctx)
 {
 	struct wpa_global *global = signal_ctx;
@@ -554,7 +571,7 @@ static void wpa_supplicant_terminate(int sig, void *signal_ctx)
 		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING "- signal %d "
 			"received", sig);
 	}
-	eloop_terminate();
+	wpa_supplicant_terminate_proc(global);
 }
 
 
@@ -653,7 +670,7 @@ static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
 	wpa_printf(MSG_DEBUG, "Signal %d received - reconfiguring", sig);
 	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
 		if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
-			eloop_terminate();
+			wpa_supplicant_terminate_proc(global);
 		}
 	}
 }

+ 1 - 0
wpa_supplicant/wpa_supplicant_i.h

@@ -478,6 +478,7 @@ void wpa_supplicant_deinit(struct wpa_global *global);
 
 int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
 			      struct wpa_ssid *ssid);
+void wpa_supplicant_terminate_proc(struct wpa_global *global);
 
 /* scan.c */
 int wpa_supplicant_enabled_networks(struct wpa_config *conf);

+ 22 - 2
wpa_supplicant/wps_supplicant.c

@@ -888,7 +888,7 @@ void wpas_wps_deinit(struct wpa_supplicant *wpa_s)
 		return;
 
 #ifdef CONFIG_WPS_ER
-	wps_er_deinit(wpa_s->wps_er);
+	wps_er_deinit(wpa_s->wps_er, NULL, NULL);
 	wpa_s->wps_er = NULL;
 #endif /* CONFIG_WPS_ER */
 
@@ -1131,7 +1131,7 @@ int wpas_wps_er_start(struct wpa_supplicant *wpa_s)
 int wpas_wps_er_stop(struct wpa_supplicant *wpa_s)
 {
 #ifdef CONFIG_WPS_ER
-	wps_er_deinit(wpa_s->wps_er);
+	wps_er_deinit(wpa_s->wps_er, NULL, NULL);
 	wpa_s->wps_er = NULL;
 #endif /* CONFIG_WPS_ER */
 	return 0;
@@ -1174,4 +1174,24 @@ int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid,
 	return wps_er_learn(wpa_s->wps_er, u, (const u8 *) pin,
 			    os_strlen(pin));
 }
+
+
+static void wpas_wps_terminate_cb(void *ctx)
+{
+	wpa_printf(MSG_DEBUG, "WPS ER: Terminated");
+	eloop_terminate();
+}
+#endif /* CONFIG_WPS_ER */
+
+
+int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s)
+{
+#ifdef CONFIG_WPS_ER
+	if (wpa_s->wps_er) {
+		wps_er_deinit(wpa_s->wps_er, wpas_wps_terminate_cb, wpa_s);
+		wpa_s->wps_er = NULL;
+		return 1;
+	}
 #endif /* CONFIG_WPS_ER */
+	return 0;
+}

+ 1 - 0
wpa_supplicant/wps_supplicant.h

@@ -56,6 +56,7 @@ int wpas_wps_er_add_pin(struct wpa_supplicant *wpa_s, const char *uuid,
 int wpas_wps_er_pbc(struct wpa_supplicant *wpa_s, const char *uuid);
 int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid,
 		      const char *pin);
+int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s);
 
 #else /* CONFIG_WPS */