<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>AI on 云淡风轻</title>
    <link>/tags/ai/</link>
    <description>Recent content in AI on 云淡风轻</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh-cn</language>
    <copyright>©2007</copyright>
    <lastBuildDate>Thu, 08 Jan 2026 11:00:00 +0800</lastBuildDate><atom:link href="/tags/ai/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>TINC 源码解读 第四篇 - 模块依赖与数据流图</title>
      <link>/posts/20260108-tinc-modules-reference/</link>
      <pubDate>Thu, 08 Jan 2026 11:00:00 +0800</pubDate>
      
      <guid>/posts/20260108-tinc-modules-reference/</guid>
      <description>&lt;p&gt;本文是 TINC 源码解读系列的第四篇，提供一份快速参考指南，包含完整的模块依赖关系、数据流图、核心数据结构和代码模式。&lt;/p&gt;
&lt;h2 id=&#34;1-文件分类一览表&#34;&gt;1. 文件分类一览表&lt;/h2&gt;
&lt;h3 id=&#34;11-核心应用程序&#34;&gt;1.1 核心应用程序&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;行数&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
          &lt;th&gt;关键函数&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;tincd.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;~730&lt;/td&gt;
          &lt;td&gt;VPN 守护进程主程序&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;main()&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;tincctl.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;~200+&lt;/td&gt;
          &lt;td&gt;控制工具客户端&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;main()&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;fsck.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;~200+&lt;/td&gt;
          &lt;td&gt;VPN 一致性检查&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;fsck()&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;info.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;~200+&lt;/td&gt;
          &lt;td&gt;VPN 信息查询&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;info()&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;12-协议处理模块&#34;&gt;1.2 协议处理模块&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
          &lt;th&gt;处理的消息&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;协议主处理&lt;/td&gt;
          &lt;td&gt;ID, ACK, ERROR, PING, PONG&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol_auth.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;认证握手&lt;/td&gt;
          &lt;td&gt;METAKEY, CHALLENGE, CHAL_REPLY&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol_edge.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;拓扑通告&lt;/td&gt;
          &lt;td&gt;ADD_EDGE, DEL_EDGE&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol_key.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;密钥交换&lt;/td&gt;
          &lt;td&gt;KEY_CHANGED, REQ_KEY, ANS_KEY&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol_subnet.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;子网通告&lt;/td&gt;
          &lt;td&gt;ADD_SUBNET, DEL_SUBNET&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol_misc.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;其他消息&lt;/td&gt;
          &lt;td&gt;STATUS, TERMREQ&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;net_packet.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;数据包转发&lt;/td&gt;
          &lt;td&gt;PACKET (UDP)&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;13-连接与加密&#34;&gt;1.3 连接与加密&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
          &lt;th&gt;核心结构&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;connection.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;TCP 连接管理&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;connection_t&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;sptps.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;SPTPS 握手/加密&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;sptps_t&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;control.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;控制接口&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;connection_t + control&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;14-节点与拓扑&#34;&gt;1.4 节点与拓扑&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
          &lt;th&gt;核心结构&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;node.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;节点管理&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;node_t&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;edge.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;链路管理&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;edge_t&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;subnet.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;子网管理&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;subnet_t&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;graph.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;拓扑算法 (Dijkstra)&lt;/td&gt;
          &lt;td&gt;-&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;route.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;路由决策&lt;/td&gt;
          &lt;td&gt;-&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;names.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;名称↔ID 映射&lt;/td&gt;
          &lt;td&gt;-&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;15-网络-io&#34;&gt;1.5 网络 I/O&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;net.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;主网络处理循环&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;net_socket.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;UDP 套接字 I/O&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;net_setup.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;网络初始化&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;net_packet.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;数据包处理&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;16-设备驱动&#34;&gt;1.6 设备驱动&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;平台&lt;/th&gt;
          &lt;th&gt;说明&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;device.h&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;通用&lt;/td&gt;
          &lt;td&gt;设备操作接口&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;linux/device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Linux&lt;/td&gt;
          &lt;td&gt;TUN/TAP 设备&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;bsd/device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;BSD&lt;/td&gt;
          &lt;td&gt;tun/tap 设备&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;bsd/darwin/tunemu.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;macOS&lt;/td&gt;
          &lt;td&gt;tunemu 模拟&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;solaris/device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Solaris&lt;/td&gt;
          &lt;td&gt;TUN 设备&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;windows/device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Windows&lt;/td&gt;
          &lt;td&gt;TAP-win32 设备&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;dummy_device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;测试&lt;/td&gt;
          &lt;td&gt;黑洞设备&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;raw_socket_device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;-&lt;/td&gt;
          &lt;td&gt;原始套接字&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;fd_device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;-&lt;/td&gt;
          &lt;td&gt;文件描述符 I/O&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;multicast_device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;-&lt;/td&gt;
          &lt;td&gt;组播&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;vde_device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;-&lt;/td&gt;
          &lt;td&gt;VDE 交换机&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;17-密码学&#34;&gt;1.7 密码学&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;功能&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;cipher.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;对称加密 (AES, ChaCha20 等)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;digest.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;哈希函数 (SHA256, SHA512 等)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;ecdsa.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;ECDSA 数字签名&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;ecdh.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;ECDH 密钥交换&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;rsa.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;RSA 签名 (遗留)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;keys.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;密钥生成与管理&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;random.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;伪随机数生成&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;openssl/*.h&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;OpenSSL 后端&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;gcrypt/*.h&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;libgcrypt 后端&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;ed25519/&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Ed25519/EdDSA 内置实现&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;chacha-poly1305/&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;ChaCha20-Poly1305 AEAD 内置实现&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;18-事件与控制&#34;&gt;1.8 事件与控制&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;event.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;事件循环核心&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;event_select.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;select() 后端&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;logger.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;日志输出&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;script.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;脚本执行 (tinc-up/down)&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;19-配置与工具&#34;&gt;1.9 配置与工具&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;conf.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;配置文件解析&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;conf_net.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;网络配置字段&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;proxy.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;SOCKS 代理支持&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;upnp.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;UPnP 端口映射&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;autoconnect.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;自动连接管理&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;address_cache.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;地址缓存&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;fs.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;文件系统操作&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;pidfile.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;PID 文件管理&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;sandbox.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;沙箱/安全限制&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;ifconfig.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;网络接口配置&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;netutl.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;网络工具函数&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;110-数据结构&#34;&gt;1.10 数据结构&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;list.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;双链表容器&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;splay_tree.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;平衡树容器&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;buffer.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;动态缓冲区&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;meta.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;元数据处理&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;2-模块依赖关系&#34;&gt;2. 模块依赖关系&lt;/h2&gt;
&lt;h3 id=&#34;21-依赖层级图&#34;&gt;2.1 依赖层级图&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Application Layer
|
+-- tincd.c (主程序)
+-- tincctl.c (控制工具)
+-- info.c (信息查询)
+-- fsck.c (一致性检查)
    |
    v
Control &amp;amp; Event Layer
|
+-- event.c (事件循环)
+-- logger.c (日志)
+-- script.c (脚本执行)
+-- control.c (控制接口)
    |
    v
Protocol &amp;amp; Connection Layer
|
+-- connection.c (连接管理)
+-- protocol*.c (协议处理)
+-- sptps.c (加密握手)
    |
    v
Topology &amp;amp; Routing Layer
|
+-- node.c (节点)
+-- edge.c (链路)
+-- subnet.c (子网)
+-- graph.c (Dijkstra)
+-- route.c (路由)
    |
    v
Network I/O Layer
|
+-- net.c (主循环)
+-- net_socket.c (UDP)
+-- net_packet.c (转发)
+-- net_setup.c (初始化)
    |
    v
Device &amp;amp; Platform Layer
|
+-- device.h (抽象接口)
+-- linux/device.c
+-- bsd/device.c
+-- windows/device.c
    |
    v
Cryptography Layer
|
+-- cipher.c (对称)
+-- digest.c (哈希)
+-- ecdsa.c (签名)
+-- ecdh.c (密钥交换)
+-- keys.c (密钥管理)
    |
    v
Utilities &amp;amp; Data Structures
|
+-- buffer.c, list.c, splay_tree.c
+-- conf.c, logger.c, random.c
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;22-模块间调用关系&#34;&gt;2.2 模块间调用关系&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tincd.c (入口)
  |
  +-- event_loop()
  |   |
  |   +-- accept_connection() -&amp;gt; connection.c
  |   +-- handle_timeout() -&amp;gt; protocol*.c
  |   +-- network_poll()
  |       |
  |       +-- receive_packet() -&amp;gt; net_packet.c
  |       |   |
  |       |   +-- decrypt() -&amp;gt; sptps.c
  |       |   +-- route_packet() -&amp;gt; route.c
  |       |
  |       +-- send_packet() -&amp;gt; net_socket.c
  |           |
  |           +-- encrypt() -&amp;gt; sptps.c
  |
  +-- graph_update()
  |   |
  |   +-- dijkstra() -&amp;gt; graph.c
  |   +-- update_routes() -&amp;gt; route.c
  |
  +-- handle_protocol_message()
      |
      +-- protocol_*.c (各消息处理)
          |
          +-- node_add() -&amp;gt; node.c
          +-- edge_add() -&amp;gt; edge.c
          +-- subnet_add() -&amp;gt; subnet.c
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;3-核心数据流图&#34;&gt;3. 核心数据流图&lt;/h2&gt;
&lt;h3 id=&#34;31-连接建立流程&#34;&gt;3.1 连接建立流程&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Client Node                         Server Node
    |                                   |
    +-- socket() ----TCP---&amp;gt;  accept()
    |
    +-- send_id()
    |   (PROT_MAJOR, PROT_MINOR)
    |   &amp;lt;--------- recv_id()
    |       (verify version)
    |
    +-- send_metakey()
    |   (cipher, digest, key)
    |   &amp;lt;--------- recv_metakey()
    |       (setup encryption)
    |
    +-- send_challenge()
    |   (hash = HMAC(...))
    |   &amp;lt;--------- recv_challenge()
    |       (compute hash)
    |
    +-- send_chal_reply()
    |   (hash reply)
    |   &amp;lt;--------- recv_chal_reply()
    |       (verify identity)
    |
    +-- send_ack()
    |   &amp;lt;--------- recv_ack()
    |
    v
Connection Established
Exchange Topology (ADD_EDGE, ADD_SUBNET)
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;32-数据包转发流程&#34;&gt;3.2 数据包转发流程&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;VPN Data (IP Packet)
    |
    v
Write to Virtual Device (device.c)
    |
    v
tinc Network Layer (route.c)
    |
    +-- Query subnet owner
    |   (route_ipv4/route_ipv6)
    |
    v
Find Next Hop (graph.c)
    |
    +-- Check if direct or via relay
    |
    v
Encrypt Packet (sptps.c)
    |
    +-- HMAC + symmetric encryption
    |
    v
Choose Transport (UDP or TCP)
    |
    +-- If udp_confirmed and recent:
    |   +-- send_udppacket() (net_socket.c)
    |
    +-- Else:
    |   +-- send_tcppacket() (connection.c)
    |
    v
Network Transmission
    |
    v (Reverse on receiving side)
Receive Packet
    |
    +-- Decrypt (sptps.c)
    +-- Verify HMAC
    +-- Check sequence number
    |
    v
Route Decision (route.c)
    |
    +-- Local delivery?
    |   +-- Write to device
    |   +-- Application reads
    |
    +-- Forward to other node?
    |   +-- Send to next hop
    |
    v
