P2P: Increase the maximum number of PD Request retries
[mech_eap.git] / src / p2p / p2p_pd.c
index 4be7098..e40f2b7 100644 (file)
@@ -19,7 +19,7 @@
  * Number of retries to attempt for provision discovery requests
  * in case the peer is not listening.
  */
-#define MAX_PROV_DISC_REQ_RETRIES 10
+#define MAX_PROV_DISC_REQ_RETRIES 120
 
 
 static void p2p_build_wps_ie_config_methods(struct wpabuf *buf,
@@ -46,8 +46,14 @@ static struct wpabuf * p2p_build_prov_disc_req(struct p2p_data *p2p,
 {
        struct wpabuf *buf;
        u8 *len;
+       size_t extra = 0;
 
-       buf = wpabuf_alloc(1000);
+#ifdef CONFIG_WIFI_DISPLAY
+       if (p2p->wfd_ie_prov_disc_req)
+               extra = wpabuf_len(p2p->wfd_ie_prov_disc_req);
+#endif /* CONFIG_WIFI_DISPLAY */
+
+       buf = wpabuf_alloc(1000 + extra);
        if (buf == NULL)
                return NULL;
 
@@ -66,17 +72,46 @@ static struct wpabuf * p2p_build_prov_disc_req(struct p2p_data *p2p,
        /* WPS IE with Config Methods attribute */
        p2p_build_wps_ie_config_methods(buf, config_methods);
 
+#ifdef CONFIG_WIFI_DISPLAY
+       if (p2p->wfd_ie_prov_disc_req)
+               wpabuf_put_buf(buf, p2p->wfd_ie_prov_disc_req);
+#endif /* CONFIG_WIFI_DISPLAY */
+
        return buf;
 }
 
 
 static struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p,
                                                u8 dialog_token,
-                                               u16 config_methods)
+                                               u16 config_methods,
+                                               const u8 *group_id,
+                                               size_t group_id_len)
 {
        struct wpabuf *buf;
+       size_t extra = 0;
 
-       buf = wpabuf_alloc(100);
+#ifdef CONFIG_WIFI_DISPLAY
+       struct wpabuf *wfd_ie = p2p->wfd_ie_prov_disc_resp;
+       if (wfd_ie && group_id) {
+               size_t i;
+               for (i = 0; i < p2p->num_groups; i++) {
+                       struct p2p_group *g = p2p->groups[i];
+                       struct wpabuf *ie;
+                       if (!p2p_group_is_group_id_match(g, group_id,
+                                                        group_id_len))
+                               continue;
+                       ie = p2p_group_get_wfd_ie(g);
+                       if (ie) {
+                               wfd_ie = ie;
+                               break;
+                       }
+               }
+       }
+       if (wfd_ie)
+               extra = wpabuf_len(wfd_ie);
+#endif /* CONFIG_WIFI_DISPLAY */
+
+       buf = wpabuf_alloc(100 + extra);
        if (buf == NULL)
                return NULL;
 
@@ -85,6 +120,11 @@ static struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p,
        /* WPS IE with Config Methods attribute */
        p2p_build_wps_ie_config_methods(buf, config_methods);
 
+#ifdef CONFIG_WIFI_DISPLAY
+       if (wfd_ie)
+               wpabuf_put_buf(buf, wfd_ie);
+#endif /* CONFIG_WIFI_DISPLAY */
+
        return buf;
 }
 
@@ -117,6 +157,9 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
                                "P2P: Provision Discovery Request add device "
                                "failed " MACSTR, MAC2STR(sa));
                }
+       } else if (msg.wfd_subelems) {
+               wpabuf_free(dev->info.wfd_subelems);
+               dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
        }
 
        if (!(msg.wps_config_methods &
@@ -162,7 +205,8 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
 
 out:
        resp = p2p_build_prov_disc_resp(p2p, msg.dialog_token,
-                                       reject ? 0 : msg.wps_config_methods);
+                                       reject ? 0 : msg.wps_config_methods,
+                                       msg.group_id, msg.group_id_len);
        if (resp == NULL) {
                p2p_parse_free(&msg);
                return;
@@ -234,11 +278,6 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
                return;
        }
 
-       if (p2p->pending_action_state == P2P_PENDING_PD) {
-               os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
-               p2p->pending_action_state = P2P_NO_PENDING_ACTION;
-       }
-
        if (dev->dialog_token != msg.dialog_token) {
                wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
                        "P2P: Ignore Provision Discovery Response with "
@@ -248,6 +287,11 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
                return;
        }
 
+       if (p2p->pending_action_state == P2P_PENDING_PD) {
+               os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
+               p2p->pending_action_state = P2P_NO_PENDING_ACTION;
+       }
+
        /*
         * If the response is from the peer to whom a user initiated request
         * was sent earlier, we reset that state info here.
@@ -347,7 +391,6 @@ int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
        if (p2p->state != P2P_IDLE)
                p2p_stop_listen_for_freq(p2p, freq);
        p2p->pending_action_state = P2P_PENDING_PD;
-       p2p_set_timeout(p2p, 0, 300000);
        if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
                            p2p->cfg->dev_addr, dev->info.p2p_device_addr,
                            wpabuf_head(req), wpabuf_len(req), 200) < 0) {
@@ -365,7 +408,8 @@ int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
 
 
 int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr,
-                     u16 config_methods, int join, int force_freq)
+                     u16 config_methods, int join, int force_freq,
+                     int user_initiated_pd)
 {
        struct p2p_device *dev;
 
@@ -403,11 +447,7 @@ int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr,
                return 0;
        }
 
-       /*
-        * We use the join param as a cue to differentiate between user
-        * initiated PD request and one issued during finds (internal).
-        */
-       p2p->user_initiated_pd = !join;
+       p2p->user_initiated_pd = user_initiated_pd;
 
        if (p2p->user_initiated_pd)
                p2p->pd_retries = MAX_PROV_DISC_REQ_RETRIES;