from pathlib import Path
root=Path('/home/lighthouse/esp32-dev/.cache/speech-playback-diagnostics-20261006')
p=root/'firmware/main/net_trace.cpp';s=p.read_text();assert 'tcp_snapshot' not in s
s=s.replace('#include <cerrno>','#include <atomic>\n#include "lwip/tcpip.h"\n#include "lwip/tcp.h"\n#include "lwip/priv/tcp_priv.h"\n#include "lwip/priv/sockets_priv.h"\n#include <cerrno>',1)
s=s.replace('static NetRecord *records;','static NetRecord *records;\nstatic std::atomic<int> trace_fd{-1};\nextern "C" void speech_diag_net_socket(int fd) {trace_fd=fd;}',1)
s=s.replace('2048','8192')
needle='extern "C" void speech_diag_net_init() {'
s=s.replace(needle,'''static void tcp_snapshot(void *) {
    if(!capturing)return;
    const int fd=trace_fd.load();if(fd<0)return;
    const auto *socket=lwip_socket_dbg_get_socket(fd);
    if(!socket || !socket->conn || NETCONNTYPE_GROUP(socket->conn->type)!=NETCONN_TCP)return;
    const auto *pcb=socket->conn->pcb.tcp;
    if(!pcb || pcb->remote_port!=443)return;
    unsigned oo_count=0,oo_bytes=0;
#if TCP_QUEUE_OOSEQ
    for(const tcp_seg *seg=pcb->ooseq;seg && oo_count<128;seg=seg->next){++oo_count;oo_bytes+=seg->len;}
#endif
    int available=-1;
#if LWIP_SO_RCVBUF
    available=socket->conn->recv_avail;
#endif
    const int64_t now=esp_timer_get_time();
    speech_diag_net_record(8,now,0,fd,(int)pcb->rcv_wnd,available,(int)socket->rcvevent);
    speech_diag_net_record(9,now,0,(int)pcb->rcv_nxt,(int)oo_count,(int)oo_bytes,(int)pcb->rcv_ann_wnd);
    speech_diag_net_record(10,now,0,(int)heap_caps_get_free_size(MALLOC_CAP_INTERNAL),(int)heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL),(int)pcb->state,0);
}
static void request_snapshot(void *) {if(capturing && trace_fd>=0)tcpip_try_callback(tcp_snapshot,nullptr);}
'''+needle,1)
s=s.replace('ESP_ERROR_CHECK(esp_timer_start_once(timer,45000000));','''ESP_ERROR_CHECK(esp_timer_start_once(timer,45000000));
    esp_timer_handle_t sample_timer;
    const esp_timer_create_args_t sample_args={.callback=request_snapshot,.arg=nullptr,.dispatch_method=ESP_TIMER_TASK,.name="tcpdiag",.skip_unhandled_events=true};
    ESP_ERROR_CHECK(esp_timer_create(&sample_args,&sample_timer));
    ESP_ERROR_CHECK(esp_timer_start_periodic(sample_timer,100000));''',1)
p.write_text(s)
p=root/'firmware/components/tcp_transport/transport_ssl.c';s=p.read_text()
s=s.replace('extern void speech_diag_net_record','extern void speech_diag_net_socket(int);\nextern void speech_diag_net_record',1)
s=s.replace('    mbedtls_ssl_context *context =','    speech_diag_net_socket(ssl->sockfd);\n    mbedtls_ssl_context *context =',1)
s=s.replace('''    if (ssl && ssl->ssl_initialized) {
        ret = esp_tls_conn_destroy''','''    if (ssl && ssl->ssl_initialized) {
        speech_diag_net_socket(-1);
        ret = esp_tls_conn_destroy''',1)
p.write_text(s)
print('Read-only TCP/IP-thread snapshots enabled; no packet or application payload persisted')