Application Data
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;33-拓扑同步流程&#34;&gt;3.3 拓扑同步流程&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Node A                  Root/Relay                Node B
    |                      |                       |
    +-- ADD_EDGE ---------&amp;gt;|-- ADD_EDGE ----------&amp;gt;|
    |   (A, Root)          | (propagate)           |
    |                      |                       |
    |&amp;lt;-- ADD_EDGE ---------|&amp;lt;-- ADD_EDGE ----------+
    |   (B, Root)          | (propagate)           |
    |                      |                       |
    +-- ADD_SUBNET -------&amp;gt;|-- ADD_SUBNET --------&amp;gt;|
    |   (A, 172.16.1.0/24) |                       |
    |                      |                       |
    +-- REQ_KEY ----------&amp;gt;|-- REQ_KEY -----------&amp;gt;|
    |   (A wants B&amp;#39;s key)  |                       |
    |                      |&amp;lt;-- ANS_KEY -----------+
    |                      |   (B&amp;#39;s key)           |
    |&amp;lt;-- ANS_KEY ----------|                       |
    |   (B&amp;#39;s key)          |                       |
    |                      |                       |
    |-- UDP Probe --------------------------------&amp;gt;|
    |   (A-&amp;gt;B direct)      |                       |
    |                      |                       |
    |&amp;lt;-- UDP Reply &amp;lt;------------------------------+|
    |   (B-&amp;gt;A direct)      |                       |
    |                      |                       |
    v (thereafter: direct UDP communication)
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;4-关键数据结构速查&#34;&gt;4. 关键数据结构速查&lt;/h2&gt;
&lt;h3 id=&#34;41-node_t-节点&#34;&gt;4.1 node_t (节点)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;name;                 &lt;span style=&#34;color:#75715e&#34;&gt;// 节点名
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;node_id_t&lt;/span&gt; id;               &lt;span style=&#34;color:#75715e&#34;&gt;// ED25519 公钥
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 状态标志
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;node_status_t&lt;/span&gt; status;       &lt;span style=&#34;color:#75715e&#34;&gt;// 连接状态位
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 网络地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;sockaddr_t&lt;/span&gt; address;         &lt;span style=&#34;color:#75715e&#34;&gt;// 节点地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;sockaddr_t&lt;/span&gt; socket_address;  &lt;span style=&#34;color:#75715e&#34;&gt;// UDP 地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 连接
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;list_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;connections; &lt;span style=&#34;color:#75715e&#34;&gt;// TCP 连接列表
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;connection_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;connection;   &lt;span style=&#34;color:#75715e&#34;&gt;// 主连接
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 拓扑
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;splay_tree_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;subnets;      &lt;span style=&#34;color:#75715e&#34;&gt;// 子网树
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;splay_tree_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;edges;        &lt;span style=&#34;color:#75715e&#34;&gt;// 关联边树
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 路由
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;via;         &lt;span style=&#34;color:#75715e&#34;&gt;// 路由下一跳
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;nexthop;     &lt;span style=&#34;color:#75715e&#34;&gt;// 直接下一跳
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; distance;          &lt;span style=&#34;color:#75715e&#34;&gt;// Dijkstra 距离
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// UDP 直连相关
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;address_cache_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;address_cache; &lt;span style=&#34;color:#75715e&#34;&gt;// 地址缓存
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; udp_confirmed;             &lt;span style=&#34;color:#75715e&#34;&gt;// UDP 已确认
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 加密
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;cipher_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;cipher;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;digest_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;digest;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint16_t&lt;/span&gt; outcipher, incipher;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 更多字段...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;42-edge_t-链路&#34;&gt;4.2 edge_t (链路)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;edge_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;from;        &lt;span style=&#34;color:#75715e&#34;&gt;// 源节点
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;to;          &lt;span style=&#34;color:#75715e&#34;&gt;// 目标节点
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;sockaddr_t&lt;/span&gt; address;         &lt;span style=&#34;color:#75715e&#34;&gt;// 目标地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; weight;                 &lt;span style=&#34;color:#75715e&#34;&gt;// Dijkstra 权重
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; options;                &lt;span style=&#34;color:#75715e&#34;&gt;// 边选项
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;connection_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;connection; &lt;span style=&#34;color:#75715e&#34;&gt;// 关联连接
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;edge_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;reverse;     &lt;span style=&#34;color:#75715e&#34;&gt;// 反向边指针
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; active;                &lt;span style=&#34;color:#75715e&#34;&gt;// 是否活跃
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;43-subnet_t-子网&#34;&gt;4.3 subnet_t (子网)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;subnet_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;owner;       &lt;span style=&#34;color:#75715e&#34;&gt;// 所有者
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;subnet_type_t&lt;/span&gt; type;         &lt;span style=&#34;color:#75715e&#34;&gt;// MAC/IPv4/IPv6
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; weight;                 &lt;span style=&#34;color:#75715e&#34;&gt;// 优先级权重
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;time_t&lt;/span&gt; expires;             &lt;span style=&#34;color:#75715e&#34;&gt;// 过期时间
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;union&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;subnet_mac_t&lt;/span&gt; mac;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;subnet_ipv4_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; in_addr address;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; prefixlength;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } ipv4;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;subnet_ipv6_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; in6_addr address;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; prefixlength;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } ipv6;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } net;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;44-connection_t-连接&#34;&gt;4.4 connection_t (连接)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;connection_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;io_t&lt;/span&gt; io;                    &lt;span style=&#34;color:#75715e&#34;&gt;// I/O 事件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;node;        &lt;span style=&#34;color:#75715e&#34;&gt;// 关联节点
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;sockaddr_t&lt;/span&gt; address;         &lt;span style=&#34;color:#75715e&#34;&gt;// 远程地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;sockaddr_t&lt;/span&gt; local_address;   &lt;span style=&#34;color:#75715e&#34;&gt;// 本地地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 缓冲
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;buffer_t&lt;/span&gt; inbuf, outbuf;     &lt;span style=&#34;color:#75715e&#34;&gt;// 输入/输出缓冲
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// SPTPS 加密
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;sptps_t&lt;/span&gt; sptps;              &lt;span style=&#34;color:#75715e&#34;&gt;// SPTPS 状态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 状态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;connection_status_t&lt;/span&gt; status; &lt;span style=&#34;color:#75715e&#34;&gt;// 连接状态位
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 选项
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; options;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; protocol_version;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 其他
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; control;               &lt;span style=&#34;color:#75715e&#34;&gt;// 是否控制连接
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; initiate;              &lt;span style=&#34;color:#75715e&#34;&gt;// 是否主动连接
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;45-sptps_t-sptps-加密&#34;&gt;4.5 sptps_t (SPTPS 加密)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;sptps_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;sptps_state_t&lt;/span&gt; state;        &lt;span style=&#34;color:#75715e&#34;&gt;// KEX/KEX1/KEX2/OPEN
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 回调
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;send_data_t&lt;/span&gt; send_data;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;receive_record_t&lt;/span&gt; receive_record;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 密钥交换
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;ecdh_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;ecdh;               &lt;span style=&#34;color:#75715e&#34;&gt;// ECDH 参数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 共享密钥
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; shared_secret[&lt;span style=&#34;color:#ae81ff&#34;&gt;32&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 会话密钥
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; key[&lt;span style=&#34;color:#ae81ff&#34;&gt;32&lt;/span&gt;];            &lt;span style=&#34;color:#75715e&#34;&gt;// 对称密钥
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; hmac_key[&lt;span style=&#34;color:#ae81ff&#34;&gt;32&lt;/span&gt;];       &lt;span style=&#34;color:#75715e&#34;&gt;// HMAC 密钥
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 序列号
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; inseq, outseq;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 缓冲
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;buffer_t&lt;/span&gt; inbuf, outbuf;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;5-常见代码模式&#34;&gt;5. 常见代码模式&lt;/h2&gt;
&lt;h3 id=&#34;51-创建新节点&#34;&gt;5.1 创建新节点&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;n &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;new_node&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;xstrdup&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;node_name&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;status.visited &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; false;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;status.reachable &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;node_add&lt;/span&gt;(n);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;52-添加子网&#34;&gt;5.2 添加子网&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;subnet_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;subnet &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;new_subnet&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subnet&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;owner &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; node;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subnet&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;type &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; SUBNET_IPV4;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subnet&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;net.ipv4.address &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ipv4_address;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subnet&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;net.ipv4.prefixlength &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;24&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;subnet_add&lt;/span&gt;(node, subnet);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;53-发送协议消息&#34;&gt;5.3 发送协议消息&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;send_request&lt;/span&gt;(c, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%s %d&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;REQUEST_NAME&amp;#34;&lt;/span&gt;, arg1);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 例如:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;send_request&lt;/span&gt;(c, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%s %s %s&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ADD_EDGE&amp;#34;&lt;/span&gt;, node_a, node_b);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;send_request&lt;/span&gt;(c, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%s %s %d&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ADD_SUBNET&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;192.168.1.0/24&amp;#34;&lt;/span&gt;, weight);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;54-注册事件回调&#34;&gt;5.4 注册事件回调&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;io_t&lt;/span&gt; io;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;io_add&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;io, handle_new_connection, handle, IO_READ);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;handle_new_connection&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;data, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; flags) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 处理 I/O 事件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(flags &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; IO_READ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 有数据可读
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;55-路由查询&#34;&gt;5.5 路由查询&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;via &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; node;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;subnet_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;s &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;route_ipv4&lt;/span&gt;(packet);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (s) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    via &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; s&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;owner;      &lt;span style=&#34;color:#75715e&#34;&gt;// 目标节点
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 检查是否直连
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (via&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;status.direct) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;send_udppacket&lt;/span&gt;(via, packet);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;send_via_relay&lt;/span&gt;(via, packet);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;56-图算法-dijkstra&#34;&gt;5.6 图算法 (Dijkstra)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;graph&lt;/span&gt;();  &lt;span style=&#34;color:#75715e&#34;&gt;// 计算所有最短路径
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 结果存储在每个 node 的:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// - node-&amp;gt;via (下一跳)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// - node-&amp;gt;distance (距离)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// - node-&amp;gt;indirect (是否间接)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 使用结果
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;n &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; node_tree&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;root; n; n &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;next) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Node %s: distance=%d, via=%s&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;name, n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;distance, n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;via&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;6-构建与运行&#34;&gt;6. 构建与运行&lt;/h2&gt;
&lt;h3 id=&#34;61-编译&#34;&gt;6.1 编译&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 基本编译&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./configure
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 带特定后端&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./configure --with-openssl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 发布版本&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;62-启动-vpn-节点&#34;&gt;6.2 启动 VPN 节点&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 初始化新 VPN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo tinc -n myvpn init nodename
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 添加子网&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo tinc -n myvpn add Subnet 172.16.1.0/24
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 启动守护进程&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo tinc -n myvpn start
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 查看状态&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo tinc -n myvpn info
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;63-控制工具使用&#34;&gt;6.3 控制工具使用&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 获取节点信息&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn info
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 查看连接&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn edges
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 查看子网&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn subnets
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 监控网络&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn top
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 启用/禁用节点&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn enable/disable &amp;lt;nodename&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;7-关键编译标志&#34;&gt;7. 关键编译标志&lt;/h2&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;标志&lt;/th&gt;
          &lt;th&gt;说明&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;-DHAVE_OPENSSL&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;使用 OpenSSL 后端&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;-DHAVE_LIBGCRYPT&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;使用 libgcrypt 后端&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;-DHAVE_LZO&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;启用 LZO 压缩&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;-DHAVE_LZ4&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;启用 LZ4 压缩&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;-DLOGGER_DEBUG&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;调试日志输出&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;-DHAVE_LIBUPNP&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;UPnP 支持&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;-DHAVE_LIBMINIUPNPC&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;miniupnpc 支持&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;8-调试技巧&#34;&gt;8. 调试技巧&lt;/h2&gt;
&lt;h3 id=&#34;81-启用详细日志&#34;&gt;8.1 启用详细日志&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 运行时设置日志级别&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn -d DEBUG
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 或运行时设置环境变量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DEBUG&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; tincd -n myvpn -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;82-数据包捕获&#34;&gt;8.2 数据包捕获&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 在 net_packet.c 中启用包转储
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (debug_level &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; DEBUG_TRAFFIC) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;fprintf&lt;/span&gt;(stderr, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Packet from %s: %d bytes&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            source_node&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;name, packet_len);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;83-追踪连接&#34;&gt;8.3 追踪连接&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 监视 TCP 连接建立&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;strace -e trace&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;socket,connect tincd -n myvpn -d DEBUG
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 监视 UDP 包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tcpdump -i eth0 &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;udp port 1194&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;84-性能分析&#34;&gt;8.4 性能分析&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 运行性能基准&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sptps_speed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 性能分析&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;perf record -g tincd -n myvpn -d
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;perf report
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;9-常见问题排查&#34;&gt;9. 常见问题排查&lt;/h2&gt;
&lt;h3 id=&#34;问题-1-节点无法连接&#34;&gt;问题 1: 节点无法连接&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;诊断步骤&lt;/strong&gt;:&lt;/p&gt;</description>
      <content>&lt;p&gt;本文是 TINC 源码解读系列的第四篇，提供一份快速参考指南，包含完整的模块依赖关系、数据流图、核心数据结构和代码模式。&lt;/p&gt;
&lt;h2 id=&#34;1-文件分类一览表&#34;&gt;1. 文件分类一览表&lt;/h2&gt;
&lt;h3 id=&#34;11-核心应用程序&#34;&gt;1.1 核心应用程序&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;行数&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
          &lt;th&gt;关键函数&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;tincd.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;~730&lt;/td&gt;
          &lt;td&gt;VPN 守护进程主程序&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;main()&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;tincctl.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;~200+&lt;/td&gt;
          &lt;td&gt;控制工具客户端&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;main()&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;fsck.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;~200+&lt;/td&gt;
          &lt;td&gt;VPN 一致性检查&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;fsck()&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;info.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;~200+&lt;/td&gt;
          &lt;td&gt;VPN 信息查询&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;info()&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;12-协议处理模块&#34;&gt;1.2 协议处理模块&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
          &lt;th&gt;处理的消息&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;协议主处理&lt;/td&gt;
          &lt;td&gt;ID, ACK, ERROR, PING, PONG&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol_auth.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;认证握手&lt;/td&gt;
          &lt;td&gt;METAKEY, CHALLENGE, CHAL_REPLY&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol_edge.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;拓扑通告&lt;/td&gt;
          &lt;td&gt;ADD_EDGE, DEL_EDGE&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol_key.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;密钥交换&lt;/td&gt;
          &lt;td&gt;KEY_CHANGED, REQ_KEY, ANS_KEY&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol_subnet.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;子网通告&lt;/td&gt;
          &lt;td&gt;ADD_SUBNET, DEL_SUBNET&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol_misc.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;其他消息&lt;/td&gt;
          &lt;td&gt;STATUS, TERMREQ&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;net_packet.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;数据包转发&lt;/td&gt;
          &lt;td&gt;PACKET (UDP)&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;13-连接与加密&#34;&gt;1.3 连接与加密&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
          &lt;th&gt;核心结构&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;connection.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;TCP 连接管理&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;connection_t&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;sptps.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;SPTPS 握手/加密&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;sptps_t&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;control.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;控制接口&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;connection_t + control&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;14-节点与拓扑&#34;&gt;1.4 节点与拓扑&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
          &lt;th&gt;核心结构&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;node.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;节点管理&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;node_t&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;edge.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;链路管理&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;edge_t&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;subnet.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;子网管理&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;subnet_t&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;graph.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;拓扑算法 (Dijkstra)&lt;/td&gt;
          &lt;td&gt;-&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;route.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;路由决策&lt;/td&gt;
          &lt;td&gt;-&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;names.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;名称↔ID 映射&lt;/td&gt;
          &lt;td&gt;-&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;15-网络-io&#34;&gt;1.5 网络 I/O&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;net.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;主网络处理循环&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;net_socket.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;UDP 套接字 I/O&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;net_setup.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;网络初始化&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;net_packet.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;数据包处理&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;16-设备驱动&#34;&gt;1.6 设备驱动&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;平台&lt;/th&gt;
          &lt;th&gt;说明&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;device.h&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;通用&lt;/td&gt;
          &lt;td&gt;设备操作接口&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;linux/device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Linux&lt;/td&gt;
          &lt;td&gt;TUN/TAP 设备&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;bsd/device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;BSD&lt;/td&gt;
          &lt;td&gt;tun/tap 设备&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;bsd/darwin/tunemu.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;macOS&lt;/td&gt;
          &lt;td&gt;tunemu 模拟&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;solaris/device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Solaris&lt;/td&gt;
          &lt;td&gt;TUN 设备&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;windows/device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Windows&lt;/td&gt;
          &lt;td&gt;TAP-win32 设备&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;dummy_device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;测试&lt;/td&gt;
          &lt;td&gt;黑洞设备&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;raw_socket_device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;-&lt;/td&gt;
          &lt;td&gt;原始套接字&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;fd_device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;-&lt;/td&gt;
          &lt;td&gt;文件描述符 I/O&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;multicast_device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;-&lt;/td&gt;
          &lt;td&gt;组播&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;vde_device.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;-&lt;/td&gt;
          &lt;td&gt;VDE 交换机&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;17-密码学&#34;&gt;1.7 密码学&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;功能&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;cipher.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;对称加密 (AES, ChaCha20 等)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;digest.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;哈希函数 (SHA256, SHA512 等)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;ecdsa.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;ECDSA 数字签名&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;ecdh.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;ECDH 密钥交换&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;rsa.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;RSA 签名 (遗留)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;keys.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;密钥生成与管理&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;random.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;伪随机数生成&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;openssl/*.h&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;OpenSSL 后端&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;gcrypt/*.h&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;libgcrypt 后端&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;ed25519/&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Ed25519/EdDSA 内置实现&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;chacha-poly1305/&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;ChaCha20-Poly1305 AEAD 内置实现&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;18-事件与控制&#34;&gt;1.8 事件与控制&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;event.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;事件循环核心&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;event_select.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;select() 后端&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;logger.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;日志输出&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;script.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;脚本执行 (tinc-up/down)&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;19-配置与工具&#34;&gt;1.9 配置与工具&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;conf.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;配置文件解析&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;conf_net.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;网络配置字段&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;proxy.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;SOCKS 代理支持&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;upnp.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;UPnP 端口映射&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;autoconnect.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;自动连接管理&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;address_cache.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;地址缓存&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;fs.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;文件系统操作&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;pidfile.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;PID 文件管理&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;sandbox.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;沙箱/安全限制&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;ifconfig.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;网络接口配置&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;netutl.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;网络工具函数&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;110-数据结构&#34;&gt;1.10 数据结构&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职能&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;list.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;双链表容器&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;splay_tree.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;平衡树容器&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;buffer.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;动态缓冲区&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;meta.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;元数据处理&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;2-模块依赖关系&#34;&gt;2. 模块依赖关系&lt;/h2&gt;
&lt;h3 id=&#34;21-依赖层级图&#34;&gt;2.1 依赖层级图&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Application Layer
|
+-- tincd.c (主程序)
+-- tincctl.c (控制工具)
+-- info.c (信息查询)
+-- fsck.c (一致性检查)
    |
    v
Control &amp;amp; Event Layer
|
+-- event.c (事件循环)
+-- logger.c (日志)
+-- script.c (脚本执行)
+-- control.c (控制接口)
    |
    v
Protocol &amp;amp; Connection Layer
|
+-- connection.c (连接管理)
+-- protocol*.c (协议处理)
+-- sptps.c (加密握手)
    |
    v
Topology &amp;amp; Routing Layer
|
+-- node.c (节点)
+-- edge.c (链路)
+-- subnet.c (子网)
+-- graph.c (Dijkstra)
+-- route.c (路由)
    |
    v
Network I/O Layer
|
+-- net.c (主循环)
+-- net_socket.c (UDP)
+-- net_packet.c (转发)
+-- net_setup.c (初始化)
    |
    v
Device &amp;amp; Platform Layer
|
+-- device.h (抽象接口)
+-- linux/device.c
+-- bsd/device.c
+-- windows/device.c
    |
    v
Cryptography Layer
|
+-- cipher.c (对称)
+-- digest.c (哈希)
+-- ecdsa.c (签名)
+-- ecdh.c (密钥交换)
+-- keys.c (密钥管理)
    |
    v
Utilities &amp;amp; Data Structures
|
+-- buffer.c, list.c, splay_tree.c
+-- conf.c, logger.c, random.c
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;22-模块间调用关系&#34;&gt;2.2 模块间调用关系&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tincd.c (入口)
  |
  +-- event_loop()
  |   |
  |   +-- accept_connection() -&amp;gt; connection.c
  |   +-- handle_timeout() -&amp;gt; protocol*.c
  |   +-- network_poll()
  |       |
  |       +-- receive_packet() -&amp;gt; net_packet.c
  |       |   |
  |       |   +-- decrypt() -&amp;gt; sptps.c
  |       |   +-- route_packet() -&amp;gt; route.c
  |       |
  |       +-- send_packet() -&amp;gt; net_socket.c
  |           |
  |           +-- encrypt() -&amp;gt; sptps.c
  |
  +-- graph_update()
  |   |
  |   +-- dijkstra() -&amp;gt; graph.c
  |   +-- update_routes() -&amp;gt; route.c
  |
  +-- handle_protocol_message()
      |
      +-- protocol_*.c (各消息处理)
          |
          +-- node_add() -&amp;gt; node.c
          +-- edge_add() -&amp;gt; edge.c
          +-- subnet_add() -&amp;gt; subnet.c
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;3-核心数据流图&#34;&gt;3. 核心数据流图&lt;/h2&gt;
&lt;h3 id=&#34;31-连接建立流程&#34;&gt;3.1 连接建立流程&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Client Node                         Server Node
    |                                   |
    +-- socket() ----TCP---&amp;gt;  accept()
    |
    +-- send_id()
    |   (PROT_MAJOR, PROT_MINOR)
    |   &amp;lt;--------- recv_id()
    |       (verify version)
    |
    +-- send_metakey()
    |   (cipher, digest, key)
    |   &amp;lt;--------- recv_metakey()
    |       (setup encryption)
    |
    +-- send_challenge()
    |   (hash = HMAC(...))
    |   &amp;lt;--------- recv_challenge()
    |       (compute hash)
    |
    +-- send_chal_reply()
    |   (hash reply)
    |   &amp;lt;--------- recv_chal_reply()
    |       (verify identity)
    |
    +-- send_ack()
    |   &amp;lt;--------- recv_ack()
    |
    v
Connection Established
Exchange Topology (ADD_EDGE, ADD_SUBNET)
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;32-数据包转发流程&#34;&gt;3.2 数据包转发流程&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;VPN Data (IP Packet)
    |
    v
Write to Virtual Device (device.c)
    |
    v
tinc Network Layer (route.c)
    |
    +-- Query subnet owner
    |   (route_ipv4/route_ipv6)
    |
    v
Find Next Hop (graph.c)
    |
    +-- Check if direct or via relay
    |
    v
Encrypt Packet (sptps.c)
    |
    +-- HMAC + symmetric encryption
    |
    v
Choose Transport (UDP or TCP)
    |
    +-- If udp_confirmed and recent:
    |   +-- send_udppacket() (net_socket.c)
    |
    +-- Else:
    |   +-- send_tcppacket() (connection.c)
    |
    v
Network Transmission
    |
    v (Reverse on receiving side)
Receive Packet
    |
    +-- Decrypt (sptps.c)
    +-- Verify HMAC
    +-- Check sequence number
    |
    v
Route Decision (route.c)
    |
    +-- Local delivery?
    |   +-- Write to device
    |   +-- Application reads
    |
    +-- Forward to other node?
    |   +-- Send to next hop
    |
    v
Application Data
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;33-拓扑同步流程&#34;&gt;3.3 拓扑同步流程&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Node A                  Root/Relay                Node B
    |                      |                       |
    +-- ADD_EDGE ---------&amp;gt;|-- ADD_EDGE ----------&amp;gt;|
    |   (A, Root)          | (propagate)           |
    |                      |                       |
    |&amp;lt;-- ADD_EDGE ---------|&amp;lt;-- ADD_EDGE ----------+
    |   (B, Root)          | (propagate)           |
    |                      |                       |
    +-- ADD_SUBNET -------&amp;gt;|-- ADD_SUBNET --------&amp;gt;|
    |   (A, 172.16.1.0/24) |                       |
    |                      |                       |
    +-- REQ_KEY ----------&amp;gt;|-- REQ_KEY -----------&amp;gt;|
    |   (A wants B&amp;#39;s key)  |                       |
    |                      |&amp;lt;-- ANS_KEY -----------+
    |                      |   (B&amp;#39;s key)           |
    |&amp;lt;-- ANS_KEY ----------|                       |
    |   (B&amp;#39;s key)          |                       |
    |                      |                       |
    |-- UDP Probe --------------------------------&amp;gt;|
    |   (A-&amp;gt;B direct)      |                       |
    |                      |                       |
    |&amp;lt;-- UDP Reply &amp;lt;------------------------------+|
    |   (B-&amp;gt;A direct)      |                       |
    |                      |                       |
    v (thereafter: direct UDP communication)
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;4-关键数据结构速查&#34;&gt;4. 关键数据结构速查&lt;/h2&gt;
&lt;h3 id=&#34;41-node_t-节点&#34;&gt;4.1 node_t (节点)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;name;                 &lt;span style=&#34;color:#75715e&#34;&gt;// 节点名
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;node_id_t&lt;/span&gt; id;               &lt;span style=&#34;color:#75715e&#34;&gt;// ED25519 公钥
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 状态标志
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;node_status_t&lt;/span&gt; status;       &lt;span style=&#34;color:#75715e&#34;&gt;// 连接状态位
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 网络地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;sockaddr_t&lt;/span&gt; address;         &lt;span style=&#34;color:#75715e&#34;&gt;// 节点地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;sockaddr_t&lt;/span&gt; socket_address;  &lt;span style=&#34;color:#75715e&#34;&gt;// UDP 地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 连接
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;list_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;connections; &lt;span style=&#34;color:#75715e&#34;&gt;// TCP 连接列表
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;connection_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;connection;   &lt;span style=&#34;color:#75715e&#34;&gt;// 主连接
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 拓扑
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;splay_tree_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;subnets;      &lt;span style=&#34;color:#75715e&#34;&gt;// 子网树
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;splay_tree_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;edges;        &lt;span style=&#34;color:#75715e&#34;&gt;// 关联边树
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 路由
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;via;         &lt;span style=&#34;color:#75715e&#34;&gt;// 路由下一跳
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;nexthop;     &lt;span style=&#34;color:#75715e&#34;&gt;// 直接下一跳
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; distance;          &lt;span style=&#34;color:#75715e&#34;&gt;// Dijkstra 距离
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// UDP 直连相关
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;address_cache_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;address_cache; &lt;span style=&#34;color:#75715e&#34;&gt;// 地址缓存
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; udp_confirmed;             &lt;span style=&#34;color:#75715e&#34;&gt;// UDP 已确认
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 加密
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;cipher_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;cipher;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;digest_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;digest;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint16_t&lt;/span&gt; outcipher, incipher;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 更多字段...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;42-edge_t-链路&#34;&gt;4.2 edge_t (链路)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;edge_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;from;        &lt;span style=&#34;color:#75715e&#34;&gt;// 源节点
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;to;          &lt;span style=&#34;color:#75715e&#34;&gt;// 目标节点
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;sockaddr_t&lt;/span&gt; address;         &lt;span style=&#34;color:#75715e&#34;&gt;// 目标地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; weight;                 &lt;span style=&#34;color:#75715e&#34;&gt;// Dijkstra 权重
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; options;                &lt;span style=&#34;color:#75715e&#34;&gt;// 边选项
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;connection_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;connection; &lt;span style=&#34;color:#75715e&#34;&gt;// 关联连接
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;edge_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;reverse;     &lt;span style=&#34;color:#75715e&#34;&gt;// 反向边指针
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; active;                &lt;span style=&#34;color:#75715e&#34;&gt;// 是否活跃
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;43-subnet_t-子网&#34;&gt;4.3 subnet_t (子网)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;subnet_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;owner;       &lt;span style=&#34;color:#75715e&#34;&gt;// 所有者
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;subnet_type_t&lt;/span&gt; type;         &lt;span style=&#34;color:#75715e&#34;&gt;// MAC/IPv4/IPv6
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; weight;                 &lt;span style=&#34;color:#75715e&#34;&gt;// 优先级权重
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;time_t&lt;/span&gt; expires;             &lt;span style=&#34;color:#75715e&#34;&gt;// 过期时间
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;union&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;subnet_mac_t&lt;/span&gt; mac;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;subnet_ipv4_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; in_addr address;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; prefixlength;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } ipv4;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;subnet_ipv6_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; in6_addr address;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; prefixlength;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } ipv6;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } net;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;44-connection_t-连接&#34;&gt;4.4 connection_t (连接)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;connection_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;io_t&lt;/span&gt; io;                    &lt;span style=&#34;color:#75715e&#34;&gt;// I/O 事件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;node;        &lt;span style=&#34;color:#75715e&#34;&gt;// 关联节点
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;sockaddr_t&lt;/span&gt; address;         &lt;span style=&#34;color:#75715e&#34;&gt;// 远程地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;sockaddr_t&lt;/span&gt; local_address;   &lt;span style=&#34;color:#75715e&#34;&gt;// 本地地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 缓冲
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;buffer_t&lt;/span&gt; inbuf, outbuf;     &lt;span style=&#34;color:#75715e&#34;&gt;// 输入/输出缓冲
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// SPTPS 加密
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;sptps_t&lt;/span&gt; sptps;              &lt;span style=&#34;color:#75715e&#34;&gt;// SPTPS 状态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 状态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;connection_status_t&lt;/span&gt; status; &lt;span style=&#34;color:#75715e&#34;&gt;// 连接状态位
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 选项
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; options;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; protocol_version;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 其他
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; control;               &lt;span style=&#34;color:#75715e&#34;&gt;// 是否控制连接
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; initiate;              &lt;span style=&#34;color:#75715e&#34;&gt;// 是否主动连接
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;45-sptps_t-sptps-加密&#34;&gt;4.5 sptps_t (SPTPS 加密)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;sptps_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;sptps_state_t&lt;/span&gt; state;        &lt;span style=&#34;color:#75715e&#34;&gt;// KEX/KEX1/KEX2/OPEN
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 回调
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;send_data_t&lt;/span&gt; send_data;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;receive_record_t&lt;/span&gt; receive_record;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 密钥交换
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;ecdh_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;ecdh;               &lt;span style=&#34;color:#75715e&#34;&gt;// ECDH 参数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 共享密钥
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; shared_secret[&lt;span style=&#34;color:#ae81ff&#34;&gt;32&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 会话密钥
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; key[&lt;span style=&#34;color:#ae81ff&#34;&gt;32&lt;/span&gt;];            &lt;span style=&#34;color:#75715e&#34;&gt;// 对称密钥
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; hmac_key[&lt;span style=&#34;color:#ae81ff&#34;&gt;32&lt;/span&gt;];       &lt;span style=&#34;color:#75715e&#34;&gt;// HMAC 密钥
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 序列号
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; inseq, outseq;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 缓冲
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;buffer_t&lt;/span&gt; inbuf, outbuf;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;5-常见代码模式&#34;&gt;5. 常见代码模式&lt;/h2&gt;
&lt;h3 id=&#34;51-创建新节点&#34;&gt;5.1 创建新节点&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;n &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;new_node&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;xstrdup&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;node_name&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;status.visited &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; false;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;status.reachable &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;node_add&lt;/span&gt;(n);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;52-添加子网&#34;&gt;5.2 添加子网&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;subnet_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;subnet &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;new_subnet&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subnet&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;owner &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; node;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subnet&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;type &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; SUBNET_IPV4;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subnet&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;net.ipv4.address &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ipv4_address;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;subnet&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;net.ipv4.prefixlength &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;24&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;subnet_add&lt;/span&gt;(node, subnet);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;53-发送协议消息&#34;&gt;5.3 发送协议消息&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;send_request&lt;/span&gt;(c, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%s %d&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;REQUEST_NAME&amp;#34;&lt;/span&gt;, arg1);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 例如:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;send_request&lt;/span&gt;(c, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%s %s %s&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ADD_EDGE&amp;#34;&lt;/span&gt;, node_a, node_b);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;send_request&lt;/span&gt;(c, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%s %s %d&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ADD_SUBNET&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;192.168.1.0/24&amp;#34;&lt;/span&gt;, weight);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;54-注册事件回调&#34;&gt;5.4 注册事件回调&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;io_t&lt;/span&gt; io;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;io_add&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;io, handle_new_connection, handle, IO_READ);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;handle_new_connection&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;data, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; flags) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 处理 I/O 事件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(flags &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; IO_READ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 有数据可读
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;55-路由查询&#34;&gt;5.5 路由查询&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;via &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; node;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;subnet_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;s &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;route_ipv4&lt;/span&gt;(packet);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (s) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    via &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; s&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;owner;      &lt;span style=&#34;color:#75715e&#34;&gt;// 目标节点
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 检查是否直连
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (via&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;status.direct) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;send_udppacket&lt;/span&gt;(via, packet);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;send_via_relay&lt;/span&gt;(via, packet);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;56-图算法-dijkstra&#34;&gt;5.6 图算法 (Dijkstra)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;graph&lt;/span&gt;();  &lt;span style=&#34;color:#75715e&#34;&gt;// 计算所有最短路径
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 结果存储在每个 node 的:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// - node-&amp;gt;via (下一跳)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// - node-&amp;gt;distance (距离)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// - node-&amp;gt;indirect (是否间接)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 使用结果
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;n &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; node_tree&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;root; n; n &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;next) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Node %s: distance=%d, via=%s&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;name, n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;distance, n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;via&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;6-构建与运行&#34;&gt;6. 构建与运行&lt;/h2&gt;
&lt;h3 id=&#34;61-编译&#34;&gt;6.1 编译&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 基本编译&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./configure
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 带特定后端&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./configure --with-openssl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 发布版本&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;62-启动-vpn-节点&#34;&gt;6.2 启动 VPN 节点&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 初始化新 VPN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo tinc -n myvpn init nodename
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 添加子网&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo tinc -n myvpn add Subnet 172.16.1.0/24
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 启动守护进程&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo tinc -n myvpn start
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 查看状态&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo tinc -n myvpn info
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;63-控制工具使用&#34;&gt;6.3 控制工具使用&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 获取节点信息&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn info
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 查看连接&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn edges
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 查看子网&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn subnets
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 监控网络&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn top
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 启用/禁用节点&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn enable/disable &amp;lt;nodename&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;7-关键编译标志&#34;&gt;7. 关键编译标志&lt;/h2&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;标志&lt;/th&gt;
          &lt;th&gt;说明&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;-DHAVE_OPENSSL&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;使用 OpenSSL 后端&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;-DHAVE_LIBGCRYPT&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;使用 libgcrypt 后端&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;-DHAVE_LZO&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;启用 LZO 压缩&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;-DHAVE_LZ4&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;启用 LZ4 压缩&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;-DLOGGER_DEBUG&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;调试日志输出&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;-DHAVE_LIBUPNP&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;UPnP 支持&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;-DHAVE_LIBMINIUPNPC&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;miniupnpc 支持&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;8-调试技巧&#34;&gt;8. 调试技巧&lt;/h2&gt;
&lt;h3 id=&#34;81-启用详细日志&#34;&gt;8.1 启用详细日志&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 运行时设置日志级别&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn -d DEBUG
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 或运行时设置环境变量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DEBUG&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; tincd -n myvpn -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;82-数据包捕获&#34;&gt;8.2 数据包捕获&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 在 net_packet.c 中启用包转储
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (debug_level &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; DEBUG_TRAFFIC) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;fprintf&lt;/span&gt;(stderr, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Packet from %s: %d bytes&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            source_node&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;name, packet_len);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;83-追踪连接&#34;&gt;8.3 追踪连接&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 监视 TCP 连接建立&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;strace -e trace&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;socket,connect tincd -n myvpn -d DEBUG
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 监视 UDP 包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tcpdump -i eth0 &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;udp port 1194&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;84-性能分析&#34;&gt;8.4 性能分析&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 运行性能基准&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sptps_speed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 性能分析&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;perf record -g tincd -n myvpn -d
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;perf report
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;9-常见问题排查&#34;&gt;9. 常见问题排查&lt;/h2&gt;
&lt;h3 id=&#34;问题-1-节点无法连接&#34;&gt;问题 1: 节点无法连接&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;诊断步骤&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 1. 检查配置&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn info
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 2. 检查网络连通性&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ping &amp;lt;remote_ip&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 3. 检查密钥文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -la ~/.tinc/myvpn/hosts/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 4. 查看详细日志&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn -d DEBUG
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;常见原因&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;防火墙阻止 TCP 655 或 UDP 1194&lt;/li&gt;
&lt;li&gt;密钥文件缺失或权限错误&lt;/li&gt;
&lt;li&gt;配置文件中 Address 字段错误&lt;/li&gt;
&lt;li&gt;DNS 解析失败&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;问题-2-高延迟&#34;&gt;问题 2: 高延迟&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;检查项&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;查看 Dijkstra 路由是否最优: &lt;code&gt;tinc -n myvpn edges&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;检查链路权重设置&lt;/li&gt;
&lt;li&gt;考虑使用 UDP 直连而非 TCP 中继&lt;/li&gt;
&lt;li&gt;检查 MTU 设置是否导致分片&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;问题-3-密钥签名错误&#34;&gt;问题 3: 密钥/签名错误&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;解决方案&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 重新生成密钥&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn generate-keys
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 验证密钥对&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sptps_keypair
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 测试加密&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sptps_test
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;问题-4-内存占用持续增长&#34;&gt;问题 4: 内存占用持续增长&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;检查&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;是否存在内存泄漏 (valgrind)&lt;/li&gt;
&lt;li&gt;是否有断开但未清理的连接&lt;/li&gt;
&lt;li&gt;检查事件循环是否正确管理&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;10-性能优化点&#34;&gt;10. 性能优化点&lt;/h2&gt;
&lt;h3 id=&#34;关键优化&#34;&gt;关键优化&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;UDP 直连&lt;/strong&gt;: 避免 TCP 元包开销 (5-10 倍吞吐量提升)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dijkstra 缓存&lt;/strong&gt;: 避免频繁重算拓扑&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;设备选择&lt;/strong&gt;: TUN (L3) 比 TAP (L2) 更高效&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;加密算法&lt;/strong&gt;: ChaCha20 &amp;gt; AES-CBC&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;子网聚合&lt;/strong&gt;: 减少 ADD_SUBNET 广播&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;事件循环&lt;/strong&gt;: epoll/kqueue &amp;gt; select&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;地址缓存&lt;/strong&gt;: 避免重复 DNS 查询&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;性能指标&#34;&gt;性能指标&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;指标&lt;/th&gt;
          &lt;th&gt;TCP 中继&lt;/th&gt;
          &lt;th&gt;UDP 直连&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;延迟&lt;/td&gt;
          &lt;td&gt;100-500ms&lt;/td&gt;
          &lt;td&gt;10-100ms&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;吞吐量&lt;/td&gt;
          &lt;td&gt;50-200 Mbps&lt;/td&gt;
          &lt;td&gt;200-1000+ Mbps&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CPU 占用&lt;/td&gt;
          &lt;td&gt;中等&lt;/td&gt;
          &lt;td&gt;低&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;11-模块学习路径建议&#34;&gt;11. 模块学习路径建议&lt;/h2&gt;
&lt;h3 id=&#34;初学者路径&#34;&gt;初学者路径&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;第一阶段：了解主程序流程&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;阅读 &lt;code&gt;tincd.c&lt;/code&gt; - 理解主程序和事件循环&lt;/li&gt;
&lt;li&gt;阅读 &lt;code&gt;main()&lt;/code&gt; 函数和初始化流程&lt;/li&gt;
&lt;li&gt;理解配置加载、设备初始化、事件循环&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;第二阶段：理解数据结构&lt;/strong&gt;
3. 阅读 &lt;code&gt;node.c&lt;/code&gt;, &lt;code&gt;edge.c&lt;/code&gt;, &lt;code&gt;subnet.c&lt;/code&gt; - 核心数据结构
4. 理解节点、边、子网的关系
5. 理解拓扑树的组织方式&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第三阶段：掌握网络逻辑&lt;/strong&gt;
6. 阅读 &lt;code&gt;net.c&lt;/code&gt;, &lt;code&gt;route.c&lt;/code&gt; - 网络处理和路由
7. 理解数据包的接收和转发流程
8. 理解路由决策和下一跳计算&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第四阶段：学习协议实现&lt;/strong&gt;
9. 阅读 &lt;code&gt;protocol.c&lt;/code&gt; - 协议消息处理
10. 理解握手流程和消息类型
11. 理解连接生命周期&lt;/p&gt;
&lt;h3 id=&#34;进阶路径&#34;&gt;进阶路径&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;第五阶段：深入加密层&lt;/strong&gt;
12. 阅读 &lt;code&gt;sptps.c&lt;/code&gt; - SPTPS 握手和加密
13. 阅读 &lt;code&gt;cipher.c&lt;/code&gt;, &lt;code&gt;digest.c&lt;/code&gt; - 密码学原语
14. 理解密钥交换和会话建立&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第六阶段：掌握拓扑算法&lt;/strong&gt;
15. 阅读 &lt;code&gt;graph.c&lt;/code&gt; - Dijkstra 最短路径
16. 理解拓扑更新和路由重计算
17. 理解环检测和分割处理&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第七阶段：系统集成&lt;/strong&gt;
18. 阅读 &lt;code&gt;device.c&lt;/code&gt; - 设备抽象和平台适配
19. 阅读 &lt;code&gt;event.c&lt;/code&gt; - 事件循环实现
20. 理解跨平台兼容性&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第八阶段：高级特性&lt;/strong&gt;
21. 学习 UDP 打洞机制 (&lt;code&gt;net_socket.c&lt;/code&gt;)
22. 学习 MTU 探测和路径优化
23. 学习性能优化技巧&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;12-快速定位代码&#34;&gt;12. 快速定位代码&lt;/h2&gt;
&lt;h3 id=&#34;按功能查找&#34;&gt;按功能查找&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;我要修改 TCP 握手流程&amp;rdquo;&lt;/strong&gt;
→ 查看 &lt;code&gt;protocol_auth.c&lt;/code&gt;, &lt;code&gt;connection.c&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;我要添加新的 UDP 功能&amp;rdquo;&lt;/strong&gt;
→ 查看 &lt;code&gt;net_socket.c&lt;/code&gt;, &lt;code&gt;net_packet.c&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;我要优化路由算法&amp;rdquo;&lt;/strong&gt;
→ 查看 &lt;code&gt;graph.c&lt;/code&gt;, &lt;code&gt;route.c&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;我要调整加密参数&amp;rdquo;&lt;/strong&gt;
→ 查看 &lt;code&gt;cipher.c&lt;/code&gt;, &lt;code&gt;digest.c&lt;/code&gt;, &lt;code&gt;sptps.c&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;我要修改拓扑同步&amp;rdquo;&lt;/strong&gt;
→ 查看 &lt;code&gt;protocol_edge.c&lt;/code&gt;, &lt;code&gt;protocol_subnet.c&lt;/code&gt;, &lt;code&gt;graph.c&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;我要支持新平台&amp;rdquo;&lt;/strong&gt;
→ 查看 &lt;code&gt;device.h&lt;/code&gt;, &lt;code&gt;bsd/device.c&lt;/code&gt;, &lt;code&gt;linux/device.c&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;按数据结构查找&#34;&gt;按数据结构查找&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;node_t 相关代码&lt;/strong&gt;
→ &lt;code&gt;node.c&lt;/code&gt;, &lt;code&gt;node.h&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;edge_t 相关代码&lt;/strong&gt;
→ &lt;code&gt;edge.c&lt;/code&gt;, &lt;code&gt;edge.h&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;subnet_t 相关代码&lt;/strong&gt;
→ &lt;code&gt;subnet.c&lt;/code&gt;, &lt;code&gt;subnet.h&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;connection_t 相关代码&lt;/strong&gt;
→ &lt;code&gt;connection.c&lt;/code&gt;, &lt;code&gt;connection.h&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;sptps_t 相关代码&lt;/strong&gt;
→ &lt;code&gt;sptps.c&lt;/code&gt;, &lt;code&gt;sptps.h&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;13-相关资源&#34;&gt;13. 相关资源&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;官网&lt;/strong&gt;: &lt;a href=&#34;https://www.tinc-vpn.org/&#34;&gt;https://www.tinc-vpn.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;文档&lt;/strong&gt;: &lt;a href=&#34;https://www.tinc-vpn.org/documentation-1.1/&#34;&gt;https://www.tinc-vpn.org/documentation-1.1/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;源码&lt;/strong&gt;: &lt;a href=&#34;https://github.com/gsliepen/tinc&#34;&gt;https://github.com/gsliepen/tinc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;协议规范&lt;/strong&gt;: PROTOCOL 文件 (项目内)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;
&lt;p&gt;TINC 的源码组织展现了大型系统软件的设计精髓：&lt;/p&gt;
&lt;h3 id=&#34;关键特点&#34;&gt;关键特点&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;清晰的分层架构&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;应用层、控制层、协议层、网络层、系统层&lt;/li&gt;
&lt;li&gt;每层通过定义良好的接口相互通信&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;灵活的数据结构&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;节点、边、子网形成拓扑&lt;/li&gt;
&lt;li&gt;连接、SPTPS 管理通信状态&lt;/li&gt;
&lt;li&gt;事件、缓冲处理异步操作&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;高效的算法&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dijkstra 最短路径&lt;/li&gt;
&lt;li&gt;MRU 地址缓存&lt;/li&gt;
&lt;li&gt;UDP 打洞和 MTU 探测&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;良好的可移植性&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;设备层抽象支持多平台&lt;/li&gt;
&lt;li&gt;密码层支持多后端&lt;/li&gt;
&lt;li&gt;平台特定代码隔离&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;学习建议&#34;&gt;学习建议&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;从主程序入手&lt;/strong&gt; - 理解整体流程&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;掌握核心数据结构&lt;/strong&gt; - 理解系统状态&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;学习协议实现&lt;/strong&gt; - 理解通信机制&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;深入加密和算法&lt;/strong&gt; - 理解安全性&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;研究平台适配&lt;/strong&gt; - 理解可移植性&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这个项目是学习系统软件开发的极好范例！&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&#34;系列预告&#34;&gt;系列预告&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;第一篇：&lt;a href=&#34;../20260108-tinc-protocol-analysis&#34;&gt;TINC 协议深度解析&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;第二篇：&lt;a href=&#34;../20260108-tinc-module-architecture&#34;&gt;TINC 模块架构与代码组织&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;第三篇：&lt;a href=&#34;../20260108-tinc-udp-holepunching&#34;&gt;UDP 打洞机制&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;第四篇：TINC 项目 - 模块依赖与数据流图&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>TINC 源码解读 第三篇 - UDP 打洞</title>
      <link>/posts/20260108-tinc-udp-holepunching/</link>
      <pubDate>Thu, 08 Jan 2026 10:00:00 +0800</pubDate>
      
      <guid>/posts/20260108-tinc-udp-holepunching/</guid>
      <description>&lt;p&gt;本文是 TINC 源码系列分析的第三篇，重点探讨 TINC 如何在 NAT 环境下建立 P2P 直连。通过 UDP 打洞技术，TINC 能够让位于不同 NAT 后的节点直接通信，大幅提升性能。&lt;/p&gt;
&lt;h2 id=&#34;1-udp-打洞概览&#34;&gt;1. UDP 打洞概览&lt;/h2&gt;
&lt;h3 id=&#34;问题背景&#34;&gt;问题背景&lt;/h3&gt;
&lt;p&gt;在互联网上，大多数终端设备都位于 NAT（Network Address Translation）或防火墙后面。这意味着两个内网节点无法直接建立 P2P 连接——它们的内网地址在公网上不可见。传统的解决方案是使用中央服务器中继，但这会增加延迟和服务器成本。&lt;/p&gt;</description>
      <content>&lt;p&gt;本文是 TINC 源码系列分析的第三篇，重点探讨 TINC 如何在 NAT 环境下建立 P2P 直连。通过 UDP 打洞技术，TINC 能够让位于不同 NAT 后的节点直接通信，大幅提升性能。&lt;/p&gt;
&lt;h2 id=&#34;1-udp-打洞概览&#34;&gt;1. UDP 打洞概览&lt;/h2&gt;
&lt;h3 id=&#34;问题背景&#34;&gt;问题背景&lt;/h3&gt;
&lt;p&gt;在互联网上，大多数终端设备都位于 NAT（Network Address Translation）或防火墙后面。这意味着两个内网节点无法直接建立 P2P 连接——它们的内网地址在公网上不可见。传统的解决方案是使用中央服务器中继，但这会增加延迟和服务器成本。&lt;/p&gt;
&lt;h3 id=&#34;核心概念&#34;&gt;核心概念&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;UDP 打洞&lt;/strong&gt; 是一种 NAT 穿透技术，允许两个在 NAT 后面的节点建立直接的 UDP 连接。基本原理是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;两个节点都在 NAT 后&lt;/li&gt;
&lt;li&gt;无法直接建立 P2P 连接&lt;/li&gt;
&lt;li&gt;通过第三方（根节点）转发连接信息&lt;/li&gt;
&lt;li&gt;两个节点同时向对方发送 UDP 包&lt;/li&gt;
&lt;li&gt;NAT 记住出站连接，允许回复通过&lt;/li&gt;
&lt;li&gt;建立直接的 UDP 通道&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;优势&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ 避免 TCP 中继的开销&lt;/li&gt;
&lt;li&gt;✅ 降低延迟&lt;/li&gt;
&lt;li&gt;✅ 减少根节点流量&lt;/li&gt;
&lt;li&gt;✅ 提高可靠性和吞吐量&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;2-tinc-中的-udp-打洞机制&#34;&gt;2. TINC 中的 UDP 打洞机制&lt;/h2&gt;
&lt;h3 id=&#34;节点状态位&#34;&gt;节点状态位&lt;/h3&gt;
&lt;p&gt;TINC 使用位字段记录节点状态，其中 &lt;code&gt;udp_confirmed&lt;/code&gt; 是关键标志位，表示 UDP 连接已双向确认可用：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;union&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_status_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; validkey: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;           &lt;span style=&#34;color:#75715e&#34;&gt;// 有有效的加密密钥
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; waitingforkey: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;      &lt;span style=&#34;color:#75715e&#34;&gt;// 等待密钥回复
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; visited: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;            &lt;span style=&#34;color:#75715e&#34;&gt;// Dijkstra 访问标记
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; reachable: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;          &lt;span style=&#34;color:#75715e&#34;&gt;// 在拓扑中可达
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; indirect: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;           &lt;span style=&#34;color:#75715e&#34;&gt;// 不可直接到达
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; sptps: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;              &lt;span style=&#34;color:#75715e&#34;&gt;// 支持 SPTPS 握手
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; udp_confirmed: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;      &lt;span style=&#34;color:#75715e&#34;&gt;// ★ UDP 已确认可用
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; send_locally: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;       &lt;span style=&#34;color:#75715e&#34;&gt;// 从本地网络发送
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; udppacket: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;          &lt;span style=&#34;color:#75715e&#34;&gt;// 最后收到 UDP 包
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; validkey_in: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;        &lt;span style=&#34;color:#75715e&#34;&gt;// 已发送有效密钥给对方
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; has_address: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;        &lt;span style=&#34;color:#75715e&#34;&gt;// 知道对方公网地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; ping_sent: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;          &lt;span style=&#34;color:#75715e&#34;&gt;// 已发送 UDP 探针包
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; value;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;node_status_t&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;关键状态变量&#34;&gt;关键状态变量&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// UDP 直连相关
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; udp_confirmed;             &lt;span style=&#34;color:#75715e&#34;&gt;// UDP 连接已确认双向
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;address_cache_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;address_cache; &lt;span style=&#34;color:#75715e&#34;&gt;// 最近地址缓存
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 打洞探测相关
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; ping_sent;                 &lt;span style=&#34;color:#75715e&#34;&gt;// UDP 探针已发送
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; timeval udp_ping_sent;   &lt;span style=&#34;color:#75715e&#34;&gt;// 探针发送时间
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; udp_ping_rtt;              &lt;span style=&#34;color:#75715e&#34;&gt;// 往返时间 (微秒)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// MTU 探测
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; mtuprobes;                  &lt;span style=&#34;color:#75715e&#34;&gt;// MTU 探针计数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint16_t&lt;/span&gt; mtu;                   &lt;span style=&#34;color:#75715e&#34;&gt;// 当前 MTU
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint16_t&lt;/span&gt; minmtu;                &lt;span style=&#34;color:#75715e&#34;&gt;// 最小 MTU
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint16_t&lt;/span&gt; maxmtu;                &lt;span style=&#34;color:#75715e&#34;&gt;// 最大 MTU
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 包大小统计
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; maxrecentlen;          &lt;span style=&#34;color:#75715e&#34;&gt;// 最近最大包长
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;3-udp-打洞流程&#34;&gt;3. UDP 打洞流程&lt;/h2&gt;
&lt;h3 id=&#34;详细步骤&#34;&gt;详细步骤&lt;/h3&gt;
&lt;h4 id=&#34;步骤-1-tcp-握手连接&#34;&gt;步骤 1: TCP 握手连接&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Node A                  Root Server                Node B
  |                        |                          |
  |------ TCP CONNECT ----&amp;gt;|                          |
  |                        |&amp;lt;------ TCP CONNECT ------|
  |                        |                          |
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;步骤-2-交换拓扑信息&#34;&gt;步骤 2: 交换拓扑信息&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Node A                  Root Server                Node B
  |                        |                          |
  |- ADD_EDGE A, Root ----&amp;gt;|                          |
  |                        | (Root learns A&amp;#39;s addr)   |
  |                        |                          |
  |                        |-- ADD_EDGE B, Root -----&amp;gt;|
  |                        |                          |
  |&amp;lt;- ADD_EDGE B, Root ----|                          |
  |   (A learns B exists)  |                          |
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;步骤-3-密钥交换&#34;&gt;步骤 3: 密钥交换&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Node A                  Root Server                Node B
  |                        |                          |
  |-- REQ_KEY A-&amp;gt;B -------&amp;gt;|                          |
  | (request B&amp;#39;s key)      |                          |
  |                        |---- REQ_KEY A-&amp;gt;B -------&amp;gt;|
  |                        |                          |
  |                        |&amp;lt;---- ANS_KEY B-&amp;gt;A -------|
  |                        | (B&amp;#39;s key)                |
  |&amp;lt;-- ANS_KEY B-&amp;gt;A -------|                          |
  | (forwarded by Root)    |                          |
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;步骤-4-udp-打洞-关键阶段&#34;&gt;步骤 4: UDP 打洞 (关键阶段)&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Node A (LAN: 192.168.1.100:1194)        Node B (LAN: 192.168.2.50:1194)
  |                                       |
  | A knows B&amp;#39;s public: 203.0.113.20:5001 | B knows A&amp;#39;s public: 203.0.113.10:5000
  |                                       |
  +-- UDP Probe (TYPE=0) ----+            |
  |   NAT A opens hole:      |            |
  |   LAN1194 &amp;lt;-&amp;gt; WAN5000    |            |
  |                          +-----------&amp;gt;| Forward to B&amp;#39;s LAN
  |                                       | B&amp;#39;s NAT opened
  |                          +------ UDP Reply (TYPE=1) --+
  |                          |  NAT B: LAN1194 &amp;lt;-&amp;gt; WAN5001|
  |                          |                            |
  |&amp;lt;-- UDP Reply received &amp;lt;--+                            |
  |    From: 203.0.113.20:5001                            |
  |    NAT A allows reply (hole remains open)             |
  |                                       |
  v (Both sides confirm UDP reachable)
  
  udp_confirmed = true [SUCCESS]
  Both NAT holes established and verified
  Start direct UDP communication
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;步骤-5-直接-udp-通信&#34;&gt;步骤 5: 直接 UDP 通信&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Node A                                            Node B
  |                                                |
  |-------- Encrypted VPN packet (UDP) -----------&amp;gt;|
  | (No longer through Root, direct forward)       |
  |                                                |
  |&amp;lt;------- Encrypted VPN packet (UDP) ------------|
  |                                                |
  |--------- High-speed bidirectional flow -------&amp;gt;|
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;代码流程示意&#34;&gt;代码流程示意&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 1. 发送 UDP 探针
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;send_udp_probe_packet&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;n, &lt;span style=&#34;color:#66d9ef&#34;&gt;size_t&lt;/span&gt; len) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;vpn_packet_t&lt;/span&gt; packet;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;DATA&lt;/span&gt;(packet)[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;  &lt;span style=&#34;color:#75715e&#34;&gt;// 探针请求类型
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 发送到 n 的公网地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;send_udppacket&lt;/span&gt;(n, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;packet);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 标记已发送
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;status.ping_sent &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;gettimeofday&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;udp_ping_sent, NULL);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 2. 接收探针回复
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;udp_probe_h&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;n, &lt;span style=&#34;color:#66d9ef&#34;&gt;vpn_packet_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;packet, &lt;span style=&#34;color:#66d9ef&#34;&gt;length_t&lt;/span&gt; len) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 收到对方的探针回复
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;status.udp_confirmed) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;status.udp_confirmed &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; true;  &lt;span style=&#34;color:#75715e&#34;&gt;// ✓ 双向 UDP 已建立
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 缓存这个 UDP 地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;address_cache) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;address_cache &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;open_address_cache&lt;/span&gt;(n);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;add_recent_address&lt;/span&gt;(n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;address_cache, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;connection&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;address);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;4-地址缓存机制&#34;&gt;4. 地址缓存机制&lt;/h2&gt;
&lt;h3 id=&#34;缓存结构&#34;&gt;缓存结构&lt;/h3&gt;
&lt;p&gt;为了避免每次都进行 DNS 查询，TINC 维护一个最近地址缓存。缓存采用 MRU（Most Recently Used）策略，保留最近 8 个已验证的 UDP 地址：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define MAX_CACHED_ADDRESSES 8
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;address_cache_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;node;              &lt;span style=&#34;color:#75715e&#34;&gt;// 关联节点
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;splay_tree_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;config_tree; &lt;span style=&#34;color:#75715e&#34;&gt;// 配置树
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;config_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;cfg;             &lt;span style=&#34;color:#75715e&#34;&gt;// 当前配置
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    addrinfo &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;ai;              &lt;span style=&#34;color:#75715e&#34;&gt;// 地址信息
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    addrinfo &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;aip;             &lt;span style=&#34;color:#75715e&#34;&gt;// 当前指针
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; tried;        &lt;span style=&#34;color:#75715e&#34;&gt;// 尝试计数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 最近 8 个已验证的 UDP 地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; version;  &lt;span style=&#34;color:#75715e&#34;&gt;// 缓存版本
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; used;     &lt;span style=&#34;color:#75715e&#34;&gt;// 已使用数量
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;sockaddr_t&lt;/span&gt; address[&lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;]; &lt;span style=&#34;color:#75715e&#34;&gt;// 地址数组 (最近优先)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } data;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;address_cache_t&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;缓存操作&#34;&gt;缓存操作&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;添加地址&lt;/strong&gt;：当成功通过 UDP 接收到来自某个地址的包时，将该地址加入缓存&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MRU 策略&lt;/strong&gt;：最近使用的地址移到第 0 位，其他地址向后移动&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;获取地址&lt;/strong&gt;：优先尝试缓存的地址，避免 DNS 查询&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;重置缓存&lt;/strong&gt;：新连接尝试时清空缓存&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;5-nat-类型检测与适应&#34;&gt;5. NAT 类型检测与适应&lt;/h2&gt;
&lt;h3 id=&#34;常见-nat-类型&#34;&gt;常见 NAT 类型&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;NAT 类型&lt;/th&gt;
          &lt;th&gt;打洞成功率&lt;/th&gt;
          &lt;th&gt;特点&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Full Cone NAT&lt;/td&gt;
          &lt;td&gt;✅ 95-99%&lt;/td&gt;
          &lt;td&gt;任何外部地址都能回复&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Address-Restricted Cone&lt;/td&gt;
          &lt;td&gt;✅ 70-90%&lt;/td&gt;
          &lt;td&gt;只有之前通信过的源 IP 能回复&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Port-Restricted Cone&lt;/td&gt;
          &lt;td&gt;⚠️ 30-60%&lt;/td&gt;
          &lt;td&gt;只有特定的源 IP:端口能回复&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Symmetric NAT&lt;/td&gt;
          &lt;td&gt;❌ 0-5%&lt;/td&gt;
          &lt;td&gt;每个目标地址分配不同源端口，无法打洞&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;tinc-的适应机制&#34;&gt;TINC 的适应机制&lt;/h3&gt;
&lt;p&gt;TINC 在协议选项中编码节点的特性，根据选项决定通信策略：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define OPTION_INDIRECT    0x0001  &lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 间接连接（已知是 Symmetric NAT）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define OPTION_TCPONLY     0x0002  &lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 仅 TCP，不支持 UDP
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define OPTION_PMTU_DISCOVERY 0x0004
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define OPTION_CLAMP_MSS   0x0008
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 根据选项决定使用策略:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(e&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;options &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; OPTION_TCPONLY) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 强制使用 TCP 中继
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;use_tcp_relay&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(e&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;options &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; OPTION_INDIRECT) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 尝试打洞，但可能需要中继
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;attempt_udp_hole_punch&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 尽量使用 UDP 直连
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;prefer_udp_direct&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;6-udp-数据传输优化&#34;&gt;6. UDP 数据传输优化&lt;/h2&gt;
&lt;h3 id=&#34;发送策略&#34;&gt;发送策略&lt;/h3&gt;
&lt;p&gt;TINC 发送包时会检查 UDP 连接状态，优先使用最快的路径：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;send_udppacket&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;n, &lt;span style=&#34;color:#66d9ef&#34;&gt;vpn_packet_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;origpkt) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;status.udp_confirmed) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// ✓ 已确认 UDP 可用
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 1. 使用缓存的 UDP 地址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;sockaddr_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;sa &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;get_recent_address&lt;/span&gt;(n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;address_cache);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;sa) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// 缓存无有效地址，降级到 TCP
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;goto&lt;/span&gt; use_tcp;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 2. 加密包
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;encrypt_packet&lt;/span&gt;(n, origpkt);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 3. 直接通过 UDP 发送
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;sendto&lt;/span&gt;(udp_socket, pkt, len, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, sa, salen);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// UDP 未确认，使用 TCP 中继
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        use_tcp:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;send_tcppacket&lt;/span&gt;(n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;connection, origpkt);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;接收处理&#34;&gt;接收处理&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;receive_udppacket&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;n, &lt;span style=&#34;color:#66d9ef&#34;&gt;vpn_packet_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;inpkt) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 收到 UDP 包
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 1. 更新最近地址缓存
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;add_recent_address&lt;/span&gt;(n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;address_cache, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;peer_addr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 2. 解密
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;decrypt_packet&lt;/span&gt;(n, inpkt);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 3. 路由转发
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;route_packet&lt;/span&gt;(inpkt);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 4. 如果是首次 UDP 通信
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;status.udp_confirmed) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;status.udp_confirmed &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;logger&lt;/span&gt;(LOG_INFO, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;UDP direct connection established with %s&amp;#34;&lt;/span&gt;, n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;7-超时与降级处理&#34;&gt;7. 超时与降级处理&lt;/h2&gt;
&lt;h3 id=&#34;超时配置&#34;&gt;超时配置&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 参数配置
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;timeout_t&lt;/span&gt; udp_probe_timeout;    &lt;span style=&#34;color:#75715e&#34;&gt;// 探针超时
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define UDP_PROBE_INTERVAL 3    &lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 3 秒发送一次
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define UDP_PROBE_TIMEOUT 10    &lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 10 秒未响应即超时
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 打洞流程时间线
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;s   &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;├─&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;发送第&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;个&lt;/span&gt; UDP &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;探针&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt;  status.ping_sent &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; true
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;s   &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;├─&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;发送第&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;个&lt;/span&gt; UDP &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;探针&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;6&lt;/span&gt;s   &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;├─&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;发送第&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;个&lt;/span&gt; UDP &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;探针&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;s  &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;├─&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;超时检查&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (now &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; last_udp_reply &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;s)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt;      status.udp_confirmed &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;switch&lt;/span&gt; to TCP relay
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...  &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;├─&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;继续定期发送&lt;/span&gt; UDP &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;探针尝试重连&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;降级逻辑&#34;&gt;降级逻辑&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// TCP/UDP 混合转发 - 智能选择最优路径
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;send_packet_to_node&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;n, &lt;span style=&#34;color:#66d9ef&#34;&gt;vpn_packet_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;pkt) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 优先级 1: UDP 直连（最快）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;status.udp_confirmed &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; is_recent_success) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;send_udppacket&lt;/span&gt;(n, pkt);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 优先级 2: SPTPS over UDP（新式，安全）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;status.sptps) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;send_sptps_udppacket&lt;/span&gt;(n, pkt);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 优先级 3: TCP 转发（可靠，较慢）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;connection &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;connection&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;status.active) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;send_tcppacket&lt;/span&gt;(n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;connection, pkt);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 优先级 4: 通过其他节点中继（绕行）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;via &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;via &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; n) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;send_via_relay&lt;/span&gt;(n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;via, n, pkt);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 无法送达
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; false;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;8-mtu-探测与优化&#34;&gt;8. MTU 探测与优化&lt;/h2&gt;
&lt;h3 id=&#34;mtu-发现流程&#34;&gt;MTU 发现流程&lt;/h3&gt;
&lt;p&gt;建立 UDP 直连后，TINC 会自动探测最优 MTU 大小，避免包分片导致的性能下降。&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1. 初始 MTU = 1500 (以太网标准)

2. 发送递增大小的探针包
   ├─ 1500 字节 ─→ OK ✓
   ├─ 1450 字节 ─→ OK ✓
   ├─ 1400 字节 ─→ OK ✓
   ├─ 1350 字节 ─→ ICMP Fragmented (失败)
   │
   └─ 回退: MTU = 1350 + padding

3. 最终 MTU 确定后
   └─ 所有包都限制在该大小内
   └─ 避免分片，提高性能
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;代码实现：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mtu_probe_timeout_handler&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;data) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;n &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; data;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;mtuprobes &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// MTU 已确定，不需要探测
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;mtuprobes&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; MAX_PROBES) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 探针已发送足够次数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;try_fix_mtu&lt;/span&gt;(n);  &lt;span style=&#34;color:#75715e&#34;&gt;// 确定最终 MTU
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 继续发送 MTU 探针
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;size_t&lt;/span&gt; len &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;maxmtu &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; n&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;mtuprobes &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;128&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;send_udp_probe_packet&lt;/span&gt;(n, len);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;9-协议扩展-udp_info&#34;&gt;9. 协议扩展 (UDP_INFO)&lt;/h2&gt;
&lt;p&gt;TINC 通过 &lt;code&gt;UDP_INFO&lt;/code&gt; 协议消息来交换 UDP 地址信息。这个消息在元协议（Meta Protocol，基于 TCP）中传输。&lt;/p&gt;
&lt;h3 id=&#34;udp_info-消息格式&#34;&gt;UDP_INFO 消息格式&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;格式: UDP_INFO originator_node address_info

流程:
1. Node A → Root: &amp;#34;UDP_INFO myself 203.0.113.10:5000&amp;#34;
   (告诉 Root 我的 UDP 地址)

2. Root → Node B: &amp;#34;UDP_INFO nodeA 203.0.113.10:5000&amp;#34;
   (告诉 B, A 的 UDP 地址)

3. Node B → Root: &amp;#34;UDP_INFO myself 203.0.113.20:5001&amp;#34;

4. Root → Node A: &amp;#34;UDP_INFO nodeB 203.0.113.20:5001&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;实现优势&#34;&gt;实现优势&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;内网节点无法自己检测公网地址，需要第三方帮助&lt;/li&gt;
&lt;li&gt;UDP_INFO 机制允许节点告诉其他节点自己的公网 UDP 地址&lt;/li&gt;
&lt;li&gt;这是打洞成功的必要条件&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;10-实际场景分析&#34;&gt;10. 实际场景分析&lt;/h2&gt;
&lt;h3 id=&#34;场景-a-双方都在-full-cone-nat-后&#34;&gt;场景 A: 双方都在 Full Cone NAT 后&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Node A (10.0.0.5:1194)          Node B (10.0.0.6:1194)
NAT: 203.0.113.10:5000          NAT: 203.0.113.20:5001

时间线:
0ms   A UDP 包 → Root → Root 转发给 B
      NAT A 记录: 内网 1194 ↔ 外网 5000 ↔ 203.0.113.20:5001

5ms   B 收到 A 的探针
      回复 UDP 包 → 203.0.113.10:5000
      NAT B 记录: 内网 1194 ↔ 外网 5001 ↔ 203.0.113.10:5000

10ms  A 收到 B 的回复
      udp_confirmed = true ✓
      后续所有包直接交换，不经过 Root

成功率: ✓ 100% (Full Cone NAT 最容易打洞成功)
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;场景-b-一方在-symmetric-nat-后&#34;&gt;场景 B: 一方在 Symmetric NAT 后&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Node A (Symmetric NAT)          Node B (Full Cone NAT)

A 的 NAT 行为:
每次发送到不同地址时使用不同的源端口
├─ → 203.0.113.20 from 5000
├─ → 203.0.113.30 from 5001
└─ → 203.0.113.40 from 5002

问题:
Root 看到多个不同的源端口，无法告诉 B 一个确定的 UDP 地址

结果: UDP 打洞失败 ❌
降级: 使用 TCP 中继
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;11-性能指标&#34;&gt;11. 性能指标&lt;/h2&gt;
&lt;h3 id=&#34;典型延迟与吞吐量&#34;&gt;典型延迟与吞吐量&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;TCP 中继路径&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;延迟：100-500ms（往返）&lt;/li&gt;
&lt;li&gt;吞吐量：50-200 Mbps&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;UDP 直连路径&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;延迟：10-100ms（往返，取决于网络）&lt;/li&gt;
&lt;li&gt;吞吐量：200-1000+ Mbps（接近原生网络）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;吞吐量提升&lt;/strong&gt;：UDP 直连相比 TCP 中继提升 &lt;strong&gt;5-10 倍&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;成功率统计&#34;&gt;成功率统计&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;NAT 场景&lt;/th&gt;
          &lt;th&gt;打洞成功率&lt;/th&gt;
          &lt;th&gt;降级方案&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Full Cone NAT&lt;/td&gt;
          &lt;td&gt;95-99%&lt;/td&gt;
          &lt;td&gt;TCP 中继&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Restricted Cone&lt;/td&gt;
          &lt;td&gt;70-90%&lt;/td&gt;
          &lt;td&gt;TCP 中继&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Port-Restricted&lt;/td&gt;
          &lt;td&gt;30-60%&lt;/td&gt;
          &lt;td&gt;TCP 中继&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Symmetric NAT&lt;/td&gt;
          &lt;td&gt;0-5%&lt;/td&gt;
          &lt;td&gt;TCP 中继（必须）&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;12-调试与监控&#34;&gt;12. 调试与监控&lt;/h2&gt;
&lt;h3 id=&#34;查看打洞状态&#34;&gt;查看打洞状态&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 运行时查询&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tinc -n myvpn info &amp;lt;node&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 输出示例:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Node: remotenode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Address: 203.0.113.20 port &lt;span style=&#34;color:#ae81ff&#34;&gt;655&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Cipher: aes-256-cbc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Digest: sha512
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Magic: &lt;span style=&#34;color:#ae81ff&#34;&gt;12345678&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Status: active validkey udp_confirmed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# udp_confirmed 出现 → UDP 直连已建立 ✓&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;调试日志&#34;&gt;调试日志&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 启用 UDP 调试&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;RUST_LOG&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;debug tincd -n myvpn -d DEBUG
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 关键日志:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;DEBUG&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; Sending UDP probe to nodeB &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;203.0.113.20:1194&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;DEBUG&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; Got UDP probe reply from nodeB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;DEBUG&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; UDP direct connection confirmed with nodeB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;DEBUG&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; Caching recent address &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; nodeB: 203.0.113.20:1194
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;DEBUG&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; MTU &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; nodeB: &lt;span style=&#34;color:#ae81ff&#34;&gt;1372&lt;/span&gt; bytes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;网络捕获&#34;&gt;网络捕获&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 捕获 UDP 直连包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tcpdump -i eth0 -n &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;udp port 1194&amp;#39;&lt;/span&gt; -w vpn.pcap
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 分析包内容&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wireshark vpn.pcap
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 查看: 源/目标 IP:端口、包大小、发送频率&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;13-常见问题与解决&#34;&gt;13. 常见问题与解决&lt;/h2&gt;
&lt;h3 id=&#34;问题-1-udp-打洞失败始终显示-tcp&#34;&gt;问题 1: UDP 打洞失败，始终显示 TCP&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;诊断&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ tinc -n myvpn info remotenode | grep -i udp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;现象&lt;/strong&gt;：无 &lt;code&gt;udp_confirmed&lt;/code&gt; 标志&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原因可能&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;节点在 Symmetric NAT 后&lt;/li&gt;
&lt;li&gt;防火墙阻止 UDP&lt;/li&gt;
&lt;li&gt;ISP 限制 UDP&lt;/li&gt;
&lt;li&gt;路由策略问题&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;确认两节点都支持 UDP&lt;/li&gt;
&lt;li&gt;检查防火墙规则：&lt;code&gt;sudo ufw allow 1194/udp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;尝试 UPnP 端口映射（如支持）&lt;/li&gt;
&lt;li&gt;确认 UDP_INFO 消息交换成功&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;问题-2-间歇性-udp-中断&#34;&gt;问题 2: 间歇性 UDP 中断&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;现象&lt;/strong&gt;：UDP 时而工作，时而不工作&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;网络波动导致超时&lt;/li&gt;
&lt;li&gt;NAT 刷新时间过短&lt;/li&gt;
&lt;li&gt;MTU 设置不当导致分片丢失&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;降低 UDP 探针超时：&lt;code&gt;udp_probe_timeout = 15&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;增加打洞频率：&lt;code&gt;udp_probe_interval = 2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;调整 MTU：&lt;code&gt;minmtu = 1280&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;问题-3-mtu-不匹配&#34;&gt;问题 3: MTU 不匹配&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;现象&lt;/strong&gt;：大包通过 UDP 时丢失&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;：中间网络 MTU &amp;lt; 节点配置的 MTU&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;启用 MTU 自动探测&lt;/li&gt;
&lt;li&gt;手动配置：&lt;code&gt;PMTU_SIZE 1280&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;启用 PMTU 发现：DF 位设置&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;
&lt;p&gt;TINC 的 UDP 打洞机制展示了如何在复杂的 NAT 环境下实现高效的 P2P 通信。关键设计包括：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心流程&lt;/strong&gt;：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;TCP 握手 + 拓扑同步
    ↓
UDP_INFO 交换公网地址
    ↓
同时发送 UDP 探针（打洞）
    ↓
建立双向 UDP 连接
    ↓
优先使用 UDP 直连
    ↓
失败自动降级到 TCP
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;关键特性&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ 自适应 NAT 类型&lt;/li&gt;
&lt;li&gt;✅ 地址缓存优化&lt;/li&gt;
&lt;li&gt;✅ 动态 MTU 发现&lt;/li&gt;
&lt;li&gt;✅ 失败自动降级&lt;/li&gt;
&lt;li&gt;✅ 支持 IPv4 和 IPv6&lt;/li&gt;
&lt;li&gt;✅ 低延迟高吞吐量&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;性能提升&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;连接方式&lt;/th&gt;
          &lt;th&gt;吞吐量&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;TCP 中继&lt;/td&gt;
          &lt;td&gt;50-200 Mbps&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;UDP 直连&lt;/td&gt;
          &lt;td&gt;200-1000 Mbps&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;提升倍数&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;5-10 倍&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这种精心设计的适应性系统使 TINC 在各种网络环境下都能提供最优的性能，是现代 VPN 软件的最佳实践。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&#34;系列预告&#34;&gt;系列预告&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;第一篇：&lt;a href=&#34;../20260108-tinc-protocol-analysis&#34;&gt;TINC 协议深度解析&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;第二篇：&lt;a href=&#34;../20260108-tinc-module-architecture&#34;&gt;TINC 模块架构与代码组织&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;第三篇：UDP 打洞机制&lt;/li&gt;
&lt;li&gt;第四篇：&lt;a href=&#34;../20260108-tinc-modules-reference&#34;&gt;TINC 项目 - 模块依赖与数据流图&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>TINC 源码解读 第二篇 - 模块架构与代码组织</title>
      <link>/posts/20260108-tinc-module-architecture/</link>
      <pubDate>Thu, 08 Jan 2026 09:00:00 +0800</pubDate>
      
      <guid>/posts/20260108-tinc-module-architecture/</guid>
      <description>&lt;p&gt;本文是 TINC 源码解读系列的第二篇，重点分析 TINC 的整体架构和代码组织。TINC 采用清晰的分层架构，将系统分为 8 个层次，从应用层到工具层，每层都有明确的职责。&lt;/p&gt;</description>
      <content>&lt;p&gt;本文是 TINC 源码解读系列的第二篇，重点分析 TINC 的整体架构和代码组织。TINC 采用清晰的分层架构，将系统分为 8 个层次，从应用层到工具层，每层都有明确的职责。&lt;/p&gt;
&lt;h2 id=&#34;1-项目概述&#34;&gt;1. 项目概述&lt;/h2&gt;
&lt;p&gt;TINC 是一个点对点 (P2P) VPN 守护进程，支持任意数量节点的虚拟专用网络。通过指定 VPN 中几个节点的位置和公钥，TINC 能够自动发现所有其他节点并建立连接。当直接连接不可用时，数据通过中间节点转发。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;支持的工作模式：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Router&lt;/strong&gt; (路由器模式) - 默认，每个节点关联 IPv4/IPv6 子网&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Switch&lt;/strong&gt; (交换机模式) - 虚拟以太网交换机&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hub&lt;/strong&gt; (集线器模式) - 虚拟以太网集线器&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;2-分层架构概览&#34;&gt;2. 分层架构概览&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;+---------------------------------------------------------------------+
|                    Application Layer                                |
| +----------+----------+----------+--------+                         |
| | tincd.c  | tincctl  | info.c   | fsck.c |                         |
| | (daemon) | (control)| (query)  |(verify)|                         |
| +----------+----------+----------+--------+                         |
+---------------------------------------------------------------------+
                            |
+---------------------------------------------------------------------+
|                      Control Layer                                  |
| +----------+----------+----------+--------+                         |
| | control  | command  | top.c    | script |                         |
| | (socket) | (handler)| (monitor)|(exec)  |                         |
| +----------+----------+----------+--------+                         |
+---------------------------------------------------------------------+
                            |
+---------------------------------------------------------------------+
|                   Protocol &amp;amp; Comm Layer                             |
| +----------+----------+----------+                                  |
| | protocol | sptps.c  | connec   |                                  |
| | * files  | (crypto) | tion.c   |                                  |
| +----------+----------+----------+                                  |
+---------------------------------------------------------------------+
                            |
+---------------------------------------------------------------------+
|                   Network &amp;amp; Routing Layer                           |
| +----------+----------+----------+--------+                         |
| | net*.c   | route.c  | graph.c  | proxy  |                         |
| | (I/O)    | (table)  | (topo)   |        |                         |
| +----------+----------+----------+--------+                         |
+---------------------------------------------------------------------+
                            |
+---------------------------------------------------------------------+
|                   Data Structure Layer                              |
| +----------+----------+----------+--------+                         |
| | node.c   | edge.c   | subnet.c | names  |                         |
| | +--------+----------+----------+--------+                         |
| | | list   | splay    | hash     |        |                         |
| | | tree   | tree     | table    |        |                         |
| +----------+----------+----------+--------+                         |
+---------------------------------------------------------------------+
                            |
+---------------------------------------------------------------------+
|                  Cryptography Layer                                 |
| +----------+----------+----------+--------+                         |
| | cipher   | digest   | ecdsa    | ecdh   |                         |
| | (sym)    | (hash)   | (sig)    | (kex)  |                         |
| | +--------+----------+----------+--------+                         |
| | | rsa    | ed25519  | OpenSSL  | gcrypt |                         |
| +----------+----------+----------+--------+                         |
+---------------------------------------------------------------------+
                            |
+---------------------------------------------------------------------+
|                   Device &amp;amp; System Layer                             |
| +----------+----------+----------+--------+                         |
| | device.h | *_device | event.c  | conf.c |                         |
| | (intf)   | (impl)   | (loop)   |(config)|                         |
| | +--------+----------+----------+--------+                         |
| | | linux  | bsd      | solaris  | win    |                         |
| +----------+----------+----------+--------+                         |
+---------------------------------------------------------------------+
                            |
+---------------------------------------------------------------------+
|                    Utilities Layer                                  |
| +----------+----------+----------+--------+                         |
| | logger   | utils    | random   | buffer |                         |
| | (log)    | (tools)  | (prng)   | (mem)  |                         |
| | +--------+----------+----------+--------+                         |
| | | fs.c   | address  | autocon  | names  |                         |
| | |        | cache.c  | nect.c   |        |                         |
| +----------+----------+----------+--------+                         |
+---------------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;3-模块详细说明&#34;&gt;3. 模块详细说明&lt;/h2&gt;
&lt;h3 id=&#34;31-应用层-application-layer&#34;&gt;3.1 应用层 (Application Layer)&lt;/h3&gt;
&lt;h4 id=&#34;tincdc---主守护进程&#34;&gt;&lt;code&gt;tincd.c&lt;/code&gt; - 主守护进程&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;职责&lt;/strong&gt;: VPN 守护进程的主程序和事件循环&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;功能&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;初始化配置和网络&lt;/li&gt;
&lt;li&gt;启动主事件循环&lt;/li&gt;
&lt;li&gt;处理信号和优雅关闭&lt;/li&gt;
&lt;li&gt;管理程序生命周期&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;依赖&lt;/strong&gt;: &lt;code&gt;conf.h&lt;/code&gt;, &lt;code&gt;event.h&lt;/code&gt;, &lt;code&gt;protocol.h&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;tincctlc---控制工具&#34;&gt;&lt;code&gt;tincctl.c&lt;/code&gt; - 控制工具&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;职责&lt;/strong&gt;: 远程控制 tincd 的命令行工具&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;功能&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;连接到 tincd 控制套接字&lt;/li&gt;
&lt;li&gt;发送/接收命令&lt;/li&gt;
&lt;li&gt;交互式命令处理&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;依赖&lt;/strong&gt;: &lt;code&gt;control.h&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;infoc-和-fsckc&#34;&gt;&lt;code&gt;info.c&lt;/code&gt; 和 &lt;code&gt;fsck.c&lt;/code&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;info.c&lt;/strong&gt;: 显示 VPN 节点信息、查询节点状态&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fsck.c&lt;/strong&gt;: VPN 配置和状态一致性验证&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&#34;32-控制层-control-layer&#34;&gt;3.2 控制层 (Control Layer)&lt;/h3&gt;
&lt;h4 id=&#34;controlc---控制连接管理&#34;&gt;&lt;code&gt;control.c&lt;/code&gt; - 控制连接管理&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;职责&lt;/strong&gt;: 管理与控制客户端的连接&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;功能&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;建立和维护控制连接&lt;/li&gt;
&lt;li&gt;接收/处理控制命令&lt;/li&gt;
&lt;li&gt;返回状态信息&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;关键结构&lt;/strong&gt;: &lt;code&gt;connection_t&lt;/code&gt; (带 control 标志)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;scriptc---脚本执行&#34;&gt;&lt;code&gt;script.c&lt;/code&gt; - 脚本执行&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;职责&lt;/strong&gt;: 执行 VPN 生命周期脚本&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;功能&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;执行 &lt;code&gt;tinc-up/tinc-down&lt;/code&gt; 脚本&lt;/li&gt;
&lt;li&gt;设置虚拟网络接口&lt;/li&gt;
&lt;li&gt;执行自定义钩子函数&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;环境&lt;/strong&gt;: 通过环境变量传递配置&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;eventc---事件循环&#34;&gt;&lt;code&gt;event.c&lt;/code&gt; - 事件循环&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;职责&lt;/strong&gt;: 异步事件处理引擎&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;功能&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;I/O 事件（select/epoll/kqueue）&lt;/li&gt;
&lt;li&gt;超时处理&lt;/li&gt;
&lt;li&gt;信号处理&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;回调类型&lt;/strong&gt;: &lt;code&gt;io_cb_t&lt;/code&gt;, &lt;code&gt;timeout_cb_t&lt;/code&gt;, &lt;code&gt;signal_cb_t&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&#34;33-协议与通信层-protocol--communication&#34;&gt;3.3 协议与通信层 (Protocol &amp;amp; Communication)&lt;/h3&gt;
&lt;h4 id=&#34;protocolc---协议处理&#34;&gt;&lt;code&gt;protocol*.c&lt;/code&gt; - 协议处理&lt;/h4&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职责&lt;/th&gt;
          &lt;th&gt;处理消息&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;主协议处理器&lt;/td&gt;
          &lt;td&gt;ID, ACK, ERROR&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol_auth.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;认证&lt;/td&gt;
          &lt;td&gt;METAKEY, CHALLENGE, CHAL_REPLY&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol_edge.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;边通告&lt;/td&gt;
          &lt;td&gt;ADD_EDGE, DEL_EDGE&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol_key.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;密钥交换&lt;/td&gt;
          &lt;td&gt;KEY_CHANGED, REQ_KEY, ANS_KEY&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol_subnet.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;子网通告&lt;/td&gt;
          &lt;td&gt;ADD_SUBNET, DEL_SUBNET&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;protocol_misc.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;其他&lt;/td&gt;
          &lt;td&gt;PING, PONG, STATUS&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;net_packet.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;包转发&lt;/td&gt;
          &lt;td&gt;PACKET&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;协议版本&lt;/strong&gt;: PROT_MAJOR=17, PROT_MINOR=7&lt;/p&gt;
&lt;h4 id=&#34;sptpsc---安全协议握手&#34;&gt;&lt;code&gt;sptps.c&lt;/code&gt; - 安全协议握手&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;职责&lt;/strong&gt;: 实现 Simple SPTPS 的点对点加密协议&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;功能&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;密钥交换 (ECDH)&lt;/li&gt;
&lt;li&gt;会话建立&lt;/li&gt;
&lt;li&gt;记录加密/解密&lt;/li&gt;
&lt;li&gt;前向保密&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;状态机&lt;/strong&gt;: &lt;code&gt;SPTPS_KEX&lt;/code&gt; → &lt;code&gt;SPTPS_KEX1&lt;/code&gt; → &lt;code&gt;SPTPS_KEX2&lt;/code&gt; → &lt;code&gt;SPTPS_OPEN&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;密钥派生&lt;/strong&gt;: 使用 SHA256/SHA512&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;connectionc---连接管理&#34;&gt;&lt;code&gt;connection.c&lt;/code&gt; - 连接管理&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;职责&lt;/strong&gt;: 管理与其他节点的 TCP 连接&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;功能&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;建立/关闭连接&lt;/li&gt;
&lt;li&gt;连接状态跟踪&lt;/li&gt;
&lt;li&gt;连接队列管理&lt;/li&gt;
&lt;li&gt;元包缓冲 (meta packets)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;io_t&lt;/span&gt; io;                    &lt;span style=&#34;color:#75715e&#34;&gt;// I/O event
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;node_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;node;        &lt;span style=&#34;color:#75715e&#34;&gt;// associated node
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;buffer_t&lt;/span&gt; inbuf, outbuf;     &lt;span style=&#34;color:#75715e&#34;&gt;// input/output buffers
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;sptps_t&lt;/span&gt; sptps;              &lt;span style=&#34;color:#75715e&#34;&gt;// SPTPS state
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;connection_status_t&lt;/span&gt; status; &lt;span style=&#34;color:#75715e&#34;&gt;// connection status
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;connection_t&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h3 id=&#34;34-网络与路由层-network--routing&#34;&gt;3.4 网络与路由层 (Network &amp;amp; Routing)&lt;/h3&gt;
&lt;h4 id=&#34;netc---网络-io&#34;&gt;&lt;code&gt;net*.c&lt;/code&gt; - 网络 I/O&lt;/h4&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;文件&lt;/th&gt;
          &lt;th&gt;职责&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;net.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;主网络处理循环&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;net_socket.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;套接字操作 (UDP)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;net_packet.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;包处理 (接收/转发)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;net_setup.c&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;网络初始化&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;功能&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;UDP 包接收/发送 (fast path)&lt;/li&gt;
&lt;li&gt;TCP 连接处理 (slow path)&lt;/li&gt;
&lt;li&gt;包加密/解密&lt;/li&gt;
&lt;li&gt;包转发&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;routec---路由管理&#34;&gt;&lt;code&gt;route.c&lt;/code&gt; - 路由管理&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;职责&lt;/strong&gt;: 处理数据包路由决策&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工作模式&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;RMODE_ROUTER&lt;/code&gt; - 基于子网的路由 (默认)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RMODE_SWITCH&lt;/code&gt; - 以太网交换&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RMODE_HUB&lt;/code&gt; - 集线器 (广播)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;graphc---拓扑算法&#34;&gt;&lt;code&gt;graph.c&lt;/code&gt; - 拓扑算法&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;职责&lt;/strong&gt;: 计算网络拓扑&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;算法&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;Dijkstra 最短路径&lt;/li&gt;
&lt;li&gt;Spanning Tree 构建&lt;/li&gt;
&lt;li&gt;连通性检查&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;应用&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;确定最优转发路径&lt;/li&gt;
&lt;li&gt;检测网络分割&lt;/li&gt;
&lt;li&gt;计算中继节点&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;proxyc---代理支持&#34;&gt;&lt;code&gt;proxy.c&lt;/code&gt; - 代理支持&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;职责&lt;/strong&gt;: 代理协议支持 (SOCKS4/SOCKS5)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;功能&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;通过代理建立连接&lt;/li&gt;
&lt;li&gt;SOCKS 握手处理&lt;/li&gt;
&lt;li&gt;认证支持&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&#34;35-数据结构层-data-structures&#34;&gt;3.5 数据结构层 (Data Structures)&lt;/h3&gt;
&lt;h4 id=&#34;核心数据结构&#34;&gt;核心数据结构&lt;/h4&gt;
&lt;h5 id=&#34;node_t-节点&#34;&gt;&lt;code&gt;node_t&lt;/code&gt; (节点)&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;node_t
|-- name: 节点名称
|-- id: 节点 ID (ED25519 pub key)
|-- status: 节点状态 flags
|-- address: 节点地址
|-- socket_address: UDP addr
|-- distance: Dijkstra distance
|-- via: routing next hop
|-- nexthop: direct next hop
|-- subnets: owned subnets tree
|-- keys: encrypt keys
+-- connections: TCP conn list
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id=&#34;edge_t-边链路&#34;&gt;&lt;code&gt;edge_t&lt;/code&gt; (边/链路)&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;edge_t
|-- from: source node
|-- to: target node
|-- address: target address
|-- options: edge opts (flags)
|-- weight: path weight
|-- connection: TCP conn
+-- reverse: reverse edge
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id=&#34;subnet_t-子网&#34;&gt;&lt;code&gt;subnet_t&lt;/code&gt; (子网)&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;subnet_t
|-- owner: owner node
|-- type: subnet type
|-- weight: priority weight
|-- expires: expire time
+-- net: subnet data
    |-- mac.address
    |-- ipv4.address/prefix
    +-- ipv6.address/prefix
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id=&#34;connection_t-连接&#34;&gt;&lt;code&gt;connection_t&lt;/code&gt; (连接)&lt;/h5&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;connection_t
|-- io: I/O event handle
|-- node: associated node
|-- address: remote address
|-- inbuf, outbuf: buffers
|-- sptps: SPTPS state
|-- status: connection state
|-- options: connection opts
|-- protocol_version: proto ver
+-- mst: in minimum tree?
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;容器结构&#34;&gt;容器结构&lt;/h4&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;容器&lt;/th&gt;
          &lt;th&gt;用途&lt;/th&gt;
          &lt;th&gt;组织方式&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;splay_tree_t&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;有序集合 (nodes, subnets, edges)&lt;/td&gt;
          &lt;td&gt;平衡树&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;list_t&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;无序列表 (connections, events)&lt;/td&gt;
          &lt;td&gt;双链表&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;hash.h&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;快速查找 (name→node mapping)&lt;/td&gt;
          &lt;td&gt;哈希表&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3 id=&#34;36-密码学与安全层-cryptography&#34;&gt;3.6 密码学与安全层 (Cryptography)&lt;/h3&gt;
&lt;h4 id=&#34;对称加密&#34;&gt;对称加密&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;cipher.c&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AES, Blowfish, Camellia 等&lt;/li&gt;
&lt;li&gt;ECB, CBC, CFB, OFB, CTR 模式&lt;/li&gt;
&lt;li&gt;后端: OpenSSL 或 libgcrypt&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;chacha-poly1305/&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ChaCha20-Poly1305 AEAD 加密&lt;/li&gt;
&lt;li&gt;独立实现&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;哈希与消息摘要&#34;&gt;哈希与消息摘要&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;digest.c&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SHA1, SHA256, SHA512&lt;/li&gt;
&lt;li&gt;MD5 (遗留)&lt;/li&gt;
&lt;li&gt;后端: OpenSSL 或 libgcrypt&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;ed25519/sha512.h&lt;/code&gt;&lt;/strong&gt;: ED25519 自带 SHA512&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;非对称加密与签名&#34;&gt;非对称加密与签名&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ecdsa.c&lt;/code&gt;&lt;/strong&gt;: ECDSA 签名 (通过 libgcrypt 或 OpenSSL)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ecdh.c&lt;/code&gt;&lt;/strong&gt;: ECDH 密钥交换 (SPTPS 握手用)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;rsa.c&lt;/code&gt;&lt;/strong&gt; (遗留): RSA 签名 (传统握手)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ed25519/&lt;/code&gt;&lt;/strong&gt;: EdDSA 实现&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;后端支持&#34;&gt;后端支持&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Cipher/Digest layers
    |
    +-- openssl/ (libssl/libcrypto)
    +-- gcrypt/  (libgcrypto)
    +-- ed25519/ (built-in)
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;密钥管理&#34;&gt;密钥管理&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;keys.c&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;生成和加载密钥&lt;/li&gt;
&lt;li&gt;密钥文件 I/O&lt;/li&gt;
&lt;li&gt;密钥验证&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;prf.h&lt;/code&gt;&lt;/strong&gt;: 伪随机函数&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&#34;37-设备与系统层-device--system&#34;&gt;3.7 设备与系统层 (Device &amp;amp; System)&lt;/h3&gt;
&lt;h4 id=&#34;虚拟网络设备&#34;&gt;虚拟网络设备&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;device.h&lt;/code&gt;&lt;/strong&gt;: 设备操作接口 (抽象)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;devops_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;setup_t&lt;/span&gt; setup;        &lt;span style=&#34;color:#75715e&#34;&gt;// initialize
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;cleanup_t&lt;/span&gt; cleanup;    &lt;span style=&#34;color:#75715e&#34;&gt;// clean up
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;read_t&lt;/span&gt; read;          &lt;span style=&#34;color:#75715e&#34;&gt;// read packet
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;write_t&lt;/span&gt; write;        &lt;span style=&#34;color:#75715e&#34;&gt;// write packet
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;devops_t&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;设备实现&lt;/strong&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;平台&lt;/th&gt;
          &lt;th&gt;实现&lt;/th&gt;
          &lt;th&gt;文件&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Linux&lt;/td&gt;
          &lt;td&gt;TUN/TAP&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;linux/device.c&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;BSD&lt;/td&gt;
          &lt;td&gt;tun/tap&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;bsd/device.c&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;macOS&lt;/td&gt;
          &lt;td&gt;tunemu&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;bsd/darwin/tunemu.c&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Solaris&lt;/td&gt;
          &lt;td&gt;TUN&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;solaris/device.c&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Windows&lt;/td&gt;
          &lt;td&gt;TAP&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;windows/device.c&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;其他设备&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dummy_device.c&lt;/code&gt; - 测试用 (黑洞)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fd_device.c&lt;/code&gt; - 文件描述符&lt;/li&gt;
&lt;li&gt;&lt;code&gt;raw_socket_device.c&lt;/code&gt; - 原始套接字&lt;/li&gt;
&lt;li&gt;&lt;code&gt;multicast_device.c&lt;/code&gt; - 组播&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vde_device.c&lt;/code&gt; - VDE 交换机&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;事件驱动&#34;&gt;事件驱动&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;event.c&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;事件循环 (select/epoll/kqueue)&lt;/li&gt;
&lt;li&gt;I/O 复用&lt;/li&gt;
&lt;li&gt;超时和信号处理&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;event_select.c&lt;/code&gt;&lt;/strong&gt;: select() 后端&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;配置管理&#34;&gt;配置管理&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;conf.c&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;配置文件解析&lt;/li&gt;
&lt;li&gt;配置树管理&lt;/li&gt;
&lt;li&gt;配置查询&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;conf_net.c&lt;/code&gt;&lt;/strong&gt;: 网络配置字段&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;平台特定代码&#34;&gt;平台特定代码&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;bsd/       - BSD 特定 (sandbox, tun)
linux/     - Linux 特定 (设备)
solaris/   - Solaris 特定
windows/   - Windows 特定
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h3 id=&#34;38-实用工具层-utilities&#34;&gt;3.8 实用工具层 (Utilities)&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;模块&lt;/th&gt;
          &lt;th&gt;职责&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;&lt;code&gt;logger.c&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;日志记录 (DEBUG/INFO/WARNING)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;&lt;code&gt;utils.c&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;通用工具函数&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;&lt;code&gt;random.c&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;伪随机数生成&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;&lt;code&gt;buffer.c&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;动态缓冲区&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;&lt;code&gt;fs.c&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;文件系统操作&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;&lt;code&gt;dropin.c&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;缺失函数替代&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;&lt;code&gt;address_cache.c&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;节点地址缓存&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;&lt;code&gt;autoconnect.c&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;自动连接管理&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;&lt;code&gt;names.c&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;名字↔ID 映射&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;&lt;code&gt;netutl.c&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;网络工具&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;&lt;code&gt;ifconfig.c&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;网络接口配置&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;&lt;code&gt;pidfile.c&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;PID 文件管理&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;&lt;code&gt;sandbox.c&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;沙箱/安全限制&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;4-模块依赖关系&#34;&gt;4. 模块依赖关系&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tincd/tincctl (Application)
    |
    v
control + event + logger (Control/Events)
    |
    v
protocol* + sptps + connection (Protocol)
    |
    v
node + edge + subnet + graph + route (Data/Topology)
    |
    v
net* + device + proxy (Network I/O)
    |
    v
cipher + digest + ecdsa + ecdh (Crypto)
    |
    v
buffer + list + splay_tree + hash (Containers)
    |
    v
utils + logger + random + conf (Utilities)
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;5-关键工作流&#34;&gt;5. 关键工作流&lt;/h2&gt;
&lt;h3 id=&#34;51-连接建立流程&#34;&gt;5.1 连接建立流程&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1. node.c: create node
    |
    v
2. connection.c: init TCP conn
    |
    v
3. protocol_auth.c: send ID
    |
    v
4. sptps.c: ECDH key exchange
    |
    v
5. protocol_key.c: exchange session key
    |
    v
6. net_packet.c: start forward UDP
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;52-数据包转发流程&#34;&gt;5.2 数据包转发流程&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1. net_socket.c: receive UDP packet
    |
    v
2. net_packet.c: decrypt packet
    |
    v
3. route.c: routing decision
    |
    v
4. graph.c: compute forward path
    |
    v
5. connection.c / net_socket.c: forward or local
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;53-拓扑更新流程&#34;&gt;5.3 拓扑更新流程&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1. protocol_edge.c: recv ADD_EDGE/DEL_EDGE
    |
    v
2. edge.c: update edge database
    |
    v
3. graph.c: recompute shortest path (Dijkstra)
    |
    v
4. route.c: update forward table
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;6-编译配置选项&#34;&gt;6. 编译配置选项&lt;/h2&gt;
&lt;p&gt;项目支持多个可选功能，通过编译标志控制：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;加密后端&lt;/strong&gt;: &lt;code&gt;HAVE_OPENSSL&lt;/code&gt; / &lt;code&gt;HAVE_LIBGCRYPTO&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;压缩&lt;/strong&gt;: &lt;code&gt;HAVE_LZO&lt;/code&gt; / &lt;code&gt;HAVE_LZ4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;高级特性&lt;/strong&gt;: &lt;code&gt;HAVE_LIBUPNP&lt;/code&gt;, &lt;code&gt;HAVE_LIBMINIUPNPC&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;平台特定&lt;/strong&gt;: &lt;code&gt;HAVE_LINUX&lt;/code&gt;, &lt;code&gt;HAVE_BSD&lt;/code&gt;, &lt;code&gt;HAVE_WINDOWS&lt;/code&gt; 等&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;7-统计信息&#34;&gt;7. 统计信息&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;核心代码文件:  60+ files
总代码行数:    15,000+ lines
支持平台:      Linux, BSD, macOS, Solaris, Windows
关键数据结构:  5+ (node, edge, subnet, connection, device)
密码算法:      10+
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;8-架构设计优势&#34;&gt;8. 架构设计优势&lt;/h2&gt;
&lt;h3 id=&#34;模块独立&#34;&gt;模块独立&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;每个模块职责清晰&lt;/li&gt;
&lt;li&gt;最小化模块间耦合&lt;/li&gt;
&lt;li&gt;便于测试和维护&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;易于移植&#34;&gt;易于移植&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;设备层、密码层可替换&lt;/li&gt;
&lt;li&gt;平台特定代码隔离&lt;/li&gt;
&lt;li&gt;支持 5+ 个操作系统&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;可扩展&#34;&gt;可扩展&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;易于添加新协议&lt;/li&gt;
&lt;li&gt;易于添加新加密算法&lt;/li&gt;
&lt;li&gt;支持可选特性编译&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;性能优化&#34;&gt;性能优化&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;关键路径 (UDP fast path) 独立优化&lt;/li&gt;
&lt;li&gt;Dijkstra 缓存避免重复计算&lt;/li&gt;
&lt;li&gt;地址缓存防止 DNS 查询风暴&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;9-从-tinc-架构到代码实现&#34;&gt;9. 从 TINC 架构到代码实现&lt;/h2&gt;
&lt;h3 id=&#34;快速导航指南&#34;&gt;快速导航指南&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;入门代码&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主程序: &lt;a href=&#34;https://github.com/gsauthof/tinc/blob/master/src/tincd.c&#34;&gt;tincd.c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;节点定义: &lt;a href=&#34;https://github.com/gsauthof/tinc/blob/master/src/node.h&#34;&gt;node.h&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;连接管理: &lt;a href=&#34;https://github.com/gsauthof/tinc/blob/master/src/connection.h&#34;&gt;connection.h&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;协议处理&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;协议分发: &lt;a href=&#34;https://github.com/gsauthof/tinc/blob/master/src/protocol.c&#34;&gt;protocol.c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;握手流程: &lt;a href=&#34;https://github.com/gsauthof/tinc/blob/master/src/protocol_auth.c&#34;&gt;protocol_auth.c&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;数据转发&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;包接收: &lt;a href=&#34;https://github.com/gsauthof/tinc/blob/master/src/net_packet.c&#34;&gt;net_packet.c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;路由决策: &lt;a href=&#34;https://github.com/gsauthof/tinc/blob/master/src/route.c&#34;&gt;route.c&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;拓扑算法&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;最短路径: &lt;a href=&#34;https://github.com/gsauthof/tinc/blob/master/src/graph.c&#34;&gt;graph.c&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;
&lt;p&gt;TINC 的分层架构展现了大型系统软件的设计哲学：&lt;/p&gt;
&lt;h3 id=&#34;核心原则&#34;&gt;核心原则&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;分层设计&lt;/strong&gt; - 将系统分为 8 个清晰的层次，每层通过定义良好的接口与其他层通信。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;模块化&lt;/strong&gt; - 每个模块职责单一，相对独立，易于理解和测试。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;可移植性&lt;/strong&gt; - 通过设备层、密码层等的抽象，支持多平台和多后端。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;高效性&lt;/strong&gt; - UDP 直接转发为 fast path，TCP 握手和控制走 slow path，最大化性能。&lt;/p&gt;
&lt;h3 id=&#34;代码启示&#34;&gt;代码启示&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;顶层应用&lt;/strong&gt; - 通过控制层与底层通信&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;中层协议&lt;/strong&gt; - 实现握手、认证、拓扑交换&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;下层系统&lt;/strong&gt; - 提供跨平台的统一接口&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工具层&lt;/strong&gt; - 提供通用服务（日志、缓冲、随机数等）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这种精心设计的架构使 TINC 成为一个既可靠又高效的 VPN 解决方案，也是学习大型系统软件架构的极好范例。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&#34;系列预告&#34;&gt;系列预告&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;第一篇：&lt;a href=&#34;../20260108-tinc-protocol-analysis&#34;&gt;TINC 协议深度解析&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;第二篇：TINC 模块架构与代码组织&lt;/li&gt;
&lt;li&gt;第三篇：&lt;a href=&#34;../20260108-tinc-udp-holepunching&#34;&gt;UDP 打洞机制&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;第四篇：&lt;a href=&#34;../20260108-tinc-modules-reference&#34;&gt;TINC 项目 - 模块依赖与数据流图&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>TINC 源码解读 第一篇 - 协议深度解析</title>
      <link>/posts/20260108-tinc-protocol-analysis/</link>
      <pubDate>Thu, 08 Jan 2026 08:00:00 +0800</pubDate>
      
      <guid>/posts/20260108-tinc-protocol-analysis/</guid>
      <description>&lt;p&gt;本文是 TINC 源码解读系列的第一篇，重点分析 TINC 的协议设计。TINC 采用分层架构，使用 Meta Protocol 处理控制平面，Packet Protocol 处理数据平面，SPTPS 提供额外的加密保证。&lt;/p&gt;</description>
      <content>&lt;p&gt;本文是 TINC 源码解读系列的第一篇，重点分析 TINC 的协议设计。TINC 采用分层架构，使用 Meta Protocol 处理控制平面，Packet Protocol 处理数据平面，SPTPS 提供额外的加密保证。&lt;/p&gt;
&lt;h2 id=&#34;1-协议概览&#34;&gt;1. 协议概览&lt;/h2&gt;
&lt;p&gt;TINC 使用两个独立的协议层：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Meta Protocol&lt;/strong&gt; - TCP 连接上的文本协议（连接建立、拓扑交换）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Packet Protocol&lt;/strong&gt; - UDP 连接上的二进制协议（数据包转发）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;协议版本&#34;&gt;协议版本&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PROT_MAJOR &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;17&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// 主版本号（不兼容时变化）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PROT_MINOR &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt;   &lt;span style=&#34;color:#75715e&#34;&gt;// 次版本号（向后兼容）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;2-meta-协议---控制平面&#34;&gt;2. Meta 协议 - 控制平面&lt;/h2&gt;
&lt;h3 id=&#34;消息类型枚举&#34;&gt;消息类型枚举&lt;/h3&gt;
&lt;p&gt;Meta Protocol 定义了 20 多种消息类型，按功能分类：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 认证阶段
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ID              &lt;span style=&#34;color:#75715e&#34;&gt;// 连接标识
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;METAKEY         &lt;span style=&#34;color:#75715e&#34;&gt;// 元数据密钥交换
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CHALLENGE       &lt;span style=&#34;color:#75715e&#34;&gt;// 密码挑战
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CHAL_REPLY      &lt;span style=&#34;color:#75715e&#34;&gt;// 挑战回复
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ACK             &lt;span style=&#34;color:#75715e&#34;&gt;// 确认
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 连接管理
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;STATUS          &lt;span style=&#34;color:#75715e&#34;&gt;// 状态信息
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ERROR           &lt;span style=&#34;color:#75715e&#34;&gt;// 错误消息
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;TERMREQ         &lt;span style=&#34;color:#75715e&#34;&gt;// 终止请求
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 保活
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PING            &lt;span style=&#34;color:#75715e&#34;&gt;// 心跳 Ping
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PONG            &lt;span style=&#34;color:#75715e&#34;&gt;// 心跳 Pong
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 拓扑交换
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ADD_SUBNET      &lt;span style=&#34;color:#75715e&#34;&gt;// 添加子网
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DEL_SUBNET      &lt;span style=&#34;color:#75715e&#34;&gt;// 删除子网
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ADD_EDGE        &lt;span style=&#34;color:#75715e&#34;&gt;// 添加边/链路
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DEL_EDGE        &lt;span style=&#34;color:#75715e&#34;&gt;// 删除边/链路
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 密钥交换
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;KEY_CHANGED     &lt;span style=&#34;color:#75715e&#34;&gt;// 密钥已更改
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;REQ_KEY         &lt;span style=&#34;color:#75715e&#34;&gt;// 请求加密密钥
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ANS_KEY         &lt;span style=&#34;color:#75715e&#34;&gt;// 应答加密密钥
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 数据转发
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PACKET          &lt;span style=&#34;color:#75715e&#34;&gt;// TCP 转发数据包
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Tinc 1.1+ 扩展
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;REQ_PUBKEY      &lt;span style=&#34;color:#75715e&#34;&gt;// 请求公钥
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ANS_PUBKEY      &lt;span style=&#34;color:#75715e&#34;&gt;// 应答公钥
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SPTPS_PACKET    &lt;span style=&#34;color:#75715e&#34;&gt;// SPTPS 加密包
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;UDP_INFO        &lt;span style=&#34;color:#75715e&#34;&gt;// UDP 地址信息
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MTU_INFO        &lt;span style=&#34;color:#75715e&#34;&gt;// MTU 信息
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;核心消息格式&#34;&gt;核心消息格式&lt;/h3&gt;
&lt;h4 id=&#34;id-消息---连接起点&#34;&gt;ID 消息 - 连接起点&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;格式: ID name version

示例: 0 mynode 17.7

含义:
├─ 0        - 消息类型标识
├─ mynode   - 节点名称
└─ 17.7     - 协议版本 (MAJOR.MINOR)
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;metakey-消息---加密参数协商&#34;&gt;METAKEY 消息 - 加密参数协商&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;格式: METAKEY cipher digest keylength [加密的密钥]

示例: 1 aes-256-cbc sha512 32 [128字节加密数据]

含义:
├─ 1              - 消息类型
├─ aes-256-cbc    - 对称加密算法
├─ sha512         - HMAC 摘要算法
└─ 32             - 密钥长度（字节）

特点:
└─ 加密密钥使用对方的公钥进行 RSA 加密
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;challenge-消息---身份验证&#34;&gt;CHALLENGE 消息 - 身份验证&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;格式: CHALLENGE &amp;lt;hash&amp;gt;

验证过程:
1. 接收方生成随机 challenge (16 字节)
2. 计算 hash = HMAC-SHA256(challenge, shared_key)
3. 发送 CHALLENGE hash
4. 发起方计算相同的 hash
5. 验证 hash 相等
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;add_edge-消息---拓扑通告&#34;&gt;ADD_EDGE 消息 - 拓扑通告&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;格式: ADD_EDGE node_from node_to address port weight options

示例: ADD_EDGE nodeA nodeB 192.168.1.100 655 100 0

解析:
├─ ADD_EDGE        - 消息类型
├─ nodeA           - 源节点
├─ nodeB           - 目标节点
├─ 192.168.1.100   - 目标地址（实际网络地址）
├─ 655             - UDP 端口
├─ 100             - 权重（用于 Dijkstra）
└─ 0               - 选项标志

选项标志:
├─ 0x0001: OPTION_INDIRECT   (间接连接)
├─ 0x0002: OPTION_TCPONLY    (仅 TCP)
├─ 0x0004: OPTION_PMTU_DISCOVERY
└─ 0x0008: OPTION_CLAMP_MSS
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;add_subnet-消息---子网通告&#34;&gt;ADD_SUBNET 消息 - 子网通告&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;格式: ADD_SUBNET owner_node network/prefixlength

IPv4 示例: ADD_SUBNET node1 192.168.1.0/24
IPv6 示例: ADD_SUBNET node1 2001:db8::/32
MAC  示例: ADD_SUBNET node1 ff:ff:ff:ff:ff:ff

用途:
└─ 通告该节点负责路由的子网地址
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;req_key-和-ans_key---数据加密密钥交换&#34;&gt;REQ_KEY 和 ANS_KEY - 数据加密密钥交换&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;REQ_KEY 格式: REQ_KEY originator destination
含义: originator 请求与 destination 的通信密钥

ANS_KEY 格式: ANS_KEY from to cipher_id digest_id key mac_length
示例: ANS_KEY nodeB nodeA 1 3 4ae0b0a82d6e0078 16

解析:
├─ nodeB         - 密钥所有者
├─ nodeA         - 请求方
├─ 1             - 对称加密算法 ID
├─ 3             - HMAC 摘要算法 ID
├─ 4ae0...78     - 128 位加密密钥
└─ 16            - MAC 长度
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;ping-和-pong---保活消息&#34;&gt;PING 和 PONG - 保活消息&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;PING 格式: PING [随机数]
PONG 格式: PONG [随机数]

用途:
├─ 检测连接是否仍然活跃
├─ 防止连接因不活动而被关闭
├─ 检测单向连接失败
└─ 通过随机数防止已知明文攻击
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;3-meta-协议握手流程&#34;&gt;3. Meta 协议握手流程&lt;/h2&gt;
&lt;h3 id=&#34;完整的连接建立过程&#34;&gt;完整的连接建立过程&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;发起方                      响应方
─────────────────────────────────────

TCP 连接 ─────────────→

                  ← 接受连接

发送 ID ──────────→
                  
                  ✓ 验证版本

                  ← 发送 ID

✓ 验证版本

发送 METAKEY ─────→
(加密的元密钥)

                  ✓ 解密元密钥

                  ← 发送 METAKEY

✓ 解密元密钥

从此以后，所有通信使用
协商的加密密钥加密

发送 CHALLENGE ────→
(hash = HMAC(...))

                  ✓ 验证 hash

                  ← CHAL_REPLY

✓ 双向认证成功

发送 ACK ─────────→

                  ← ACK

✓ 连接完全建立
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;握手状态机&#34;&gt;握手状态机&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[TCP Connected]
    ↓
[ID Exchanged]
├─ 校验版本号
├─ 确定协议版本
└─ 准备加密
    ↓
[METAKEY Exchanged]
├─ 选择加密算法
├─ 交换元数据密钥
└─ 开始加密通信
    ↓
[CHALLENGE Issued]
├─ 单向认证
├─ 验证对方公钥
└─ 生成共享密钥
    ↓
[CHAL_REPLY Received]
├─ 双向认证完成
├─ 确认对方身份
└─ 建立信任
    ↓
[ACK Sent/Received]
├─ 连接活跃
├─ 准备数据交换
└─ 拓扑同步
    ↓
[ACTIVE]
├─ 双向 PING/PONG
├─ 转发 ADD_EDGE
├─ 转发 ADD_SUBNET
├─ 转发 REQ_KEY/ANS_KEY
└─ 转发数据包
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;4-packet-protocol---数据平面&#34;&gt;4. Packet Protocol - 数据平面&lt;/h2&gt;
&lt;h3 id=&#34;udp-数据包格式&#34;&gt;UDP 数据包格式&lt;/h3&gt;
&lt;h4 id=&#34;加密前的包结构&#34;&gt;加密前的包结构&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Byte:  0-3         4-...           ...      ...+16
      +----------+---------------+--------+--------+
      | seqno    | payload       | padding| MAC    |
      | (32 bit) | (VPN data)    |        |(256bit)|
      +----------+---------------+--------+--------+
      +-----------------------------------+--------+
              Covered by HMAC
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;加密后的完整-udp-包&#34;&gt;加密后的完整 UDP 包&lt;/h4&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;+-------------------------------------------------+
| UDP Header (20 bytes)                           |
| +--- Source IP                                  |
| +--- Dest IP                                    |
| +--- Source Port (1194 or configured)           |
| +--- Dest Port                                  |
+-------------------------------------------------+
| Encrypted Payload (variable length)             |
| +--- Nonce/IV (optional)                        |
| +--- Ciphertext:                                |
| |    +--- seqno (sequence number)               |
| |    +--- VPN data (virtual network packet)     |
| |    +--- HMAC (message authentication code)    |
| +--- Authentication Tag (AEAD encryption)       |
+-------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;vpn-数据包结构&#34;&gt;VPN 数据包结构&lt;/h3&gt;
&lt;p&gt;虚拟网络上传输的是标准 Ethernet Frame：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;+----------+----------+----------+---------+-----+
| Dest MAC | Src MAC  | EtherType| Payload | CRC |
| (6 Byte) | (6 Byte) | (2 Byte) |(var len)| (4) |
+----------+----------+----------+---------+-----+

EtherType:
+-- 0x0800: IPv4
+-- 0x86DD: IPv6
+-- 0x0806: ARP
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;支持的加密算法&#34;&gt;支持的加密算法&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;对称加密:
├─ ChaCha20-Poly1305  (推荐，AEAD)
├─ AES-256-GCM        (AEAD)
├─ AES-256-CBC        (需要 HMAC)
└─ null cipher        (调试用，无加密)

消息摘要:
├─ SHA512             (推荐)
├─ SHA256
├─ SHA1
└─ MD5 (遗留，不安全)

密钥长度:
├─ 256 bit (标准)
└─ 128 bit (弱密钥，不推荐)
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;5-sptps-协议---安全的点对点通信&#34;&gt;5. SPTPS 协议 - 安全的点对点通信&lt;/h2&gt;
&lt;h3 id=&#34;sptps-设计目的&#34;&gt;SPTPS 设计目的&lt;/h3&gt;
&lt;p&gt;SPTPS（Simple Peer-to-Peer Security）是一个轻量级的加密层，用于在 UDP 上建立直接的加密通道，不需要依赖 Meta Protocol 的握手。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;与 Meta Protocol 的区别&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Meta Protocol: 文本协议，TCP，用于控制平面&lt;/li&gt;
&lt;li&gt;SPTPS: 二进制协议，UDP，用于数据平面持久化会话&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;sptps-记录类型&#34;&gt;SPTPS 记录类型&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define SPTPS_HANDSHAKE 128   &lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 密钥交换和认证
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define SPTPS_ALERT 129       &lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 警告或错误消息
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define SPTPS_CLOSE 130       &lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 应用程序关闭连接
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;sptps-握手状态&#34;&gt;SPTPS 握手状态&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;sptps_state_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    SPTPS_KEX &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;,           &lt;span style=&#34;color:#75715e&#34;&gt;// 等待第一个密钥交换记录
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    SPTPS_SECONDARY_KEX &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#75715e&#34;&gt;// 准备接收二次密钥交换
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    SPTPS_SIG &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;,           &lt;span style=&#34;color:#75715e&#34;&gt;// 等待签名记录
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    SPTPS_ACK &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;,           &lt;span style=&#34;color:#75715e&#34;&gt;// 等待确认记录
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;sptps_state_t&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;sptps-密钥交换结构&#34;&gt;SPTPS 密钥交换结构&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;sptps_kex_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; version;           &lt;span style=&#34;color:#75715e&#34;&gt;// 版本号
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; nonce[&lt;span style=&#34;color:#ae81ff&#34;&gt;32&lt;/span&gt;];         &lt;span style=&#34;color:#75715e&#34;&gt;// 随机数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; pubkey[&lt;span style=&#34;color:#ae81ff&#34;&gt;32&lt;/span&gt;];        &lt;span style=&#34;color:#75715e&#34;&gt;// 临时 ECDH 公钥 (Curve25519)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 总大小: 65 字节
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;sptps-握手流程&#34;&gt;SPTPS 握手流程&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Initiator                   Responder
─────────────────────────────────────

生成临时密钥对
(Curve25519 ECDH)

发送 HANDSHAKE ────────────→
  payload: kex1
  (version, nonce, pubkey)

                           收到 kex1
                           生成临时密钥对
                           计算共享密钥

                           ← 发送 HANDSHAKE
                             payload: kex2

收到 kex2
计算共享密钥

验证: ECDH(A_priv, B_pub)
    == ECDH(B_priv, A_pub) ✓

使用 PRF 派生会话密钥

发送签名记录 ───────────────→
  签署握手数据

                           验证签名

                           ← 发送 ACK 记录

验证 ACK
握手完成 ✓

双向 AEAD 加密通信开始
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;密钥派生&#34;&gt;密钥派生&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Shared_Secret = ECDH(my_private_key, peer_public_key)

Session_Keys = PRF-SHA512(
    Shared_Secret,
    label = &amp;#34;SPTPS key expansion&amp;#34; 
          + initiator_pubkey 
          + responder_pubkey
)

派生密钥 (共 64 字节):
├─ Key_A (32 字节): Initiator → Responder
├─ Key_B (32 字节): Responder → Initiator
└─ 每个方向使用不同密钥 (前向保密)
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;6-身份验证与安全机制&#34;&gt;6. 身份验证与安全机制&lt;/h2&gt;
&lt;h3 id=&#34;签名与验证&#34;&gt;签名与验证&lt;/h3&gt;
&lt;p&gt;每个节点都有持久的 ECDSA/EdDSA 密钥对：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;公钥位置: hosts 目录 ($TINC_HOME/hosts/nodename)
私钥位置: 配置目录 ($TINC_HOME/rsa_key.priv, ed25519_key.priv)

认证流程:
1. 交换 ID → 校验版本
2. 交换 METAKEY → 协商加密算法
3. 计算 challenge hash
4. 发送 CHALLENGE + CHAL_REPLY
5. 验证签名：数据已被对方的私钥签署
6. 发送 ACK

验证公钥:
├─ 从 hosts 目录读取对方的公钥
├─ 验证签名: Verify(signature, data, peer_pubkey)
├─ 若验证失败，拒绝连接
└─ 若验证成功，建立信任
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;重放保护&#34;&gt;重放保护&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Meta Protocol 重放保护&lt;/strong&gt;：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;├─ past_request_tree 跟踪已处理的请求
├─ 相同请求在一定时间内被忽略
└─ 防止攻击者重复发送拓扑更新
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;数据包重放保护&lt;/strong&gt;：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;├─ 序列号 (seqno): 递增计数器
├─ 验证 seqno &amp;gt; last_seqno
├─ 丢弃重复包
└─ 使用滑动窗口防止乱序问题
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;7-拓扑同步协议&#34;&gt;7. 拓扑同步协议&lt;/h2&gt;
&lt;h3 id=&#34;完整的拓扑交换过程&#34;&gt;完整的拓扑交换过程&lt;/h3&gt;
&lt;p&gt;当两个节点建立连接后，会进行完整的拓扑交换：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Node A ──────TCP──────→ Node B

1. 身份验证完成
   (ID, METAKEY, CHALLENGE, ACK)

2. Node A 发送其知道的拓扑:
   
   ADD_EDGE nodeA nodeC 10.0.0.3 655 50 0
   ADD_EDGE nodeA nodeD 10.0.0.4 655 100 0
   ADD_SUBNET nodeA 172.16.1.0/24
   ADD_SUBNET nodeC 172.16.2.0/24

3. Node B 发送其知道的拓扑:
   
   ADD_EDGE nodeB nodeE 10.0.0.5 655 50 0
   ADD_SUBNET nodeB 172.16.4.0/24
   ADD_SUBNET nodeE 172.16.5.0/24

4. 每当拓扑变化时：
   └─ 通过 ADD_EDGE/ADD_SUBNET 发布增量更新

5. 当边或节点失败时：
   └─ 广播 DEL_EDGE/DEL_SUBNET
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;拓扑维护机制&#34;&gt;拓扑维护机制&lt;/h3&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;变化检测:
├─ 新节点加入 → ADD_EDGE + ADD_SUBNET
├─ 节点离开 → DEL_EDGE + DEL_SUBNET
├─ 链路权重变化 → ADD_EDGE (新权重)
└─ 密钥更新 → KEY_CHANGED

广播机制:
├─ 每个连接都转发其收到的拓扑消息
├─ 防环：记录消息源，不回复给源
└─ 定期同步：每个连接建立时交换完整拓扑
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;8-协议扩展-tinc-11&#34;&gt;8. 协议扩展 (Tinc 1.1+)&lt;/h2&gt;
&lt;h3 id=&#34;新增消息类型&#34;&gt;新增消息类型&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;REQ_PUBKEY / ANS_PUBKEY&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;格式: REQ_PUBKEY from to [timestamp]
      ANS_PUBKEY from to [key_data]

用途:
├─ 请求/应答节点的公钥
├─ 用于拓展的密钥交换
└─ 支持在线密钥更新
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;UDP_INFO&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;格式: UDP_INFO originator address:port

用途:
├─ 通告节点可用的 UDP 地址
├─ 支持多地址（IPv4, IPv6）
└─ 加速 UDP 直连建立
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;MTU_INFO&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;格式: MTU_INFO node mtu

用途:
├─ 通告路径的最大传输单元
├─ 支持 PMTU 发现
└─ 优化包大小
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;SPTPS_PACKET&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;用途:
├─ 使用 SPTPS 加密的 TCP 包
├─ 在 meta 协议上层的加密
└─ 增强安全性
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;9-安全性分析&#34;&gt;9. 安全性分析&lt;/h2&gt;
&lt;h3 id=&#34;已实现的安全特性&#34;&gt;已实现的安全特性&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;特性&lt;/th&gt;
          &lt;th&gt;实现&lt;/th&gt;
          &lt;th&gt;说明&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;前向保密 (PFS)&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;✓&lt;/td&gt;
          &lt;td&gt;ECDH 临时密钥，会话独立&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;数据完整性&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;✓&lt;/td&gt;
          &lt;td&gt;HMAC/AEAD 认证&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;数据机密性&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;✓&lt;/td&gt;
          &lt;td&gt;对称加密 (AES/ChaCha20)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;重放保护&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;✓&lt;/td&gt;
          &lt;td&gt;序列号 + 滑动窗口&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;身份认证&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;✓&lt;/td&gt;
          &lt;td&gt;ECDSA/EdDSA 签名&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;密钥交换&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;✓&lt;/td&gt;
          &lt;td&gt;ECDH (P-256/Curve25519)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;已知明文保护&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;✓&lt;/td&gt;
          &lt;td&gt;Ping/Pong 随机值&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;潜在的风险和对策&#34;&gt;潜在的风险和对策&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;风险&lt;/th&gt;
          &lt;th&gt;严重度&lt;/th&gt;
          &lt;th&gt;现状&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;密钥重用&lt;/td&gt;
          &lt;td&gt;中&lt;/td&gt;
          &lt;td&gt;支持密钥轮换 (KEY_CHANGED)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;时钟偏差&lt;/td&gt;
          &lt;td&gt;低&lt;/td&gt;
          &lt;td&gt;支持时钟偏差检测&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;实现漏洞&lt;/td&gt;
          &lt;td&gt;高&lt;/td&gt;
          &lt;td&gt;定期安全审计&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;算法选择&lt;/td&gt;
          &lt;td&gt;低&lt;/td&gt;
          &lt;td&gt;支持现代算法 (ChaCha20)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;密钥缓存&lt;/td&gt;
          &lt;td&gt;中&lt;/td&gt;
          &lt;td&gt;支持定期过期&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;10-连接到完整通信的时间线&#34;&gt;10. 连接到完整通信的时间线&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;时间   事件
──────────────────────────────────────────────
0ms    TCP 连接建立
       ↓
10ms   交换 ID (版本协商)
       ↓
20ms   交换 METAKEY (加密参数)
       ↓
30ms   发送 CHALLENGE (单向认证)
       ↓
40ms   接收 CHAL_REPLY (双向认证)
       ↓
50ms   从此以后所有通信加密
       ↓
60ms   交换 ADD_EDGE (拓扑)
       ↓
100ms  交换 ADD_SUBNET (子网)
       ↓
150ms  定期 PING/PONG (保活)
       ↓
∞      数据转发 &amp;amp; 拓扑维护
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;11-协议调试&#34;&gt;11. 协议调试&lt;/h2&gt;
&lt;h3 id=&#34;启用协议日志&#34;&gt;启用协议日志&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 启用详细的协议调试输出&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tincd -n myvpn -d DEBUG
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 典型输出示例:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;DEBUG&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; Sending ID to node1: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;0 mynode 17.7&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;DEBUG&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; Sending METAKEY to node1: cipher&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; digest&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; maclength&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;16&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;DEBUG&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; Sending CHALLENGE to node1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;DEBUG&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; Sending ACK to node1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;DEBUG&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; Sending ADD_EDGE node1 node2 192.168.1.2 &lt;span style=&#34;color:#ae81ff&#34;&gt;655&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;DEBUG&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; Sending ADD_SUBNET node2 172.16.2.0/24
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;DEBUG&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; Sending PING to node1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;DEBUG&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; Received PONG from node1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;网络包捕获&#34;&gt;网络包捕获&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 捕获 Meta Protocol (TCP 655)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tcpdump -i eth0 -n tcp port &lt;span style=&#34;color:#ae81ff&#34;&gt;655&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 捕获 Packet Protocol (UDP 1194)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tcpdump -i eth0 -n udp port &lt;span style=&#34;color:#ae81ff&#34;&gt;1194&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 使用 Wireshark 分析&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wireshark -i eth0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;
&lt;p&gt;TINC 协议是一个分层的、设计精良的 VPN 协议体系：&lt;/p&gt;
&lt;h3 id=&#34;核心设计&#34;&gt;核心设计&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Meta Protocol&lt;/strong&gt; (控制平面)：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TCP 文本协议，用于控制和管理&lt;/li&gt;
&lt;li&gt;握手、认证、拓扑交换&lt;/li&gt;
&lt;li&gt;可靠但相对低频&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Packet Protocol&lt;/strong&gt; (数据平面)：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;UDP 二进制协议，用于数据转发&lt;/li&gt;
&lt;li&gt;高效、低延迟&lt;/li&gt;
&lt;li&gt;支持快速加密/解密&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;SPTPS&lt;/strong&gt; (加密层)：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;额外的 UDP 加密层&lt;/li&gt;
&lt;li&gt;前向保密和轻量级握手&lt;/li&gt;
&lt;li&gt;支持直接 P2P 加密通信&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;安全特性&#34;&gt;安全特性&lt;/h3&gt;
&lt;p&gt;✅ 现代密钥交换 (ECDH)&lt;br&gt;
✅ 强力数字签名 (ECDSA/EdDSA)&lt;br&gt;
✅ 前向保密 (PFS)&lt;br&gt;
✅ 重放保护&lt;br&gt;
✅ 完整性认证 (HMAC/AEAD)&lt;br&gt;
✅ 灵活的算法选择&lt;/p&gt;
&lt;h3 id=&#34;性能考虑&#34;&gt;性能考虑&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Meta Protocol 低频交互，控制开销小&lt;/li&gt;
&lt;li&gt;Packet Protocol 用 UDP，转发延迟低&lt;/li&gt;
&lt;li&gt;数据密钥缓存，避免频繁协商&lt;/li&gt;
&lt;li&gt;支持直接 P2P（避免中继）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这种精心设计的两层协议架构使 TINC 成为一个既可靠又高效的 VPN 解决方案，是现代 VPN 软件的最佳实践。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&#34;系列预告&#34;&gt;系列预告&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;第一篇：TINC 协议深度解析&lt;/li&gt;
&lt;li&gt;第二篇：&lt;a href=&#34;../20260108-tinc-module-architecture&#34;&gt;TINC 模块架构与代码组织&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;第三篇：&lt;a href=&#34;../20260108-tinc-udp-holepunching&#34;&gt;UDP 打洞机制&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;第四篇：&lt;a href=&#34;../20260108-tinc-modules-reference&#34;&gt;TINC 项目 - 模块依赖与数据流图&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>Write A 2048 Game with AI</title>
      <link>/posts/20260105/</link>
      <pubDate>Mon, 05 Jan 2026 14:51:13 +0800</pubDate>
      
      <guid>/posts/20260105/</guid>
      <description>&lt;h1 id=&#34;2048-game-development-prompt-professional-stable-edition&#34;&gt;2048 Game Development Prompt: Professional Stable Edition&lt;/h1&gt;
&lt;h2 id=&#34;objective&#34;&gt;Objective&lt;/h2&gt;
&lt;p&gt;Create a high-performance, mobile-optimized 2048 game in a single HTML file. The goal is &amp;ldquo;Industrial-Grade Smoothness&amp;rdquo;—zero flicker, state persistence, and polished mobile UX.&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;2048-game-development-prompt-professional-stable-edition&#34;&gt;2048 Game Development Prompt: Professional Stable Edition&lt;/h1&gt;
&lt;h2 id=&#34;objective&#34;&gt;Objective&lt;/h2&gt;
&lt;p&gt;Create a high-performance, mobile-optimized 2048 game in a single HTML file. The goal is &amp;ldquo;Industrial-Grade Smoothness&amp;rdquo;—zero flicker, state persistence, and polished mobile UX.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;1-visual--layout-architecture&#34;&gt;1. Visual &amp;amp; Layout Architecture&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Coordinate System&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;Tiles MUST use &lt;code&gt;position: absolute&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Movement MUST be handled via &lt;code&gt;transform: translate(x, y)&lt;/code&gt; using CSS &lt;code&gt;calc()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Formula&lt;/em&gt;: &lt;code&gt;transform: translate(calc(col * (100% + gap)), calc(row * (100% + gap)))&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero-Flicker Injection&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;When a new tile is created, its &lt;code&gt;transform&lt;/code&gt; coordinates must be calculated and set &lt;strong&gt;before&lt;/strong&gt; it is appended to the DOM to prevent &amp;ldquo;top-left corner flashing.&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mobile-First CSS&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;Body: &lt;code&gt;padding-top: 5vh&lt;/code&gt; to pull the game down from the notch/status bar.&lt;/li&gt;
&lt;li&gt;Container: &lt;code&gt;touch-action: none&lt;/code&gt; and &lt;code&gt;overflow: hidden&lt;/code&gt; to disable browser pull-to-refresh and scrolling.&lt;/li&gt;
&lt;li&gt;Layout: Center the game board horizontally.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;2-persistence--state-management&#34;&gt;2. Persistence &amp;amp; State Management&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Auto-Save&lt;/strong&gt;: After every move and new tile generation, serialize the 4x4 grid (tile values) and current score to &lt;code&gt;localStorage&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Session Recovery&lt;/strong&gt;: On page load, check for saved data. If found, rebuild the grid silently (disable the &amp;ldquo;appear&amp;rdquo; animation for recovered tiles) so the player can continue exactly where they left off.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Score Tracking&lt;/strong&gt;: Maintain &amp;ldquo;Current Score&amp;rdquo; and a persistent &amp;ldquo;Best Score.&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;3-core-logic--animation-sync&#34;&gt;3. Core Logic &amp;amp; Animation Sync&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Atomic Move Sequence&lt;/strong&gt;:
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Calculate&lt;/strong&gt;: Map out all tile destinations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Visual Slide&lt;/strong&gt;: Update &lt;code&gt;transform&lt;/code&gt; for all moving tiles (including those marked for deletion).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Delayed Cleanup&lt;/strong&gt;: Remove merged tiles from the DOM only after the &lt;code&gt;150ms&lt;/code&gt; transition ends.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Merge Pop&lt;/strong&gt;: Trigger a &lt;code&gt;1.15x&lt;/code&gt; scale pulse on the new tile AFTER the sliding tiles overlap.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Animation Lock&lt;/strong&gt;: Use a &lt;code&gt;lock&lt;/code&gt; flag to ignore inputs for &lt;code&gt;200ms&lt;/code&gt; during active animations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Win/Loss Detection&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Win&lt;/strong&gt;: Detect value &lt;code&gt;2048&lt;/code&gt; and show a &amp;ldquo;You Win&amp;rdquo; overlay.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Loss&lt;/strong&gt;: If the grid is full AND no adjacent tiles (horizontal/vertical) match, show a &amp;ldquo;Game Over&amp;rdquo; overlay.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;4-interaction--ux-polish&#34;&gt;4. Interaction &amp;amp; UX Polish&lt;/h2&gt;
&lt;hr&gt;
&lt;p&gt;Play the game below or goto &lt;a href=&#34;/2048.html&#34;&gt;this link&lt;/a&gt;:&lt;/p&gt;

&lt;iframe src=&#34;/2048.html&#34; style=&#34;width: 100%; height: 600px; border: none; border-radius: 6px;&#34;&gt;&lt;/iframe&gt;</content>
    </item>
    
  </channel>
</rss>
