diff --git a/network/ARP协议实现指导书.docx b/network/arpicmplab/ARP协议实现指导书.docx similarity index 100% rename from network/ARP协议实现指导书.docx rename to network/arpicmplab/ARP协议实现指导书.docx diff --git a/network/ICMP协议实现详解.docx b/network/arpicmplab/ICMP协议实现详解.docx similarity index 100% rename from network/ICMP协议实现详解.docx rename to network/arpicmplab/ICMP协议实现详解.docx diff --git a/network/arp/ARP响应.png b/network/arpicmplab/arp/ARP响应.png similarity index 100% rename from network/arp/ARP响应.png rename to network/arpicmplab/arp/ARP响应.png diff --git a/network/arp/cmake编译运行.png b/network/arpicmplab/arp/cmake编译运行.png similarity index 100% rename from network/arp/cmake编译运行.png rename to network/arpicmplab/arp/cmake编译运行.png diff --git a/network/arp/labtemplate.typ b/network/arpicmplab/arp/labtemplate.typ similarity index 100% rename from network/arp/labtemplate.typ rename to network/arpicmplab/arp/labtemplate.typ diff --git a/network/arp/main.pdf b/network/arpicmplab/arp/main.pdf similarity index 100% rename from network/arp/main.pdf rename to network/arpicmplab/arp/main.pdf diff --git a/network/arp/main.txt b/network/arpicmplab/arp/main.txt similarity index 100% rename from network/arp/main.txt rename to network/arpicmplab/arp/main.txt diff --git a/network/arp/main.typ b/network/arpicmplab/arp/main.typ similarity index 100% rename from network/arp/main.typ rename to network/arpicmplab/arp/main.typ diff --git a/network/arp/ping通.png b/network/arpicmplab/arp/ping通.png similarity index 100% rename from network/arp/ping通.png rename to network/arpicmplab/arp/ping通.png diff --git a/network/arp/ref.yml b/network/arpicmplab/arp/ref.yml similarity index 100% rename from network/arp/ref.yml rename to network/arpicmplab/arp/ref.yml diff --git a/network/arp/tmp.md b/network/arpicmplab/arp/tmp.md similarity index 100% rename from network/arp/tmp.md rename to network/arpicmplab/arp/tmp.md diff --git a/network/arp/一秒一个.png b/network/arpicmplab/arp/一秒一个.png similarity index 100% rename from network/arp/一秒一个.png rename to network/arpicmplab/arp/一秒一个.png diff --git a/network/arp/分析结构2.png b/network/arpicmplab/arp/分析结构2.png similarity index 100% rename from network/arp/分析结构2.png rename to network/arpicmplab/arp/分析结构2.png diff --git a/network/arp/十秒一个.png b/network/arpicmplab/arp/十秒一个.png similarity index 100% rename from network/arp/十秒一个.png rename to network/arpicmplab/arp/十秒一个.png diff --git a/network/arp/十秒一个2.png b/network/arpicmplab/arp/十秒一个2.png similarity index 100% rename from network/arp/十秒一个2.png rename to network/arpicmplab/arp/十秒一个2.png diff --git a/network/arp/启动ARP.png b/network/arpicmplab/arp/启动ARP.png similarity index 100% rename from network/arp/启动ARP.png rename to network/arpicmplab/arp/启动ARP.png diff --git a/network/arp/启动ARP2.png b/network/arpicmplab/arp/启动ARP2.png similarity index 100% rename from network/arp/启动ARP2.png rename to network/arpicmplab/arp/启动ARP2.png diff --git a/network/arp/抓一个arp分析结构.png b/network/arpicmplab/arp/抓一个arp分析结构.png similarity index 100% rename from network/arp/抓一个arp分析结构.png rename to network/arpicmplab/arp/抓一个arp分析结构.png diff --git a/network/arp/物理机虚拟机IP配置.png b/network/arpicmplab/arp/物理机虚拟机IP配置.png similarity index 100% rename from network/arp/物理机虚拟机IP配置.png rename to network/arpicmplab/arp/物理机虚拟机IP配置.png diff --git a/network/arp/环境配置ping测试.png b/network/arpicmplab/arp/环境配置ping测试.png similarity index 100% rename from network/arp/环境配置ping测试.png rename to network/arpicmplab/arp/环境配置ping测试.png diff --git a/network/check.md b/network/arpicmplab/check.md similarity index 100% rename from network/check.md rename to network/arpicmplab/check.md diff --git a/network/implementation_report.md b/network/arpicmplab/implementation_report.md similarity index 100% rename from network/implementation_report.md rename to network/arpicmplab/implementation_report.md diff --git a/network/start/.idea/.gitignore b/network/arpicmplab/start/.idea/.gitignore similarity index 100% rename from network/start/.idea/.gitignore rename to network/arpicmplab/start/.idea/.gitignore diff --git a/network/start/.idea/deployment.xml b/network/arpicmplab/start/.idea/deployment.xml similarity index 100% rename from network/start/.idea/deployment.xml rename to network/arpicmplab/start/.idea/deployment.xml diff --git a/network/start/.idea/inspectionProfiles/Project_Default.xml b/network/arpicmplab/start/.idea/inspectionProfiles/Project_Default.xml similarity index 100% rename from network/start/.idea/inspectionProfiles/Project_Default.xml rename to network/arpicmplab/start/.idea/inspectionProfiles/Project_Default.xml diff --git a/network/start/.idea/misc.xml b/network/arpicmplab/start/.idea/misc.xml similarity index 100% rename from network/start/.idea/misc.xml rename to network/arpicmplab/start/.idea/misc.xml diff --git a/network/start/.idea/modules.xml b/network/arpicmplab/start/.idea/modules.xml similarity index 100% rename from network/start/.idea/modules.xml rename to network/arpicmplab/start/.idea/modules.xml diff --git a/network/start/.idea/vcs.xml b/network/arpicmplab/start/.idea/vcs.xml similarity index 100% rename from network/start/.idea/vcs.xml rename to network/arpicmplab/start/.idea/vcs.xml diff --git a/network/start/.idea/xnet-tiny.iml b/network/arpicmplab/start/.idea/xnet-tiny.iml similarity index 100% rename from network/start/.idea/xnet-tiny.iml rename to network/arpicmplab/start/.idea/xnet-tiny.iml diff --git a/network/start/htdocs/1.jpg b/network/arpicmplab/start/htdocs/1.jpg similarity index 100% rename from network/start/htdocs/1.jpg rename to network/arpicmplab/start/htdocs/1.jpg diff --git a/network/start/htdocs/2.jpg b/network/arpicmplab/start/htdocs/2.jpg similarity index 100% rename from network/start/htdocs/2.jpg rename to network/arpicmplab/start/htdocs/2.jpg diff --git a/network/start/htdocs/3.jpg b/network/arpicmplab/start/htdocs/3.jpg similarity index 100% rename from network/start/htdocs/3.jpg rename to network/arpicmplab/start/htdocs/3.jpg diff --git a/network/start/htdocs/4.jpg b/network/arpicmplab/start/htdocs/4.jpg similarity index 100% rename from network/start/htdocs/4.jpg rename to network/arpicmplab/start/htdocs/4.jpg diff --git a/network/start/htdocs/5.jpg b/network/arpicmplab/start/htdocs/5.jpg similarity index 100% rename from network/start/htdocs/5.jpg rename to network/arpicmplab/start/htdocs/5.jpg diff --git a/network/start/htdocs/6.jpg b/network/arpicmplab/start/htdocs/6.jpg similarity index 100% rename from network/start/htdocs/6.jpg rename to network/arpicmplab/start/htdocs/6.jpg diff --git a/network/start/htdocs/7.jpg b/network/arpicmplab/start/htdocs/7.jpg similarity index 100% rename from network/start/htdocs/7.jpg rename to network/arpicmplab/start/htdocs/7.jpg diff --git a/network/start/htdocs/index.html b/network/arpicmplab/start/htdocs/index.html similarity index 100% rename from network/start/htdocs/index.html rename to network/arpicmplab/start/htdocs/index.html diff --git a/network/start/htdocs/javascript.js b/network/arpicmplab/start/htdocs/javascript.js similarity index 100% rename from network/start/htdocs/javascript.js rename to network/arpicmplab/start/htdocs/javascript.js diff --git a/network/start/htdocs/page1.html b/network/arpicmplab/start/htdocs/page1.html similarity index 100% rename from network/start/htdocs/page1.html rename to network/arpicmplab/start/htdocs/page1.html diff --git a/network/start/htdocs/page2.html b/network/arpicmplab/start/htdocs/page2.html similarity index 100% rename from network/start/htdocs/page2.html rename to network/arpicmplab/start/htdocs/page2.html diff --git a/network/start/htdocs/page3.html b/network/arpicmplab/start/htdocs/page3.html similarity index 100% rename from network/start/htdocs/page3.html rename to network/arpicmplab/start/htdocs/page3.html diff --git a/network/start/htdocs/style.css b/network/arpicmplab/start/htdocs/style.css similarity index 100% rename from network/start/htdocs/style.css rename to network/arpicmplab/start/htdocs/style.css diff --git a/network/start/lib/npcap/Examples-pcap/GNUmakefile b/network/arpicmplab/start/lib/npcap/Examples-pcap/GNUmakefile similarity index 100% rename from network/start/lib/npcap/Examples-pcap/GNUmakefile rename to network/arpicmplab/start/lib/npcap/Examples-pcap/GNUmakefile diff --git a/network/start/lib/npcap/Examples-pcap/MakeAll.sln b/network/arpicmplab/start/lib/npcap/Examples-pcap/MakeAll.sln similarity index 100% rename from network/start/lib/npcap/Examples-pcap/MakeAll.sln rename to network/arpicmplab/start/lib/npcap/Examples-pcap/MakeAll.sln diff --git a/network/start/lib/npcap/Examples-pcap/UDPdump/GNUmakefile b/network/arpicmplab/start/lib/npcap/Examples-pcap/UDPdump/GNUmakefile similarity index 100% rename from network/start/lib/npcap/Examples-pcap/UDPdump/GNUmakefile rename to network/arpicmplab/start/lib/npcap/Examples-pcap/UDPdump/GNUmakefile diff --git a/network/start/lib/npcap/Examples-pcap/UDPdump/UDPdump.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-pcap/UDPdump/UDPdump.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-pcap/UDPdump/UDPdump.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-pcap/UDPdump/UDPdump.vcxproj diff --git a/network/start/lib/npcap/Examples-pcap/UDPdump/udpdump.c b/network/arpicmplab/start/lib/npcap/Examples-pcap/UDPdump/udpdump.c similarity index 100% rename from network/start/lib/npcap/Examples-pcap/UDPdump/udpdump.c rename to network/arpicmplab/start/lib/npcap/Examples-pcap/UDPdump/udpdump.c diff --git a/network/start/lib/npcap/Examples-pcap/basic_dump/GNUmakefile b/network/arpicmplab/start/lib/npcap/Examples-pcap/basic_dump/GNUmakefile similarity index 100% rename from network/start/lib/npcap/Examples-pcap/basic_dump/GNUmakefile rename to network/arpicmplab/start/lib/npcap/Examples-pcap/basic_dump/GNUmakefile diff --git a/network/start/lib/npcap/Examples-pcap/basic_dump/basic_dump.c b/network/arpicmplab/start/lib/npcap/Examples-pcap/basic_dump/basic_dump.c similarity index 100% rename from network/start/lib/npcap/Examples-pcap/basic_dump/basic_dump.c rename to network/arpicmplab/start/lib/npcap/Examples-pcap/basic_dump/basic_dump.c diff --git a/network/start/lib/npcap/Examples-pcap/basic_dump/basic_dump.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-pcap/basic_dump/basic_dump.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-pcap/basic_dump/basic_dump.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-pcap/basic_dump/basic_dump.vcxproj diff --git a/network/start/lib/npcap/Examples-pcap/basic_dump_ex/GNUmakefile b/network/arpicmplab/start/lib/npcap/Examples-pcap/basic_dump_ex/GNUmakefile similarity index 100% rename from network/start/lib/npcap/Examples-pcap/basic_dump_ex/GNUmakefile rename to network/arpicmplab/start/lib/npcap/Examples-pcap/basic_dump_ex/GNUmakefile diff --git a/network/start/lib/npcap/Examples-pcap/basic_dump_ex/basic_dump_ex.c b/network/arpicmplab/start/lib/npcap/Examples-pcap/basic_dump_ex/basic_dump_ex.c similarity index 100% rename from network/start/lib/npcap/Examples-pcap/basic_dump_ex/basic_dump_ex.c rename to network/arpicmplab/start/lib/npcap/Examples-pcap/basic_dump_ex/basic_dump_ex.c diff --git a/network/start/lib/npcap/Examples-pcap/basic_dump_ex/basic_dump_ex.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-pcap/basic_dump_ex/basic_dump_ex.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-pcap/basic_dump_ex/basic_dump_ex.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-pcap/basic_dump_ex/basic_dump_ex.vcxproj diff --git a/network/start/lib/npcap/Examples-pcap/iflist/GNUmakefile b/network/arpicmplab/start/lib/npcap/Examples-pcap/iflist/GNUmakefile similarity index 100% rename from network/start/lib/npcap/Examples-pcap/iflist/GNUmakefile rename to network/arpicmplab/start/lib/npcap/Examples-pcap/iflist/GNUmakefile diff --git a/network/start/lib/npcap/Examples-pcap/iflist/iflist.c b/network/arpicmplab/start/lib/npcap/Examples-pcap/iflist/iflist.c similarity index 100% rename from network/start/lib/npcap/Examples-pcap/iflist/iflist.c rename to network/arpicmplab/start/lib/npcap/Examples-pcap/iflist/iflist.c diff --git a/network/start/lib/npcap/Examples-pcap/iflist/iflist.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-pcap/iflist/iflist.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-pcap/iflist/iflist.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-pcap/iflist/iflist.vcxproj diff --git a/network/start/lib/npcap/Examples-pcap/pcap_filter/GNUmakefile b/network/arpicmplab/start/lib/npcap/Examples-pcap/pcap_filter/GNUmakefile similarity index 100% rename from network/start/lib/npcap/Examples-pcap/pcap_filter/GNUmakefile rename to network/arpicmplab/start/lib/npcap/Examples-pcap/pcap_filter/GNUmakefile diff --git a/network/start/lib/npcap/Examples-pcap/pcap_filter/Makefile.unix b/network/arpicmplab/start/lib/npcap/Examples-pcap/pcap_filter/Makefile.unix similarity index 100% rename from network/start/lib/npcap/Examples-pcap/pcap_filter/Makefile.unix rename to network/arpicmplab/start/lib/npcap/Examples-pcap/pcap_filter/Makefile.unix diff --git a/network/start/lib/npcap/Examples-pcap/pcap_filter/pcap_filter.c b/network/arpicmplab/start/lib/npcap/Examples-pcap/pcap_filter/pcap_filter.c similarity index 100% rename from network/start/lib/npcap/Examples-pcap/pcap_filter/pcap_filter.c rename to network/arpicmplab/start/lib/npcap/Examples-pcap/pcap_filter/pcap_filter.c diff --git a/network/start/lib/npcap/Examples-pcap/pcap_filter/pcap_filter.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-pcap/pcap_filter/pcap_filter.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-pcap/pcap_filter/pcap_filter.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-pcap/pcap_filter/pcap_filter.vcxproj diff --git a/network/start/lib/npcap/Examples-pcap/pktdump_ex/GNUmakefile b/network/arpicmplab/start/lib/npcap/Examples-pcap/pktdump_ex/GNUmakefile similarity index 100% rename from network/start/lib/npcap/Examples-pcap/pktdump_ex/GNUmakefile rename to network/arpicmplab/start/lib/npcap/Examples-pcap/pktdump_ex/GNUmakefile diff --git a/network/start/lib/npcap/Examples-pcap/pktdump_ex/pktdump_ex.c b/network/arpicmplab/start/lib/npcap/Examples-pcap/pktdump_ex/pktdump_ex.c similarity index 100% rename from network/start/lib/npcap/Examples-pcap/pktdump_ex/pktdump_ex.c rename to network/arpicmplab/start/lib/npcap/Examples-pcap/pktdump_ex/pktdump_ex.c diff --git a/network/start/lib/npcap/Examples-pcap/pktdump_ex/pktdump_ex.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-pcap/pktdump_ex/pktdump_ex.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-pcap/pktdump_ex/pktdump_ex.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-pcap/pktdump_ex/pktdump_ex.vcxproj diff --git a/network/start/lib/npcap/Examples-pcap/readfile/GNUmakefile b/network/arpicmplab/start/lib/npcap/Examples-pcap/readfile/GNUmakefile similarity index 100% rename from network/start/lib/npcap/Examples-pcap/readfile/GNUmakefile rename to network/arpicmplab/start/lib/npcap/Examples-pcap/readfile/GNUmakefile diff --git a/network/start/lib/npcap/Examples-pcap/readfile/readfile.c b/network/arpicmplab/start/lib/npcap/Examples-pcap/readfile/readfile.c similarity index 100% rename from network/start/lib/npcap/Examples-pcap/readfile/readfile.c rename to network/arpicmplab/start/lib/npcap/Examples-pcap/readfile/readfile.c diff --git a/network/start/lib/npcap/Examples-pcap/readfile/readfile.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-pcap/readfile/readfile.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-pcap/readfile/readfile.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-pcap/readfile/readfile.vcxproj diff --git a/network/start/lib/npcap/Examples-pcap/readfile_ex/GNUmakefile b/network/arpicmplab/start/lib/npcap/Examples-pcap/readfile_ex/GNUmakefile similarity index 100% rename from network/start/lib/npcap/Examples-pcap/readfile_ex/GNUmakefile rename to network/arpicmplab/start/lib/npcap/Examples-pcap/readfile_ex/GNUmakefile diff --git a/network/start/lib/npcap/Examples-pcap/readfile_ex/readfile_ex.c b/network/arpicmplab/start/lib/npcap/Examples-pcap/readfile_ex/readfile_ex.c similarity index 100% rename from network/start/lib/npcap/Examples-pcap/readfile_ex/readfile_ex.c rename to network/arpicmplab/start/lib/npcap/Examples-pcap/readfile_ex/readfile_ex.c diff --git a/network/start/lib/npcap/Examples-pcap/readfile_ex/readfile_ex.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-pcap/readfile_ex/readfile_ex.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-pcap/readfile_ex/readfile_ex.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-pcap/readfile_ex/readfile_ex.vcxproj diff --git a/network/start/lib/npcap/Examples-pcap/savedump/GNUmakefile b/network/arpicmplab/start/lib/npcap/Examples-pcap/savedump/GNUmakefile similarity index 100% rename from network/start/lib/npcap/Examples-pcap/savedump/GNUmakefile rename to network/arpicmplab/start/lib/npcap/Examples-pcap/savedump/GNUmakefile diff --git a/network/start/lib/npcap/Examples-pcap/savedump/savedump.c b/network/arpicmplab/start/lib/npcap/Examples-pcap/savedump/savedump.c similarity index 100% rename from network/start/lib/npcap/Examples-pcap/savedump/savedump.c rename to network/arpicmplab/start/lib/npcap/Examples-pcap/savedump/savedump.c diff --git a/network/start/lib/npcap/Examples-pcap/savedump/savedump.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-pcap/savedump/savedump.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-pcap/savedump/savedump.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-pcap/savedump/savedump.vcxproj diff --git a/network/start/lib/npcap/Examples-pcap/sendpack/GNUmakefile b/network/arpicmplab/start/lib/npcap/Examples-pcap/sendpack/GNUmakefile similarity index 100% rename from network/start/lib/npcap/Examples-pcap/sendpack/GNUmakefile rename to network/arpicmplab/start/lib/npcap/Examples-pcap/sendpack/GNUmakefile diff --git a/network/start/lib/npcap/Examples-pcap/sendpack/sendpack.c b/network/arpicmplab/start/lib/npcap/Examples-pcap/sendpack/sendpack.c similarity index 100% rename from network/start/lib/npcap/Examples-pcap/sendpack/sendpack.c rename to network/arpicmplab/start/lib/npcap/Examples-pcap/sendpack/sendpack.c diff --git a/network/start/lib/npcap/Examples-pcap/sendpack/sendpack.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-pcap/sendpack/sendpack.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-pcap/sendpack/sendpack.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-pcap/sendpack/sendpack.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/MakeAll.sln b/network/arpicmplab/start/lib/npcap/Examples-remote/MakeAll.sln similarity index 100% rename from network/start/lib/npcap/Examples-remote/MakeAll.sln rename to network/arpicmplab/start/lib/npcap/Examples-remote/MakeAll.sln diff --git a/network/start/lib/npcap/Examples-remote/PacketDriver/GetMacAddress/GetMacAddress.c b/network/arpicmplab/start/lib/npcap/Examples-remote/PacketDriver/GetMacAddress/GetMacAddress.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/PacketDriver/GetMacAddress/GetMacAddress.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/PacketDriver/GetMacAddress/GetMacAddress.c diff --git a/network/start/lib/npcap/Examples-remote/PacketDriver/GetMacAddress/GetMacAddress.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/PacketDriver/GetMacAddress/GetMacAddress.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/PacketDriver/GetMacAddress/GetMacAddress.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/PacketDriver/GetMacAddress/GetMacAddress.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/PacketDriver/TestPacketCapture/TestPacketCapture.c b/network/arpicmplab/start/lib/npcap/Examples-remote/PacketDriver/TestPacketCapture/TestPacketCapture.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/PacketDriver/TestPacketCapture/TestPacketCapture.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/PacketDriver/TestPacketCapture/TestPacketCapture.c diff --git a/network/start/lib/npcap/Examples-remote/PacketDriver/TestPacketCapture/TestPacketCapture.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/PacketDriver/TestPacketCapture/TestPacketCapture.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/PacketDriver/TestPacketCapture/TestPacketCapture.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/PacketDriver/TestPacketCapture/TestPacketCapture.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/PacketDriver/TestPacketSend/TestPacketSend.c b/network/arpicmplab/start/lib/npcap/Examples-remote/PacketDriver/TestPacketSend/TestPacketSend.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/PacketDriver/TestPacketSend/TestPacketSend.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/PacketDriver/TestPacketSend/TestPacketSend.c diff --git a/network/start/lib/npcap/Examples-remote/PacketDriver/TestPacketSend/TestPacketSend.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/PacketDriver/TestPacketSend/TestPacketSend.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/PacketDriver/TestPacketSend/TestPacketSend.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/PacketDriver/TestPacketSend/TestPacketSend.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/PacketDriver/readme.txt b/network/arpicmplab/start/lib/npcap/Examples-remote/PacketDriver/readme.txt similarity index 100% rename from network/start/lib/npcap/Examples-remote/PacketDriver/readme.txt rename to network/arpicmplab/start/lib/npcap/Examples-remote/PacketDriver/readme.txt diff --git a/network/start/lib/npcap/Examples-remote/UDPdump/UDPdump.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/UDPdump/UDPdump.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/UDPdump/UDPdump.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/UDPdump/UDPdump.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/UDPdump/udpdump.c b/network/arpicmplab/start/lib/npcap/Examples-remote/UDPdump/udpdump.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/UDPdump/udpdump.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/UDPdump/udpdump.c diff --git a/network/start/lib/npcap/Examples-remote/UserLevelBridge/UserBridge.c b/network/arpicmplab/start/lib/npcap/Examples-remote/UserLevelBridge/UserBridge.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/UserLevelBridge/UserBridge.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/UserLevelBridge/UserBridge.c diff --git a/network/start/lib/npcap/Examples-remote/UserLevelBridge/UserBridge.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/UserLevelBridge/UserBridge.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/UserLevelBridge/UserBridge.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/UserLevelBridge/UserBridge.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/iflist/iflist.c b/network/arpicmplab/start/lib/npcap/Examples-remote/iflist/iflist.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/iflist/iflist.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/iflist/iflist.c diff --git a/network/start/lib/npcap/Examples-remote/iflist/iflist.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/iflist/iflist.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/iflist/iflist.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/iflist/iflist.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/iflist/iflist.vcxproj.filters b/network/arpicmplab/start/lib/npcap/Examples-remote/iflist/iflist.vcxproj.filters similarity index 100% rename from network/start/lib/npcap/Examples-remote/iflist/iflist.vcxproj.filters rename to network/arpicmplab/start/lib/npcap/Examples-remote/iflist/iflist.vcxproj.filters diff --git a/network/start/lib/npcap/Examples-remote/misc/basic_dump.c b/network/arpicmplab/start/lib/npcap/Examples-remote/misc/basic_dump.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/misc/basic_dump.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/misc/basic_dump.c diff --git a/network/start/lib/npcap/Examples-remote/misc/basic_dump.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/misc/basic_dump.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/misc/basic_dump.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/misc/basic_dump.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/misc/basic_dump_ex.c b/network/arpicmplab/start/lib/npcap/Examples-remote/misc/basic_dump_ex.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/misc/basic_dump_ex.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/misc/basic_dump_ex.c diff --git a/network/start/lib/npcap/Examples-remote/misc/basic_dump_ex.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/misc/basic_dump_ex.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/misc/basic_dump_ex.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/misc/basic_dump_ex.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/misc/misc.h b/network/arpicmplab/start/lib/npcap/Examples-remote/misc/misc.h similarity index 100% rename from network/start/lib/npcap/Examples-remote/misc/misc.h rename to network/arpicmplab/start/lib/npcap/Examples-remote/misc/misc.h diff --git a/network/start/lib/npcap/Examples-remote/misc/readfile.c b/network/arpicmplab/start/lib/npcap/Examples-remote/misc/readfile.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/misc/readfile.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/misc/readfile.c diff --git a/network/start/lib/npcap/Examples-remote/misc/readfile.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/misc/readfile.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/misc/readfile.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/misc/readfile.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/misc/readfile_ex.c b/network/arpicmplab/start/lib/npcap/Examples-remote/misc/readfile_ex.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/misc/readfile_ex.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/misc/readfile_ex.c diff --git a/network/start/lib/npcap/Examples-remote/misc/readfile_ex.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/misc/readfile_ex.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/misc/readfile_ex.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/misc/readfile_ex.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/misc/savedump.c b/network/arpicmplab/start/lib/npcap/Examples-remote/misc/savedump.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/misc/savedump.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/misc/savedump.c diff --git a/network/start/lib/npcap/Examples-remote/misc/savedump.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/misc/savedump.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/misc/savedump.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/misc/savedump.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/misc/sendpack.c b/network/arpicmplab/start/lib/npcap/Examples-remote/misc/sendpack.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/misc/sendpack.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/misc/sendpack.c diff --git a/network/start/lib/npcap/Examples-remote/misc/sendpack.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/misc/sendpack.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/misc/sendpack.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/misc/sendpack.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/pcap_filter/pcap_filter.c b/network/arpicmplab/start/lib/npcap/Examples-remote/pcap_filter/pcap_filter.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/pcap_filter/pcap_filter.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/pcap_filter/pcap_filter.c diff --git a/network/start/lib/npcap/Examples-remote/pcap_filter/pcap_filter.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/pcap_filter/pcap_filter.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/pcap_filter/pcap_filter.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/pcap_filter/pcap_filter.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/pcap_fopen/pcap_fopen.cpp b/network/arpicmplab/start/lib/npcap/Examples-remote/pcap_fopen/pcap_fopen.cpp similarity index 100% rename from network/start/lib/npcap/Examples-remote/pcap_fopen/pcap_fopen.cpp rename to network/arpicmplab/start/lib/npcap/Examples-remote/pcap_fopen/pcap_fopen.cpp diff --git a/network/start/lib/npcap/Examples-remote/pcap_fopen/pcap_fopen.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/pcap_fopen/pcap_fopen.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/pcap_fopen/pcap_fopen.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/pcap_fopen/pcap_fopen.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/pktdump_ex/pktdump_ex.c b/network/arpicmplab/start/lib/npcap/Examples-remote/pktdump_ex/pktdump_ex.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/pktdump_ex/pktdump_ex.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/pktdump_ex/pktdump_ex.c diff --git a/network/start/lib/npcap/Examples-remote/pktdump_ex/pktdump_ex.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/pktdump_ex/pktdump_ex.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/pktdump_ex/pktdump_ex.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/pktdump_ex/pktdump_ex.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/sendcap/sendcap.c b/network/arpicmplab/start/lib/npcap/Examples-remote/sendcap/sendcap.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/sendcap/sendcap.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/sendcap/sendcap.c diff --git a/network/start/lib/npcap/Examples-remote/sendcap/sendcap.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/sendcap/sendcap.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/sendcap/sendcap.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/sendcap/sendcap.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/sendcap/sendcap.vcxproj.filters b/network/arpicmplab/start/lib/npcap/Examples-remote/sendcap/sendcap.vcxproj.filters similarity index 100% rename from network/start/lib/npcap/Examples-remote/sendcap/sendcap.vcxproj.filters rename to network/arpicmplab/start/lib/npcap/Examples-remote/sendcap/sendcap.vcxproj.filters diff --git a/network/start/lib/npcap/Examples-remote/smp_1/smp_1.c b/network/arpicmplab/start/lib/npcap/Examples-remote/smp_1/smp_1.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/smp_1/smp_1.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/smp_1/smp_1.c diff --git a/network/start/lib/npcap/Examples-remote/smp_1/smp_1.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/smp_1/smp_1.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/smp_1/smp_1.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/smp_1/smp_1.vcxproj diff --git a/network/start/lib/npcap/Examples-remote/tcptop/tcptop.c b/network/arpicmplab/start/lib/npcap/Examples-remote/tcptop/tcptop.c similarity index 100% rename from network/start/lib/npcap/Examples-remote/tcptop/tcptop.c rename to network/arpicmplab/start/lib/npcap/Examples-remote/tcptop/tcptop.c diff --git a/network/start/lib/npcap/Examples-remote/tcptop/tcptop.vcxproj b/network/arpicmplab/start/lib/npcap/Examples-remote/tcptop/tcptop.vcxproj similarity index 100% rename from network/start/lib/npcap/Examples-remote/tcptop/tcptop.vcxproj rename to network/arpicmplab/start/lib/npcap/Examples-remote/tcptop/tcptop.vcxproj diff --git a/network/start/lib/npcap/Include/Packet32.h b/network/arpicmplab/start/lib/npcap/Include/Packet32.h similarity index 100% rename from network/start/lib/npcap/Include/Packet32.h rename to network/arpicmplab/start/lib/npcap/Include/Packet32.h diff --git a/network/start/lib/npcap/Include/pcap-bpf.h b/network/arpicmplab/start/lib/npcap/Include/pcap-bpf.h similarity index 100% rename from network/start/lib/npcap/Include/pcap-bpf.h rename to network/arpicmplab/start/lib/npcap/Include/pcap-bpf.h diff --git a/network/start/lib/npcap/Include/pcap-namedb.h b/network/arpicmplab/start/lib/npcap/Include/pcap-namedb.h similarity index 100% rename from network/start/lib/npcap/Include/pcap-namedb.h rename to network/arpicmplab/start/lib/npcap/Include/pcap-namedb.h diff --git a/network/start/lib/npcap/Include/pcap.h b/network/arpicmplab/start/lib/npcap/Include/pcap.h similarity index 100% rename from network/start/lib/npcap/Include/pcap.h rename to network/arpicmplab/start/lib/npcap/Include/pcap.h diff --git a/network/start/lib/npcap/Include/pcap/bluetooth.h b/network/arpicmplab/start/lib/npcap/Include/pcap/bluetooth.h similarity index 100% rename from network/start/lib/npcap/Include/pcap/bluetooth.h rename to network/arpicmplab/start/lib/npcap/Include/pcap/bluetooth.h diff --git a/network/start/lib/npcap/Include/pcap/bpf.h b/network/arpicmplab/start/lib/npcap/Include/pcap/bpf.h similarity index 100% rename from network/start/lib/npcap/Include/pcap/bpf.h rename to network/arpicmplab/start/lib/npcap/Include/pcap/bpf.h diff --git a/network/start/lib/npcap/Include/pcap/can_socketcan.h b/network/arpicmplab/start/lib/npcap/Include/pcap/can_socketcan.h similarity index 100% rename from network/start/lib/npcap/Include/pcap/can_socketcan.h rename to network/arpicmplab/start/lib/npcap/Include/pcap/can_socketcan.h diff --git a/network/start/lib/npcap/Include/pcap/compiler-tests.h b/network/arpicmplab/start/lib/npcap/Include/pcap/compiler-tests.h similarity index 100% rename from network/start/lib/npcap/Include/pcap/compiler-tests.h rename to network/arpicmplab/start/lib/npcap/Include/pcap/compiler-tests.h diff --git a/network/start/lib/npcap/Include/pcap/dlt.h b/network/arpicmplab/start/lib/npcap/Include/pcap/dlt.h similarity index 100% rename from network/start/lib/npcap/Include/pcap/dlt.h rename to network/arpicmplab/start/lib/npcap/Include/pcap/dlt.h diff --git a/network/start/lib/npcap/Include/pcap/funcattrs.h b/network/arpicmplab/start/lib/npcap/Include/pcap/funcattrs.h similarity index 100% rename from network/start/lib/npcap/Include/pcap/funcattrs.h rename to network/arpicmplab/start/lib/npcap/Include/pcap/funcattrs.h diff --git a/network/start/lib/npcap/Include/pcap/ipnet.h b/network/arpicmplab/start/lib/npcap/Include/pcap/ipnet.h similarity index 100% rename from network/start/lib/npcap/Include/pcap/ipnet.h rename to network/arpicmplab/start/lib/npcap/Include/pcap/ipnet.h diff --git a/network/start/lib/npcap/Include/pcap/namedb.h b/network/arpicmplab/start/lib/npcap/Include/pcap/namedb.h similarity index 100% rename from network/start/lib/npcap/Include/pcap/namedb.h rename to network/arpicmplab/start/lib/npcap/Include/pcap/namedb.h diff --git a/network/start/lib/npcap/Include/pcap/nflog.h b/network/arpicmplab/start/lib/npcap/Include/pcap/nflog.h similarity index 100% rename from network/start/lib/npcap/Include/pcap/nflog.h rename to network/arpicmplab/start/lib/npcap/Include/pcap/nflog.h diff --git a/network/start/lib/npcap/Include/pcap/pcap-inttypes.h b/network/arpicmplab/start/lib/npcap/Include/pcap/pcap-inttypes.h similarity index 100% rename from network/start/lib/npcap/Include/pcap/pcap-inttypes.h rename to network/arpicmplab/start/lib/npcap/Include/pcap/pcap-inttypes.h diff --git a/network/start/lib/npcap/Include/pcap/pcap.h b/network/arpicmplab/start/lib/npcap/Include/pcap/pcap.h similarity index 100% rename from network/start/lib/npcap/Include/pcap/pcap.h rename to network/arpicmplab/start/lib/npcap/Include/pcap/pcap.h diff --git a/network/start/lib/npcap/Include/pcap/sll.h b/network/arpicmplab/start/lib/npcap/Include/pcap/sll.h similarity index 100% rename from network/start/lib/npcap/Include/pcap/sll.h rename to network/arpicmplab/start/lib/npcap/Include/pcap/sll.h diff --git a/network/start/lib/npcap/Include/pcap/socket.h b/network/arpicmplab/start/lib/npcap/Include/pcap/socket.h similarity index 100% rename from network/start/lib/npcap/Include/pcap/socket.h rename to network/arpicmplab/start/lib/npcap/Include/pcap/socket.h diff --git a/network/start/lib/npcap/Include/pcap/usb.h b/network/arpicmplab/start/lib/npcap/Include/pcap/usb.h similarity index 100% rename from network/start/lib/npcap/Include/pcap/usb.h rename to network/arpicmplab/start/lib/npcap/Include/pcap/usb.h diff --git a/network/start/lib/npcap/Include/pcap/vlan.h b/network/arpicmplab/start/lib/npcap/Include/pcap/vlan.h similarity index 100% rename from network/start/lib/npcap/Include/pcap/vlan.h rename to network/arpicmplab/start/lib/npcap/Include/pcap/vlan.h diff --git a/network/start/lib/npcap/Lib/Packet.lib b/network/arpicmplab/start/lib/npcap/Lib/Packet.lib similarity index 100% rename from network/start/lib/npcap/Lib/Packet.lib rename to network/arpicmplab/start/lib/npcap/Lib/Packet.lib diff --git a/network/start/lib/npcap/Lib/wpcap.lib b/network/arpicmplab/start/lib/npcap/Lib/wpcap.lib similarity index 100% rename from network/start/lib/npcap/Lib/wpcap.lib rename to network/arpicmplab/start/lib/npcap/Lib/wpcap.lib diff --git a/network/start/lib/npcap/Lib/x64/Packet.lib b/network/arpicmplab/start/lib/npcap/Lib/x64/Packet.lib similarity index 100% rename from network/start/lib/npcap/Lib/x64/Packet.lib rename to network/arpicmplab/start/lib/npcap/Lib/x64/Packet.lib diff --git a/network/start/lib/npcap/Lib/x64/wpcap.lib b/network/arpicmplab/start/lib/npcap/Lib/x64/wpcap.lib similarity index 100% rename from network/start/lib/npcap/Lib/x64/wpcap.lib rename to network/arpicmplab/start/lib/npcap/Lib/x64/wpcap.lib diff --git a/network/start/lib/npcap/Npcap_Guide.html b/network/arpicmplab/start/lib/npcap/Npcap_Guide.html similarity index 100% rename from network/start/lib/npcap/Npcap_Guide.html rename to network/arpicmplab/start/lib/npcap/Npcap_Guide.html diff --git a/network/start/lib/npcap/docs/index.html b/network/arpicmplab/start/lib/npcap/docs/index.html similarity index 100% rename from network/start/lib/npcap/docs/index.html rename to network/arpicmplab/start/lib/npcap/docs/index.html diff --git a/network/start/lib/npcap/docs/npcap-devguide.html b/network/arpicmplab/start/lib/npcap/docs/npcap-devguide.html similarity index 100% rename from network/start/lib/npcap/docs/npcap-devguide.html rename to network/arpicmplab/start/lib/npcap/docs/npcap-devguide.html diff --git a/network/start/lib/npcap/docs/npcap-internals.html b/network/arpicmplab/start/lib/npcap/docs/npcap-internals.html similarity index 100% rename from network/start/lib/npcap/docs/npcap-internals.html rename to network/arpicmplab/start/lib/npcap/docs/npcap-internals.html diff --git a/network/start/lib/npcap/docs/npcap-tutorial.html b/network/arpicmplab/start/lib/npcap/docs/npcap-tutorial.html similarity index 100% rename from network/start/lib/npcap/docs/npcap-tutorial.html rename to network/arpicmplab/start/lib/npcap/docs/npcap-tutorial.html diff --git a/network/start/lib/npcap/docs/npcap-users-guide.html b/network/arpicmplab/start/lib/npcap/docs/npcap-users-guide.html similarity index 100% rename from network/start/lib/npcap/docs/npcap-users-guide.html rename to network/arpicmplab/start/lib/npcap/docs/npcap-users-guide.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap-filter.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap-filter.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap-filter.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap-filter.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap-linktype.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap-linktype.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap-linktype.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap-linktype.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap-savefile.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap-savefile.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap-savefile.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap-savefile.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap-tstamp.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap-tstamp.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap-tstamp.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap-tstamp.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_activate.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_activate.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_activate.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_activate.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_breakloop.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_breakloop.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_breakloop.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_breakloop.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_can_set_rfmon.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_can_set_rfmon.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_can_set_rfmon.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_can_set_rfmon.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_close.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_close.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_close.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_close.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_compile.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_compile.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_compile.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_compile.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_create.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_create.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_create.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_create.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_datalink.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_datalink.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_datalink.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_datalink.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_datalink_name_to_val.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_datalink_name_to_val.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_datalink_name_to_val.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_datalink_name_to_val.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_datalink_val_to_name.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_datalink_val_to_name.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_datalink_val_to_name.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_datalink_val_to_name.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_dump.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_dump.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_dump.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_dump.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_dump_close.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_dump_close.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_dump_close.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_dump_close.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_dump_file.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_dump_file.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_dump_file.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_dump_file.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_dump_flush.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_dump_flush.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_dump_flush.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_dump_flush.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_dump_ftell.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_dump_ftell.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_dump_ftell.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_dump_ftell.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_dump_open.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_dump_open.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_dump_open.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_dump_open.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_file.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_file.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_file.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_file.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_fileno.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_fileno.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_fileno.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_fileno.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_findalldevs.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_findalldevs.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_findalldevs.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_findalldevs.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_freecode.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_freecode.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_freecode.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_freecode.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_get_required_select_timeout.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_get_required_select_timeout.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_get_required_select_timeout.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_get_required_select_timeout.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_get_selectable_fd.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_get_selectable_fd.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_get_selectable_fd.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_get_selectable_fd.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_get_tstamp_precision.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_get_tstamp_precision.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_get_tstamp_precision.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_get_tstamp_precision.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_geterr.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_geterr.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_geterr.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_geterr.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_inject.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_inject.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_inject.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_inject.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_is_swapped.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_is_swapped.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_is_swapped.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_is_swapped.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_lib_version.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_lib_version.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_lib_version.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_lib_version.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_list_datalinks.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_list_datalinks.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_list_datalinks.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_list_datalinks.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_list_tstamp_types.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_list_tstamp_types.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_list_tstamp_types.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_list_tstamp_types.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_lookupdev.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_lookupdev.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_lookupdev.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_lookupdev.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_lookupnet.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_lookupnet.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_lookupnet.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_lookupnet.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_loop.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_loop.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_loop.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_loop.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_major_version.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_major_version.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_major_version.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_major_version.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_next_ex.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_next_ex.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_next_ex.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_next_ex.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_offline_filter.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_offline_filter.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_offline_filter.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_offline_filter.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_open_dead.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_open_dead.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_open_dead.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_open_dead.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_open_live.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_open_live.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_open_live.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_open_live.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_open_offline.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_open_offline.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_open_offline.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_open_offline.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_set_buffer_size.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_buffer_size.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_set_buffer_size.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_buffer_size.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_set_datalink.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_datalink.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_set_datalink.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_datalink.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_set_promisc.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_promisc.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_set_promisc.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_promisc.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_set_protocol_linux.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_protocol_linux.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_set_protocol_linux.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_protocol_linux.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_set_rfmon.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_rfmon.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_set_rfmon.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_rfmon.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_set_snaplen.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_snaplen.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_set_snaplen.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_snaplen.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_set_timeout.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_timeout.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_set_timeout.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_timeout.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_set_tstamp_precision.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_tstamp_precision.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_set_tstamp_precision.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_tstamp_precision.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_set_tstamp_type.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_tstamp_type.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_set_tstamp_type.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_set_tstamp_type.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_setdirection.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_setdirection.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_setdirection.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_setdirection.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_setfilter.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_setfilter.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_setfilter.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_setfilter.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_setnonblock.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_setnonblock.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_setnonblock.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_setnonblock.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_snapshot.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_snapshot.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_snapshot.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_snapshot.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_stats.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_stats.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_stats.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_stats.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_statustostr.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_statustostr.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_statustostr.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_statustostr.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_strerror.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_strerror.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_strerror.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_strerror.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_tstamp_type_name_to_val.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_tstamp_type_name_to_val.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_tstamp_type_name_to_val.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_tstamp_type_name_to_val.html diff --git a/network/start/lib/npcap/docs/wpcap/pcap_tstamp_type_val_to_name.html b/network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_tstamp_type_val_to_name.html similarity index 100% rename from network/start/lib/npcap/docs/wpcap/pcap_tstamp_type_val_to_name.html rename to network/arpicmplab/start/lib/npcap/docs/wpcap/pcap_tstamp_type_val_to_name.html diff --git a/network/start/lib/xnet/CMakeLists.txt b/network/arpicmplab/start/lib/xnet/CMakeLists.txt similarity index 100% rename from network/start/lib/xnet/CMakeLists.txt rename to network/arpicmplab/start/lib/xnet/CMakeLists.txt diff --git a/network/start/lib/xnet/enc28j60_device.c b/network/arpicmplab/start/lib/xnet/enc28j60_device.c similarity index 100% rename from network/start/lib/xnet/enc28j60_device.c rename to network/arpicmplab/start/lib/xnet/enc28j60_device.c diff --git a/network/start/lib/xnet/enc28j60_device.h b/network/arpicmplab/start/lib/xnet/enc28j60_device.h similarity index 100% rename from network/start/lib/xnet/enc28j60_device.h rename to network/arpicmplab/start/lib/xnet/enc28j60_device.h diff --git a/network/start/lib/xnet/pcap_device.c b/network/arpicmplab/start/lib/xnet/pcap_device.c similarity index 100% rename from network/start/lib/xnet/pcap_device.c rename to network/arpicmplab/start/lib/xnet/pcap_device.c diff --git a/network/start/lib/xnet/pcap_device.h b/network/arpicmplab/start/lib/xnet/pcap_device.h similarity index 100% rename from network/start/lib/xnet/pcap_device.h rename to network/arpicmplab/start/lib/xnet/pcap_device.h diff --git a/network/start/xnet_tiny/.idea/.name b/network/arpicmplab/start/xnet_tiny/.idea/.name similarity index 100% rename from network/start/xnet_tiny/.idea/.name rename to network/arpicmplab/start/xnet_tiny/.idea/.name diff --git a/network/start/xnet_tiny/.idea/misc.xml b/network/arpicmplab/start/xnet_tiny/.idea/misc.xml similarity index 100% rename from network/start/xnet_tiny/.idea/misc.xml rename to network/arpicmplab/start/xnet_tiny/.idea/misc.xml diff --git a/network/start/xnet_tiny/.idea/modules.xml b/network/arpicmplab/start/xnet_tiny/.idea/modules.xml similarity index 100% rename from network/start/xnet_tiny/.idea/modules.xml rename to network/arpicmplab/start/xnet_tiny/.idea/modules.xml diff --git a/network/start/xnet_tiny/.idea/vcs.xml b/network/arpicmplab/start/xnet_tiny/.idea/vcs.xml similarity index 100% rename from network/start/xnet_tiny/.idea/vcs.xml rename to network/arpicmplab/start/xnet_tiny/.idea/vcs.xml diff --git a/network/start/xnet_tiny/.idea/workspace.xml b/network/arpicmplab/start/xnet_tiny/.idea/workspace.xml similarity index 100% rename from network/start/xnet_tiny/.idea/workspace.xml rename to network/arpicmplab/start/xnet_tiny/.idea/workspace.xml diff --git a/network/start/xnet_tiny/.idea/xnet_core_c101.iml b/network/arpicmplab/start/xnet_tiny/.idea/xnet_core_c101.iml similarity index 100% rename from network/start/xnet_tiny/.idea/xnet_core_c101.iml rename to network/arpicmplab/start/xnet_tiny/.idea/xnet_core_c101.iml diff --git a/network/start/xnet_tiny/CMakeLists.txt b/network/arpicmplab/start/xnet_tiny/CMakeLists.txt similarity index 100% rename from network/start/xnet_tiny/CMakeLists.txt rename to network/arpicmplab/start/xnet_tiny/CMakeLists.txt diff --git a/network/start/xnet_tiny/src/app.c b/network/arpicmplab/start/xnet_tiny/src/app.c similarity index 100% rename from network/start/xnet_tiny/src/app.c rename to network/arpicmplab/start/xnet_tiny/src/app.c diff --git a/network/start/xnet_tiny/src/xnet_app/CMakeLists.txt b/network/arpicmplab/start/xnet_tiny/src/xnet_app/CMakeLists.txt similarity index 100% rename from network/start/xnet_tiny/src/xnet_app/CMakeLists.txt rename to network/arpicmplab/start/xnet_tiny/src/xnet_app/CMakeLists.txt diff --git a/network/start/xnet_tiny/src/xnet_app/port_pcap.c b/network/arpicmplab/start/xnet_tiny/src/xnet_app/port_pcap.c similarity index 100% rename from network/start/xnet_tiny/src/xnet_app/port_pcap.c rename to network/arpicmplab/start/xnet_tiny/src/xnet_app/port_pcap.c diff --git a/network/start/xnet_tiny/src/xnet_app/xserver_datetime.c b/network/arpicmplab/start/xnet_tiny/src/xnet_app/xserver_datetime.c similarity index 100% rename from network/start/xnet_tiny/src/xnet_app/xserver_datetime.c rename to network/arpicmplab/start/xnet_tiny/src/xnet_app/xserver_datetime.c diff --git a/network/start/xnet_tiny/src/xnet_app/xserver_datetime.h b/network/arpicmplab/start/xnet_tiny/src/xnet_app/xserver_datetime.h similarity index 100% rename from network/start/xnet_tiny/src/xnet_app/xserver_datetime.h rename to network/arpicmplab/start/xnet_tiny/src/xnet_app/xserver_datetime.h diff --git a/network/start/xnet_tiny/src/xnet_app/xserver_http.c b/network/arpicmplab/start/xnet_tiny/src/xnet_app/xserver_http.c similarity index 100% rename from network/start/xnet_tiny/src/xnet_app/xserver_http.c rename to network/arpicmplab/start/xnet_tiny/src/xnet_app/xserver_http.c diff --git a/network/start/xnet_tiny/src/xnet_app/xserver_http.h b/network/arpicmplab/start/xnet_tiny/src/xnet_app/xserver_http.h similarity index 100% rename from network/start/xnet_tiny/src/xnet_app/xserver_http.h rename to network/arpicmplab/start/xnet_tiny/src/xnet_app/xserver_http.h diff --git a/network/start/xnet_tiny/src/xnet_tiny/CMakeLists.txt b/network/arpicmplab/start/xnet_tiny/src/xnet_tiny/CMakeLists.txt similarity index 100% rename from network/start/xnet_tiny/src/xnet_tiny/CMakeLists.txt rename to network/arpicmplab/start/xnet_tiny/src/xnet_tiny/CMakeLists.txt diff --git a/network/start/xnet_tiny/src/xnet_tiny/xarp.c b/network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xarp.c similarity index 100% rename from network/start/xnet_tiny/src/xnet_tiny/xarp.c rename to network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xarp.c diff --git a/network/start/xnet_tiny/src/xnet_tiny/xarp.h b/network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xarp.h similarity index 100% rename from network/start/xnet_tiny/src/xnet_tiny/xarp.h rename to network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xarp.h diff --git a/network/start/xnet_tiny/src/xnet_tiny/xicmp.c b/network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xicmp.c similarity index 100% rename from network/start/xnet_tiny/src/xnet_tiny/xicmp.c rename to network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xicmp.c diff --git a/network/start/xnet_tiny/src/xnet_tiny/xicmp.h b/network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xicmp.h similarity index 100% rename from network/start/xnet_tiny/src/xnet_tiny/xicmp.h rename to network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xicmp.h diff --git a/network/start/xnet_tiny/src/xnet_tiny/xip.c b/network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xip.c similarity index 100% rename from network/start/xnet_tiny/src/xnet_tiny/xip.c rename to network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xip.c diff --git a/network/start/xnet_tiny/src/xnet_tiny/xip.h b/network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xip.h similarity index 100% rename from network/start/xnet_tiny/src/xnet_tiny/xip.h rename to network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xip.h diff --git a/network/start/xnet_tiny/src/xnet_tiny/xlog.h b/network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xlog.h similarity index 100% rename from network/start/xnet_tiny/src/xnet_tiny/xlog.h rename to network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xlog.h diff --git a/network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.c b/network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xnet_tiny.c similarity index 100% rename from network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.c rename to network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xnet_tiny.c diff --git a/network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.h b/network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xnet_tiny.h similarity index 100% rename from network/start/xnet_tiny/src/xnet_tiny/xnet_tiny.h rename to network/arpicmplab/start/xnet_tiny/src/xnet_tiny/xnet_tiny.h diff --git a/network/xnet-record.pcapng b/network/arpicmplab/xnet-record.pcapng similarity index 100% rename from network/xnet-record.pcapng rename to network/arpicmplab/xnet-record.pcapng diff --git a/network/实验2讲解.pptx b/network/arpicmplab/实验2讲解.pptx similarity index 100% rename from network/实验2讲解.pptx rename to network/arpicmplab/实验2讲解.pptx diff --git a/network/tcpquiclab/Makefile b/network/tcpquiclab/Makefile new file mode 100644 index 0000000..f688051 --- /dev/null +++ b/network/tcpquiclab/Makefile @@ -0,0 +1,32 @@ +CC = gcc +CFLAGS = -Wall -g +LDFLAGS = -lquiche -ldl -lpthread -lm + +all: tcp_server tcp_client quic_server quic_client tcp_perf_server tcp_perf_client quic_perf_server quic_perf_client + +tcp_server: tcp_server.c + $(CC) $(CFLAGS) -o tcp_server tcp_server.c + +tcp_client: tcp_client.c + $(CC) $(CFLAGS) -o tcp_client tcp_client.c + +quic_server: quic_server.c + $(CC) $(CFLAGS) -o quic_server quic_server.c $(LDFLAGS) + +quic_client: quic_client.c + $(CC) $(CFLAGS) -o quic_client quic_client.c $(LDFLAGS) + +tcp_perf_server: tcp_perf_server.c + $(CC) $(CFLAGS) -o tcp_perf_server tcp_perf_server.c + +tcp_perf_client: tcp_perf_client.c + $(CC) $(CFLAGS) -o tcp_perf_client tcp_perf_client.c + +quic_perf_server: quic_perf_server.c + $(CC) $(CFLAGS) -o quic_perf_server quic_perf_server.c $(LDFLAGS) + +quic_perf_client: quic_perf_client.c + $(CC) $(CFLAGS) -o quic_perf_client quic_perf_client.c $(LDFLAGS) + +clean: + rm -f tcp_server tcp_client quic_server quic_client tcp_perf_server tcp_perf_client quic_perf_server quic_perf_client diff --git a/network/tcpquiclab/README_LINUX.md b/network/tcpquiclab/README_LINUX.md new file mode 100644 index 0000000..5219954 --- /dev/null +++ b/network/tcpquiclab/README_LINUX.md @@ -0,0 +1,109 @@ +# Computer Network Experiment: TCP vs QUIC (Linux Guide) + +This guide adapts the Windows-based experiment manual for a Linux environment. + +## 1. Prerequisites + +Ensure you have the following installed: +- `gcc` (Compiler) +- `quiche` library (Headers and Shared Object installed) +- `openssl` (For certificates) +- `tcpdump` or `wireshark` (For packet capture) +- `iproute2` (For `tc` traffic control) + +## 2. Compilation + +Compile all programs using the provided Makefile: + +```bash +make +``` + +This will generate: +- `tcp_server`, `tcp_client` (Task 1) +- `quic_server`, `quic_client` (Task 2) +- `tcp_perf_server`, `tcp_perf_client` (Task 3 Performance) +- `quic_perf_server`, `quic_perf_client` (Task 3 Performance) + +*Note: If `quiche` is not in the standard system path, edit the `Makefile` to point to the include/lib directories.* + +## 3. Task 1: Basic TCP Client-Server + +1. **Start the Server:** + ```bash + ./tcp_server + ``` +2. **Run the Client (in a new terminal):** + ```bash + ./tcp_client + ``` + + **Expected Output:** The client sends "Hello...", server receives it and replies. + +## 4. Task 2: Basic QUIC Client-Server + +1. **Start the Server:** + ```bash + ./quic_server + ``` +2. **Run the Client (in a new terminal):** + ```bash + ./quic_client + ``` + + **Expected Output:** QUIC handshake completes, client sends data on a stream, server echoes it back. + +## 5. Task 3: Performance Analysis + +### 3.1 Connection Establishment Time + +1. Start capture on loopback: + ```bash + sudo tcpdump -i lo -w handshake.pcap + ``` + *(Or use Wireshark on the `lo` interface)* + +2. Run the TCP or QUIC client/server pairs again. +3. Open `handshake.pcap` in Wireshark to analyze the time difference between the first packet (SYN for TCP, Initial for QUIC) and the completion of the handshake. + +### 3.2 Throughput Test (100MB Transfer) + +**Baseline (Normal Network):** + +1. Run TCP Perf Server: `./tcp_perf_server` +2. Run TCP Perf Client: `./tcp_perf_client` +3. Record the MB/s output. +4. Repeat for QUIC (`./quic_perf_server`, `./quic_perf_client`). + +**Simulating Network Conditions (Packet Loss / Delay):** + +We use Linux `tc` (Traffic Control) with `netem` instead of `clumsy`. + +**Scenario A: 5% Packet Loss** + +1. Apply 5% loss to the loopback interface: + ```bash + sudo tc qdisc add dev lo root netem loss 5% + ``` +2. Run the perf tests again. +3. **Important:** Remove the rule after testing! + ```bash + sudo tc qdisc del dev lo root + ``` + +**Scenario B: 100ms Delay** + +1. Apply 100ms delay: + ```bash + sudo tc qdisc add dev lo root netem delay 100ms + ``` +2. Run the perf tests again. +3. Remove the rule: + ```bash + sudo tc qdisc del dev lo root + ``` + +### 3.3 & 3.4 Advanced Tests + +- **Multiplexing:** The current `quic_perf_client` uses a single stream (Stream ID 4). You can modify the code to launch multiple streams in parallel to test head-of-line blocking resilience. +- **Network Recovery:** Use `tc` to drop 100% packets (`loss 100%`) for 30 seconds during a long transfer, then remove the rule (`del`) to see if the connection recovers. diff --git a/network/tcpquiclab/README_LINUX_CN.md b/network/tcpquiclab/README_LINUX_CN.md new file mode 100644 index 0000000..0dcd0af --- /dev/null +++ b/network/tcpquiclab/README_LINUX_CN.md @@ -0,0 +1,109 @@ +# 计算机网络实验:TCP 与 QUIC 协议对比 (Linux 指南) + +本指南根据 Windows 版本的实验手册,针对 Linux 环境进行了适配。 + +## 1. 预备工作 + +确保已安装以下工具和库: +- `gcc` (编译器) +- `quiche` 库 (已安装头文件和共享库/静态库) +- `openssl` (用于生成证书) +- `tcpdump` 或 `wireshark` (用于抓包) +- `iproute2` (用于 `tc` 流量控制) + +## 2. 编译 + +使用提供的 Makefile 编译所有程序: + +```bash +make +``` + +这将生成以下可执行文件: +- `tcp_server`, `tcp_client` (任务一:基础 TCP) +- `quic_server`, `quic_client` (任务二:基础 QUIC) +- `tcp_perf_server`, `tcp_perf_client` (任务三:TCP 性能测试) +- `quic_perf_server`, `quic_perf_client` (任务三:QUIC 性能测试) + +*注意:如果编译报错提示找不到 `quiche.h` 或库文件,请修改 `Makefile` 中的路径,指向您本地 `quiche` 安装的 `include` 和 `lib` 目录。* + +## 3. 任务一:基础 TCP 客户端-服务器 + +1. **启动服务器:** + ```bash + ./tcp_server + ``` +2. **运行客户端 (在新的终端窗口):** + ```bash + ./tcp_client + ``` + + **预期输出:** 客户端发送消息,服务器接收并回复。 + +## 4. 任务二:基础 QUIC 客户端-服务器 + +1. **启动服务器:** + ```bash + ./quic_server + ``` +2. **运行客户端 (在新的终端窗口):** + ```bash + ./quic_client + ``` + + **预期输出:** 完成 QUIC 握手,客户端发送流数据,服务器回显数据。 + +## 5. 任务三:性能分析 + +### 3.1 连接建立时间 + +1. 在回环接口 (`lo`) 上开始抓包: + ```bash + sudo tcpdump -i lo -w handshake.pcap + ``` + *(或者使用 Wireshark 监听 `lo` 接口)* + +2. 再次运行 TCP 或 QUIC 的客户端/服务器程序。 +3. 使用 Wireshark 打开 `handshake.pcap`,分析从第一个包 (TCP 的 SYN 或 QUIC 的 Initial) 到握手完成的时间差。 + +### 3.2 吞吐量测试 (100MB 传输) + +**基准测试 (正常网络):** + +1. 运行 TCP 性能服务器:`./tcp_perf_server` +2. 运行 TCP 性能客户端:`./tcp_perf_client` +3. 记录输出的 MB/s 吞吐量。 +4. 重复上述步骤测试 QUIC (`./quic_perf_server`, `./quic_perf_client`)。 + +**模拟网络环境 (丢包 / 延迟):** + +在 Linux 下我们使用 `tc` (Traffic Control) 的 `netem` 模块,替代 Windows 下的 `clumsy` 工具。 + +**场景 A: 5% 丢包率** + +1. 设置回环接口 5% 丢包: + ```bash + sudo tc qdisc add dev lo root netem loss 5% + ``` +2. 再次运行性能测试程序。 +3. **重要:** 测试结束后删除规则! + ```bash + sudo tc qdisc del dev lo root + ``` + +**场景 B: 100ms 延迟** + +1. 设置 100ms 延迟: + ```bash + sudo tc qdisc add dev lo root netem delay 100ms + ``` +2. 再次运行性能测试程序。 +3. 删除规则: + ```bash + sudo tc qdisc del dev lo root + ``` + +### 3.3 & 3.4 进阶测试 + +- **多路复用:** 当前的 `quic_perf_client` 使用单个流 (Stream ID 4)。您可以修改代码并行启动多个流,以测试 QUIC 解决队头阻塞问题的能力。 +- **网络恢复:** 在长传输过程中,使用 `tc` 设置 100% 丢包 (`loss 100%`) 持续 30 秒,然后删除规则 (`del`),观察连接是否能恢复传输。 diff --git a/network/tcpquiclab/cert.crt b/network/tcpquiclab/cert.crt new file mode 100644 index 0000000..58a161f --- /dev/null +++ b/network/tcpquiclab/cert.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCTCCAfGgAwIBAgIUW5+jEv1Pf4vBxjbLWEyXBhyKM5EwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MTIyNTA2MjEyN1oXDTI2MTIy +NTA2MjEyN1owFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAq+DK/kcAQ7oID4P/tDWT7gGaOJjbHYenPKMxqC67IBC1 +x3hlu2ze828p0K81XNUmnlzhgjw9jnIlIc/oLtBZ7SQrH9o2mXB6wXeSxcVuDbUY +qp7SiqFWF8L3ZBgi+uhY3dtFN/1CrEtBgiqSyDsTGqa4MZq5L/Nh4GTzkUYyzQG1 +52C/1VjDqcPLNdVoJGfMUCA2jC7rdkO+9IRqlkJQMb5XsE4kDMfal80TZiCqzH6I +FRjFCTXtoI8YlzofOlRSbChdYj0xutiH9i9UE6yb+0JHS9KVgYcUBhQ+qeHje8w5 +siCrJ4s4NFSyl7GUjawCzEhLmdVCHrEMi4y7FXSbowIDAQABo1MwUTAdBgNVHQ4E +FgQU9+ZRlQIBxZZBv2Z0p1xAwoj2IeQwHwYDVR0jBBgwFoAU9+ZRlQIBxZZBv2Z0 +p1xAwoj2IeQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAYj9D +DGopooNlH6ltJ5DIQuSXtd1FfSE3QF62vVDkPr2xhnuiHpKDjFnEQvEgYd6aCG6J +rf5YhM3yOnQMHH10WZl3bAlQ+bQUv+cHLn2X72QMZ8TumwYaIFgkkXgAHl3z309b +ZWQojJMwCIk9fy1Fl/PQQ3gjBi/5JfUtxRFeWmhbDNOJUOKlskaIdynvrgwnlJUk +0rwOMqhvHahUaJxqa7VCEx4NfmchpK9UmdXVVWSv5rrBFJUzBFPVdI4HoQeVAXCK +kuRWiHk4EOtweoJILOfDwZtIsS/yJQ4gF903GBKxJsjosKMrI0Z3ClRlRUoqxA+h +kvzgZsTfps3a3+1Zgg== +-----END CERTIFICATE----- diff --git a/network/tcpquiclab/cert.key b/network/tcpquiclab/cert.key new file mode 100644 index 0000000..a90f469 --- /dev/null +++ b/network/tcpquiclab/cert.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCr4Mr+RwBDuggP +g/+0NZPuAZo4mNsdh6c8ozGoLrsgELXHeGW7bN7zbynQrzVc1SaeXOGCPD2OciUh +z+gu0FntJCsf2jaZcHrBd5LFxW4NtRiqntKKoVYXwvdkGCL66Fjd20U3/UKsS0GC +KpLIOxMaprgxmrkv82HgZPORRjLNAbXnYL/VWMOpw8s11WgkZ8xQIDaMLut2Q770 +hGqWQlAxvlewTiQMx9qXzRNmIKrMfogVGMUJNe2gjxiXOh86VFJsKF1iPTG62If2 +L1QTrJv7QkdL0pWBhxQGFD6p4eN7zDmyIKsnizg0VLKXsZSNrALMSEuZ1UIesQyL +jLsVdJujAgMBAAECggEABnWhS2MhuGniaardTkmBML2wrRXZjkeN2nKLqDVxZOgb +3M5CjIOv8VgpKyWajM2Z8POuqfVXnuXdTWMB59h+uLHWSRErYiLfCixTQMmFtFAt +CCSF5x3fHW9/Wqypi+J1jIj0FgGXouAFKz4sXAgUVLkVTQ/yi8HK2OMSYFBSEnBB +JPPKScFfDGCbsC3ij9/Jl0IB2o3qRuwUNkcwvdeMm3iK+N9CHOqZ0yx/2L+EncsD +SH9FQEFkCa0u2aroVFddfDikzzPXxYeG+WYrEkLjr+Blfq54PHeJzfV35ppO4lZ5 +U0o71hqX7guzb2XQFBLGw6GxVqrQzfCU6ADveO1jIQKBgQDrxKJRF4BxjS0QdF7w +DmnFg9aU8K6jXzaOdWQ9h7lcFanw9hNdbi5ZFEBqhgiw6IpEnm/raD0+diJiJuyd +u/WH6mT8tZpXRNmoKJcRuxft5XXLdpgG3Dy+AEpINpnH9Od0ZzuGBHcXuSKay8sN +/gChZotwg4bASnu4DhE61szH0wKBgQC6oJ60191vIvb4NJEaq6CJps7DvqgA6MMR +RypBh30pbY08RwrCBzD4i+9Lg1fBoKQD53qfrjV1KUIlqw2VhyIBU0oUFntBbNFm +nmRYVhcgwN9cpLF4ngnDGyv9t/aRvdb7XXEjBe5kzmJ6bHWZYsiABEzQPXmySiNd +Xjak8wDK8QKBgGCjneDdYEGrG3CmMo/1aHeUfa1ZJkxC58rm5WqvKlRLcPga9X8T +fZ33xhujywYwmxRbWQbGGGx04c0XpV9WPuMyOai4C4Z/6zOZR6r15G4X4vu+JbyS +I7fByLDm6Ivkn8a/1c8uH16y/TM0G4wltD50GO3Ki75gCWw9H+TdTN0PAoGAS/EI +I7ajWJH1xVI+qYelL948zNJMMvKETgeTXk7v02fMzPZrnkCm4Lywhx3PG+9uTlhn +QYr2HdLII+PTB0GRyNBHmJz9UsYg/4z8cCW4C4/wVBaAUQCeIFJyODAfmXaSgH6p +hwLm2wZQdFimEeBsjgsx5prdZntcoKWxvrVTYUECgYAfcIaMcIO6BNhPnYsHmqlV +NcELQnRg/GHw42SiDQ1V772TivrTfOPn5MzPg9/PmrDlCa5ZIqecKtWcgjF8TJkH +1Xltn+Ar+ERDJWuFSS5Wu0CT8n1jp0rfxAuzRL7/zN9wWqn4t5Bd6vebU4RmENyr +s/UT4EovEshPpRCY3mQawg== +-----END PRIVATE KEY----- diff --git a/network/tcpquiclab/quic_client b/network/tcpquiclab/quic_client new file mode 100755 index 0000000..1a4de72 Binary files /dev/null and b/network/tcpquiclab/quic_client differ diff --git a/network/tcpquiclab/quic_client.c b/network/tcpquiclab/quic_client.c new file mode 100644 index 0000000..3401a0f --- /dev/null +++ b/network/tcpquiclab/quic_client.c @@ -0,0 +1,118 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_DATAGRAM_SIZE 1350 + +int main(int argc, char *argv[]) { + quiche_config *config = quiche_config_new(QUICHE_PROTOCOL_VERSION); + if (config == NULL) return -1; + + quiche_config_verify_peer(config, false); + quiche_config_set_application_protos(config, (uint8_t *) "\x0ahq-interop\x05hq-29\x05hq-28\x05hq-27\x08http/0.9", 38); + quiche_config_set_max_idle_timeout(config, 5000); + quiche_config_set_max_recv_udp_payload_size(config, MAX_DATAGRAM_SIZE); + quiche_config_set_max_send_udp_payload_size(config, MAX_DATAGRAM_SIZE); + quiche_config_set_initial_max_data(config, 10000000); + quiche_config_set_initial_max_stream_data_bidi_local(config, 1000000); + quiche_config_set_initial_max_streams_bidi(config, 100); + + int sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) return -1; + + struct sockaddr_in peer_addr; + memset(&peer_addr, 0, sizeof(peer_addr)); + peer_addr.sin_family = AF_INET; + peer_addr.sin_port = htons(8888); + inet_pton(AF_INET, "127.0.0.1", &peer_addr.sin_addr); + + if (connect(sock, (struct sockaddr *)&peer_addr, sizeof(peer_addr)) < 0) { + perror("connect"); + return -1; + } + + int flags = fcntl(sock, F_GETFL, 0); + fcntl(sock, F_SETFL, flags | O_NONBLOCK); + + uint8_t scid[QUICHE_MAX_CONN_ID_LEN]; + int rng = open("/dev/urandom", O_RDONLY); + if (rng >= 0) { + read(rng, scid, sizeof(scid)); + close(rng); + } + + quiche_conn *conn = quiche_connect("127.0.0.1", (const uint8_t *)scid, sizeof(scid), NULL, 0, (struct sockaddr *)&peer_addr, sizeof(peer_addr), config); + if (conn == NULL) { + fprintf(stderr, "quiche_connect failed\n"); + return -1; + } + + printf("Connecting to QUIC server...\n"); + + uint8_t buf[65535]; + uint8_t out[MAX_DATAGRAM_SIZE]; + bool req_sent = false; + + while (1) { + ssize_t read_len = recv(sock, buf, sizeof(buf), 0); + if (read_len > 0) { + quiche_conn_recv(conn, buf, read_len, &(quiche_recv_info){ + .to = NULL, + .to_len = 0, + .from = (struct sockaddr *)&peer_addr, + .from_len = sizeof(peer_addr), + }); + } + + if (quiche_conn_is_closed(conn)) { + printf("Connection closed.\n"); + break; + } + + if (quiche_conn_is_established(conn)) { + if (!req_sent) { + const char *msg = "Hello from QUIC Client!"; + uint64_t err_code = 0; + quiche_conn_stream_send(conn, 4, (uint8_t*)msg, strlen(msg), true, &err_code); + printf("Sent: %s\n", msg); + req_sent = true; + } + + uint64_t s = 0; + quiche_stream_iter *readable = quiche_conn_readable(conn); + while (quiche_stream_iter_next(readable, &s)) { + uint8_t recv_buf[1024]; + bool fin = false; + uint64_t err_code = 0; + ssize_t len = quiche_conn_stream_recv(conn, s, recv_buf, sizeof(recv_buf), &fin, &err_code); + if (len > 0) { + printf("Received: %.*s\n", (int)len, recv_buf); + quiche_conn_close(conn, true, 0, (const uint8_t *)"Done", 4); + } + } + quiche_stream_iter_free(readable); + } + + while (1) { + quiche_send_info send_info; + ssize_t written = quiche_conn_send(conn, out, sizeof(out), &send_info); + if (written == QUICHE_ERR_DONE) break; + if (written < 0) break; + send(sock, out, written, 0); + } + + quiche_conn_on_timeout(conn); + usleep(1000); + } + + quiche_conn_free(conn); + quiche_config_free(config); + return 0; +} \ No newline at end of file diff --git a/network/tcpquiclab/quic_perf_client b/network/tcpquiclab/quic_perf_client new file mode 100755 index 0000000..53e4a20 Binary files /dev/null and b/network/tcpquiclab/quic_perf_client differ diff --git a/network/tcpquiclab/quic_perf_client.c b/network/tcpquiclab/quic_perf_client.c new file mode 100644 index 0000000..e7c9fdb --- /dev/null +++ b/network/tcpquiclab/quic_perf_client.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_DATAGRAM_SIZE 1350 +#define TARGET_MB 100 + +int main(int argc, char *argv[]) { + quiche_config *config = quiche_config_new(QUICHE_PROTOCOL_VERSION); + if (config == NULL) return -1; + + quiche_config_verify_peer(config, false); + quiche_config_set_application_protos(config, (uint8_t *) "\x0ahq-interop\x05hq-29\x05hq-28\x05hq-27\x08http/0.9", 38); + quiche_config_set_max_idle_timeout(config, 10000); + quiche_config_set_max_recv_udp_payload_size(config, MAX_DATAGRAM_SIZE); + quiche_config_set_max_send_udp_payload_size(config, MAX_DATAGRAM_SIZE); + quiche_config_set_initial_max_data(config, 1024 * 1024 * 200); + quiche_config_set_initial_max_stream_data_bidi_local(config, 1024 * 1024 * 200); + quiche_config_set_initial_max_stream_data_bidi_remote(config, 1024 * 1024 * 200); + quiche_config_set_initial_max_streams_bidi(config, 100); + quiche_config_set_cc_algorithm(config, QUICHE_CC_RENO); + + int sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) return -1; + + struct sockaddr_in peer_addr; + memset(&peer_addr, 0, sizeof(peer_addr)); + peer_addr.sin_family = AF_INET; + peer_addr.sin_port = htons(8889); + inet_pton(AF_INET, "127.0.0.1", &peer_addr.sin_addr); + + if (connect(sock, (struct sockaddr *)&peer_addr, sizeof(peer_addr)) < 0) return -1; + + int flags = fcntl(sock, F_GETFL, 0); + fcntl(sock, F_SETFL, flags | O_NONBLOCK); + + uint8_t scid[QUICHE_MAX_CONN_ID_LEN]; + int rng = open("/dev/urandom", O_RDONLY); + if (rng >= 0) { + read(rng, scid, sizeof(scid)); + close(rng); + } + + quiche_conn *conn = quiche_connect("127.0.0.1", (const uint8_t *)scid, sizeof(scid), NULL, 0, (struct sockaddr *)&peer_addr, sizeof(peer_addr), config); + + printf("Connecting to QUIC Perf Server and sending %d MB...\n", TARGET_MB); + + uint8_t buf[65535]; + uint8_t out[MAX_DATAGRAM_SIZE]; + uint8_t payload[4096]; + memset(payload, 'A', sizeof(payload)); + + long long bytes_to_send = (long long)TARGET_MB * 1024 * 1024; + long long bytes_sent = 0; + bool finished_sending = false; + + while (1) { + ssize_t read_len = recv(sock, buf, sizeof(buf), 0); + if (read_len > 0) { + quiche_conn_recv(conn, buf, read_len, &(quiche_recv_info){ + .to = NULL, + .to_len = 0, + .from = (struct sockaddr *)&peer_addr, + .from_len = sizeof(peer_addr), + }); + } + + if (quiche_conn_is_closed(conn)) break; + + if (quiche_conn_is_established(conn)) { + while (!finished_sending) { + uint64_t err_code = 0; + ssize_t sent = quiche_conn_stream_send(conn, 4, payload, sizeof(payload), false, &err_code); + if (sent > 0) { + bytes_sent += sent; + if (bytes_sent >= bytes_to_send) { + quiche_conn_stream_send(conn, 4, NULL, 0, true, &err_code); + finished_sending = true; + printf("Finished sending data.\n"); + } + } else { + break; + } + } + } + + while (1) { + quiche_send_info send_info; + ssize_t written = quiche_conn_send(conn, out, sizeof(out), &send_info); + if (written == QUICHE_ERR_DONE) break; + if (written < 0) break; + send(sock, out, written, 0); + } + + quiche_conn_on_timeout(conn); + usleep(100); + } + + quiche_conn_free(conn); + quiche_config_free(config); + return 0; +} \ No newline at end of file diff --git a/network/tcpquiclab/quic_perf_server b/network/tcpquiclab/quic_perf_server new file mode 100755 index 0000000..0706e1b Binary files /dev/null and b/network/tcpquiclab/quic_perf_server differ diff --git a/network/tcpquiclab/quic_perf_server.c b/network/tcpquiclab/quic_perf_server.c new file mode 100644 index 0000000..6bdd3d4 --- /dev/null +++ b/network/tcpquiclab/quic_perf_server.c @@ -0,0 +1,187 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_DATAGRAM_SIZE 1350 +#define LOCAL_CONN_ID_LEN 16 + +// Simple structure to hold connection state +typedef struct { + int sock; + struct sockaddr_storage peer_addr; + socklen_t peer_addr_len; + quiche_conn *conn; + long long total_bytes; + struct timespec start_time; + int timer_started; +} Client; + +int main(int argc, char *argv[]) { + // 1. Configuration + quiche_config *config = quiche_config_new(QUICHE_PROTOCOL_VERSION); + if (config == NULL) return -1; + + quiche_config_load_cert_chain_from_pem_file(config, "cert.crt"); + quiche_config_load_priv_key_from_pem_file(config, "cert.key"); + + quiche_config_set_application_protos(config, (uint8_t *) "\x0ahq-interop\x05hq-29\x05hq-28\x05hq-27\x08http/0.9", 38); + quiche_config_set_max_idle_timeout(config, 10000); + quiche_config_set_max_recv_udp_payload_size(config, MAX_DATAGRAM_SIZE); + quiche_config_set_max_send_udp_payload_size(config, MAX_DATAGRAM_SIZE); + // Increase limits for performance + quiche_config_set_initial_max_data(config, 1024 * 1024 * 200); + quiche_config_set_initial_max_stream_data_bidi_local(config, 1024 * 1024 * 200); + quiche_config_set_initial_max_stream_data_bidi_remote(config, 1024 * 1024 * 200); + quiche_config_set_initial_max_streams_bidi(config, 100); + quiche_config_set_cc_algorithm(config, QUICHE_CC_RENO); + + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_port = htons(8889); + sa.sin_addr.s_addr = INADDR_ANY; + + int sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) return -1; + if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) return -1; + + int flags = fcntl(sock, F_GETFL, 0); + fcntl(sock, F_SETFL, flags | O_NONBLOCK); + + printf("QUIC Performance Server listening on port 8889\n"); + + Client *client = NULL; + uint8_t buf[65535]; + uint8_t out[MAX_DATAGRAM_SIZE]; + bool done_printing = false; + + while (1) { + struct sockaddr_storage peer_addr; + socklen_t peer_addr_len = sizeof(peer_addr); + ssize_t read_len = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&peer_addr, &peer_addr_len); + + if (read_len > 0) { + uint8_t type; + uint32_t version; + uint8_t scid[QUICHE_MAX_CONN_ID_LEN]; + size_t scid_len = sizeof(scid); + uint8_t dcid[QUICHE_MAX_CONN_ID_LEN]; + size_t dcid_len = sizeof(dcid); + uint8_t token[256]; + size_t token_len = sizeof(token); + + int rc = quiche_header_info(buf, read_len, LOCAL_CONN_ID_LEN, &version, &type, scid, &scid_len, dcid, &dcid_len, token, &token_len); + + if (rc >= 0) { + if (client == NULL) { + if (!quiche_version_is_supported(version)) { + ssize_t written = quiche_negotiate_version(scid, scid_len, dcid, dcid_len, out, sizeof(out)); + if (written > 0) sendto(sock, out, written, 0, (struct sockaddr *)&peer_addr, peer_addr_len); + } else if (token_len == 0) { + uint8_t new_scid[QUICHE_MAX_CONN_ID_LEN]; + int rng = open("/dev/urandom", O_RDONLY); + if (rng >= 0) { + read(rng, new_scid, sizeof(new_scid)); + close(rng); + } + ssize_t written = quiche_retry(scid, scid_len, dcid, dcid_len, new_scid, sizeof(new_scid), token, token_len, version, out, sizeof(out)); + if (written > 0) sendto(sock, out, written, 0, (struct sockaddr *)&peer_addr, peer_addr_len); + } else { + client = malloc(sizeof(Client)); + client->sock = sock; + client->peer_addr = peer_addr; + client->peer_addr_len = peer_addr_len; + + uint8_t server_scid[QUICHE_MAX_CONN_ID_LEN]; + int rng = open("/dev/urandom", O_RDONLY); + if (rng >= 0) { + read(rng, server_scid, sizeof(server_scid)); + close(rng); + } + + client->conn = quiche_accept(server_scid, sizeof(server_scid), dcid, dcid_len, (struct sockaddr *)&sa, sizeof(sa), (struct sockaddr *)&peer_addr, peer_addr_len, config); + client->total_bytes = 0; + client->timer_started = 0; + printf("New performance connection accepted.\n"); + } + } + + if (client != NULL) { + quiche_conn_recv(client->conn, buf, read_len, &(quiche_recv_info){ + .to = (struct sockaddr *)&sa, + .to_len = sizeof(sa), + .from = (struct sockaddr *)&peer_addr, + .from_len = peer_addr_len, + }); + } + } + } + + if (client != NULL) { + quiche_conn *conn = client->conn; + + if (quiche_conn_is_closed(conn)) { + printf("Connection closed.\n"); + quiche_conn_free(conn); + free(client); + client = NULL; + continue; + } + + if (quiche_conn_is_established(conn)) { + uint64_t s = 0; + quiche_stream_iter *readable = quiche_conn_readable(conn); + while (quiche_stream_iter_next(readable, &s)) { + if (!client->timer_started) { + clock_gettime(CLOCK_MONOTONIC, &client->start_time); + client->timer_started = 1; + } + + uint8_t recv_buf[65535]; + bool fin = false; + uint64_t err_code = 0; + ssize_t recv_bytes = quiche_conn_stream_recv(conn, s, recv_buf, sizeof(recv_buf), &fin, &err_code); + if (recv_bytes > 0) { + client->total_bytes += recv_bytes; + } + if (fin) { + struct timespec end; + clock_gettime(CLOCK_MONOTONIC, &end); + double time_taken = (end.tv_sec - client->start_time.tv_sec) + (end.tv_nsec - client->start_time.tv_nsec) / 1e9; + double mb = client->total_bytes / (1024.0 * 1024.0); + double throughput = mb / time_taken; + + if (!done_printing) { + printf("Received %.2f MB in %.2f seconds.\n", mb, time_taken); + printf("Throughput: %.2f MB/s\n", throughput); + done_printing = true; + } + } + } + quiche_stream_iter_free(readable); + } + + while (1) { + quiche_send_info send_info; + ssize_t written = quiche_conn_send(conn, out, sizeof(out), &send_info); + if (written == QUICHE_ERR_DONE) break; + if (written < 0) break; + sendto(sock, out, written, 0, (struct sockaddr *)&send_info.to, send_info.to_len); + } + + quiche_conn_on_timeout(conn); + } + usleep(100); + } + + quiche_config_free(config); + return 0; +} \ No newline at end of file diff --git a/network/tcpquiclab/quic_server b/network/tcpquiclab/quic_server new file mode 100755 index 0000000..40dae07 Binary files /dev/null and b/network/tcpquiclab/quic_server differ diff --git a/network/tcpquiclab/quic_server.c b/network/tcpquiclab/quic_server.c new file mode 100644 index 0000000..02dca5f --- /dev/null +++ b/network/tcpquiclab/quic_server.c @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOCAL_CONN_ID_LEN 16 +#define MAX_DATAGRAM_SIZE 1350 + +typedef struct { + int sock; + struct sockaddr_storage peer_addr; + socklen_t peer_addr_len; + quiche_conn *conn; +} Client; + +int main(int argc, char *argv[]) { + quiche_config *config = quiche_config_new(QUICHE_PROTOCOL_VERSION); + if (config == NULL) { + fprintf(stderr, "failed to create config\n"); + return -1; + } + + quiche_config_load_cert_chain_from_pem_file(config, "cert.crt"); + quiche_config_load_priv_key_from_pem_file(config, "cert.key"); + + quiche_config_set_application_protos(config, (uint8_t *) "\x0ahq-interop\x05hq-29\x05hq-28\x05hq-27\x08http/0.9", 38); + quiche_config_set_max_idle_timeout(config, 5000); + quiche_config_set_max_recv_udp_payload_size(config, MAX_DATAGRAM_SIZE); + quiche_config_set_max_send_udp_payload_size(config, MAX_DATAGRAM_SIZE); + quiche_config_set_initial_max_data(config, 10000000); + quiche_config_set_initial_max_stream_data_bidi_local(config, 1000000); + quiche_config_set_initial_max_stream_data_bidi_remote(config, 1000000); + quiche_config_set_initial_max_streams_bidi(config, 100); + quiche_config_set_cc_algorithm(config, QUICHE_CC_RENO); + + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_port = htons(8888); + sa.sin_addr.s_addr = INADDR_ANY; + + int sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + perror("socket"); + return -1; + } + + if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) { + perror("bind"); + return -1; + } + + int flags = fcntl(sock, F_GETFL, 0); + fcntl(sock, F_SETFL, flags | O_NONBLOCK); + + printf("QUIC Server listening on port 8888\n"); + + Client *client = NULL; + uint8_t buf[65535]; + uint8_t out[MAX_DATAGRAM_SIZE]; + + while (1) { + struct sockaddr_storage peer_addr; + socklen_t peer_addr_len = sizeof(peer_addr); + ssize_t read_len = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&peer_addr, &peer_addr_len); + + if (read_len < 0) { + if (errno != EWOULDBLOCK && errno != EAGAIN) { + perror("recvfrom"); + break; + } + } else { + uint8_t type; + uint32_t version; + uint8_t scid[QUICHE_MAX_CONN_ID_LEN]; + size_t scid_len = sizeof(scid); + uint8_t dcid[QUICHE_MAX_CONN_ID_LEN]; + size_t dcid_len = sizeof(dcid); + uint8_t token[256]; + size_t token_len = sizeof(token); + + int rc = quiche_header_info(buf, read_len, LOCAL_CONN_ID_LEN, &version, &type, scid, &scid_len, dcid, &dcid_len, token, &token_len); + + if (rc >= 0) { + if (client == NULL) { + if (!quiche_version_is_supported(version)) { + ssize_t written = quiche_negotiate_version(scid, scid_len, dcid, dcid_len, out, sizeof(out)); + if (written > 0) sendto(sock, out, written, 0, (struct sockaddr *)&peer_addr, peer_addr_len); + } else if (token_len == 0) { + uint8_t new_scid[QUICHE_MAX_CONN_ID_LEN]; + int rng = open("/dev/urandom", O_RDONLY); + if (rng >= 0) { + read(rng, new_scid, sizeof(new_scid)); + close(rng); + } + ssize_t written = quiche_retry(scid, scid_len, dcid, dcid_len, new_scid, sizeof(new_scid), token, token_len, version, out, sizeof(out)); + if (written > 0) sendto(sock, out, written, 0, (struct sockaddr *)&peer_addr, peer_addr_len); + } else { + client = malloc(sizeof(Client)); + client->sock = sock; + client->peer_addr = peer_addr; + client->peer_addr_len = peer_addr_len; + + uint8_t server_scid[QUICHE_MAX_CONN_ID_LEN]; + int rng = open("/dev/urandom", O_RDONLY); + if (rng >= 0) { + read(rng, server_scid, sizeof(server_scid)); + close(rng); + } + + client->conn = quiche_accept(server_scid, sizeof(server_scid), dcid, dcid_len, (struct sockaddr *)&sa, sizeof(sa), (struct sockaddr *)&peer_addr, peer_addr_len, config); + printf("New connection accepted.\n"); + } + } + + if (client != NULL) { + quiche_conn_recv(client->conn, buf, read_len, &(quiche_recv_info){ + .to = (struct sockaddr *)&sa, + .to_len = sizeof(sa), + .from = (struct sockaddr *)&peer_addr, + .from_len = peer_addr_len, + }); + } + } + } + + if (client != NULL) { + quiche_conn *conn = client->conn; + + if (quiche_conn_is_closed(conn)) { + printf("Connection closed.\n"); + quiche_conn_free(conn); + free(client); + client = NULL; + continue; + } + + if (quiche_conn_is_established(conn)) { + uint64_t s = 0; + quiche_stream_iter *readable = quiche_conn_readable(conn); + while (quiche_stream_iter_next(readable, &s)) { + uint8_t recv_buf[1024]; + bool fin = false; + uint64_t err_code = 0; + ssize_t recv_bytes = quiche_conn_stream_recv(conn, s, recv_buf, sizeof(recv_buf), &fin, &err_code); + if (recv_bytes > 0) { + printf("Received %zd bytes on stream %lu: %.*s\n", recv_bytes, s, (int)recv_bytes, recv_buf); + char resp[1200]; + snprintf(resp, sizeof(resp), "Server received: %.*s", (int)recv_bytes, recv_buf); + quiche_conn_stream_send(conn, s, (uint8_t*)resp, strlen(resp), true, &err_code); + } + } + quiche_stream_iter_free(readable); + } + + while (1) { + quiche_send_info send_info; + ssize_t written = quiche_conn_send(conn, out, sizeof(out), &send_info); + if (written == QUICHE_ERR_DONE) break; + if (written < 0) break; + sendto(sock, out, written, 0, (struct sockaddr *)&send_info.to, send_info.to_len); + } + + quiche_conn_on_timeout(conn); + } + usleep(1000); + } + + quiche_config_free(config); + return 0; +} \ No newline at end of file diff --git a/network/tcpquiclab/quiche.h b/network/tcpquiclab/quiche.h new file mode 100644 index 0000000..a5ed358 --- /dev/null +++ b/network/tcpquiclab/quiche.h @@ -0,0 +1,1196 @@ +// Copyright (C) 2018-2019, Cloudflare, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef QUICHE_H +#define QUICHE_H + +#include +#include +#include + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) +#include +#include +#include +#else +#include +#include +#endif + +#ifdef __unix__ +#include +#endif +#ifdef _MSC_VER +#include +#define ssize_t SSIZE_T +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +// QUIC transport API. +// + +// The current QUIC wire version. +#define QUICHE_PROTOCOL_VERSION 0x00000001 + +// The maximum length of a connection ID. +#define QUICHE_MAX_CONN_ID_LEN 20 + +// The minimum length of Initial packets sent by a client. +#define QUICHE_MIN_CLIENT_INITIAL_LEN 1200 + +enum quiche_error { + // There is no more work to do. + QUICHE_ERR_DONE = -1, + + // The provided buffer is too short. + QUICHE_ERR_BUFFER_TOO_SHORT = -2, + + // The provided packet cannot be parsed because its version is unknown. + QUICHE_ERR_UNKNOWN_VERSION = -3, + + // The provided packet cannot be parsed because it contains an invalid + // frame. + QUICHE_ERR_INVALID_FRAME = -4, + + // The provided packet cannot be parsed. + QUICHE_ERR_INVALID_PACKET = -5, + + // The operation cannot be completed because the connection is in an + // invalid state. + QUICHE_ERR_INVALID_STATE = -6, + + // The operation cannot be completed because the stream is in an + // invalid state. + QUICHE_ERR_INVALID_STREAM_STATE = -7, + + // The peer's transport params cannot be parsed. + QUICHE_ERR_INVALID_TRANSPORT_PARAM = -8, + + // A cryptographic operation failed. + QUICHE_ERR_CRYPTO_FAIL = -9, + + // The TLS handshake failed. + QUICHE_ERR_TLS_FAIL = -10, + + // The peer violated the local flow control limits. + QUICHE_ERR_FLOW_CONTROL = -11, + + // The peer violated the local stream limits. + QUICHE_ERR_STREAM_LIMIT = -12, + + // The specified stream was stopped by the peer. + QUICHE_ERR_STREAM_STOPPED = -15, + + // The specified stream was reset by the peer. + QUICHE_ERR_STREAM_RESET = -16, + + // The received data exceeds the stream's final size. + QUICHE_ERR_FINAL_SIZE = -13, + + // Error in congestion control. + QUICHE_ERR_CONGESTION_CONTROL = -14, + + // Too many identifiers were provided. + QUICHE_ERR_ID_LIMIT = -17, + + // Not enough available identifiers. + QUICHE_ERR_OUT_OF_IDENTIFIERS = -18, + + // Error in key update. + QUICHE_ERR_KEY_UPDATE = -19, + + // The peer sent more data in CRYPTO frames than we can buffer. + QUICHE_ERR_CRYPTO_BUFFER_EXCEEDED = -20, + + // The peer sent an ACK frame with an invalid range. + QUICHE_ERR_INVALID_ACK_RANGE = -21, + + // The peer send an ACK frame for a skipped packet used for Optimistic ACK + // mitigation. + QUICHE_ERR_OPTIMISTIC_ACK_DETECTED = -22, +}; + +// Returns a human readable string with the quiche version number. +const char *quiche_version(void); + +// Enables logging. |cb| will be called with log messages +int quiche_enable_debug_logging(void (*cb)(const char *line, void *argp), + void *argp); + +// Stores configuration shared between multiple connections. +typedef struct quiche_config quiche_config; + +// Creates a config object with the given version. +quiche_config *quiche_config_new(uint32_t version); + +// Configures the given certificate chain. +int quiche_config_load_cert_chain_from_pem_file(quiche_config *config, + const char *path); + +// Configures the given private key. +int quiche_config_load_priv_key_from_pem_file(quiche_config *config, + const char *path); + +// Specifies a file where trusted CA certificates are stored for the purposes of certificate verification. +int quiche_config_load_verify_locations_from_file(quiche_config *config, + const char *path); + +// Specifies a directory where trusted CA certificates are stored for the purposes of certificate verification. +int quiche_config_load_verify_locations_from_directory(quiche_config *config, + const char *path); + +// Configures whether to verify the peer's certificate. +void quiche_config_verify_peer(quiche_config *config, bool v); + +// Configures whether to send GREASE. +void quiche_config_grease(quiche_config *config, bool v); + +// Configures whether to do path MTU discovery. +void quiche_config_discover_pmtu(quiche_config *config, bool v); + +// Enables logging of secrets. +void quiche_config_log_keys(quiche_config *config); + +// Enables sending or receiving early data. +void quiche_config_enable_early_data(quiche_config *config); + +// Configures the list of supported application protocols. +int quiche_config_set_application_protos(quiche_config *config, + const uint8_t *protos, + size_t protos_len); + +// Sets the anti-amplification limit factor. +void quiche_config_set_max_amplification_factor(quiche_config *config, size_t v); + +// Sets the `max_idle_timeout` transport parameter, in milliseconds, default is +// no timeout. +void quiche_config_set_max_idle_timeout(quiche_config *config, uint64_t v); + +// Sets the `max_udp_payload_size transport` parameter. +void quiche_config_set_max_recv_udp_payload_size(quiche_config *config, size_t v); + +// Sets the maximum outgoing UDP payload size. +void quiche_config_set_max_send_udp_payload_size(quiche_config *config, size_t v); + +// Sets the `initial_max_data` transport parameter. +void quiche_config_set_initial_max_data(quiche_config *config, uint64_t v); + +// Sets the `initial_max_stream_data_bidi_local` transport parameter. +void quiche_config_set_initial_max_stream_data_bidi_local(quiche_config *config, uint64_t v); + +// Sets the `initial_max_stream_data_bidi_remote` transport parameter. +void quiche_config_set_initial_max_stream_data_bidi_remote(quiche_config *config, uint64_t v); + +// Sets the `initial_max_stream_data_uni` transport parameter. +void quiche_config_set_initial_max_stream_data_uni(quiche_config *config, uint64_t v); + +// Sets the `initial_max_streams_bidi` transport parameter. +void quiche_config_set_initial_max_streams_bidi(quiche_config *config, uint64_t v); + +// Sets the `initial_max_streams_uni` transport parameter. +void quiche_config_set_initial_max_streams_uni(quiche_config *config, uint64_t v); + +// Sets the `ack_delay_exponent` transport parameter. +void quiche_config_set_ack_delay_exponent(quiche_config *config, uint64_t v); + +// Sets the `max_ack_delay` transport parameter. +void quiche_config_set_max_ack_delay(quiche_config *config, uint64_t v); + +// Sets the `disable_active_migration` transport parameter. +void quiche_config_set_disable_active_migration(quiche_config *config, bool v); + +// Sets the congestion control algorithm used by string. +int quiche_config_set_cc_algorithm_name(quiche_config *config, const char *algo); + +// Sets the initial cwnd for the connection in terms of packet count. +void quiche_config_set_initial_congestion_window_packets(quiche_config *config, size_t packets); + +enum quiche_cc_algorithm { + QUICHE_CC_RENO = 0, + QUICHE_CC_CUBIC = 1, + QUICHE_CC_BBR = 2, + QUICHE_CC_BBR2 = 3, +}; + +// Sets the congestion control algorithm used. +void quiche_config_set_cc_algorithm(quiche_config *config, enum quiche_cc_algorithm algo); + +// Configures whether to use HyStart++. +void quiche_config_enable_hystart(quiche_config *config, bool v); + +// Configures whether to enable pacing (enabled by default). +void quiche_config_enable_pacing(quiche_config *config, bool v); + +// Configures max pacing rate to be used. +void quiche_config_set_max_pacing_rate(quiche_config *config, uint64_t v); + +// Configures whether to enable receiving DATAGRAM frames. +void quiche_config_enable_dgram(quiche_config *config, bool enabled, + size_t recv_queue_len, + size_t send_queue_len); + +// Sets the maximum connection window. +void quiche_config_set_max_connection_window(quiche_config *config, uint64_t v); + +// Sets the maximum stream window. +void quiche_config_set_max_stream_window(quiche_config *config, uint64_t v); + +// Sets the limit of active connection IDs. +void quiche_config_set_active_connection_id_limit(quiche_config *config, uint64_t v); + +// Sets the initial stateless reset token. |v| must contain 16 bytes, otherwise the behaviour is undefined. +void quiche_config_set_stateless_reset_token(quiche_config *config, const uint8_t *v); + +// Sets whether the QUIC connection should avoid reusing DCIDs over different paths. +void quiche_config_set_disable_dcid_reuse(quiche_config *config, bool v); + +// Configures the session ticket key material. +int quiche_config_set_ticket_key(quiche_config *config, const uint8_t *key, size_t key_len); + +// Frees the config object. +void quiche_config_free(quiche_config *config); + +// Extracts version, type, source / destination connection ID and address +// verification token from the packet in |buf|. +int quiche_header_info(const uint8_t *buf, size_t buf_len, size_t dcil, + uint32_t *version, uint8_t *type, + uint8_t *scid, size_t *scid_len, + uint8_t *dcid, size_t *dcid_len, + uint8_t *token, size_t *token_len); + +// A QUIC connection. +typedef struct quiche_conn quiche_conn; + +// Creates a new server-side connection. +quiche_conn *quiche_accept(const uint8_t *scid, size_t scid_len, + const uint8_t *odcid, size_t odcid_len, + const struct sockaddr *local, socklen_t local_len, + const struct sockaddr *peer, socklen_t peer_len, + quiche_config *config); + +// Creates a new client-side connection. +quiche_conn *quiche_connect(const char *server_name, + const uint8_t *scid, size_t scid_len, + const struct sockaddr *local, socklen_t local_len, + const struct sockaddr *peer, socklen_t peer_len, + quiche_config *config); + +// Writes a version negotiation packet. +ssize_t quiche_negotiate_version(const uint8_t *scid, size_t scid_len, + const uint8_t *dcid, size_t dcid_len, + uint8_t *out, size_t out_len); + +// Writes a retry packet. +ssize_t quiche_retry(const uint8_t *scid, size_t scid_len, + const uint8_t *dcid, size_t dcid_len, + const uint8_t *new_scid, size_t new_scid_len, + const uint8_t *token, size_t token_len, + uint32_t version, uint8_t *out, size_t out_len); + +// Returns true if the given protocol version is supported. +bool quiche_version_is_supported(uint32_t version); + +quiche_conn *quiche_conn_new_with_tls(const uint8_t *scid, size_t scid_len, + const uint8_t *odcid, size_t odcid_len, + const struct sockaddr *local, socklen_t local_len, + const struct sockaddr *peer, socklen_t peer_len, + const quiche_config *config, void *ssl, + bool is_server); + +// Enables keylog to the specified file path. Returns true on success. +bool quiche_conn_set_keylog_path(quiche_conn *conn, const char *path); + +// Enables keylog to the specified file descriptor. Unix only. +void quiche_conn_set_keylog_fd(quiche_conn *conn, int fd); + +// Enables qlog to the specified file path. Returns true on success. +bool quiche_conn_set_qlog_path(quiche_conn *conn, const char *path, + const char *log_title, const char *log_desc); + +// Enables qlog to the specified file descriptor. Unix only. +void quiche_conn_set_qlog_fd(quiche_conn *conn, int fd, const char *log_title, + const char *log_desc); + +// Configures the given session for resumption. +int quiche_conn_set_session(quiche_conn *conn, const uint8_t *buf, size_t buf_len); + +// Sets the `max_idle_timeout` transport parameter, in milliseconds, default is +// no timeout. +int quiche_conn_set_max_idle_timeout(quiche_conn *conn, uint64_t v); + +typedef struct { + // The remote address the packet was received from. + struct sockaddr *from; + socklen_t from_len; + + // The local address the packet was received on. + struct sockaddr *to; + socklen_t to_len; +} quiche_recv_info; + +// Processes QUIC packets received from the peer. +ssize_t quiche_conn_recv(quiche_conn *conn, uint8_t *buf, size_t buf_len, + const quiche_recv_info *info); + +typedef struct { + // The local address the packet should be sent from. + struct sockaddr_storage from; + socklen_t from_len; + + // The remote address the packet should be sent to. + struct sockaddr_storage to; + socklen_t to_len; + + // The time to send the packet out. + struct timespec at; +} quiche_send_info; + +// Writes a single QUIC packet to be sent to the peer. +ssize_t quiche_conn_send(quiche_conn *conn, uint8_t *out, size_t out_len, + quiche_send_info *out_info); + +// Returns the size of the send quantum, in bytes. +size_t quiche_conn_send_quantum(const quiche_conn *conn); + +// Writes a single QUIC packet to be sent to the peer from the specified +// local address "from" to the destination address "to". +ssize_t quiche_conn_send_on_path(quiche_conn *conn, uint8_t *out, size_t out_len, + const struct sockaddr *from, socklen_t from_len, + const struct sockaddr *to, socklen_t to_len, + quiche_send_info *out_info); + +// Returns the size of the send quantum over the given 4-tuple, in bytes. +size_t quiche_conn_send_quantum_on_path(const quiche_conn *conn, + const struct sockaddr *local_addr, socklen_t local_len, + const struct sockaddr *peer_addr, socklen_t peer_len); + + +// Reads contiguous data from a stream. +// out_error_code is only set when STREAM_STOPPED or STREAM_RESET are returned. +// Set to the reported error code associated with STOP_SENDING or STREAM_RESET. +ssize_t quiche_conn_stream_recv(quiche_conn *conn, uint64_t stream_id, + uint8_t *out, size_t buf_len, bool *fin, + uint64_t *out_error_code); + +// Writes data to a stream. +// out_error_code is only set when STREAM_STOPPED or STREAM_RESET are returned. +// Set to the reported error code associated with STOP_SENDING or STREAM_RESET. +ssize_t quiche_conn_stream_send(quiche_conn *conn, uint64_t stream_id, + const uint8_t *buf, size_t buf_len, bool fin, + uint64_t *out_error_code); + +// The side of the stream to be shut down. +enum quiche_shutdown { + QUICHE_SHUTDOWN_READ = 0, + QUICHE_SHUTDOWN_WRITE = 1, +}; + +// Sets the priority for a stream. +int quiche_conn_stream_priority(quiche_conn *conn, uint64_t stream_id, + uint8_t urgency, bool incremental); + +// Shuts down reading or writing from/to the specified stream. +int quiche_conn_stream_shutdown(quiche_conn *conn, uint64_t stream_id, + enum quiche_shutdown direction, uint64_t err); + +// Returns the stream's send capacity in bytes. +ssize_t quiche_conn_stream_capacity(const quiche_conn *conn, uint64_t stream_id); + +// Returns true if the stream has data that can be read. +bool quiche_conn_stream_readable(const quiche_conn *conn, uint64_t stream_id); + +// Returns the next stream that has data to read, or -1 if no such stream is +// available. +int64_t quiche_conn_stream_readable_next(quiche_conn *conn); + +// Returns true if the stream has enough send capacity. +// +// On error a value lower than 0 is returned. +int quiche_conn_stream_writable(quiche_conn *conn, uint64_t stream_id, size_t len); + +// Returns the next stream that can be written to, or -1 if no such stream is +// available. +int64_t quiche_conn_stream_writable_next(quiche_conn *conn); + +// Returns true if all the data has been read from the specified stream. +bool quiche_conn_stream_finished(const quiche_conn *conn, uint64_t stream_id); + +typedef struct quiche_stream_iter quiche_stream_iter; + +// Returns an iterator over streams that have outstanding data to read. +quiche_stream_iter *quiche_conn_readable(const quiche_conn *conn); + +// Returns an iterator over streams that can be written to. +quiche_stream_iter *quiche_conn_writable(const quiche_conn *conn); + +// Returns the maximum possible size of egress UDP payloads. +size_t quiche_conn_max_send_udp_payload_size(const quiche_conn *conn); + +// Returns the amount of time until the next timeout event, in nanoseconds. +uint64_t quiche_conn_timeout_as_nanos(const quiche_conn *conn); + +// Returns the amount of time until the next timeout event, in milliseconds. +uint64_t quiche_conn_timeout_as_millis(const quiche_conn *conn); + +// Processes a timeout event. +void quiche_conn_on_timeout(quiche_conn *conn); + +// Closes the connection with the given error and reason. +int quiche_conn_close(quiche_conn *conn, bool app, uint64_t err, + const uint8_t *reason, size_t reason_len); + +// Returns a string uniquely representing the connection. +void quiche_conn_trace_id(const quiche_conn *conn, const uint8_t **out, size_t *out_len); + +// Returns the source connection ID. +void quiche_conn_source_id(const quiche_conn *conn, const uint8_t **out, size_t *out_len); + +typedef struct quiche_connection_id_iter quiche_connection_id_iter; + +// Returns all active source connection IDs. +quiche_connection_id_iter *quiche_conn_source_ids(quiche_conn *conn); + +// Fetches the next id from the given iterator. Returns false if there are +// no more elements in the iterator. +bool quiche_connection_id_iter_next(quiche_connection_id_iter *iter, const uint8_t **out, size_t *out_len); + +// Frees the given path iterator object. +void quiche_connection_id_iter_free(quiche_connection_id_iter *iter); + +// Returns the destination connection ID. +void quiche_conn_destination_id(const quiche_conn *conn, const uint8_t **out, size_t *out_len); + +// Returns the negotiated ALPN protocol. +void quiche_conn_application_proto(const quiche_conn *conn, const uint8_t **out, + size_t *out_len); + +// Returns the peer's leaf certificate (if any) as a DER-encoded buffer. +void quiche_conn_peer_cert(const quiche_conn *conn, const uint8_t **out, size_t *out_len); + +// Returns the serialized cryptographic session for the connection. +void quiche_conn_session(const quiche_conn *conn, const uint8_t **out, size_t *out_len); + +// Returns the server name requested by the client. +void quiche_conn_server_name(const quiche_conn *conn, const uint8_t **out, size_t *out_len); + +// Returns true if the connection handshake is complete. +bool quiche_conn_is_established(const quiche_conn *conn); + +// Returns true if the connection is resumed. +bool quiche_conn_is_resumed(const quiche_conn *conn); + +// Returns true if the connection has a pending handshake that has progressed +// enough to send or receive early data. +bool quiche_conn_is_in_early_data(const quiche_conn *conn); + +// Returns whether there is stream or DATAGRAM data available to read. +bool quiche_conn_is_readable(const quiche_conn *conn); + +// Returns true if the connection is draining. +bool quiche_conn_is_draining(const quiche_conn *conn); + +// Returns the number of bidirectional streams that can be created +// before the peer's stream count limit is reached. +uint64_t quiche_conn_peer_streams_left_bidi(const quiche_conn *conn); + +// Returns the number of unidirectional streams that can be created +// before the peer's stream count limit is reached. +uint64_t quiche_conn_peer_streams_left_uni(const quiche_conn *conn); + +// Returns true if the connection is closed. +bool quiche_conn_is_closed(const quiche_conn *conn); + +// Returns true if the connection was closed due to the idle timeout. +bool quiche_conn_is_timed_out(const quiche_conn *conn); + +// Returns true if a connection error was received, and updates the provided +// parameters accordingly. +bool quiche_conn_peer_error(const quiche_conn *conn, + bool *is_app, + uint64_t *error_code, + const uint8_t **reason, + size_t *reason_len); + +// Returns true if a connection error was queued or sent, and updates the provided +// parameters accordingly. +bool quiche_conn_local_error(const quiche_conn *conn, + bool *is_app, + uint64_t *error_code, + const uint8_t **reason, + size_t *reason_len); + +// Fetches the next stream from the given iterator. Returns false if there are +// no more elements in the iterator. +bool quiche_stream_iter_next(quiche_stream_iter *iter, uint64_t *stream_id); + +// Frees the given stream iterator object. +void quiche_stream_iter_free(quiche_stream_iter *iter); + +typedef struct { + // The number of QUIC packets received on this connection. + size_t recv; + + // The number of QUIC packets sent on this connection. + size_t sent; + + // The number of QUIC packets that were lost. + size_t lost; + + // The number of sent QUIC packets with retransmitted data. + size_t retrans; + + // The number of sent bytes. + uint64_t sent_bytes; + + // The number of received bytes. + uint64_t recv_bytes; + + // The number of bytes acked. + uint64_t acked_bytes; + + // The number of bytes lost. + uint64_t lost_bytes; + + // The number of stream bytes retransmitted. + uint64_t stream_retrans_bytes; + + // The number of known paths for the connection. + size_t paths_count; + + // The number of streams reset by local. + uint64_t reset_stream_count_local; + + // The number of streams stopped by local. + uint64_t stopped_stream_count_local; + + // The number of streams reset by remote. + uint64_t reset_stream_count_remote; + + // The number of streams stopped by remote. + uint64_t stopped_stream_count_remote; +} quiche_stats; + +// Collects and returns statistics about the connection. +void quiche_conn_stats(const quiche_conn *conn, quiche_stats *out); + +typedef struct { + // The maximum idle timeout. + uint64_t peer_max_idle_timeout; + + // The maximum UDP payload size. + uint64_t peer_max_udp_payload_size; + + // The initial flow control maximum data for the connection. + uint64_t peer_initial_max_data; + + // The initial flow control maximum data for local bidirectional streams. + uint64_t peer_initial_max_stream_data_bidi_local; + + // The initial flow control maximum data for remote bidirectional streams. + uint64_t peer_initial_max_stream_data_bidi_remote; + + // The initial flow control maximum data for unidirectional streams. + uint64_t peer_initial_max_stream_data_uni; + + // The initial maximum bidirectional streams. + uint64_t peer_initial_max_streams_bidi; + + // The initial maximum unidirectional streams. + uint64_t peer_initial_max_streams_uni; + + // The ACK delay exponent. + uint64_t peer_ack_delay_exponent; + + // The max ACK delay. + uint64_t peer_max_ack_delay; + + // Whether active migration is disabled. + bool peer_disable_active_migration; + + // The active connection ID limit. + uint64_t peer_active_conn_id_limit; + + // DATAGRAM frame extension parameter, if any. + ssize_t peer_max_datagram_frame_size; +} quiche_transport_params; + +// Returns the peer's transport parameters in |out|. Returns false if we have +// not yet processed the peer's transport parameters. +bool quiche_conn_peer_transport_params(const quiche_conn *conn, quiche_transport_params *out); + +typedef struct { + // The local address used by this path. + struct sockaddr_storage local_addr; + socklen_t local_addr_len; + + // The peer address seen by this path. + struct sockaddr_storage peer_addr; + socklen_t peer_addr_len; + + // The validation state of the path. + ssize_t validation_state; + + // Whether this path is active. + bool active; + + // The number of QUIC packets received on this path. + size_t recv; + + // The number of QUIC packets sent on this path. + size_t sent; + + // The number of QUIC packets that were lost on this path. + size_t lost; + + // The number of sent QUIC packets with retransmitted data on this path. + size_t retrans; + + // The estimated round-trip time of the path (in nanoseconds). + uint64_t rtt; + + // The minimum round-trip time observed (in nanoseconds). + uint64_t min_rtt; + + // The estimated round-trip time variation (in nanoseconds). + uint64_t rttvar; + + // The size of the path's congestion window in bytes. + size_t cwnd; + + // The number of sent bytes on this path. + uint64_t sent_bytes; + + // The number of received bytes on this path. + uint64_t recv_bytes; + + // The number of bytes lost on this path. + uint64_t lost_bytes; + + // The number of stream bytes retransmitted on this path. + uint64_t stream_retrans_bytes; + + // The current PMTU for the path. + size_t pmtu; + + // The most recent data delivery rate estimate in bytes/s. + uint64_t delivery_rate; +} quiche_path_stats; + + +// Collects and returns statistics about the specified path for the connection. +// +// The `idx` argument represent the path's index (also see the `paths_count` +// field of `quiche_stats`). +int quiche_conn_path_stats(const quiche_conn *conn, size_t idx, quiche_path_stats *out); + +// Returns whether or not this is a server-side connection. +bool quiche_conn_is_server(const quiche_conn *conn); + +// Returns the maximum DATAGRAM payload that can be sent. +ssize_t quiche_conn_dgram_max_writable_len(const quiche_conn *conn); + +// Returns the length of the first stored DATAGRAM. +ssize_t quiche_conn_dgram_recv_front_len(const quiche_conn *conn); + +// Returns the number of items in the DATAGRAM receive queue. +ssize_t quiche_conn_dgram_recv_queue_len(const quiche_conn *conn); + +// Returns the total size of all items in the DATAGRAM receive queue. +ssize_t quiche_conn_dgram_recv_queue_byte_size(const quiche_conn *conn); + +// Returns the number of items in the DATAGRAM send queue. +ssize_t quiche_conn_dgram_send_queue_len(const quiche_conn *conn); + +// Returns the total size of all items in the DATAGRAM send queue. +ssize_t quiche_conn_dgram_send_queue_byte_size(const quiche_conn *conn); + +// Reads the first received DATAGRAM. +ssize_t quiche_conn_dgram_recv(quiche_conn *conn, uint8_t *buf, + size_t buf_len); + +// Sends data in a DATAGRAM frame. +ssize_t quiche_conn_dgram_send(quiche_conn *conn, const uint8_t *buf, + size_t buf_len); + +// Purges queued outgoing DATAGRAMs matching the predicate. +void quiche_conn_dgram_purge_outgoing(quiche_conn *conn, + bool (*f)(uint8_t *, size_t)); + +// Returns whether or not the DATAGRAM send queue is full. +bool quiche_conn_is_dgram_send_queue_full(const quiche_conn *conn); + +// Returns whether or not the DATAGRAM recv queue is full. +bool quiche_conn_is_dgram_recv_queue_full(const quiche_conn *conn); + +// Schedule an ack-eliciting packet on the active path. +ssize_t quiche_conn_send_ack_eliciting(quiche_conn *conn); + +// Schedule an ack-eliciting packet on the specified path. +ssize_t quiche_conn_send_ack_eliciting_on_path(quiche_conn *conn, + const struct sockaddr *local, socklen_t local_len, + const struct sockaddr *peer, socklen_t peer_len); + +// Returns true if there are retired source connection ids and fill the parameters +bool quiche_conn_retired_scid_next(const quiche_conn *conn, const uint8_t **out, size_t *out_len); + +// Returns the number of source Connection IDs that are retired. +size_t quiche_conn_retired_scids(const quiche_conn *conn); + +// Returns the number of spare Destination Connection IDs, i.e., +// Destination Connection IDs that are still unused. +size_t quiche_conn_available_dcids(const quiche_conn *conn); + +// Returns the number of source Connection IDs that should be provided +// to the peer without exceeding the limit it advertised. +size_t quiche_conn_scids_left(quiche_conn *conn); + +// Returns the number of source Connection IDs that are active. This is +// only meaningful if the host uses non-zero length Source Connection IDs. +size_t quiche_conn_active_scids(quiche_conn *conn); + +// Provides additional source Connection IDs that the peer can use to reach +// this host. Writes the sequence number to "scid_seq" and returns 0. +int quiche_conn_new_scid(quiche_conn *conn, + const uint8_t *scid, size_t scid_len, + const uint8_t *reset_token, bool retire_if_needed, uint64_t *scid_seq); + +// Requests the stack to perform path validation of the proposed 4-tuple. +int quiche_conn_probe_path(quiche_conn *conn, + const struct sockaddr *local, socklen_t local_len, + const struct sockaddr *peer, socklen_t peer_len, uint64_t *seq); + +// Migrates the connection to a new local address. +int quiche_conn_migrate_source(quiche_conn *conn, const struct sockaddr *local, socklen_t local_len, uint64_t *seq); + +// Migrates the connection over the given network path between "local" +// and "peer". +int quiche_conn_migrate(quiche_conn *conn, + const struct sockaddr *local, socklen_t local_len, + const struct sockaddr *peer, socklen_t peer_len, + uint64_t *seq); + +enum quiche_path_event_type { + QUICHE_PATH_EVENT_NEW, + QUICHE_PATH_EVENT_VALIDATED, + QUICHE_PATH_EVENT_FAILED_VALIDATION, + QUICHE_PATH_EVENT_CLOSED, + QUICHE_PATH_EVENT_REUSED_SOURCE_CONNECTION_ID, + QUICHE_PATH_EVENT_PEER_MIGRATED, +}; + +typedef struct quiche_path_event quiche_path_event; + +// Retrieves the next event. Returns NULL if there is no event to process. +quiche_path_event *quiche_conn_path_event_next(quiche_conn *conn); + +// Returns the type of the event. +enum quiche_path_event_type quiche_path_event_type(const quiche_path_event *ev); + +// Should be called if the quiche_path_event_type(...) returns QUICHE_PATH_EVENT_NEW. +void quiche_path_event_new(const quiche_path_event *ev, + struct sockaddr_storage *local, socklen_t *local_len, struct sockaddr_storage *peer, socklen_t *peer_len); + +// Should be called if the quiche_path_event_type(...) returns QUICHE_PATH_EVENT_VALIDATED. +void quiche_path_event_validated(const quiche_path_event *ev, + struct sockaddr_storage *local, socklen_t *local_len, struct sockaddr_storage *peer, socklen_t *peer_len); + +// Should be called if the quiche_path_event_type(...) returns QUICHE_PATH_EVENT_FAILED_VALIDATION. +void quiche_path_event_failed_validation(const quiche_path_event *ev, + struct sockaddr_storage *local, socklen_t *local_len, struct sockaddr_storage *peer, socklen_t *peer_len); + +// Should be called if the quiche_path_event_type(...) returns QUICHE_PATH_EVENT_CLOSED. +void quiche_path_event_closed(const quiche_path_event *ev, + struct sockaddr_storage *local, socklen_t *local_len, struct sockaddr_storage *peer, socklen_t *peer_len); + +// Should be called if the quiche_path_event_type(...) returns QUICHE_PATH_EVENT_REUSED_SOURCE_CONNECTION_ID. +void quiche_path_event_reused_source_connection_id(const quiche_path_event *ev, uint64_t *id, + struct sockaddr_storage *old_local, socklen_t *old_local_len, + struct sockaddr_storage *old_peer, socklen_t *old_peer_len, + struct sockaddr_storage *local, socklen_t *local_len, + struct sockaddr_storage *peer, socklen_t *peer_len); + +// Should be called if the quiche_path_event_type(...) returns QUICHE_PATH_EVENT_PEER_MIGRATED. +void quiche_path_event_peer_migrated(const quiche_path_event *ev, + struct sockaddr_storage *local, socklen_t *local_len, + struct sockaddr_storage *peer, socklen_t *peer_len); + +// Frees the path event object. +void quiche_path_event_free(quiche_path_event *ev); + +// Requests the retirement of the destination Connection ID used by the +// host to reach its peer. +int quiche_conn_retire_dcid(quiche_conn *conn, uint64_t dcid_seq); + +typedef struct quiche_socket_addr_iter quiche_socket_addr_iter; + +// Returns an iterator over destination `SockAddr`s whose association +// with "from" forms a known QUIC path on which packets can be sent to. +quiche_socket_addr_iter *quiche_conn_paths_iter(quiche_conn *conn, const struct sockaddr *from, size_t from_len); + +// Fetches the next peer from the given iterator. Returns false if there are +// no more elements in the iterator. +bool quiche_socket_addr_iter_next(quiche_socket_addr_iter *iter, struct sockaddr_storage *peer, size_t *peer_len); + +// Frees the given path iterator object. +void quiche_socket_addr_iter_free(quiche_socket_addr_iter *iter); + +// Returns whether the network path with local address "from and remote address "to" has been validated. +// If the 4-tuple does not exist over the connection, returns an InvalidState. +int quiche_conn_is_path_validated(const quiche_conn *conn, const struct sockaddr *from, size_t from_len, const struct sockaddr *to, size_t to_len); + +// Frees the connection object. +void quiche_conn_free(quiche_conn *conn); + +// Writes an unsigned variable-length integer in network byte-order into +// the provided buffer. +int quiche_put_varint(uint8_t *buf, size_t buf_len, + uint64_t val); + +// Reads an unsigned variable-length integer in network byte-order from +// the provided buffer and returns the wire length. +ssize_t quiche_get_varint(const uint8_t *buf, size_t buf_len, + uint64_t *val); + +// HTTP/3 API +// + +// List of ALPN tokens of supported HTTP/3 versions. +#define QUICHE_H3_APPLICATION_PROTOCOL "\x02h3" + +enum quiche_h3_error { + // There is no error or no work to do + QUICHE_H3_ERR_DONE = -1, + + // The provided buffer is too short. + QUICHE_H3_ERR_BUFFER_TOO_SHORT = -2, + + // Internal error in the HTTP/3 stack. + QUICHE_H3_ERR_INTERNAL_ERROR = -3, + + // Endpoint detected that the peer is exhibiting behavior that causes. + // excessive load. + QUICHE_H3_ERR_EXCESSIVE_LOAD = -4, + + // Stream ID or Push ID greater that current maximum was + // used incorrectly, such as exceeding a limit, reducing a limit, + // or being reused. + QUICHE_H3_ERR_ID_ERROR= -5, + + // The endpoint detected that its peer created a stream that it will not + // accept. + QUICHE_H3_ERR_STREAM_CREATION_ERROR = -6, + + // A required critical stream was closed. + QUICHE_H3_ERR_CLOSED_CRITICAL_STREAM = -7, + + // No SETTINGS frame at beginning of control stream. + QUICHE_H3_ERR_MISSING_SETTINGS = -8, + + // A frame was received which is not permitted in the current state. + QUICHE_H3_ERR_FRAME_UNEXPECTED = -9, + + // Frame violated layout or size rules. + QUICHE_H3_ERR_FRAME_ERROR = -10, + + // QPACK Header block decompression failure. + QUICHE_H3_ERR_QPACK_DECOMPRESSION_FAILED = -11, + + // -12 was previously used for TransportError, skip it + + // The underlying QUIC stream (or connection) doesn't have enough capacity + // for the operation to complete. The application should retry later on. + QUICHE_H3_ERR_STREAM_BLOCKED = -13, + + // Error in the payload of a SETTINGS frame. + QUICHE_H3_ERR_SETTINGS_ERROR = -14, + + // Server rejected request. + QUICHE_H3_ERR_REQUEST_REJECTED = -15, + + // Request or its response cancelled. + QUICHE_H3_ERR_REQUEST_CANCELLED = -16, + + // Client's request stream terminated without containing a full-formed + // request. + QUICHE_H3_ERR_REQUEST_INCOMPLETE = -17, + + // An HTTP message was malformed and cannot be processed. + QUICHE_H3_ERR_MESSAGE_ERROR = -18, + + // The TCP connection established in response to a CONNECT request was + // reset or abnormally closed. + QUICHE_H3_ERR_CONNECT_ERROR = -19, + + // The requested operation cannot be served over HTTP/3. Peer should retry + // over HTTP/1.1. + QUICHE_H3_ERR_VERSION_FALLBACK = -20, + + // The following QUICHE_H3_TRANSPORT_ERR_* errors are propagated + // from the QUIC transport layer. + + // See QUICHE_ERR_DONE. + QUICHE_H3_TRANSPORT_ERR_DONE = QUICHE_ERR_DONE - 1000, + + // See QUICHE_ERR_BUFFER_TOO_SHORT. + QUICHE_H3_TRANSPORT_ERR_BUFFER_TOO_SHORT = QUICHE_ERR_BUFFER_TOO_SHORT - 1000, + + // See QUICHE_ERR_UNKNOWN_VERSION. + QUICHE_H3_TRANSPORT_ERR_UNKNOWN_VERSION = QUICHE_ERR_UNKNOWN_VERSION - 1000, + + // See QUICHE_ERR_INVALID_FRAME. + QUICHE_H3_TRANSPORT_ERR_INVALID_FRAME = QUICHE_ERR_INVALID_FRAME - 1000, + + // See QUICHE_ERR_INVALID_PACKET. + QUICHE_H3_TRANSPORT_ERR_INVALID_PACKET = QUICHE_ERR_INVALID_PACKET - 1000, + + // See QUICHE_ERR_INVALID_STATE. + QUICHE_H3_TRANSPORT_ERR_INVALID_STATE = QUICHE_ERR_INVALID_STATE - 1000, + + // See QUICHE_ERR_INVALID_STREAM_STATE. + QUICHE_H3_TRANSPORT_ERR_INVALID_STREAM_STATE = QUICHE_ERR_INVALID_STREAM_STATE - 1000, + + // See QUICHE_ERR_INVALID_TRANSPORT_PARAM. + QUICHE_H3_TRANSPORT_ERR_INVALID_TRANSPORT_PARAM = QUICHE_ERR_INVALID_TRANSPORT_PARAM - 1000, + + // See QUICHE_ERR_CRYPTO_FAIL. + QUICHE_H3_TRANSPORT_ERR_CRYPTO_FAIL = QUICHE_ERR_CRYPTO_FAIL - 1000, + + // See QUICHE_ERR_TLS_FAIL. + QUICHE_H3_TRANSPORT_ERR_TLS_FAIL = QUICHE_ERR_TLS_FAIL - 1000, + + // See QUICHE_ERR_FLOW_CONTROL. + QUICHE_H3_TRANSPORT_ERR_FLOW_CONTROL = QUICHE_ERR_FLOW_CONTROL - 1000, + + // See QUICHE_ERR_STREAM_LIMIT. + QUICHE_H3_TRANSPORT_ERR_STREAM_LIMIT = QUICHE_ERR_STREAM_LIMIT - 1000, + + // See QUICHE_ERR_STREAM_STOPPED. + QUICHE_H3_TRANSPORT_ERR_STREAM_STOPPED = QUICHE_ERR_STREAM_STOPPED - 1000, + + // See QUICHE_ERR_STREAM_RESET. + QUICHE_H3_TRANSPORT_ERR_STREAM_RESET = QUICHE_ERR_STREAM_RESET - 1000, + + // See QUICHE_ERR_FINAL_SIZE. + QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE = QUICHE_ERR_FINAL_SIZE - 1000, + + // See QUICHE_ERR_CONGESTION_CONTROL. + QUICHE_H3_TRANSPORT_ERR_CONGESTION_CONTROL = QUICHE_ERR_CONGESTION_CONTROL - 1000, + + // See QUICHE_ERR_ID_LIMIT. + QUICHE_H3_TRANSPORT_ERR_ID_LIMIT = QUICHE_ERR_ID_LIMIT - 1000, + + // See QUICHE_ERR_OUT_OF_IDENTIFIERS. + QUICHE_H3_TRANSPORT_ERR_OUT_OF_IDENTIFIERS = QUICHE_ERR_OUT_OF_IDENTIFIERS - 1000, + + // See QUICHE_ERR_KEY_UPDATE. + QUICHE_H3_TRANSPORT_ERR_KEY_UPDATE = QUICHE_ERR_KEY_UPDATE - 1000, + + // See QUICHE_ERR_CRYPTO_BUFFER_EXCEEDED. + QUICHE_H3_TRANSPORT_ERR_CRYPTO_BUFFER_EXCEEDED = QUICHE_ERR_CRYPTO_BUFFER_EXCEEDED - 1000, + + // See QUICHE_ERR_INVALID_ACK_RANGE. + QUICHE_H3_TRANSPORT_ERR_INVALID_ACK_RANGE = QUICHE_ERR_INVALID_ACK_RANGE - 1000, + + // See QUICHE_ERR_OPTIMISTIC_ACK_DETECTED. + QUICHE_H3_TRANSPORT_ERR_OPTIMISTIC_ACK_DETECTED = QUICHE_ERR_OPTIMISTIC_ACK_DETECTED - 1000, +}; + +// Stores configuration shared between multiple connections. +typedef struct quiche_h3_config quiche_h3_config; + +// Creates an HTTP/3 config object with default settings values. +quiche_h3_config *quiche_h3_config_new(void); + +// Sets the `SETTINGS_MAX_FIELD_SECTION_SIZE` setting. +void quiche_h3_config_set_max_field_section_size(quiche_h3_config *config, uint64_t v); + +// Sets the `SETTINGS_QPACK_MAX_TABLE_CAPACITY` setting. +void quiche_h3_config_set_qpack_max_table_capacity(quiche_h3_config *config, uint64_t v); + +// Sets the `SETTINGS_QPACK_BLOCKED_STREAMS` setting. +void quiche_h3_config_set_qpack_blocked_streams(quiche_h3_config *config, uint64_t v); + +// Sets the `SETTINGS_ENABLE_CONNECT_PROTOCOL` setting. +void quiche_h3_config_enable_extended_connect(quiche_h3_config *config, bool enabled); + +// Frees the HTTP/3 config object. +void quiche_h3_config_free(quiche_h3_config *config); + +// An HTTP/3 connection. +typedef struct quiche_h3_conn quiche_h3_conn; + +// Creates a new HTTP/3 connection using the provided QUIC connection. +quiche_h3_conn *quiche_h3_conn_new_with_transport(quiche_conn *quiche_conn, + quiche_h3_config *config); + +enum quiche_h3_event_type { + QUICHE_H3_EVENT_HEADERS, + QUICHE_H3_EVENT_DATA, + QUICHE_H3_EVENT_FINISHED, + QUICHE_H3_EVENT_GOAWAY, + QUICHE_H3_EVENT_RESET, + QUICHE_H3_EVENT_PRIORITY_UPDATE, +}; + +typedef struct quiche_h3_event quiche_h3_event; + +// Processes HTTP/3 data received from the peer. +int64_t quiche_h3_conn_poll(quiche_h3_conn *conn, quiche_conn *quic_conn, + quiche_h3_event **ev); + +// Returns the type of the event. +enum quiche_h3_event_type quiche_h3_event_type(quiche_h3_event *ev); + +// Iterates over the headers in the event. +// +// The `cb` callback will be called for each header in `ev`. `cb` should check +// the validity of pseudo-headers and headers. If `cb` returns any value other +// than `0`, processing will be interrupted and the value is returned to the +// caller. +int quiche_h3_event_for_each_header(quiche_h3_event *ev, + int (*cb)(uint8_t *name, size_t name_len, + uint8_t *value, size_t value_len, + void *argp), + void *argp); + +// Iterates over the peer's HTTP/3 settings. +// +// The `cb` callback will be called for each setting in `conn`. +// If `cb` returns any value other than `0`, processing will be interrupted and +// the value is returned to the caller. +int quiche_h3_for_each_setting(quiche_h3_conn *conn, + int (*cb)(uint64_t identifier, + uint64_t value, void *argp), + void *argp); + +// Check whether more frames will follow the headers on the stream. +bool quiche_h3_event_headers_has_more_frames(quiche_h3_event *ev); + +// Check whether or not extended connection is enabled by the peer +bool quiche_h3_extended_connect_enabled_by_peer(quiche_h3_conn *conn); + +// Frees the HTTP/3 event object. +void quiche_h3_event_free(quiche_h3_event *ev); + +typedef struct { + const uint8_t *name; + size_t name_len; + + const uint8_t *value; + size_t value_len; +} quiche_h3_header; + +// Extensible Priorities parameters. +typedef struct { + uint8_t urgency; + bool incremental; +} quiche_h3_priority; + +// Sends an HTTP/3 request. +int64_t quiche_h3_send_request(quiche_h3_conn *conn, quiche_conn *quic_conn, + const quiche_h3_header *headers, size_t headers_len, + bool fin); + +// Sends an HTTP/3 response on the specified stream with default priority. +int quiche_h3_send_response(quiche_h3_conn *conn, quiche_conn *quic_conn, + uint64_t stream_id, const quiche_h3_header *headers, + size_t headers_len, bool fin); + +// Sends an HTTP/3 response on the specified stream with specified priority. +int quiche_h3_send_response_with_priority(quiche_h3_conn *conn, + quiche_conn *quic_conn, uint64_t stream_id, + const quiche_h3_header *headers, size_t headers_len, + quiche_h3_priority *priority, bool fin); + +// Sends additional HTTP/3 headers on the specified stream. +int quiche_h3_send_additional_headers(quiche_h3_conn *conn, + quiche_conn *quic_conn, uint64_t stream_id, + quiche_h3_header *headers, size_t headers_len, + bool is_trailer_section, bool fin); + +// Sends an HTTP/3 body chunk on the given stream. +ssize_t quiche_h3_send_body(quiche_h3_conn *conn, quiche_conn *quic_conn, + uint64_t stream_id, const uint8_t *body, size_t body_len, + bool fin); + +// Reads request or response body data into the provided buffer. +ssize_t quiche_h3_recv_body(quiche_h3_conn *conn, quiche_conn *quic_conn, + uint64_t stream_id, uint8_t *out, size_t out_len); + +// Sends a GOAWAY frame to initiate graceful connection closure. +int quiche_h3_send_goaway(quiche_h3_conn *conn, quiche_conn *quic_conn, + uint64_t id); + +// Try to parse an Extensible Priority field value. +int quiche_h3_parse_extensible_priority(uint8_t *priority, + size_t priority_len, + quiche_h3_priority *parsed); + +/// Sends a PRIORITY_UPDATE frame on the control stream with specified +/// request stream ID and priority. +int quiche_h3_send_priority_update_for_request(quiche_h3_conn *conn, + quiche_conn *quic_conn, + uint64_t stream_id, + quiche_h3_priority *priority); + +// Take the last received PRIORITY_UPDATE frame for a stream. +// +// The `cb` callback will be called once. `cb` should check the validity of +// priority field value contents. If `cb` returns any value other than `0`, +// processing will be interrupted and the value is returned to the caller. +int quiche_h3_take_last_priority_update(quiche_h3_conn *conn, + uint64_t prioritized_element_id, + int (*cb)(uint8_t *priority_field_value, + uint64_t priority_field_value_len, + void *argp), + void *argp); + +// Returns whether the peer enabled HTTP/3 DATAGRAM frame support. +bool quiche_h3_dgram_enabled_by_peer(quiche_h3_conn *conn, + quiche_conn *quic_conn); + +typedef struct { + // The number of bytes received on the QPACK encoder stream. + uint64_t qpack_encoder_stream_recv_bytes; + + // The number of bytes received on the QPACK decoder stream. + uint64_t qpack_decoder_stream_recv_bytes; +} quiche_h3_stats; + +// Collects and returns statistics about the connection. +void quiche_h3_conn_stats(const quiche_h3_conn *conn, quiche_h3_stats *out); + +// Frees the HTTP/3 connection object. +void quiche_h3_conn_free(quiche_h3_conn *conn); + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // QUICHE_H diff --git a/network/tcpquiclab/tcp_client b/network/tcpquiclab/tcp_client new file mode 100755 index 0000000..8706ff6 Binary files /dev/null and b/network/tcpquiclab/tcp_client differ diff --git a/network/tcpquiclab/tcp_client.c b/network/tcpquiclab/tcp_client.c new file mode 100644 index 0000000..ca6c725 --- /dev/null +++ b/network/tcpquiclab/tcp_client.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include +#include + +#define PORT 8080 +#define SERVER_IP "127.0.0.1" +#define BUFFER_SIZE 1024 + +int main() { + int sock = 0; + struct sockaddr_in serv_addr; + const char *hello = "Hello from TCP Client"; + char buffer[BUFFER_SIZE] = {0}; + + // 1. Create socket + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("\n Socket creation error \n"); + return -1; + } + + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(PORT); + + // Convert IPv4 and IPv6 addresses from text to binary form + if (inet_pton(AF_INET, SERVER_IP, &serv_addr.sin_addr) <= 0) { + printf("\nInvalid address/ Address not supported \n"); + return -1; + } + + // 2. Connect to server + if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { + printf("\nConnection Failed \n"); + return -1; + } + + // 3. Send data + send(sock, hello, strlen(hello), 0); + printf("Message sent to server: %s\n", hello); + + // 4. Receive response + int valread = read(sock, buffer, BUFFER_SIZE); + if (valread > 0) { + printf("Server response: %s\n", buffer); + } + + // 5. Close socket + close(sock); + + return 0; +} diff --git a/network/tcpquiclab/tcp_perf_client b/network/tcpquiclab/tcp_perf_client new file mode 100755 index 0000000..4aec67a Binary files /dev/null and b/network/tcpquiclab/tcp_perf_client differ diff --git a/network/tcpquiclab/tcp_perf_client.c b/network/tcpquiclab/tcp_perf_client.c new file mode 100644 index 0000000..2c56706 --- /dev/null +++ b/network/tcpquiclab/tcp_perf_client.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include + +#define PORT 8081 +#define SERVER_IP "127.0.0.1" +#define BUFFER_SIZE 4096 +#define TARGET_MB 100 + +int main() { + int sock = 0; + struct sockaddr_in serv_addr; + char buffer[BUFFER_SIZE]; + memset(buffer, 'A', BUFFER_SIZE); // Dummy data + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("\n Socket creation error \n"); + return -1; + } + + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(PORT); + + if (inet_pton(AF_INET, SERVER_IP, &serv_addr.sin_addr) <= 0) { + printf("\nInvalid address/ Address not supported \n"); + return -1; + } + + if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { + printf("\nConnection Failed \n"); + return -1; + } + + printf("Sending %d MB of data...\n", TARGET_MB); + + long long bytes_to_send = TARGET_MB * 1024 * 1024; + long long bytes_sent = 0; + + while (bytes_sent < bytes_to_send) { + int to_send = (bytes_to_send - bytes_sent > BUFFER_SIZE) ? BUFFER_SIZE : (bytes_to_send - bytes_sent); + send(sock, buffer, to_send, 0); + bytes_sent += to_send; + } + + printf("Data sent.\n"); + close(sock); + + return 0; +} diff --git a/network/tcpquiclab/tcp_perf_server b/network/tcpquiclab/tcp_perf_server new file mode 100755 index 0000000..ab1adac Binary files /dev/null and b/network/tcpquiclab/tcp_perf_server differ diff --git a/network/tcpquiclab/tcp_perf_server.c b/network/tcpquiclab/tcp_perf_server.c new file mode 100644 index 0000000..393481e --- /dev/null +++ b/network/tcpquiclab/tcp_perf_server.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include +#include + +#define PORT 8081 +#define BUFFER_SIZE 4096 + +int main() { + int server_fd, new_socket; + struct sockaddr_in address; + int opt = 1; + int addrlen = sizeof(address); + char buffer[BUFFER_SIZE] = {0}; + + if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { + perror("socket failed"); + exit(EXIT_FAILURE); + } + + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { + perror("setsockopt"); + exit(EXIT_FAILURE); + } + + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(PORT); + + if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { + perror("bind failed"); + exit(EXIT_FAILURE); + } + + if (listen(server_fd, 3) < 0) { + perror("listen"); + exit(EXIT_FAILURE); + } + + printf("TCP Performance Server listening on port %d...\n", PORT); + + if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) { + perror("accept"); + exit(EXIT_FAILURE); + } + + printf("Client connected. Receiving data...\n"); + + long long total_bytes = 0; + int valread; + struct timespec start, end; + clock_gettime(CLOCK_MONOTONIC, &start); + + while ((valread = read(new_socket, buffer, BUFFER_SIZE)) > 0) { + total_bytes += valread; + } + + clock_gettime(CLOCK_MONOTONIC, &end); + + double time_taken = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9; + double mb = total_bytes / (1024.0 * 1024.0); + double throughput = mb / time_taken; + + printf("Received %.2f MB in %.2f seconds.\n", mb, time_taken); + printf("Throughput: %.2f MB/s\n", throughput); + + close(new_socket); + close(server_fd); + + return 0; +} diff --git a/network/tcpquiclab/tcp_server b/network/tcpquiclab/tcp_server new file mode 100755 index 0000000..1071399 Binary files /dev/null and b/network/tcpquiclab/tcp_server differ diff --git a/network/tcpquiclab/tcp_server.c b/network/tcpquiclab/tcp_server.c new file mode 100644 index 0000000..f021d20 --- /dev/null +++ b/network/tcpquiclab/tcp_server.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include + +#define PORT 8080 +#define BUFFER_SIZE 1024 + +int main() { + int server_fd, new_socket; + struct sockaddr_in address; + int opt = 1; + int addrlen = sizeof(address); + char buffer[BUFFER_SIZE] = {0}; + + // 1. Create socket file descriptor + // AF_INET: IPv4, SOCK_STREAM: TCP + if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { + perror("socket failed"); + exit(EXIT_FAILURE); + } + + // 2. Attach socket to the port 8080 + // SO_REUSEADDR allows restarting the server immediately after closing + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { + perror("setsockopt"); + exit(EXIT_FAILURE); + } + + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; // Listen on all interfaces + address.sin_port = htons(PORT); + + // Bind + if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { + perror("bind failed"); + exit(EXIT_FAILURE); + } + + // 3. Listen for incoming connections + if (listen(server_fd, 3) < 0) { + perror("listen"); + exit(EXIT_FAILURE); + } + + printf("TCP Server listening on port %d...\n", PORT); + + // 4. Accept connection + if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) { + perror("accept"); + exit(EXIT_FAILURE); + } + + printf("Client connected.\n"); + + // 5. Receive data + int valread = read(new_socket, buffer, BUFFER_SIZE); + if (valread > 0) { + printf("Received %d bytes: %s\n", valread, buffer); + + // 6. Send response (Echo length or simple ack) + char response[BUFFER_SIZE]; + snprintf(response, BUFFER_SIZE, "Server received %d bytes", valread); + send(new_socket, response, strlen(response), 0); + printf("Response sent to client.\n"); + } + + // 7. Close socket + close(new_socket); + close(server_fd); + + return 0; +} diff --git a/network/tcpquiclab/实验3讲解最终版.pptx b/network/tcpquiclab/实验3讲解最终版.pptx new file mode 100644 index 0000000..e5a119c Binary files /dev/null and b/network/tcpquiclab/实验3讲解最终版.pptx differ diff --git a/network/tcpquiclab/计算机网络实验指导手册.pdf b/network/tcpquiclab/计算机网络实验指导手册.pdf new file mode 100644 index 0000000..d3759ac Binary files /dev/null and b/network/tcpquiclab/计算机网络实验指导手册.pdf differ diff --git a/network/tcpquiclab/计算机网络实验指导手册.txt b/network/tcpquiclab/计算机网络实验指导手册.txt new file mode 100644 index 0000000..93f4201 --- /dev/null +++ b/network/tcpquiclab/计算机网络实验指导手册.txt @@ -0,0 +1,326 @@ +任务一:头歌平台编程实现WEB服务器 +任务二:TCP 与 QUIC 协议性能对比分析 +任务要求: +1. 基于 TCP 的客户端-服务器程序实现,TCP服务器功能包括:监听指定端口;接受 +客户端连接;接收客户端发送的消息;向客户端返回响应(包含接收数据的长 +度)。客户端功能包括:连接到TCP服务器;向服务器发送指定消息;接收服务器 +响应并显示。 +2. 基于QUIC的客户端-服务器程序实现:使用quiche库实现QUIC服务器与客户端,功 +能与第一条类似。 +实验环境: +操作系统:Windows或Linux; +编程语言:C语言(其他语言也可,能实现实验功能即可) +依赖库:socket库、quiche库 +实验步骤: +1. 基于TCP的客户端-服务器程序实现 +(1)环境配置 +此处以Windows系统下使用VSCode运行c语言代码为例(不同的系统、运行软件、 +编程语言之间会有差异,自行决定选用工具,实现功能即可)。 +在 Windows 系统中使用 VSCode 运行 C 语言代码之前,需要先配置 C 语言开 +发环境。首先,在官网下载并安装 MinGW(下载链接:https://sourceforge.net/pr +ojects/mingw/)。安装完成后,需将 MinGW 的 bin 目录添加到系统的环境变量 +Path 中,以确保能够在命令行中直接调用 gcc 等编译工具; +添加完成之后使用Windows+R命令打开cmd窗口,运行命令gcc --version可验证是否成功安装。 + + +在完成.c文件编写后,必须编译并生成对应的.exe可执行文件,才能启动调试过 +程。 + +以上图中的hello.c为例(其余代码的运行调试过程相同,修改相应命令即可), +首先在终端运行命令gcc hello.c -o hello.exe生成对应的hello.exe文件,之后在对应 +的路径下运行./hello.exe即可得到输出。 + +(2)代码书写 +① 服务端代码 +a. 引入相关头文件,链接 ws2_32.lib 库,对服务器监听的端口号和缓冲区大小 +进行宏定义 + +定义需要用到的变量 + +使用Windows套接字编程,首先需要初始化 Winsock 库。如果初始化失败, +打印错误信息,返回 -1 值,结束程序运行 + +使用socket()函数创建服务器套接字,如果创建失败,打印错误信息,清理 + +Winsock 资源并返回 -1 表示程序异常结束。 +使用memset将 serverAddr 结构体清零,确保没有残留数据,设置地址族为 +IPv4(AF_INET),绑定到所有可用的网络接口(INADDR_ANY 表示接受任意IP 地址的连接),设置端口号,使用 htons() 函数确保端口号以网络字节序 +(大端)传输。然后通过bind()绑定套接字,如果绑定失败将打印错误信息, +释放资源后结束程序运行。 + +使用listen()命令开始监听客户端连接,输出服务器正在监听的端口号。 +等待客户端连接,输出客户端已连接的信息。 +从客户端接收数据,存入 buffer 中,输出接收到的消息,向客户端返回响 + +应,包含接收到数据的长度。在通信完成后,关闭套接字,并清理资源。 +② 客户端代码 +a. 引入相关头文件,链接 ws2_32.lib 库,定义客户端连接的目标端口号,必须 +与服务器端口一致。 + +b. + +定义相关变量。 + +c. + +初始化Winsock库,确保在使用套接字之前初始化 Winsock。 + +d. + +创建客户端套接字。设置地址族为 + +IPv4(AF_INET),设置目标服务器的端 + +口号,使用 htons() 转换为网络字节序。使用inet_addr() 将字符串格式的 IP + +地址转换为 in_addr 结构体中可使用的二进制格式。此处使用的是本地回环 +地址(localhost),意味着客户端将连接到本地运行的服务器。 + +连接到服务器。 +和服务器进行通讯。 +send() 函数将消息从客户端发送到服务器。参数 sock 是套接字,message + +是要发送的消息,strlen(message) 是消息的长度,0 表示没有使用附加标志。 +recv() 函数从服务器接收数据,将其存储在 buffer 中。valread 存储实际接 +收到的字节数。如果接收失败,返回值为负数,程序将打印错误信息。否则,打 +印服务器的响应内容。 +完成数据交换后,关闭套接字并清理 Winsock 库。 + +(3)实验结果示例 +编写好.c文件后,先在终端使用gcc命令生成.exe文件(每次对代码进行改动后都 +需要重新生成.exe文件):gcc server.c -o server.exe -lws2_32,其中-lws2_32表示链接 +Winsock 库;生成并运行 server.exe 和 client.exe 后,可以看到以下实验结果。 + +(4)总结 +本实验通过实现基于 TCP 协议的客户端-服务器通信,帮助理解网络编程的基本 +原理。要求完成服务器端和客户端的代码编写,并通过实际运行验证通信功能。 +2. 基于QUIC的客户端-服务器程序实现 +(1)实验环境 +本实验需要使用quiche库实现QUIC服务器与客户端,除了要配置好VSCode的C语言 +环境之外,还需要安装quiche库,确保它支持C语言的绑定。 +安装quiche库的步骤如下: +① 安装 Rust 和 Cargo +首先,需要安装Rust开发环境,Rust 包括了 cargo,这是构建和管理 Rust +项目的工具。按照官网提供的下载地址和下载步骤下载Rust和cargo:https://rust-l +ang.org/zh-CN/tools/install/ +② 克隆并构建quiche仓库 +a. 使用git工具进行克隆(这一步需要确保自己的主机安装了git工具,如果没有 +安装,可以通过https://git-scm.com/install/windows下载安装),使用Window +s+R快捷键打开cmd窗口运行克隆命令: +git clone https://github.com/cloudflare/quiche +cd quiche +如果上述方法遇到问题,可以通过访问quiche库的github主页下载并解压其源 +代码,网址为https://github.com/cloudflare/quiche。 +b. 准备好quiche仓库后在cmd窗口运行命令cargo build --release --features ffi构建 +quiche的C语言接口(注意,这一步需要再下载好的quiche文件夹下完成)运 +行这条命令没有报错后,在quiche相应的文件夹下查找是否生成以下文件: +Your local quiche Path\target\release\quiche.lib +Your local quiche Path\target\release\quiche.dll.lib +Your local quiche Path\target\release\libquiche.d +Your local quiche Path\target\release\libquiche.rlib +Your local quiche Path\quiche\include\quiche.h +确认存在就说明已经配置好quiche库的C语言静态库。 +如果在构建quiche库的C语言接口时出现问题可以尝试检查以下问题: + + +系统缺少 Visual Studio 或 Visual Studio Build Tools。访问https://visual +studio.microsoft.com/zh-hans/visual-cpp-build-tools/下载并安装Microsoft C +++生成工具,在安装过程中,确保选择了 C++ 构建工具(包括 Visual C + +++ 编译器和链接器)。安装完成之后,找到编译工具链link.exe所在地 +址(一般位于D:\Program Files (x86)\Visual Studio 2022\Build Tools\VC\Tool +s\MSVC + + + +\14.44.35207\bin),将bin文件地址添加到系统环境变量中。 + +未安装cmake工具。访问Cmake官网(https://cmake.org/download/)下 +载并安装适用于 Windows 的安装程序,选择 Windows x64 Installer。安装时,确保勾选了 "Add CMake to the system PATH" 选项,这样可以在 +命令行中直接使用 cmake。 + +安装完成后可以在终端检查是否成功安装。 + + + +未安装NASM编译器。访问官网(https://www.nasm.us/)下载并安装适 +合你系统的版本。安装后,将 NASM 的路径添加到 PATH 环境变量 +中。在cmd窗口检验是否安装成功。 + + + +未安装clang编译器。可以参照这个博客下载并测试安装: +https://blog.csdn.net/weixin_44565660/article/details/121758517 + +Clang安装后,需要设置LIBCLANG_PATH环境变量,指向libclang.dll的位 +置。该文件通常位于Clang安装目录的bin文件夹下,可以在该目录下找到这个 +文件。检查该文件确实存在之后打开系统环境变量设置,在系统变量部分点 +击新建然后添加一个新的环境变量,如下图所示。 + + 之后验证通过运行命令echo %LIBCLANG_PATH%验证环境变量设置正确, +正确的话会返回Clang安装目录的路径。 + +③ 书写C语言代码熟悉quiche库的使用 +a. VSCode运行环境 +使用MinGW编译工具运行quiche库难度比较大,不推荐新手使用,因此,本 +课程选用MSVC环境(VS Build Tools)运行C项目。打开“x64 Native Tools Command + +Prompt for VS 2022”,在窗口中cd到你的C工程目录,然后输入code .启动VSCode。 +b. VSCode配置文件 +为了链接到quiche库,需要改写相应C工程目录下.vscode的配置文件,通过ar + +gs命令指定静态库的位置。 + + c. + +最小验证程序 +新建verify_quiche.c,先把quiche工具链跑通: +#include +#include + +int main(void) { +const char *v = quiche_version(); +printf("quiche version: %s\n", v ? v : "(null)"); +return 0; +} + +使用cl命令生成相应的.exe文件: + +cl /nologo /Zi /EHsc /MD ` +/I E:\quiche\quiche-master\quiche\include verify_quiche.c ` +/Fe:verify_quiche.exe ` +/link /LIBPATH:E:\quiche\quiche-master\target\release ` +quiche.lib ws2_32.lib advapi32.lib ` +crypt32.lib userenv.lib ntdll.lib + +然后在VSCode终端运行该.exe文件,输出quiche版本号就说明quiche的c语言 +接口构建完成: + +(2)代码书写 +① 服务端代码 +a. 准备quiche配置 +b. 创建UDP socket并监听端口:用socket(AF_INET/AF_INET6, SOCK_DGRAM, ...)创 +建 UDP socket,bind() 到指定端口(比如 5555),设置成 non-blocking,这 +样循环不会卡死在 recvfrom() 上,此时 server 已经在 “UDP 层”听包了,但 +还没有 QUIC 连接对象 +c. 进行主循环(核心框架) +主循环反复执行:收UDP包。recvfrom()收到一个 QUIC UDP 包,同时拿到客 +户端地址 peer_addr(用于后续回包) +d. 解析包头:收到 UDP 包后,先用 quiche_header_info() 解析 QUIC 头部, +拿到:version:QUIC 版本,dcid / scid:连接 ID(用于识别连接),token: +实验里可以不深入理解 +e. 第一次收到合法包时,创建 QUIC 连接(accept) + + f. 把 UDP 包交给 quiche 处理(conn_recv) +g. 如果连接已建立(established),就读 stream 并生成响应 +h. 把 quiche 产生的所有 UDP 包发出去(conn_send 循环) +② 客户端代码 +a. 初始化 quiche_config +b. 创建 QUIC 连接 quiche_connect +c. 触发握手 +d. recvfrom 后喂给 quiche(quiche_conn_recv) +e. 建立连接后(quiche_conn_is_established(conn))发送一次消息 +f. 调用quiche_conn_readable(conn) 函数获取可读 stream,对每个 stream id +调 quiche_conn_stream_recv,打印响应并设置 got_resp = true +g. 每轮循环 flush_egress,否则ACK / handshake / stream data 都可能“卡在内存 +里没发出去”,表现为建立慢或收不到响应 +h. timeout 处理 +i. +收到响应后关闭连接 +③ 运行代码 +首先需要在终端使用openssl命令生成证书,否则不能编译通过: + +生成证书之后使用cl命令得到相应的.exe文件,cl命令参考: + +cl /nologo /Zi /EHsc /MD ` +/I E:\quiche\quiche-master\quiche\include quic_server.c +` +/Fe:quic_server.exe +` +/link /LIBPATH:E:\quiche\quiche-master\target\release ` +quiche.lib ws2_32.lib advapi32.lib crypt32.lib userenv.lib ntdll.lib + +(3)实验结果示例 +运行生成的.exe文件得到结果如下: + +任务三:对比分析TCP与QUIC性能 +任务 3.1:连接建立时间对比 +任务要求: +1. 测量 TCP 三次握手时间:使用 Wireshark 捕获 TCP 连接建立过程;记录从客户 +端发送 SYN 到收到服务器 ACK 的时间。 +2. 测量 QUIC 连接建立时间:使用 Wireshark 捕获 QUIC 连接建立过程;记录从客 + +户端发送初始数据包到完成握手的时间。 +3. 对比分析:记录 3 次测试的平均值,比较两种协议的连接建立效率 +实验环境: + +安装好wireshark软件即可 +实验步骤: +1. 打开wireshark主界面之后根据书写的代码选择正确的网卡,之后开始捕获; +2. 根据代码端口或者协议类型设置wireshark的显示过滤器; + +3. 运行书写的代码模拟通信过程即可得到结果并进行分析。 +实验结果示例: + +任务 3.2:吞吐量测试 +任务要求: +1. 修改 TCP 和 QUIC 程序,实现大文件传输功能(如传输 100MB 的随机文件) +2. 在不同网络条件下测试吞吐量: +正常网络(无丢包) +使用 tc 模拟 5% 丢包率:sudo tc qdisc add dev eth0 root netem loss 5% +使用 tc 模拟 100ms 延迟:sudo tc qdisc add dev eth0 root netem delay 100ms +计算并对比两种协议的吞吐量(MB/s) +实验环境: +为了在Windows系统上实现第2点,需要准备一个网络故障模拟工具clumsy,当然, +也可以在Windows系统下安装WSL2或者Linux虚拟机使用sudo tc命令运行相同的代码并 +测试吞吐量。 +本手册以clumsy为例进行教学,使用WSL或虚拟机工具请自行学习。 +首先,打开clumsy的下载网址(http://jagt.github.io/clumsy/download)根据系统 + +版本下载对应的软件压缩包。解压后得到一个文件夹: + +右键clumsy.exe以管理员身份运行,其主界面如下: + +有疑问可以参考这篇博客: +https://blog.csdn.net/hgftgfffg/article/details/147412888 +实验步骤: +1. 实现大文件传输功能 +(1) TCP程序 +① 按照提示补全TCP程序即可 +② 编译与运行 +gcc -O2 tcp_server.c -o tcp_server.exe -lws2_32 +gcc -O2 tcp_client.c -o tcp_client.exe -lws2_32 +(2) QUIC程序 +① 按照提示补全QUIC程序即可 +② 编译与运行 +依旧参照之前的格式使用cl命令进行编译,得到可运行文件后运行观察结 +果。 +2. 在不同网络条件下测试吞吐量 +使用clumsy模拟 5% 丢包率:首先以管理员身份打开clumsy.exe,选择Lag=100m +s,点击开始,然后再次运行程序,观察实验结果。 + +使用clumsy模拟 100ms 延迟:首先以管理员身份打开clumsy.exe,选择Lag=100m + +s,点击开始,然后再次运行程序,观察实验结果。 + +3. 实验结果示例: + +此处仅提供了正常网络环境下tcp传输大文件的结果示例,并且是以本地loopback +进行实验作为例子,建议在自己做实验的时候可以改用本级IP尝试实现实验,这样结 +果会更加接近真实网络,且clumsy对真实网卡路径更加稳定。 +任务 3.3:多路复用性能测试 +任务要求: +设计多流传输测试:同时建立 5 个 TCP 连接传输数据,在单个 QUIC 连接上建 +立 5 个流传输数据,测量并对比两种方式的总传输时间和资源占用,分析 QUIC 多 +路复用如何解决 TCP 的队头阻塞问题。 +任务 3.4:网络异常恢复测试 + +任务要求: +模拟网络中断后恢复的场景: +建立连接并开始传输数据 +使用tc qdisc add dev eth0 root netem loss 100%模拟网络中断 +30 秒后使用tc qdisc del dev eth0 root恢复网络 +对比两种协议的恢复能力和数据完整性 +测试 QUIC 的连接迁移能力(服务器 IP 或端口变化后) + +