feat: add HTTP CONNECT proxy support for Telegram and Claude API
Enable ESP32-S3 to reach api.telegram.org and api.anthropic.com through an HTTP CONNECT proxy (e.g. Clash Verge), required in regions where these services are blocked. - New proxy module (http_proxy.c/h): CONNECT tunnel + TLS via esp_tls with pre-connected socket injection (esp_tls_set_conn_sockfd) - Telegram and LLM modules split into direct/proxy paths - CLI commands: set_proxy <host> <port>, clear_proxy - Proxy config persisted in NVS - Fix TLS buffer: MBEDTLS_SSL_IN_CONTENT_LEN 4096 → 16384 - Increase task stacks for TLS overhead (poll 12KB, agent 12KB, outbound 8KB) - Default model changed to claude-opus-4-6 - Capture raw error body for non-200 API responses Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include "telegram_bot.h"
|
||||
#include "mimi_config.h"
|
||||
#include "bus/message_bus.h"
|
||||
#include "proxy/http_proxy.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@@ -43,7 +44,76 @@ static esp_err_t http_event_handler(esp_http_client_event_t *evt)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static char *tg_api_call(const char *method, const char *post_data)
|
||||
/* ── Proxy path: manual HTTP over CONNECT tunnel ────────────── */
|
||||
|
||||
static char *tg_api_call_via_proxy(const char *path, const char *post_data)
|
||||
{
|
||||
proxy_conn_t *conn = proxy_conn_open("api.telegram.org", 443,
|
||||
(MIMI_TG_POLL_TIMEOUT_S + 5) * 1000);
|
||||
if (!conn) return NULL;
|
||||
|
||||
/* Build HTTP request */
|
||||
char header[512];
|
||||
int hlen;
|
||||
if (post_data) {
|
||||
hlen = snprintf(header, sizeof(header),
|
||||
"POST /bot%s/%s HTTP/1.1\r\n"
|
||||
"Host: api.telegram.org\r\n"
|
||||
"Content-Type: application/json\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
"Connection: close\r\n\r\n",
|
||||
s_bot_token, path, (int)strlen(post_data));
|
||||
} else {
|
||||
hlen = snprintf(header, sizeof(header),
|
||||
"GET /bot%s/%s HTTP/1.1\r\n"
|
||||
"Host: api.telegram.org\r\n"
|
||||
"Connection: close\r\n\r\n",
|
||||
s_bot_token, path);
|
||||
}
|
||||
|
||||
if (proxy_conn_write(conn, header, hlen) < 0) {
|
||||
proxy_conn_close(conn);
|
||||
return NULL;
|
||||
}
|
||||
if (post_data && proxy_conn_write(conn, post_data, strlen(post_data)) < 0) {
|
||||
proxy_conn_close(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Read response — accumulate until connection close */
|
||||
size_t cap = 4096, len = 0;
|
||||
char *buf = calloc(1, cap);
|
||||
if (!buf) { proxy_conn_close(conn); return NULL; }
|
||||
|
||||
int timeout = (MIMI_TG_POLL_TIMEOUT_S + 5) * 1000;
|
||||
while (1) {
|
||||
if (len + 1024 >= cap) {
|
||||
cap *= 2;
|
||||
char *tmp = realloc(buf, cap);
|
||||
if (!tmp) break;
|
||||
buf = tmp;
|
||||
}
|
||||
int n = proxy_conn_read(conn, buf + len, cap - len - 1, timeout);
|
||||
if (n <= 0) break;
|
||||
len += n;
|
||||
}
|
||||
buf[len] = '\0';
|
||||
proxy_conn_close(conn);
|
||||
|
||||
/* Skip HTTP headers — find \r\n\r\n */
|
||||
char *body = strstr(buf, "\r\n\r\n");
|
||||
if (!body) { free(buf); return NULL; }
|
||||
body += 4;
|
||||
|
||||
/* Return just the body */
|
||||
char *result = strdup(body);
|
||||
free(buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ── Direct path: esp_http_client ───────────────────────────── */
|
||||
|
||||
static char *tg_api_call_direct(const char *method, const char *post_data)
|
||||
{
|
||||
char url[256];
|
||||
snprintf(url, sizeof(url), "https://api.telegram.org/bot%s/%s", s_bot_token, method);
|
||||
@@ -89,6 +159,14 @@ static char *tg_api_call(const char *method, const char *post_data)
|
||||
return resp.buf;
|
||||
}
|
||||
|
||||
static char *tg_api_call(const char *method, const char *post_data)
|
||||
{
|
||||
if (http_proxy_is_enabled()) {
|
||||
return tg_api_call_via_proxy(method, post_data);
|
||||
}
|
||||
return tg_api_call_direct(method, post_data);
|
||||
}
|
||||
|
||||
static void process_updates(const char *json_str)
|
||||
{
|
||||
cJSON *root = cJSON_Parse(json_str);
|
||||
|
||||
Reference in New Issue
Block a user