Re: [PATCH v4 5/9] wispr: Refactor 'wispr_portal_web_result' to leverage 'GError'.
Denis Kenzior <[email protected]> Tue, 25 Mar 2025 09:28:45 -0500
| Newsgroups | dev.linux.lists.connman |
|---|---|
| Message-ID | <[email protected]> |
Hi Grant,
On 3/24/25 11:59 PM, Grant Erickson wrote:
> Leverages the newly-added GError parameter to the 'GWebResultFunc' to
> refactor 'wispr_portal_web_result' into
> 'wispr_portal_web_result_failure' and
> 'wispr_portal_web_result_success' with the former handling
> non-successful cases and the latter handling successful HTTP status
> code cases.
>
> Prior to the introduction of an optional, immutable 'GError' parameter
> to 'GWebResultFunc' and this refactor, there existed a "hole" in the
> finalization of WISPr IPv4 and IPv6 "online" HTTP-based Internet
> reachability checks web request sessions that both could and did leave
> such checks "dangling" and non-renewing such that an expected active,
> default network service failover does not occur when it should.
>
> The "hole" involves an end-of-file (EOF) condition. In the normal
> case, there are a series of one or more data receipts for the web
> request as headers of the request response are fulfilled. When there
> is no further data to send, the final receive completes a normal EOF
> that leads to the successful closure of the web request, typically
> with HTTP 200 "OK" in the nominal success case.
>
> However, there is a second EOF case that appears to happen with a
> random distribution in the nginx server backing the default "online"
> HTTP-based Internet reachability check URLs,
> 'ipv[46].connman.net/online/status.html'. In that case, the nginx
> server appears to periodically do an unexpected and spontaneous remote
> connection close after the initial connection but before any data has
> been received. Prior to this change, all such failures hit the same
> WISPr error-handling block which effectively maps such a failure to the
> effective 'GWebResult' "null" GWEB_HTTP_STATUS_CODE_UNKNOWN status
> value. Unfortunately, WISPr historically had no way to distinguish
> this as an actual failure or success and so it lands on the case:
>
> case GWEB_HTTP_STATUS_CODE_UNKNOWN:
> wispr_portal_context_ref(wp_context);
> __connman_agent_request_browser(wp_context->service,
> wispr_portal_browser_reply_cb,
> wp_context->status_url, wp_context);
>
> which does not "bookend" the original, initiating WISPr web request
> and leaves the original request "dangling" and non-renewed, eventually
> leading to the aforementioned "hole".
>
> With this change, the second, failure EOF case will now return a
> GError instance pointer synthesized from 'ECONNRESET' and will be
> handled as a failure by 'wispr_portal_web_result_failure',
> "bookending" the original "online" HTTP-based Internet reachability
> check.
>
> All of the prior HTTP status code cases are handled by
> 'wispr_portal_web_result_success'.
> ---
> src/wispr.c | 105 +++++++++++++++++++++++++++++++++++-----------------
> 1 file changed, 71 insertions(+), 34 deletions(-)
>
<snip>
> @@ -1085,15 +1078,15 @@ static bool wispr_portal_web_result(const GError *error, GWebResult *result,
>
> goto done;
This part seems fishy. Previous version of this function had
wispr_portal_context_unref() call after the 'done' label...
> case GWEB_HTTP_STATUS_CODE_BAD_REQUEST:
> - portal_manage_failure_status(wp_context, -EINVAL);
> + portal_manage_failure_status(wp_context, 0, "bad request");
> break;
>
> case GWEB_HTTP_STATUS_CODE_NOT_FOUND:
> - portal_manage_failure_status(wp_context, -ENOENT);
> + portal_manage_failure_status(wp_context, 0, "resource not found");
> break;
>
> case GWEB_HTTP_STATUS_CODE_REQUEST_TIMEOUT:
> - portal_manage_failure_status(wp_context, -ETIMEDOUT);
> + portal_manage_failure_status(wp_context, 0, "request timeout");
> break;
>
> case GWEB_HTTP_STATUS_CODE_HTTP_VERSION_NOT_SUPPORTED:
> @@ -1102,12 +1095,55 @@ static bool wispr_portal_web_result(const GError *error, GWebResult *result,
> wispr_portal_browser_reply_cb,
> wp_context->status_url, wp_context);
> break;
> +
> default:
> break;
> }
>
> free_wispr_routes(wp_context);
> wp_context->request_id = 0;
> +
> +done:
> + return;
But now you have a simple return at the end of the function. Which by the way
is discouraged and should have been picked up by the compiler or static analysis.
> +}
> +
> +static bool wispr_portal_web_result(const GError *error, GWebResult *result,
> + gpointer user_data)
> +{
> + struct connman_wispr_portal_context *wp_context = user_data;
> + const guint8 *chunk = NULL;
> + gsize length;
> +
> + DBG("error %p result %p user_data %p wispr_result %d",
> + error, result, user_data, wp_context->wispr_result);
> +
> + if (wp_context->wispr_result != CONNMAN_WISPR_RESULT_ONLINE) {
> + g_web_result_get_chunk(result, &chunk, &length);
> +
> + DBG("length %zu", length);
> +
> + if (length > 0) {
> + g_web_parser_feed_data(wp_context->wispr_parser,
> + chunk, length);
> + /* read more data */
> + return true;
> + }
> +
> + g_web_parser_end_data(wp_context->wispr_parser);
> +
> + DBG("wp_context->wispr_msg.message_type %d", wp_context->wispr_msg.message_type);
We still use 80 character lines, so please break up accordingly.
> +
> + if (wp_context->wispr_msg.message_type >= 0) {
> + if (wispr_manage_message(result, wp_context))
> + goto done;
> + }
> + }
> +
> + if (error)
> + wispr_portal_web_result_failure(error, result, wp_context);
> + else
> + wispr_portal_web_result_success(result, wp_context);
> +
> done:
> wp_context->wispr_msg.message_type = -1;
>
> @@ -1117,6 +1153,7 @@ done:
> * maintaining a weak reference to it.
> */
> wispr_portal_context_unref(wp_context);
> +
Please don't introduce spurious whitespace changes and keep the patches minimal.
> return false;
> }
>
<snip>
> @@ -1629,7 +1666,7 @@ int __connman_wispr_cancel(struct connman_service *service,
>
> cancel_connman_wispr_portal_context(wp_context);
>
> - portal_manage_failure_status(wp_context, -ECANCELED);
> + portal_manage_failure_status(wp_context, -ECANCELED, strerror(-ECANCELED));
> 80 chars again
>
> wispr_portal_context_unref(wp_context);
>
Regards,
-Denis