Skip to content

fix(time): stabilize Date header parsing for direct clock sync#85

Open
IRONICBo wants to merge 1 commit intomemovai:mainfrom
IRONICBo:fix/tool-get-time-http-date
Open

fix(time): stabilize Date header parsing for direct clock sync#85
IRONICBo wants to merge 1 commit intomemovai:mainfrom
IRONICBo:fix/tool-get-time-http-date

Conversation

@IRONICBo
Copy link
Copy Markdown
Member

@IRONICBo IRONICBo commented Feb 24, 2026

This patch fixes tool_get_time failures in direct mode by switching the HTTP time source to http://captive.apple.com/ and capturing the Date header via
HTTP_EVENT_ON_HEADER.

It also avoids using header memory after client cleanup by copying Date into a local buffer before parsing. Time parsing still uses temporary UTC (TZ=UTC0)
and then restores MIMI_TIMEZONE, so both system clock and agent-facing formatted time stay consistent with local timezone settings.

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced stability of network time synchronization by implementing a more robust mechanism for capturing and processing date information from HTTP responses.
    • Optimized the direct HTTP time fetch process to ensure more consistent and reliable time updates.

@IRONICBo IRONICBo requested a review from crispyberry February 24, 2026 04:40
@IRONICBo IRONICBo self-assigned this Feb 24, 2026
@IRONICBo IRONICBo added the bug Something isn't working label Feb 24, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 24, 2026

📝 Walkthrough

Walkthrough

The PR refactors the time fetching mechanism in the tool by replacing direct Date header extraction with a context-driven capture approach. It introduces a new handler and struct to capture HTTP Date headers, changes the fetch endpoint from Telegram API to Apple's captive portal, and updates validation logic to use the captured date value instead of direct header access.

Changes

Cohort / File(s) Summary
HTTP Time Fetch Refactoring
main/tools/tool_get_time.c
Introduces time_http_ctx_t context struct and date_header_capture_handler to capture HTTP Date headers into a local buffer. Replaces esp_http_client_get_header calls with context-driven approach. Updates direct HTTPS endpoint from https://api.telegram.org/ to http://captive.apple.com/. Adds #include <strings.h> and rewires handler into HTTP client configuration. Preserves proxy-based fetch flow while changing primary fetch path.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A hop towards cleaner headers fair,
Date values captured with care,
From Telegram's gates to Apple's way,
Context handlers save the day!
No more direct reads, just context flow—
Time fetching's hat trick, a burrow's bravo! 🎩✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and concisely describes the main change: stabilizing Date header parsing for direct clock synchronization by implementing a more robust capture mechanism.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
main/tools/tool_get_time.c (1)

138-161: ⚠️ Potential issue | 🟡 Minor

captive.apple.com is an undocumented internal probe, not a public time API

Apple's own developer documentation notes that "the details of these probes are not considered API", meaning the endpoint's response format, availability, and behaviour can change without notice. The previous api.telegram.org was similarly unofficial for time sync, but worth calling out for tracking purposes.

Additionally, captive.apple.com is intentionally non-HTTPS, designed to allow captive portal interception. This means its Date header is susceptible to spoofing by any on-path attacker. For an IoT device where system time gates TLS certificate validation, an adversary who controls a Wi-Fi AP could push an arbitrary clock value. This is an inherent limitation of HTTP-based clock sync (NTP has the same property), so it's a conscious tradeoff — just make sure it's documented.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@main/tools/tool_get_time.c` around lines 138 - 161, This code uses an
undocumented, non-HTTPS probe (captive.apple.com) to obtain a Date header via
time_http_ctx_t and date_header_capture_handler and then calls
parse_and_set_time; change this to a safer, documented approach by either (1)
switching to a public, supported time API over HTTPS (and validate TLS certs) or
(2) switching to a proper time protocol (e.g., esp-sntp) for time sync;
alternatively make the URL configurable and add a clear comment/warning about
the spoofing risk and DNS/probe instability so callers can opt in. Ensure
changes touch the esp_http_client_config_t.url usage and any logic that assumes
trust in the Date header before calling parse_and_set_time.
🧹 Nitpick comments (1)
main/tools/tool_get_time.c (1)

113-133: Optional: log a warning when the Date value is truncated

The silent truncation at lines 126–128 means an overlong (malformed) Date header becomes an unparseable string at Line 160 with no log trail. Since any valid RFC 7231 Date value is ~29 characters, this will never fire in practice, but a one-liner would make debugging easier if it ever does.

🔧 Proposed change
     if (len >= sizeof(ctx->date_value)) {
+        ESP_LOGW(TAG, "Date header value truncated (%zu bytes)", len);
         len = sizeof(ctx->date_value) - 1;
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@main/tools/tool_get_time.c` around lines 113 - 133, The Date header capture
silently truncates overlong values in date_header_capture_handler when copying
evt->header_value into ctx->date_value; modify the handler to detect when
strlen(evt->header_value) >= sizeof(ctx->date_value) and emit a warning (e.g.
ESP_LOGW) that the Date header was truncated, including the actual
header_key/header_value or a truncated preview for diagnostics, before
performing the memcpy and null-termination so there is an explicit log trail if
parsing later fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@main/tools/tool_get_time.c`:
- Around line 138-161: This code uses an undocumented, non-HTTPS probe
(captive.apple.com) to obtain a Date header via time_http_ctx_t and
date_header_capture_handler and then calls parse_and_set_time; change this to a
safer, documented approach by either (1) switching to a public, supported time
API over HTTPS (and validate TLS certs) or (2) switching to a proper time
protocol (e.g., esp-sntp) for time sync; alternatively make the URL configurable
and add a clear comment/warning about the spoofing risk and DNS/probe
instability so callers can opt in. Ensure changes touch the
esp_http_client_config_t.url usage and any logic that assumes trust in the Date
header before calling parse_and_set_time.

---

Nitpick comments:
In `@main/tools/tool_get_time.c`:
- Around line 113-133: The Date header capture silently truncates overlong
values in date_header_capture_handler when copying evt->header_value into
ctx->date_value; modify the handler to detect when strlen(evt->header_value) >=
sizeof(ctx->date_value) and emit a warning (e.g. ESP_LOGW) that the Date header
was truncated, including the actual header_key/header_value or a truncated
preview for diagnostics, before performing the memcpy and null-termination so
there is an explicit log trail if parsing later fails.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c3dbc4 and 324432f.

📒 Files selected for processing (1)
  • main/tools/tool_get_time.c

@crispyberry
Copy link
Copy Markdown
Contributor

Hi @mogenson, thanks for the fix! 🙏

It looks like the core issue (capturing the Date response header via event handler instead of esp_http_client_get_header) has already been addressed on main (via PR #86), which is why this PR now has merge conflicts.

That said, your PR still has two valuable changes that main doesn't have yet:

  1. Switch URL to http://captive.apple.com/ — removes the TLS dependency, making the time fetch lighter and faster on ESP32
  2. Add #include <strings.h> — proper declaration for strcasecmp

Could you rebase onto the latest main and keep just these two incremental changes? That should make the PR clean and mergeable. Thanks!

@mogenson
Copy link
Copy Markdown
Contributor

Hi @mogenson, thanks for the fix! 🙏

@crispyberry this PR was authored by @IRONICBo. I'll let them respond.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants