PublicIP / Weather: fixes possible can only be used once due to internal limitations error

This commit is contained in:
李通洲
2026-09-21 20:08:11 +08:00
parent aaa9153f5a
commit 256c6a4257
5 changed files with 21 additions and 5 deletions
+1
View File
@@ -89,6 +89,7 @@ Bugfixes:
* Fixed building on FreeBSD 16.0-CURRENT, where `<string.h>` defines `memrchr` as a qualifier-preserving function-like macro. (General, FreeBSD)
* Worked around an iTerm bug where the image logo may be moved out of view. (Logo)
* Increased the terminal response wait time to 1s to improve compatibility with slower terminals. (General)
* Fixed the `PublicIp` and `Weather` modules exiting with "can only be used once due to internal limitations" on the round after a failed request when `--dynamic-interval` is used, instead of retrying. (PublicIp / Weather)
* Some internal cleanups and optimizations.
Logos:
+9
View File
@@ -34,6 +34,15 @@ typedef struct FFNetworkingState {
[[gnu::nonnull(1, 2, 4), nodiscard]] const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, uint16_t port, const char* path, const char* headers);
[[gnu::nonnull(1, 2), nodiscard]] const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer);
// Releases what a finished request holds and returns `state` to the idle state, so that the next
// `ffNetworkingSendHttpRequest` starts from scratch. A request that never reached the wire can
// still own the request buffer, so a plain zeroing of the struct is not enough.
// The caller stays responsible for its own bookkeeping, such as clearing a "request sent" latch.
[[gnu::nonnull(1)]] static inline void ffNetworkingResetState(FFNetworkingState* state) {
ffStrbufDestroy(&state->command);
*state = (FFNetworkingState) {};
}
// Case-insensitive header lookup restricted to the header block [0, headerEnd).
// Restricting the range matters because the body may already share the same buffer.
// Returns a pointer to the first character of the value; `valueLen` receives its
+5 -2
View File
@@ -103,13 +103,16 @@ const char* ffDetectPublicIp(FFPublicIPOptions* options, FFPublicIpResult* resul
}
if (*status != nullptr) {
return *status;
const char* error = *status;
ffNetworkingResetState(state);
*status = FF_UNINITIALIZED;
return error;
}
FF_STRBUF_AUTO_DESTROY response = ffStrbufCreateA(4096);
const char* error = ffNetworkingRecvHttpResponse(state, &response);
*state = (FFNetworkingState) {};
ffNetworkingResetState(state);
*status = FF_UNINITIALIZED;
if (error == nullptr) {
+5 -2
View File
@@ -38,13 +38,16 @@ const char* ffDetectWeather(FFWeatherOptions* options, FFstrbuf* result) {
}
if (status != nullptr) {
return status;
const char* error = status;
ffNetworkingResetState(&state);
status = FF_UNITIALIZED;
return error;
}
ffStrbufEnsureFree(result, 4095);
const char* error = ffNetworkingRecvHttpResponse(&state, result);
state = (FFNetworkingState) {};
ffNetworkingResetState(&state);
status = FF_UNITIALIZED;
if (error == nullptr) {
+1 -1
View File
@@ -690,7 +690,7 @@ static void parseCommand(FFdata* data, char* key, char* value) {
enableJsonOutput(data);
}
} else if (ffStrEqualsIgnCase(key, "--dynamic-interval")) {
instance.state.dynamicInterval = ffOptionParseUInt32(key, value); // seconds to milliseconds
instance.state.dynamicInterval = ffOptionParseUInt32(key, value); // ms
} else if (ffStrEqualsIgnCase(key, "-w") || ffStrEqualsIgnCase(key, "--watch")) {
if (value == nullptr) {
instance.state.dynamicInterval = 1000; // default to 1 second if no value is provided