from pathlib import Path
import sys
root=Path('/home/lighthouse/esp32-dev/.cache/speech-playback-diagnostics-20261006')
p=root/'firmware/main/cloud_client.cpp';s=p.read_text().replace('config.cert_pem = DIAG_LAN_CA;','config.crt_bundle_attach = esp_crt_bundle_attach;');p.write_text(s)
p=root/'.cache/lan_config.h';p.write_text((root/'.cache/lan_config.home-network.h').read_text());p.chmod(0o600)
p=root/'firmware/components/tcp_transport/transport_ssl.c';s=p.read_text()
if '[TLS_PEER]' not in s:
 s=s.replace('#include "esp_tls.h"','#include "lwip/sockets.h"\n#include "lwip/inet.h"\n#include "esp_tls.h"',1)
 needle='    mbedtls_ssl_context *context ='
 s=s.replace(needle,'''    struct sockaddr_in peer = {0}; socklen_t peer_size=sizeof(peer); char peer_ip[16];
    if (getpeername(ssl->sockfd,(struct sockaddr *)&peer,&peer_size)==0 && peer.sin_family==AF_INET && inet_ntop(AF_INET,&peer.sin_addr,peer_ip,sizeof(peer_ip))) {
        ESP_LOGI(TAG,"[TLS_PEER] ip=%s port=%u",peer_ip,(unsigned)ntohs(peer.sin_port));
    }
'''+needle,1)
 p.write_text(s)
p=root/'firmware/main/net_trace.cpp';s=p.read_text()
if '__wrap_lwip_getaddrinfo' not in s:
 s=s.replace('#include <cerrno>','#include <cerrno>\n#include <cstring>\n#include "lwip/netdb.h"\n#include "lwip/inet.h"\n#include "../../.cache/speech-diagnostics/ip_choice.h"',1)
 needle='extern "C" void speech_diag_net_init() {'
 s=s.replace(needle,'''static void alloc_failed(size_t size,uint32_t caps,const char *) {
    speech_diag_net_record(7,esp_timer_get_time(),0,(int)size,(int)caps,0,0);
}
'''+needle,1)
 s=s.replace('records=(NetRecord*)heap_caps_calloc(2048,sizeof(NetRecord),MALLOC_CAP_SPIRAM);','records=(NetRecord*)heap_caps_calloc(2048,sizeof(NetRecord),MALLOC_CAP_SPIRAM);\n    ESP_ERROR_CHECK(heap_caps_register_failed_alloc_callback(alloc_failed));',1)
 s+='''
extern "C" int __real_lwip_getaddrinfo(const char*,const char*,const struct addrinfo*,struct addrinfo**);
extern "C" int __wrap_lwip_getaddrinfo(const char *name,const char *service,const struct addrinfo *hints,struct addrinfo **result) {
    const bool original=name && strcmp(name,"gw.pangtiao.men")==0;
    const char *choice=original && DIAG_FIXED_IP[0] ? DIAG_FIXED_IP : name;
    const int ret=__real_lwip_getaddrinfo(choice,service,hints,result);
    if(original && ret==0) {
        unsigned n=0;
        for(auto *p=*result;p;p=p->ai_next) {
            if(p->ai_family==AF_INET) {
                const auto *address=(const struct sockaddr_in*)p->ai_addr;
                char ip[16];inet_ntop(AF_INET,&address->sin_addr,ip,sizeof(ip));
                ESP_LOGI("NETDIAG","[DNS_DIAG] index=%u ip=%s forced=%d",n++,ip,DIAG_FIXED_IP[0]!=0);
            }
        }
    }
    return ret;
}
'''
 p.write_text(s)
p=root/'firmware/main/CMakeLists.txt';s=p.read_text()
if '--wrap=lwip_getaddrinfo' not in s:s+='\ntarget_link_options(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=lwip_getaddrinfo")\n'
p.write_text(s)
ip=sys.argv[1] if len(sys.argv)>1 else ''
assert ip in ('','104.21.8.37','172.67.156.197')
(root/'.cache/speech-diagnostics/ip_choice.h').write_text('#define DIAG_FIXED_IP "'+ip+'"\n')
print('Public peer/alloc metadata enabled; DNS choice='+str(ip or 'default')+'; original host, SNI and authentication preserved')
