From 1240ee1bf4eb14347422e4580df359b9adfd9f48 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Thu, 2 Jan 2025 23:05:13 -0800 Subject: [PATCH] [ntcore] Remove NT3 support (#7625) - Remove StartClient3 - Rename StartClient4 to StartClient - Remove port3 parameter from StartServer - Remove 3-suffix constants - Remove 4 suffix from constants Also remove Shuffleboard build from CI. --- .github/workflows/tools.yml | 78 --- .../src/main/java/edu/wpi/Main.java | 2 +- .../src/main/native/cpp/main.cpp | 2 +- glass/src/app/native/cpp/main.cpp | 2 +- glass/src/libnt/native/cpp/NetworkTables.cpp | 2 +- .../native/cpp/NetworkTablesSettings.cpp | 61 +-- .../networktables/NetworkTablesSettings.h | 6 +- .../main/native/systemcore/SystemServer.cpp | 2 +- ntcore/src/dev/native/cpp/main.cpp | 18 +- .../main/java/NetworkTableInstance.java.jinja | 49 +- .../main/java/NetworkTablesJNI.java.jinja | 17 +- .../networktables/NetworkTableInstance.java | 49 +- .../first/networktables/NetworkTablesJNI.java | 17 +- .../first/networktables/ConnectionInfo.java | 2 +- ntcore/src/main/native/cpp/InstanceImpl.cpp | 25 +- ntcore/src/main/native/cpp/InstanceImpl.h | 6 +- ntcore/src/main/native/cpp/NetworkClient.cpp | 157 +----- ntcore/src/main/native/cpp/NetworkClient.h | 26 +- ntcore/src/main/native/cpp/NetworkServer.cpp | 104 +--- ntcore/src/main/native/cpp/NetworkServer.h | 11 +- .../main/native/cpp/jni/NetworkTablesJNI.cpp | 28 +- .../src/main/native/cpp/net3/ClientImpl3.cpp | 468 ----------------- ntcore/src/main/native/cpp/net3/ClientImpl3.h | 177 ------- ntcore/src/main/native/cpp/net3/Message3.h | 156 ------ .../src/main/native/cpp/net3/SequenceNumber.h | 38 -- .../native/cpp/net3/UvStreamConnection3.cpp | 66 --- .../native/cpp/net3/UvStreamConnection3.h | 78 --- .../main/native/cpp/net3/WireConnection3.h | 72 --- .../src/main/native/cpp/net3/WireDecoder3.cpp | 458 ----------------- .../src/main/native/cpp/net3/WireDecoder3.h | 183 ------- .../src/main/native/cpp/net3/WireEncoder3.cpp | 321 ------------ .../src/main/native/cpp/net3/WireEncoder3.h | 49 -- ntcore/src/main/native/cpp/ntcore_c.cpp | 14 +- ntcore/src/main/native/cpp/ntcore_cpp.cpp | 15 +- .../main/native/cpp/server/ServerClient3.cpp | 482 ------------------ .../main/native/cpp/server/ServerClient3.h | 97 ---- .../src/main/native/cpp/server/ServerImpl.cpp | 15 - .../src/main/native/cpp/server/ServerImpl.h | 3 - .../networktables/NetworkTableInstance.h | 36 +- ntcore/src/main/native/include/ntcore_c.h | 31 +- ntcore/src/main/native/include/ntcore_cpp.h | 21 +- .../networktables/ConnectionListenerTest.java | 8 +- .../wpi/first/networktables/LoggerTest.java | 4 +- .../wpi/first/networktables/TimeSyncTest.java | 17 +- .../networktables/TopicListenerTest.java | 4 +- .../native/cpp/ConnectionListenerTest.cpp | 14 +- ntcore/src/test/native/cpp/LoggerTest.cpp | 2 +- ntcore/src/test/native/cpp/TestPrinters.cpp | 54 -- ntcore/src/test/native/cpp/TimeSyncTest.cpp | 16 +- .../src/test/native/cpp/TopicListenerTest.cpp | 4 +- .../test/native/cpp/net3/MessageMatcher3.cpp | 45 -- .../test/native/cpp/net3/MessageMatcher3.h | 34 -- .../native/cpp/net3/MockWireConnection3.h | 49 -- .../test/native/cpp/net3/WireDecoder3Test.cpp | 279 ---------- .../test/native/cpp/net3/WireEncoder3Test.cpp | 284 ----------- ntcoreffi/src/main/native/symbols.txt | 3 +- outlineviewer/src/main/native/cpp/main.cpp | 2 +- .../wpi/first/wpilibj/PreferencesTest.java | 2 +- 58 files changed, 149 insertions(+), 4116 deletions(-) delete mode 100644 ntcore/src/main/native/cpp/net3/ClientImpl3.cpp delete mode 100644 ntcore/src/main/native/cpp/net3/ClientImpl3.h delete mode 100644 ntcore/src/main/native/cpp/net3/Message3.h delete mode 100644 ntcore/src/main/native/cpp/net3/SequenceNumber.h delete mode 100644 ntcore/src/main/native/cpp/net3/UvStreamConnection3.cpp delete mode 100644 ntcore/src/main/native/cpp/net3/UvStreamConnection3.h delete mode 100644 ntcore/src/main/native/cpp/net3/WireConnection3.h delete mode 100644 ntcore/src/main/native/cpp/net3/WireDecoder3.cpp delete mode 100644 ntcore/src/main/native/cpp/net3/WireDecoder3.h delete mode 100644 ntcore/src/main/native/cpp/net3/WireEncoder3.cpp delete mode 100644 ntcore/src/main/native/cpp/net3/WireEncoder3.h delete mode 100644 ntcore/src/main/native/cpp/server/ServerClient3.cpp delete mode 100644 ntcore/src/main/native/cpp/server/ServerClient3.h delete mode 100644 ntcore/src/test/native/cpp/net3/MessageMatcher3.cpp delete mode 100644 ntcore/src/test/native/cpp/net3/MessageMatcher3.h delete mode 100644 ntcore/src/test/native/cpp/net3/MockWireConnection3.h delete mode 100644 ntcore/src/test/native/cpp/net3/WireDecoder3Test.cpp delete mode 100644 ntcore/src/test/native/cpp/net3/WireEncoder3Test.cpp diff --git a/.github/workflows/tools.yml b/.github/workflows/tools.yml index 34619300bc..34bbfffc59 100644 --- a/.github/workflows/tools.yml +++ b/.github/workflows/tools.yml @@ -43,84 +43,6 @@ jobs: development retention-days: 1 - # Robotbuilder: - # name: "Build - RobotBuilder" - # needs: [build-artifacts] - # runs-on: ubuntu-24.04 - # env: - # DISPLAY: ':10' - # steps: - # - uses: actions/checkout@v4 - # with: - # repository: wpilibsuite/robotbuilder - # fetch-depth: 0 - # - uses: actions/download-artifact@v4 - # with: - # name: MavenArtifacts - # - name: Patch RobotBuilder to use local development - # run: cd src/main/resources/export && echo "wpi.maven.useLocal = false" >> java/build.gradle && echo "wpi.maven.useFrcMavenLocalDevelopment = true" >> java/build.gradle && echo "wpi.versions.wpilibVersion = '$YEAR.424242.+'" >> java/build.gradle && echo "wpi.versions.wpimathVersion = '$YEAR.424242.+'" >> java/build.gradle && echo "wpi.maven.useLocal = false" >> cpp/build.gradle && echo "wpi.maven.useFrcMavenLocalDevelopment = true" >> cpp/build.gradle && echo "wpi.versions.wpilibVersion = '$YEAR.424242.+'" >> cpp/build.gradle && echo "wpi.versions.wpimathVersion = '$YEAR.424242.+'" >> cpp/build.gradle - # - name: Install and run xvfb - # run: sudo apt-get update && sudo apt-get install -y xvfb && Xvfb $DISPLAY & - # - name: Move artifacts - # run: mkdir -p ~/releases/maven/development && cp -r edu ~/releases/maven/development - # - uses: actions/setup-java@v4 - # with: - # java-version: 17 - # distribution: 'temurin' - # - name: Build RobotBuilder with Gradle - # run: ./gradlew build test --tests 'robotbuilder.exporters.*' -x htmlSanityCheck -PbuildServer -PreleaseMode ; cat build/test-results/test/TEST-robotbuilder.exporters.*.xml ; - # - name: Summarize RobotBuilder Test Results - # uses: EnricoMi/publish-unit-test-result-action@v2 - # if: always() - # with: - # files: | - # build/test-results/test/TEST*.xml - # check_run: false - # comment_mode: off - # - uses: actions/upload-artifact@v4 - # if: always() - # with: - # name: RobotBuilderTestResults - # path: | - # build/reports/ - # - uses: actions/upload-artifact@v4 - # with: - # name: RobotBuilder Build - # path: | - # build/libs/ - # retention-days: 7 - - Shuffleboard: - name: "Build - Shuffleboard" - needs: [build-artifacts] - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v4 - with: - repository: wpilibsuite/shuffleboard - fetch-depth: 0 - - name: Patch Shuffleboard to use local development - run: sed -i "s/wpilibTools.deps.wpilibVersion.*/wpilibTools.deps.wpilibVersion = \'$YEAR\.424242\.+\'/" app/app.gradle && sed -i "s/wpilibTools.deps.wpilibVersion.*/wpilibTools.deps.wpilibVersion = \'$YEAR\.424242\.+\'/" plugins/cameraserver/cameraserver.gradle && sed -i "s/wpilibTools.deps.wpilibVersion.*/wpilibTools.deps.wpilibVersion = \'$YEAR\.424242\.+\'/" plugins/networktables/networktables.gradle - - uses: actions/download-artifact@v4 - with: - name: MavenArtifacts - - uses: actions/setup-java@v4 - with: - java-version: 17 - distribution: 'temurin' - - name: Move artifacts - run: mkdir -p ~/releases/maven/development && cp -r edu ~/releases/maven/development - - name: Install dependencies - run: sudo apt-get install -y libgtk2.0-0 - - name: Build with Gradle - run: ./gradlew build -x Javadoc - - uses: actions/upload-artifact@v4 - with: - name: Shuffleboard Build - path: | - build/allOutputs/ - retention-days: 7 - PathWeaver: name: "Build - PathWeaver" needs: [build-artifacts] diff --git a/cameraserver/multiCameraServer/src/main/java/edu/wpi/Main.java b/cameraserver/multiCameraServer/src/main/java/edu/wpi/Main.java index f69a6feec5..fb85333b27 100644 --- a/cameraserver/multiCameraServer/src/main/java/edu/wpi/Main.java +++ b/cameraserver/multiCameraServer/src/main/java/edu/wpi/Main.java @@ -176,7 +176,7 @@ public final class Main { } else { System.out.println("Setting up NetworkTables client for team " + team); ntinst.setServerTeam(team); - ntinst.startClient4("multicameraserver"); + ntinst.startClient("multicameraserver"); } // start cameras diff --git a/cameraserver/multiCameraServer/src/main/native/cpp/main.cpp b/cameraserver/multiCameraServer/src/main/native/cpp/main.cpp index f3e0a7b72e..196477e565 100644 --- a/cameraserver/multiCameraServer/src/main/native/cpp/main.cpp +++ b/cameraserver/multiCameraServer/src/main/native/cpp/main.cpp @@ -190,7 +190,7 @@ int main(int argc, char* argv[]) { ntinst.StartServer(); } else { wpi::print("Setting up NetworkTables client for team {}\n", team); - ntinst.StartClient4("multicameraserver"); + ntinst.StartClient("multicameraserver"); ntinst.SetServerTeam(team); } diff --git a/glass/src/app/native/cpp/main.cpp b/glass/src/app/native/cpp/main.cpp index 63715b2578..188ab4a4f7 100644 --- a/glass/src/app/native/cpp/main.cpp +++ b/glass/src/app/native/cpp/main.cpp @@ -83,7 +83,7 @@ static std::string MakeTitle(NT_Inst inst, nt::Event event) { auto numClients = nt::GetConnections(inst).size(); return fmt::format("Glass - {} Client{} Connected", numClients, (numClients == 1 ? "" : "s")); - } else if (mode & NT_NET_MODE_CLIENT3 || mode & NT_NET_MODE_CLIENT4) { + } else if (mode & NT_NET_MODE_CLIENT) { if (event.Is(NT_EVENT_CONNECTED)) { return fmt::format("Glass - Connected ({})", event.GetConnectionInfo()->remote_ip); diff --git a/glass/src/libnt/native/cpp/NetworkTables.cpp b/glass/src/libnt/native/cpp/NetworkTables.cpp index d661ee5f05..78ff8e1ba9 100644 --- a/glass/src/libnt/native/cpp/NetworkTables.cpp +++ b/glass/src/libnt/native/cpp/NetworkTables.cpp @@ -1997,7 +1997,7 @@ void glass::DisplayNetworkTablesInfo(NetworkTablesModel* model) { } auto netMode = inst.GetNetworkMode(); - if (netMode == NT_NET_MODE_SERVER || netMode == NT_NET_MODE_CLIENT4) { + if (netMode == NT_NET_MODE_SERVER || netMode == NT_NET_MODE_CLIENT) { if (CollapsingHeader("Server")) { PushID("Server"); ImGui::Indent(); diff --git a/glass/src/libnt/native/cpp/NetworkTablesSettings.cpp b/glass/src/libnt/native/cpp/NetworkTablesSettings.cpp index bca067f779..aac53b50ac 100644 --- a/glass/src/libnt/native/cpp/NetworkTablesSettings.cpp +++ b/glass/src/libnt/native/cpp/NetworkTablesSettings.cpp @@ -44,66 +44,59 @@ void NetworkTablesSettings::Thread::Main() { // if just changing servers in client mode, no need to stop and restart unsigned int curMode = nt::GetNetworkMode(m_inst); - if ((mode == 0 || mode == 3) || - (mode == 1 && (curMode & NT_NET_MODE_CLIENT4) == 0) || - (mode == 2 && (curMode & NT_NET_MODE_CLIENT3) == 0)) { + if ((mode == 0 || mode == 2) || + (mode == 1 && (curMode & NT_NET_MODE_CLIENT) == 0)) { nt::StopClient(m_inst); nt::StopServer(m_inst); nt::StopLocal(m_inst); } - if ((m_mode == 0 || m_mode == 3) || !dsClient) { + if ((m_mode == 0 || m_mode == 2) || !dsClient) { nt::StopDSClient(m_inst); } lock.lock(); } while (mode != m_mode || dsClient != m_dsClient); - if (m_mode == 1 || m_mode == 2) { + if (m_mode == 1) { std::string_view serverTeam{m_serverTeam}; std::optional team; if (m_mode == 1) { - nt::StartClient4(m_inst, m_clientName); - } else if (m_mode == 2) { - nt::StartClient3(m_inst, m_clientName); + nt::StartClient(m_inst, m_clientName); } - unsigned int port = m_mode == 1 ? m_port4 : m_port3; if (!wpi::contains(serverTeam, '.') && (team = wpi::parse_integer(serverTeam, 10))) { - nt::SetServerTeam(m_inst, team.value(), port); + nt::SetServerTeam(m_inst, team.value(), m_port); } else { wpi::SmallVector serverNames; std::vector> servers; wpi::split(serverTeam, serverNames, ',', -1, false); for (auto&& serverName : serverNames) { - servers.emplace_back(serverName, port); + servers.emplace_back(serverName, m_port); } nt::SetServer(m_inst, servers); } if (m_dsClient) { - nt::StartDSClient(m_inst, port); + nt::StartDSClient(m_inst, m_port); } } else if (m_mode == 3) { nt::StartServer(m_inst, m_iniName.c_str(), m_listenAddress.c_str(), - m_port3, m_port4); + m_port); } } } NetworkTablesSettings::NetworkTablesSettings(std::string_view clientName, Storage& storage, NT_Inst inst) - : m_mode{storage.GetString("mode"), - 0, - {"Disabled", "Client (NT4)", "Client (NT3)", "Server"}}, + : m_mode{storage.GetString("mode"), 0, {"Disabled", "Client", "Server"}}, m_persistentFilename{ storage.GetString("persistentFilename", "networktables.json")}, m_serverTeam{storage.GetString("serverTeam")}, m_listenAddress{storage.GetString("listenAddress")}, m_clientName{storage.GetString("clientName", clientName)}, - m_port3{storage.GetInt("port3", NT_DEFAULT_PORT3)}, - m_port4{storage.GetInt("port4", NT_DEFAULT_PORT4)}, + m_port{storage.GetInt("port", NT_DEFAULT_PORT)}, m_dsClient{storage.GetBool("dsClient", true)} { m_thread.Start(inst); } @@ -122,8 +115,7 @@ void NetworkTablesSettings::Update() { thr->m_serverTeam = m_serverTeam; thr->m_listenAddress = m_listenAddress; thr->m_clientName = m_clientName; - thr->m_port3 = m_port3; - thr->m_port4 = m_port4; + thr->m_port = m_port; thr->m_dsClient = m_dsClient; thr->m_cond.notify_one(); } @@ -137,24 +129,22 @@ static void LimitPortRange(int* port) { } bool NetworkTablesSettings::Display() { - m_mode.Combo("Mode", m_serverOption ? 4 : 3); + m_mode.Combo("Mode", m_serverOption ? 3 : 2); switch (m_mode.GetValue()) { case 1: - case 2: { ImGui::InputText("Team/IP", &m_serverTeam); if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) { ImGui::SetTooltip("Team number or IP/MDNS address of server"); } - int* port = m_mode.GetValue() == 1 ? &m_port4 : &m_port3; - if (ImGui::InputInt("Port", port)) { - LimitPortRange(port); + if (ImGui::InputInt("Port", &m_port)) { + LimitPortRange(&m_port); } if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) { ImGui::SetTooltip("TCP Port - leave this at the default"); } ImGui::SameLine(); if (ImGui::SmallButton("Default")) { - *port = m_mode.GetValue() == 1 ? NT_DEFAULT_PORT4 : NT_DEFAULT_PORT3; + m_port = NT_DEFAULT_PORT; } ImGui::InputText("Network Identity", &m_clientName); if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) { @@ -167,33 +157,22 @@ bool NetworkTablesSettings::Display() { ImGui::SetTooltip("Attempt to fetch server IP from Driver Station"); } break; - } - case 3: + case 2: ImGui::InputText("Listen Address", &m_listenAddress); if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) { ImGui::SetTooltip( "Address for server to listen on. Leave blank to listen on all " "interfaces."); } - if (ImGui::InputInt("NT3 port", &m_port3)) { - LimitPortRange(&m_port3); - } - if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) { - ImGui::SetTooltip("TCP Port for NT3. Leave at default if unsure."); - } - ImGui::SameLine(); - if (ImGui::SmallButton("Default##default3")) { - m_port3 = NT_DEFAULT_PORT3; - } - if (ImGui::InputInt("NT4 port", &m_port4)) { - LimitPortRange(&m_port4); + if (ImGui::InputInt("Port", &m_port)) { + LimitPortRange(&m_port); } if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) { ImGui::SetTooltip("TCP Port for NT4. Leave at default if unsure."); } ImGui::SameLine(); if (ImGui::SmallButton("Default##default4")) { - m_port4 = NT_DEFAULT_PORT4; + m_port = NT_DEFAULT_PORT; } ImGui::InputText("Persistent Filename", &m_persistentFilename); if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) { diff --git a/glass/src/libnt/native/include/glass/networktables/NetworkTablesSettings.h b/glass/src/libnt/native/include/glass/networktables/NetworkTablesSettings.h index 5f2ea19d78..897eb9e249 100644 --- a/glass/src/libnt/native/include/glass/networktables/NetworkTablesSettings.h +++ b/glass/src/libnt/native/include/glass/networktables/NetworkTablesSettings.h @@ -41,8 +41,7 @@ class NetworkTablesSettings { std::string& m_serverTeam; std::string& m_listenAddress; std::string& m_clientName; - int& m_port3; - int& m_port4; + int& m_port; bool& m_dsClient; class Thread : public wpi::SafeThread { @@ -58,8 +57,7 @@ class NetworkTablesSettings { std::string m_serverTeam; std::string m_listenAddress; std::string m_clientName; - int m_port3; - int m_port4; + int m_port; bool m_dsClient; }; wpi::SafeThreadOwner m_thread; diff --git a/hal/src/main/native/systemcore/SystemServer.cpp b/hal/src/main/native/systemcore/SystemServer.cpp index 584643e71b..ff38070eed 100644 --- a/hal/src/main/native/systemcore/SystemServer.cpp +++ b/hal/src/main/native/systemcore/SystemServer.cpp @@ -16,7 +16,7 @@ void InitializeSystemServer() { } ServerInstance = nt::NetworkTableInstance::Create(); ServerInstance.SetServer("localhost", ROBOT_SYSTEM_SERVER_NT_PORT); - ServerInstance.StartClient4("RobotProgram"); + ServerInstance.StartClient("RobotProgram"); } void ShutdownSystemServer() { diff --git a/ntcore/src/dev/native/cpp/main.cpp b/ntcore/src/dev/native/cpp/main.cpp index c37949a295..f2736696da 100644 --- a/ntcore/src/dev/native/cpp/main.cpp +++ b/ntcore/src/dev/native/cpp/main.cpp @@ -81,8 +81,8 @@ void bench() { auto server = nt::CreateInstance(); // connect client and server - nt::StartServer(server, "bench.json", "127.0.0.1", 0, 10000); - nt::StartClient4(client, "client"); + nt::StartServer(server, "bench.json", "127.0.0.1", 10000); + nt::StartClient(client, "client"); nt::SetServer(client, "127.0.0.1", 10000); using namespace std::chrono_literals; @@ -142,11 +142,11 @@ void bench2() { auto server = nt::CreateInstance(); // connect client and server - nt::StartServer(server, "bench2.json", "127.0.0.1", 10001, 10000); - nt::StartClient4(client1, "client1"); - nt::StartClient3(client2, "client2"); + nt::StartServer(server, "bench2.json", "127.0.0.1", 10000); + nt::StartClient(client1, "client1"); + nt::StartClient(client2, "client2"); nt::SetServer(client1, "127.0.0.1", 10000); - nt::SetServer(client2, "127.0.0.1", 10001); + nt::SetServer(client2, "127.0.0.1", 10000); using namespace std::chrono_literals; std::this_thread::sleep_for(1s); @@ -214,7 +214,7 @@ static std::uniform_real_distribution dist; void stress() { auto server = nt::CreateInstance(); - nt::StartServer(server, "stress.json", "127.0.0.1", 0, 10000); + nt::StartServer(server, "stress.json", "127.0.0.1", 10000); nt::SubscribeMultiple(server, {{std::string_view{}}}); using namespace std::chrono_literals; @@ -228,7 +228,7 @@ void stress() { std::this_thread::sleep_for(0.1s * dist(gen)); // connect - nt::StartClient4(client, "client"); + nt::StartClient(client, "client"); nt::SetServer(client, "127.0.0.1", 10000); // sleep a random amount of time @@ -308,7 +308,7 @@ void stress2() { auto client = nt::NetworkTableInstance::Create(); client.SetServer("localhost"); auto clientName = "test client"; - client.StartClient4(clientName); + client.StartClient(clientName); std::this_thread::sleep_for(2s); // Startup time. int sentCount = 0; while (sentCount < count) { diff --git a/ntcore/src/generate/main/java/NetworkTableInstance.java.jinja b/ntcore/src/generate/main/java/NetworkTableInstance.java.jinja index 6ebc879870..529b25015e 100644 --- a/ntcore/src/generate/main/java/NetworkTableInstance.java.jinja +++ b/ntcore/src/generate/main/java/NetworkTableInstance.java.jinja @@ -49,11 +49,8 @@ public final class NetworkTableInstance implements AutoCloseable { /** Running in server mode. */ kServer(0x01), - /** Running in NT3 client mode. */ - kClient3(0x02), - - /** Running in NT4 client mode. */ - kClient4(0x04), + /** Running in client mode. */ + kClient(0x04), /** Currently starting up (either client or server). */ kStarting(0x08), @@ -77,11 +74,8 @@ public final class NetworkTableInstance implements AutoCloseable { } } - /** The default port that network tables operates on for NT3. */ - public static final int kDefaultPort3 = 1735; - - /** The default port that network tables operates on for NT4. */ - public static final int kDefaultPort4 = 5810; + /** The default port that network tables operates on. */ + public static final int kDefaultPort = 5810; /** * Construct from native handle. @@ -897,7 +891,7 @@ public final class NetworkTableInstance implements AutoCloseable { * @param listenAddress the address to listen on, or empty to listen on any address */ public void startServer(String persistFilename, String listenAddress) { - startServer(persistFilename, listenAddress, kDefaultPort3, kDefaultPort4); + startServer(persistFilename, listenAddress, kDefaultPort); } /** @@ -905,22 +899,10 @@ public final class NetworkTableInstance implements AutoCloseable { * * @param persistFilename the name of the persist file to use * @param listenAddress the address to listen on, or empty to listen on any address - * @param port3 port to communicate over (NT3) + * @param port port to communicate over */ - public void startServer(String persistFilename, String listenAddress, int port3) { - startServer(persistFilename, listenAddress, port3, kDefaultPort4); - } - - /** - * Starts a server using the specified filename, listening address, and port. - * - * @param persistFilename the name of the persist file to use - * @param listenAddress the address to listen on, or empty to listen on any address - * @param port3 port to communicate over (NT3) - * @param port4 port to communicate over (NT4) - */ - public void startServer(String persistFilename, String listenAddress, int port3, int port4) { - NetworkTablesJNI.startServer(m_handle, persistFilename, listenAddress, port3, port4); + public void startServer(String persistFilename, String listenAddress, int port) { + NetworkTablesJNI.startServer(m_handle, persistFilename, listenAddress, port); } /** Stops the server if it is running. */ @@ -929,21 +911,12 @@ public final class NetworkTableInstance implements AutoCloseable { } /** - * Starts a NT3 client. Use SetServer or SetServerTeam to set the server name and port. + * Starts a client. Use SetServer or SetServerTeam to set the server name and port. * * @param identity network identity to advertise (cannot be empty string) */ - public void startClient3(String identity) { - NetworkTablesJNI.startClient3(m_handle, identity); - } - - /** - * Starts a NT4 client. Use SetServer or SetServerTeam to set the server name and port. - * - * @param identity network identity to advertise (cannot be empty string) - */ - public void startClient4(String identity) { - NetworkTablesJNI.startClient4(m_handle, identity); + public void startClient(String identity) { + NetworkTablesJNI.startClient(m_handle, identity); } /** Stops the client if it is running. */ diff --git a/ntcore/src/generate/main/java/NetworkTablesJNI.java.jinja b/ntcore/src/generate/main/java/NetworkTablesJNI.java.jinja index 628006c264..c63515d3e0 100644 --- a/ntcore/src/generate/main/java/NetworkTablesJNI.java.jinja +++ b/ntcore/src/generate/main/java/NetworkTablesJNI.java.jinja @@ -864,11 +864,10 @@ public final class NetworkTablesJNI { * @param inst NT instance handle. * @param persistFilename the name of the persist file to use * @param listenAddress the address to listen on, or empty to listen on any address - * @param port3 port to communicate over (NT3) - * @param port4 port to communicate over (NT4) + * @param port port to communicate over */ public static native void startServer( - int inst, String persistFilename, String listenAddress, int port3, int port4); + int inst, String persistFilename, String listenAddress, int port); /** * Stops the server if it is running. @@ -878,20 +877,12 @@ public final class NetworkTablesJNI { public static native void stopServer(int inst); /** - * Starts a NT3 client. Use SetServer or SetServerTeam to set the server name and port. + * Starts a client. Use SetServer or SetServerTeam to set the server name and port. * * @param inst NT instance handle. * @param identity network identity to advertise (cannot be empty string) */ - public static native void startClient3(int inst, String identity); - - /** - * Starts a NT4 client. Use SetServer or SetServerTeam to set the server name and port. - * - * @param inst NT instance handle. - * @param identity network identity to advertise (cannot be empty string) - */ - public static native void startClient4(int inst, String identity); + public static native void startClient(int inst, String identity); /** * Stops the client if it is running. diff --git a/ntcore/src/generated/main/java/edu/wpi/first/networktables/NetworkTableInstance.java b/ntcore/src/generated/main/java/edu/wpi/first/networktables/NetworkTableInstance.java index e7023d4043..361e670d83 100644 --- a/ntcore/src/generated/main/java/edu/wpi/first/networktables/NetworkTableInstance.java +++ b/ntcore/src/generated/main/java/edu/wpi/first/networktables/NetworkTableInstance.java @@ -49,11 +49,8 @@ public final class NetworkTableInstance implements AutoCloseable { /** Running in server mode. */ kServer(0x01), - /** Running in NT3 client mode. */ - kClient3(0x02), - - /** Running in NT4 client mode. */ - kClient4(0x04), + /** Running in client mode. */ + kClient(0x04), /** Currently starting up (either client or server). */ kStarting(0x08), @@ -77,11 +74,8 @@ public final class NetworkTableInstance implements AutoCloseable { } } - /** The default port that network tables operates on for NT3. */ - public static final int kDefaultPort3 = 1735; - - /** The default port that network tables operates on for NT4. */ - public static final int kDefaultPort4 = 5810; + /** The default port that network tables operates on. */ + public static final int kDefaultPort = 5810; /** * Construct from native handle. @@ -1177,7 +1171,7 @@ public final class NetworkTableInstance implements AutoCloseable { * @param listenAddress the address to listen on, or empty to listen on any address */ public void startServer(String persistFilename, String listenAddress) { - startServer(persistFilename, listenAddress, kDefaultPort3, kDefaultPort4); + startServer(persistFilename, listenAddress, kDefaultPort); } /** @@ -1185,22 +1179,10 @@ public final class NetworkTableInstance implements AutoCloseable { * * @param persistFilename the name of the persist file to use * @param listenAddress the address to listen on, or empty to listen on any address - * @param port3 port to communicate over (NT3) + * @param port port to communicate over */ - public void startServer(String persistFilename, String listenAddress, int port3) { - startServer(persistFilename, listenAddress, port3, kDefaultPort4); - } - - /** - * Starts a server using the specified filename, listening address, and port. - * - * @param persistFilename the name of the persist file to use - * @param listenAddress the address to listen on, or empty to listen on any address - * @param port3 port to communicate over (NT3) - * @param port4 port to communicate over (NT4) - */ - public void startServer(String persistFilename, String listenAddress, int port3, int port4) { - NetworkTablesJNI.startServer(m_handle, persistFilename, listenAddress, port3, port4); + public void startServer(String persistFilename, String listenAddress, int port) { + NetworkTablesJNI.startServer(m_handle, persistFilename, listenAddress, port); } /** Stops the server if it is running. */ @@ -1209,21 +1191,12 @@ public final class NetworkTableInstance implements AutoCloseable { } /** - * Starts a NT3 client. Use SetServer or SetServerTeam to set the server name and port. + * Starts a client. Use SetServer or SetServerTeam to set the server name and port. * * @param identity network identity to advertise (cannot be empty string) */ - public void startClient3(String identity) { - NetworkTablesJNI.startClient3(m_handle, identity); - } - - /** - * Starts a NT4 client. Use SetServer or SetServerTeam to set the server name and port. - * - * @param identity network identity to advertise (cannot be empty string) - */ - public void startClient4(String identity) { - NetworkTablesJNI.startClient4(m_handle, identity); + public void startClient(String identity) { + NetworkTablesJNI.startClient(m_handle, identity); } /** Stops the client if it is running. */ diff --git a/ntcore/src/generated/main/java/edu/wpi/first/networktables/NetworkTablesJNI.java b/ntcore/src/generated/main/java/edu/wpi/first/networktables/NetworkTablesJNI.java index d47add6046..4fddd9f51f 100644 --- a/ntcore/src/generated/main/java/edu/wpi/first/networktables/NetworkTablesJNI.java +++ b/ntcore/src/generated/main/java/edu/wpi/first/networktables/NetworkTablesJNI.java @@ -1404,11 +1404,10 @@ public final class NetworkTablesJNI { * @param inst NT instance handle. * @param persistFilename the name of the persist file to use * @param listenAddress the address to listen on, or empty to listen on any address - * @param port3 port to communicate over (NT3) - * @param port4 port to communicate over (NT4) + * @param port port to communicate over */ public static native void startServer( - int inst, String persistFilename, String listenAddress, int port3, int port4); + int inst, String persistFilename, String listenAddress, int port); /** * Stops the server if it is running. @@ -1418,20 +1417,12 @@ public final class NetworkTablesJNI { public static native void stopServer(int inst); /** - * Starts a NT3 client. Use SetServer or SetServerTeam to set the server name and port. + * Starts a client. Use SetServer or SetServerTeam to set the server name and port. * * @param inst NT instance handle. * @param identity network identity to advertise (cannot be empty string) */ - public static native void startClient3(int inst, String identity); - - /** - * Starts a NT4 client. Use SetServer or SetServerTeam to set the server name and port. - * - * @param inst NT instance handle. - * @param identity network identity to advertise (cannot be empty string) - */ - public static native void startClient4(int inst, String identity); + public static native void startClient(int inst, String identity); /** * Stops the client if it is running. diff --git a/ntcore/src/main/java/edu/wpi/first/networktables/ConnectionInfo.java b/ntcore/src/main/java/edu/wpi/first/networktables/ConnectionInfo.java index 147b2ea63a..1881190540 100644 --- a/ntcore/src/main/java/edu/wpi/first/networktables/ConnectionInfo.java +++ b/ntcore/src/main/java/edu/wpi/first/networktables/ConnectionInfo.java @@ -9,7 +9,7 @@ package edu.wpi.first.networktables; public final class ConnectionInfo { /** * The remote identifier (as set on the remote node by {@link - * NetworkTableInstance#startClient4(String)}). + * NetworkTableInstance#startClient(String)}). */ public final String remote_id; diff --git a/ntcore/src/main/native/cpp/InstanceImpl.cpp b/ntcore/src/main/native/cpp/InstanceImpl.cpp index fd442ccb8a..471ddcd14d 100644 --- a/ntcore/src/main/native/cpp/InstanceImpl.cpp +++ b/ntcore/src/main/native/cpp/InstanceImpl.cpp @@ -102,14 +102,14 @@ void InstanceImpl::StopLocal() { void InstanceImpl::StartServer(std::string_view persistFilename, std::string_view listenAddress, - unsigned int port3, unsigned int port4) { + unsigned int port) { std::scoped_lock lock{m_mutex}; if (networkMode != NT_NET_MODE_NONE) { return; } m_networkServer = std::make_shared( - persistFilename, listenAddress, port3, port4, localStorage, - connectionList, logger, [this] { + persistFilename, listenAddress, port, localStorage, connectionList, + logger, [this] { std::scoped_lock lock{m_mutex}; networkMode &= ~NT_NET_MODE_STARTING; }); @@ -134,20 +134,7 @@ void InstanceImpl::StopServer() { } } -void InstanceImpl::StartClient3(std::string_view identity) { - std::scoped_lock lock{m_mutex}; - if (networkMode != NT_NET_MODE_NONE) { - return; - } - m_networkClient = std::make_shared( - m_inst, identity, localStorage, connectionList, logger); - if (!m_servers.empty()) { - m_networkClient->SetServers(m_servers); - } - networkMode = NT_NET_MODE_CLIENT3; -} - -void InstanceImpl::StartClient4(std::string_view identity) { +void InstanceImpl::StartClient(std::string_view identity) { std::scoped_lock lock{m_mutex}; if (networkMode != NT_NET_MODE_NONE) { return; @@ -169,14 +156,14 @@ void InstanceImpl::StartClient4(std::string_view identity) { if (!m_servers.empty()) { m_networkClient->SetServers(m_servers); } - networkMode = NT_NET_MODE_CLIENT4; + networkMode = NT_NET_MODE_CLIENT; } void InstanceImpl::StopClient() { std::shared_ptr client; { std::scoped_lock lock{m_mutex}; - if ((networkMode & (NT_NET_MODE_CLIENT3 | NT_NET_MODE_CLIENT4)) == 0) { + if ((networkMode & NT_NET_MODE_CLIENT) == 0) { return; } client = std::move(m_networkClient); diff --git a/ntcore/src/main/native/cpp/InstanceImpl.h b/ntcore/src/main/native/cpp/InstanceImpl.h index a7b4742fa7..eefb2536ff 100644 --- a/ntcore/src/main/native/cpp/InstanceImpl.h +++ b/ntcore/src/main/native/cpp/InstanceImpl.h @@ -45,11 +45,9 @@ class InstanceImpl { void StartLocal(); void StopLocal(); void StartServer(std::string_view persistFilename, - std::string_view listenAddress, unsigned int port3, - unsigned int port4); + std::string_view listenAddress, unsigned int port); void StopServer(); - void StartClient3(std::string_view identity); - void StartClient4(std::string_view identity); + void StartClient(std::string_view identity); void StopClient(); void SetServers( std::span> servers); diff --git a/ntcore/src/main/native/cpp/NetworkClient.cpp b/ntcore/src/main/native/cpp/NetworkClient.cpp index c39d7d1dda..e01b53a9fc 100644 --- a/ntcore/src/main/native/cpp/NetworkClient.cpp +++ b/ntcore/src/main/native/cpp/NetworkClient.cpp @@ -61,7 +61,7 @@ void NetworkClientBase::StartDSClient(unsigned int port) { if (m_dsClient) { return; } - m_dsClientServer.second = port == 0 ? NT_DEFAULT_PORT4 : port; + m_dsClientServer.second = port == 0 ? NT_DEFAULT_PORT : port; m_dsClient = wpi::DsClient::Create(m_loop, m_logger); if (m_dsClient) { m_dsClient->setIp.connect([this](std::string_view ip) { @@ -142,161 +142,6 @@ void NetworkClientBase::DoDisconnect(std::string_view reason) { }); } -NetworkClient3::NetworkClient3(int inst, std::string_view id, - net::ILocalStorage& localStorage, - IConnectionList& connList, wpi::Logger& logger) - : NetworkClientBase{inst, id, localStorage, connList, logger} { - m_loopRunner.ExecAsync([this](uv::Loop& loop) { - m_parallelConnect = wpi::ParallelTcpConnector::Create( - loop, kReconnectRate, m_logger, - [this](uv::Tcp& tcp) { TcpConnected(tcp); }, true); - - m_sendOutgoingTimer = uv::Timer::Create(loop); - if (m_sendOutgoingTimer) { - m_sendOutgoingTimer->timeout.connect([this] { - if (m_clientImpl) { - HandleLocal(); - m_clientImpl->SendPeriodic(m_loop.Now().count(), false); - } - }); - } - - // set up flush async - m_flush = uv::Async<>::Create(m_loop); - if (m_flush) { - m_flush->wakeup.connect([this] { - if (m_clientImpl) { - HandleLocal(); - m_clientImpl->SendPeriodic(m_loop.Now().count(), true); - } - }); - } - m_flushAtomic = m_flush.get(); - - m_flushLocal = uv::Async<>::Create(m_loop); - if (m_flushLocal) { - m_flushLocal->wakeup.connect([this] { HandleLocal(); }); - } - m_flushLocalAtomic = m_flushLocal.get(); - }); -} - -NetworkClient3::~NetworkClient3() { - // must explicitly destroy these on loop - m_loopRunner.ExecSync([&](auto&) { - m_clientImpl.reset(); - m_wire.reset(); - }); - // shut down loop here to avoid race - m_loopRunner.Stop(); -} - -void NetworkClient3::HandleLocal() { - for (;;) { - auto msgs = m_localQueue.ReadQueue(m_localMsgs); - if (msgs.empty()) { - return; - } - if (m_clientImpl) { - m_clientImpl->HandleLocal(msgs); - } - } -} - -void NetworkClient3::TcpConnected(uv::Tcp& tcp) { - tcp.SetNoDelay(true); - - // create as shared_ptr and capture in lambda because there may be multiple - // simultaneous attempts - auto wire = std::make_shared(tcp); - auto clientImpl = std::make_shared( - m_loop.Now().count(), m_inst, *wire, m_logger, [this](uint32_t repeatMs) { - DEBUG4("Setting periodic timer to {}", repeatMs); - if (m_sendOutgoingTimer && - (!m_sendOutgoingTimer->IsActive() || - uv::Timer::Time{repeatMs} != m_sendOutgoingTimer->GetRepeat())) { - m_sendOutgoingTimer->Start(uv::Timer::Time{repeatMs}, - uv::Timer::Time{repeatMs}); - } - }); - clientImpl->Start( - m_id, [this, wire, - clientWeak = std::weak_ptr{clientImpl}, &tcp] { - auto clientImpl = clientWeak.lock(); - if (!clientImpl) { - return; - } - if (m_connList.IsConnected()) { - tcp.Close(); // no longer needed - return; - } - - if (m_parallelConnect) { - m_parallelConnect->Succeeded(tcp); - } - - m_wire = std::move(wire); - m_clientImpl = std::move(clientImpl); - - ConnectionInfo connInfo; - uv::AddrToName(tcp.GetPeer(), &connInfo.remote_ip, - &connInfo.remote_port); - connInfo.protocol_version = 0x0300; - - INFO("CONNECTED NT3 to {} port {}", connInfo.remote_ip, - connInfo.remote_port); - m_connHandle = m_connList.AddConnection(connInfo); - - tcp.error.connect([this, &tcp](uv::Error err) { - DEBUG3("NT3 TCP error {}", err.str()); - if (!tcp.IsLoopClosing()) { - // we could be in the middle of sending data, so defer disconnect - uv::Timer::SingleShot(m_loop, uv::Timer::Time{0}, - [this, reason = std::string{err.str()}] { - DoDisconnect(reason); - }); - } - }); - tcp.end.connect([this, &tcp] { - DEBUG3("NT3 TCP read ended"); - if (!tcp.IsLoopClosing()) { - DoDisconnect("remote end closed connection"); - } - }); - tcp.closed.connect([this, &tcp] { - DEBUG3("NT3 TCP connection closed"); - if (!tcp.IsLoopClosing()) { - DoDisconnect(m_wire ? m_wire->GetDisconnectReason() : "unknown"); - } - }); - - m_clientImpl->SetLocal(&m_localStorage); - m_localStorage.StartNetwork(&m_localQueue); - HandleLocal(); - }); - - tcp.SetData(clientImpl); - tcp.data.connect( - [clientImpl = clientImpl.get()](uv::Buffer& buf, size_t len) { - clientImpl->ProcessIncoming( - {reinterpret_cast(buf.base), len}); - }); - tcp.StartRead(); -} - -void NetworkClient3::ForceDisconnect(std::string_view reason) { - if (m_wire) { - m_wire->Disconnect(reason); - } -} - -void NetworkClient3::DoDisconnect(std::string_view reason) { - INFO("DISCONNECTED NT3 connection: {}", reason); - m_clientImpl.reset(); - m_wire.reset(); - NetworkClientBase::DoDisconnect(reason); -} - NetworkClient::NetworkClient( int inst, std::string_view id, net::ILocalStorage& localStorage, IConnectionList& connList, wpi::Logger& logger, diff --git a/ntcore/src/main/native/cpp/NetworkClient.h b/ntcore/src/main/native/cpp/NetworkClient.h index 77da5dd8aa..5345614b5b 100644 --- a/ntcore/src/main/native/cpp/NetworkClient.h +++ b/ntcore/src/main/native/cpp/NetworkClient.h @@ -25,8 +25,6 @@ #include "net/ClientMessageQueue.h" #include "net/Message.h" #include "net/WebSocketConnection.h" -#include "net3/ClientImpl3.h" -#include "net3/UvStreamConnection3.h" namespace wpi { class Logger; @@ -98,28 +96,6 @@ class NetworkClientBase : public INetworkClient { wpi::uv::Loop& m_loop; }; -class NetworkClient3 final : public NetworkClientBase { - public: - NetworkClient3(int inst, std::string_view id, - net::ILocalStorage& localStorage, IConnectionList& connList, - wpi::Logger& logger); - ~NetworkClient3() final; - - void SetServers( - std::span> servers) final { - DoSetServers(servers, NT_DEFAULT_PORT3); - } - - private: - void HandleLocal(); - void TcpConnected(wpi::uv::Tcp& tcp) final; - void ForceDisconnect(std::string_view reason) override; - void DoDisconnect(std::string_view reason) override; - - std::shared_ptr m_wire; - std::shared_ptr m_clientImpl; -}; - class NetworkClient final : public NetworkClientBase { public: NetworkClient( @@ -131,7 +107,7 @@ class NetworkClient final : public NetworkClientBase { void SetServers( std::span> servers) final { - DoSetServers(servers, NT_DEFAULT_PORT4); + DoSetServers(servers, NT_DEFAULT_PORT); } private: diff --git a/ntcore/src/main/native/cpp/NetworkServer.cpp b/ntcore/src/main/native/cpp/NetworkServer.cpp index 8fb419a12b..f3d0ef4681 100644 --- a/ntcore/src/main/native/cpp/NetworkServer.cpp +++ b/ntcore/src/main/native/cpp/NetworkServer.cpp @@ -34,7 +34,6 @@ #include "net/WebSocketConnection.h" #include "net/WireDecoder.h" #include "net/WireEncoder.h" -#include "net3/UvStreamConnection3.h" using namespace nt; namespace uv = wpi::uv; @@ -72,16 +71,6 @@ class NetworkServer::ServerConnection { std::shared_ptr m_outgoingTimer; }; -class NetworkServer::ServerConnection3 : public ServerConnection { - public: - ServerConnection3(std::shared_ptr stream, NetworkServer& server, - std::string_view addr, unsigned int port, - wpi::Logger& logger); - - private: - std::shared_ptr m_wire; -}; - class NetworkServer::ServerConnection4 final : public ServerConnection, public wpi::HttpWebSocketServerConnection { @@ -134,55 +123,6 @@ void NetworkServer::ServerConnection::ConnectionClosed() { m_outgoingTimer->Close(); } -NetworkServer::ServerConnection3::ServerConnection3( - std::shared_ptr stream, NetworkServer& server, - std::string_view addr, unsigned int port, wpi::Logger& logger) - : ServerConnection{server, addr, port, logger}, - m_wire{std::make_shared(*stream)} { - m_info.remote_ip = addr; - m_info.remote_port = port; - - // TODO: set local flag appropriately - m_clientId = m_server.m_serverImpl.AddClient3( - m_connInfo, false, *m_wire, - [this](std::string_view name, uint16_t proto) { - m_info.remote_id = name; - m_info.protocol_version = proto; - m_server.AddConnection(this, m_info); - INFO("CONNECTED NT3 client '{}' (from {})", name, m_connInfo); - }, - [this](uint32_t repeatMs) { UpdateOutgoingTimer(repeatMs); }); - - stream->error.connect([this](uv::Error err) { - if (!m_wire->GetDisconnectReason().empty()) { - return; - } - m_wire->Disconnect(fmt::format("stream error: {}", err.name())); - m_wire->GetStream().Shutdown([this] { m_wire->GetStream().Close(); }); - }); - stream->end.connect([this] { - if (!m_wire->GetDisconnectReason().empty()) { - return; - } - m_wire->Disconnect("remote end closed connection"); - m_wire->GetStream().Shutdown([this] { m_wire->GetStream().Close(); }); - }); - stream->closed.connect([this] { - INFO("DISCONNECTED NT3 client '{}' (from {}): {}", m_info.remote_id, - m_connInfo, m_wire->GetDisconnectReason()); - ConnectionClosed(); - }); - stream->data.connect([this](uv::Buffer& buf, size_t size) { - if (m_server.m_serverImpl.ProcessIncomingBinary( - m_clientId, {reinterpret_cast(buf.base), size})) { - m_server.m_idle->Start(); - } - }); - stream->StartRead(); - - SetupOutgoingTimer(); -} - void NetworkServer::ServerConnection4::ProcessRequest() { DEBUG1("HTTP request: '{}'", m_request.GetUrl()); wpi::UrlParser url{m_request.GetUrl(), @@ -311,8 +251,7 @@ void NetworkServer::ServerConnection4::ProcessWsUpgrade() { } NetworkServer::NetworkServer(std::string_view persistentFilename, - std::string_view listenAddress, unsigned int port3, - unsigned int port4, + std::string_view listenAddress, unsigned int port, net::ILocalStorage& localStorage, IConnectionList& connList, wpi::Logger& logger, std::function initDone) @@ -322,8 +261,7 @@ NetworkServer::NetworkServer(std::string_view persistentFilename, m_initDone{std::move(initDone)}, m_persistentFilename{persistentFilename}, m_listenAddress{wpi::trim(listenAddress)}, - m_port3{port3}, - m_port4{port4}, + m_port{port}, m_serverImpl{logger}, m_localQueue{logger}, m_loop(*m_loopRunner.GetLoop()) { @@ -485,46 +423,14 @@ void NetworkServer::Init() { }); } - INFO("Listening on NT3 port {}, NT4 port {}", m_port3, m_port4); + INFO("Listening on port {}", m_port); - if (m_port3 != 0) { - auto tcp3 = uv::Tcp::Create(m_loop); - tcp3->error.connect([logger = &m_logger](uv::Error err) { - WPI_INFO(*logger, "NT3 server socket error: {}", err.str()); - }); - tcp3->Bind(m_listenAddress, m_port3); - - // when we get a NT3 connection, accept it and start reading - tcp3->connection.connect([this, srv = tcp3.get()] { - auto tcp = srv->Accept(); - if (!tcp) { - return; - } - tcp->error.connect([logger = &m_logger](uv::Error err) { - WPI_INFO(*logger, "NT3 socket error: {}", err.str()); - }); - tcp->SetNoDelay(true); - std::string peerAddr; - unsigned int peerPort = 0; - if (uv::AddrToName(tcp->GetPeer(), &peerAddr, &peerPort) == 0) { - INFO("Got a NT3 connection from {} port {}", peerAddr, peerPort); - } else { - INFO("Got a NT3 connection from unknown"); - } - auto conn = std::make_shared(tcp, *this, peerAddr, - peerPort, m_logger); - tcp->SetData(conn); - }); - - tcp3->Listen(); - } - - if (m_port4 != 0) { + if (m_port != 0) { auto tcp4 = uv::Tcp::Create(m_loop); tcp4->error.connect([logger = &m_logger](uv::Error err) { WPI_INFO(*logger, "NT4 server socket error: {}", err.str()); }); - tcp4->Bind(m_listenAddress, m_port4); + tcp4->Bind(m_listenAddress, m_port); // when we get a NT4 connection, accept it and start reading tcp4->connection.connect([this, srv = tcp4.get()] { diff --git a/ntcore/src/main/native/cpp/NetworkServer.h b/ntcore/src/main/native/cpp/NetworkServer.h index 14e7dc95ba..3cbcbf0d2b 100644 --- a/ntcore/src/main/native/cpp/NetworkServer.h +++ b/ntcore/src/main/native/cpp/NetworkServer.h @@ -36,10 +36,9 @@ class IConnectionList; class NetworkServer { public: NetworkServer(std::string_view persistentFilename, - std::string_view listenAddress, unsigned int port3, - unsigned int port4, net::ILocalStorage& localStorage, - IConnectionList& connList, wpi::Logger& logger, - std::function initDone); + std::string_view listenAddress, unsigned int port, + net::ILocalStorage& localStorage, IConnectionList& connList, + wpi::Logger& logger, std::function initDone); ~NetworkServer(); void FlushLocal(); @@ -47,7 +46,6 @@ class NetworkServer { private: class ServerConnection; - class ServerConnection3; class ServerConnection4; void ProcessAllLocal(); @@ -64,8 +62,7 @@ class NetworkServer { std::string m_persistentData; std::string m_persistentFilename; std::string m_listenAddress; - unsigned int m_port3; - unsigned int m_port4; + unsigned int m_port; // used only from loop std::shared_ptr m_readLocalTimer; diff --git a/ntcore/src/main/native/cpp/jni/NetworkTablesJNI.cpp b/ntcore/src/main/native/cpp/jni/NetworkTablesJNI.cpp index c075518776..0c3d60d775 100644 --- a/ntcore/src/main/native/cpp/jni/NetworkTablesJNI.cpp +++ b/ntcore/src/main/native/cpp/jni/NetworkTablesJNI.cpp @@ -1173,12 +1173,12 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_stopLocal /* * Class: edu_wpi_first_networktables_NetworkTablesJNI * Method: startServer - * Signature: (ILjava/lang/String;Ljava/lang/String;II)V + * Signature: (ILjava/lang/String;Ljava/lang/String;I)V */ JNIEXPORT void JNICALL Java_edu_wpi_first_networktables_NetworkTablesJNI_startServer (JNIEnv* env, jclass, jint inst, jstring persistFilename, - jstring listenAddress, jint port3, jint port4) + jstring listenAddress, jint port) { if (!persistFilename) { nullPointerEx.Throw(env, "persistFilename cannot be null"); @@ -1189,7 +1189,7 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_startServer return; } nt::StartServer(inst, JStringRef{env, persistFilename}.str(), - JStringRef{env, listenAddress}.c_str(), port3, port4); + JStringRef{env, listenAddress}.c_str(), port); } /* @@ -1206,34 +1206,18 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_stopServer /* * Class: edu_wpi_first_networktables_NetworkTablesJNI - * Method: startClient3 + * Method: startClient * Signature: (ILjava/lang/String;)V */ JNIEXPORT void JNICALL -Java_edu_wpi_first_networktables_NetworkTablesJNI_startClient3 +Java_edu_wpi_first_networktables_NetworkTablesJNI_startClient (JNIEnv* env, jclass, jint inst, jstring identity) { if (!identity) { nullPointerEx.Throw(env, "identity cannot be null"); return; } - nt::StartClient3(inst, JStringRef{env, identity}.str()); -} - -/* - * Class: edu_wpi_first_networktables_NetworkTablesJNI - * Method: startClient4 - * Signature: (ILjava/lang/String;)V - */ -JNIEXPORT void JNICALL -Java_edu_wpi_first_networktables_NetworkTablesJNI_startClient4 - (JNIEnv* env, jclass, jint inst, jstring identity) -{ - if (!identity) { - nullPointerEx.Throw(env, "identity cannot be null"); - return; - } - nt::StartClient4(inst, JStringRef{env, identity}.str()); + nt::StartClient(inst, JStringRef{env, identity}.str()); } /* diff --git a/ntcore/src/main/native/cpp/net3/ClientImpl3.cpp b/ntcore/src/main/native/cpp/net3/ClientImpl3.cpp deleted file mode 100644 index d8813ff6ac..0000000000 --- a/ntcore/src/main/native/cpp/net3/ClientImpl3.cpp +++ /dev/null @@ -1,468 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include "ClientImpl3.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "Log.h" -#include "Types_internal.h" -#include "net/Message.h" -#include "net/NetworkInterface.h" -#include "net3/WireEncoder3.h" -#include "networktables/NetworkTableValue.h" - -using namespace nt; -using namespace nt::net3; - -static constexpr uint32_t kMinPeriodMs = 5; - -// maximum amount of time the wire can be not ready to send another -// transmission before we close the connection -static constexpr uint32_t kWireMaxNotReadyUs = 1000000; - -wpi::json ClientImpl3::Entry::SetFlags(unsigned int flags_) { - bool wasPersistent = IsPersistent(); - flags = flags_; - bool isPersistent = IsPersistent(); - if (isPersistent && !wasPersistent) { - properties["persistent"] = true; - return {{"persistent", true}}; - } else if (!isPersistent && wasPersistent) { - properties.erase("persistent"); - return {{"persistent", wpi::json()}}; - } else { - return wpi::json::object(); - } -} - -ClientImpl3::ClientImpl3(uint64_t curTimeMs, int inst, WireConnection3& wire, - wpi::Logger& logger, - std::function setPeriodic) - : m_wire{wire}, - m_logger{logger}, - m_setPeriodic{std::move(setPeriodic)}, - m_initTimeMs{curTimeMs}, - m_nextKeepAliveTimeMs{curTimeMs + kKeepAliveIntervalMs}, - m_decoder{*this} {} - -ClientImpl3::~ClientImpl3() { - DEBUG4("NT3 ClientImpl destroyed"); -} - -void ClientImpl3::ProcessIncoming(std::span data) { - DEBUG4("received {} bytes", data.size()); - if (!m_decoder.Execute(&data)) { - m_wire.Disconnect(m_decoder.GetError()); - } -} - -void ClientImpl3::HandleLocal(std::span msgs) { - for (const auto& elem : msgs) { // NOLINT - // common case is value - if (auto msg = std::get_if(&elem.contents)) { - SetValue(msg->pubuid, msg->value); - } else if (auto msg = std::get_if(&elem.contents)) { - Publish(msg->pubuid, msg->name, msg->typeStr, msg->properties, - msg->options); - } else if (auto msg = std::get_if(&elem.contents)) { - Unpublish(msg->pubuid); - } else if (auto msg = std::get_if(&elem.contents)) { - SetProperties(msg->name, msg->update); - } - } -} - -void ClientImpl3::DoSendPeriodic(uint64_t curTimeMs, bool initial, bool flush) { - DEBUG4("SendPeriodic({})", curTimeMs); - - // rate limit sends - if (curTimeMs < (m_lastSendMs + kMinPeriodMs)) { - return; - } - - auto out = m_wire.Send(); - - // send keep-alive - if (curTimeMs >= m_nextKeepAliveTimeMs) { - if (!CheckNetworkReady(curTimeMs)) { - return; - } - DEBUG4("Sending keep alive"); - WireEncodeKeepAlive(out.stream()); - // drift isn't critical here, so just go from current time - m_nextKeepAliveTimeMs = curTimeMs + kKeepAliveIntervalMs; - } - - // send any stored-up flags updates - if (!m_outgoingFlags.empty()) { - if (!CheckNetworkReady(curTimeMs)) { - return; - } - for (auto&& p : m_outgoingFlags) { - WireEncodeFlagsUpdate(out.stream(), p.first, p.second); - } - m_outgoingFlags.resize(0); - } - - // send any pending updates due to be sent - bool checkedNetwork = false; - for (auto&& pub : m_publishers) { - if (pub && !pub->outValues.empty() && - (flush || curTimeMs >= pub->nextSendMs)) { - if (!checkedNetwork) { - if (!CheckNetworkReady(curTimeMs)) { - return; - } - checkedNetwork = true; - } - for (auto&& val : pub->outValues) { - SendValue(out, pub->entry, val); - } - pub->outValues.resize(0); - pub->nextSendMs = curTimeMs + pub->periodMs; - } - } - - if (initial) { - DEBUG4("Sending ClientHelloDone"); - WireEncodeClientHelloDone(out.stream()); - } - - m_wire.Flush(); - m_lastSendMs = curTimeMs; -} - -void ClientImpl3::SendValue(Writer& out, Entry* entry, const Value& value) { - DEBUG4("sending value for '{}', seqnum {}", entry->name, - entry->seqNum.value()); - - // bump sequence number - ++entry->seqNum; - - // only send assigns during initial handshake - if (entry->id == 0xffff || m_state == kStateInitialAssignments) { - // send assign - WireEncodeEntryAssign(out.stream(), entry->name, entry->id, - entry->seqNum.value(), value, entry->flags); - } else { - // send update - WireEncodeEntryUpdate(out.stream(), entry->id, entry->seqNum.value(), - value); - } -} - -bool ClientImpl3::CheckNetworkReady(uint64_t curTimeMs) { - if (!m_wire.Ready()) { - uint64_t lastFlushTime = m_wire.GetLastFlushTime(); - uint64_t now = wpi::Now(); - if (lastFlushTime != 0 && now > (lastFlushTime + kWireMaxNotReadyUs)) { - m_wire.Disconnect("transmit stalled"); - } - return false; - } - return true; -} - -void ClientImpl3::Publish(int pubuid, std::string_view name, - std::string_view typeStr, const wpi::json& properties, - const PubSubOptionsImpl& options) { - DEBUG4("Publish('{}', '{}')", name, typeStr); - if (static_cast(pubuid) >= m_publishers.size()) { - m_publishers.resize(pubuid + 1); - } - auto& publisher = m_publishers[pubuid]; - if (!publisher) { - publisher = std::make_unique(GetOrNewEntry(name)); - publisher->entry->typeStr = typeStr; - publisher->entry->type = StringToType3(typeStr); - publisher->entry->publishers.emplace_back(publisher.get()); - } - publisher->options = options; - publisher->periodMs = std::lround(options.periodicMs / 10.0) * 10; - if (publisher->periodMs < 10) { - publisher->periodMs = 10; - } - - // update period - m_periodMs = std::gcd(m_periodMs, publisher->periodMs); - m_setPeriodic(m_periodMs); -} - -void ClientImpl3::Unpublish(int pubuid) { - DEBUG4("Unpublish({})", pubuid); - if (static_cast(pubuid) >= m_publishers.size()) { - return; - } - auto& publisher = m_publishers[pubuid]; - publisher->entry->publishers.erase( - std::remove(publisher->entry->publishers.begin(), - publisher->entry->publishers.end(), publisher.get()), - publisher->entry->publishers.end()); - publisher.reset(); - - // loop over all publishers to update period - m_periodMs = kKeepAliveIntervalMs + 10; - for (auto&& pub : m_publishers) { - if (pub) { - m_periodMs = std::gcd(m_periodMs, pub->periodMs); - } - } - m_setPeriodic(m_periodMs); -} - -void ClientImpl3::SetProperties(std::string_view name, - const wpi::json& update) { - DEBUG4("SetProperties({}, {})", name, update.dump()); - auto entry = GetOrNewEntry(name); - bool updated = false; - for (auto&& elem : update.items()) { - entry->properties[elem.key()] = elem.value(); - if (elem.key() == "persistent") { - if (auto val = elem.value().get_ptr()) { - if (*val) { - entry->flags |= NT_PERSISTENT; - } else { - entry->flags &= ~NT_PERSISTENT; - } - updated = true; - } - } - } - if (updated && entry->id == 0xffff) { - m_outgoingFlags.emplace_back(entry->id, entry->flags); - } -} - -void ClientImpl3::SetValue(int pubuid, const Value& value) { - DEBUG4("SetValue({})", pubuid); - assert(static_cast(pubuid) < m_publishers.size() && - m_publishers[pubuid]); - auto& publisher = *m_publishers[pubuid]; - if (value == publisher.entry->value) { - return; - } - publisher.entry->value = value; - if (publisher.outValues.empty() || publisher.options.sendAll) { - publisher.outValues.emplace_back(value); - } else { - publisher.outValues.back() = value; - } -} - -void ClientImpl3::KeepAlive() { - DEBUG4("KeepAlive()"); - if (m_state != kStateRunning && m_state != kStateInitialAssignments) { - m_decoder.SetError("received unexpected KeepAlive message"); - return; - } - // ignore -} - -void ClientImpl3::ServerHelloDone() { - DEBUG4("ServerHelloDone()"); - if (m_state != kStateInitialAssignments) { - m_decoder.SetError("received unexpected ServerHelloDone message"); - return; - } - - // send initial assignments - DoSendPeriodic(m_initTimeMs, true, true); - - m_state = kStateRunning; - m_setPeriodic(m_periodMs); -} - -void ClientImpl3::ClientHelloDone() { - DEBUG4("ClientHelloDone()"); - m_decoder.SetError("received unexpected ClientHelloDone message"); -} - -void ClientImpl3::ProtoUnsup(unsigned int proto_rev) { - DEBUG4("ProtoUnsup({})", proto_rev); - m_decoder.SetError(fmt::format("received ProtoUnsup(version={})", proto_rev)); -} - -void ClientImpl3::ClientHello(std::string_view self_id, - unsigned int proto_rev) { - DEBUG4("ClientHello({}, {})", self_id, proto_rev); - m_decoder.SetError("received unexpected ClientHello message"); -} - -void ClientImpl3::ServerHello(unsigned int flags, std::string_view self_id) { - DEBUG4("ServerHello({}, {})", flags, self_id); - if (m_state != kStateHelloSent) { - m_decoder.SetError("received unexpected ServerHello message"); - return; - } - m_state = kStateInitialAssignments; - m_remoteId = self_id; - m_handshakeSucceeded(); - m_handshakeSucceeded = nullptr; // no longer required -} - -void ClientImpl3::EntryAssign(std::string_view name, unsigned int id, - unsigned int seq_num, const Value& value, - unsigned int flags) { - DEBUG4("EntryAssign({}, {}, {}, value, {})", name, id, seq_num, flags); - if (m_state != kStateInitialAssignments && m_state != kStateRunning) { - m_decoder.SetError("received unexpected EntryAssign message"); - return; - } - auto entry = GetOrNewEntry(name); - bool flagsChanged = entry->flags != flags; - bool typeChanged; - bool valueChanged; - - // don't update value if we locally published a "strong" value - if (m_state == kStateInitialAssignments && entry->value && - entry->value.server_time() != 0) { - typeChanged = false; - valueChanged = false; - } else { - typeChanged = entry->type != value.type(); - valueChanged = entry->value != value; - if (m_state == kStateInitialAssignments) { - // remove outgoing during initial assignments so we don't get out of sync - for (auto publisher : entry->publishers) { - publisher->outValues.clear(); - } - } - } - - entry->id = id; - entry->seqNum = SequenceNumber{seq_num}; - entry->SetFlags(flags); - if (typeChanged) { - entry->type = value.type(); - entry->typeStr = TypeToString(value.type()); - } - if (valueChanged) { - entry->value = value; - } - - // add to id map - if (id >= m_idMap.size()) { - m_idMap.resize(id + 1); - } - m_idMap[id] = entry; - - if (m_local) { - // XXX: need to handle type change specially? (e.g. with unannounce) - if (!entry->topic || flagsChanged || typeChanged) { - DEBUG4("NetworkAnnounce({}, {})", name, entry->typeStr); - entry->topic = m_local->ServerAnnounce(name, 0, entry->typeStr, - entry->properties, std::nullopt); - } - if (valueChanged) { - m_local->ServerSetValue(entry->topic.value(), entry->value); - } - } -} - -void ClientImpl3::EntryUpdate(unsigned int id, unsigned int seq_num, - const Value& value) { - DEBUG4("EntryUpdate({}, {}, value)", id, seq_num); - if (m_state != kStateRunning) { - m_decoder.SetError("received EntryUpdate message before ServerHelloDone"); - return; - } - if (auto entry = LookupId(id)) { - entry->value = value; - if (m_local && entry->topic) { - m_local->ServerSetValue(entry->topic.value(), entry->value); - } - } -} - -void ClientImpl3::FlagsUpdate(unsigned int id, unsigned int flags) { - DEBUG4("FlagsUpdate({}, {})", id, flags); - if (m_state != kStateRunning) { - m_decoder.SetError("received FlagsUpdate message before ServerHelloDone"); - return; - } - if (auto entry = LookupId(id)) { - wpi::json update = entry->SetFlags(flags); - if (!update.empty() && m_local) { - m_local->ServerPropertiesUpdate(entry->name, update, false); - } - } - - // erase any outgoing flags updates - m_outgoingFlags.erase( - std::remove_if(m_outgoingFlags.begin(), m_outgoingFlags.end(), - [&](const auto& p) { return p.first == id; }), - m_outgoingFlags.end()); -} - -void ClientImpl3::EntryDelete(unsigned int id) { - DEBUG4("EntryDelete({})", id); - if (m_state != kStateRunning) { - m_decoder.SetError("received EntryDelete message before ServerHelloDone"); - return; - } - if (auto entry = LookupId(id)) { - m_idMap[id] = nullptr; - // set id to 0xffff so any future local setvalue will result in assign - entry->id = 0xffff; - entry->value = Value{}; - - // if we have no local publishers, unannounce - if (entry->publishers.empty() && m_local && entry->topic) { - m_local->ServerUnannounce(entry->name, entry->topic.value()); - } - } - - // erase any outgoing flags updates - m_outgoingFlags.erase( - std::remove_if(m_outgoingFlags.begin(), m_outgoingFlags.end(), - [&](const auto& p) { return p.first == id; }), - m_outgoingFlags.end()); -} - -void ClientImpl3::ClearEntries() { - DEBUG4("ClearEntries()"); - if (m_state != kStateRunning) { - m_decoder.SetError("received ClearEntries message before ServerHelloDone"); - return; - } - for (auto& entry : m_idMap) { - if (entry && entry->id != 0xffff && !entry->IsPersistent()) { - entry->id = 0xffff; - entry->value = Value{}; - - // if we have no local publishers, unannounce - if (entry->publishers.empty() && m_local && entry->topic) { - m_local->ServerUnannounce(entry->name, entry->topic.value()); - } - - entry = nullptr; // clear id mapping - } - } - - // erase all outgoing flags updates - m_outgoingFlags.resize(0); -} - -void ClientImpl3::Start(std::string_view selfId, - std::function succeeded) { - if (m_state != kStateInitial) { - return; - } - m_handshakeSucceeded = std::move(succeeded); - auto writer = m_wire.Send(); - WireEncodeClientHello(writer.stream(), selfId, 0x0300); - m_wire.Flush(); - m_state = kStateHelloSent; -} diff --git a/ntcore/src/main/native/cpp/net3/ClientImpl3.h b/ntcore/src/main/native/cpp/net3/ClientImpl3.h deleted file mode 100644 index f31b27ce34..0000000000 --- a/ntcore/src/main/native/cpp/net3/ClientImpl3.h +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "PubSubOptions.h" -#include "net/MessageHandler.h" -#include "net3/Message3.h" -#include "net3/SequenceNumber.h" -#include "net3/WireConnection3.h" -#include "net3/WireDecoder3.h" - -namespace wpi { -class Logger; -} // namespace wpi - -namespace nt::net { -struct ClientMessage; -class LocalInterface; -} // namespace nt::net - -namespace nt::net3 { - -class WireConnection3; - -class ClientImpl3 final : private MessageHandler3 { - public: - explicit ClientImpl3(uint64_t curTimeMs, int inst, WireConnection3& wire, - wpi::Logger& logger, - std::function setPeriodic); - ~ClientImpl3() final; - - void Start(std::string_view selfId, std::function succeeded); - void ProcessIncoming(std::span data); - void HandleLocal(std::span msgs); - - void SendPeriodic(uint64_t curTimeMs, bool flush) { - DoSendPeriodic(curTimeMs, false, flush); - } - - void SetLocal(net::ServerMessageHandler* local) { m_local = local; } - - private: - struct Entry; - - struct PublisherData { - explicit PublisherData(Entry* entry) : entry{entry} {} - - Entry* entry; - PubSubOptionsImpl options; - // in options as double, but copy here as integer; rounded to the nearest - // 10 ms - uint32_t periodMs; - uint64_t nextSendMs{0}; - std::vector outValues; // outgoing values - }; - - // data for each entry - struct Entry { - explicit Entry(std::string_view name_) : name(name_) {} - bool IsPersistent() const { return (flags & NT_PERSISTENT) != 0; } - wpi::json SetFlags(unsigned int flags_); - - std::string name; - - std::string typeStr; - NT_Type type{NT_UNASSIGNED}; - - wpi::json properties = wpi::json::object(); - - // The current value and flags - Value value; - unsigned int flags{0}; - - // Unique ID used in network messages; this is 0xffff until assigned - // by the server. - unsigned int id{0xffff}; - - // Sequence number for update resolution - SequenceNumber seqNum; - - // Local topic id - std::optional topic; - - // Local publishers - std::vector publishers; - }; - - void DoSendPeriodic(uint64_t curTimeMs, bool initial, bool flush); - void SendValue(Writer& out, Entry* entry, const Value& value); - bool CheckNetworkReady(uint64_t curTimeMs); - - // Outgoing handlers - void Publish(int pubuid, std::string_view name, std::string_view typeStr, - const wpi::json& properties, const PubSubOptionsImpl& options); - void Unpublish(int pubuid); - void SetProperties(std::string_view name, const wpi::json& update); - void SetValue(int pubuid, const Value& value); - - // MessageHandler interface - void KeepAlive() final; - void ServerHelloDone() final; - void ClientHelloDone() final; - void ClearEntries() final; - void ProtoUnsup(unsigned int proto_rev) final; - void ClientHello(std::string_view self_id, unsigned int proto_rev) final; - void ServerHello(unsigned int flags, std::string_view self_id) final; - void EntryAssign(std::string_view name, unsigned int id, unsigned int seq_num, - const Value& value, unsigned int flags) final; - void EntryUpdate(unsigned int id, unsigned int seq_num, - const Value& value) final; - void FlagsUpdate(unsigned int id, unsigned int flags) final; - void EntryDelete(unsigned int id) final; - void ExecuteRpc(unsigned int id, unsigned int uid, - std::span params) final {} - void RpcResponse(unsigned int id, unsigned int uid, - std::span result) final {} - - enum State { - kStateInitial, - kStateHelloSent, - kStateInitialAssignments, - kStateRunning - }; - - WireConnection3& m_wire; - wpi::Logger& m_logger; - net::ServerMessageHandler* m_local{nullptr}; - std::function m_setPeriodic; - uint64_t m_initTimeMs; - - // periodic sweep handling - static constexpr uint32_t kKeepAliveIntervalMs = 1000; - uint32_t m_periodMs{kKeepAliveIntervalMs + 10}; - uint64_t m_lastSendMs{0}; - uint64_t m_nextKeepAliveTimeMs; - - // indexed by publisher index - std::vector> m_publishers; - - State m_state{kStateInitial}; - WireDecoder3 m_decoder; - std::string m_remoteId; - std::function m_handshakeSucceeded; - - std::vector> m_outgoingFlags; - - using NameMap = wpi::StringMap; - using IdMap = std::vector; - - NameMap m_nameMap; - IdMap m_idMap; - - Entry* GetOrNewEntry(std::string_view name) { - return &m_nameMap.try_emplace(name, name).first->second; - } - Entry* LookupId(unsigned int id) { - return id < m_idMap.size() ? m_idMap[id] : nullptr; - } -}; - -} // namespace nt::net3 diff --git a/ntcore/src/main/native/cpp/net3/Message3.h b/ntcore/src/main/native/cpp/net3/Message3.h deleted file mode 100644 index ebac75f966..0000000000 --- a/ntcore/src/main/native/cpp/net3/Message3.h +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#include - -#include -#include - -#include "networktables/NetworkTableValue.h" -#include "ntcore_c.h" - -namespace nt::net3 { - -class WireDecoder3; - -class Message3 { - struct private_init {}; - friend class WireDecoder3; - - public: - enum MsgType { - kUnknown = -1, - kKeepAlive = 0x00, - kClientHello = 0x01, - kProtoUnsup = 0x02, - kServerHelloDone = 0x03, - kServerHello = 0x04, - kClientHelloDone = 0x05, - kEntryAssign = 0x10, - kEntryUpdate = 0x11, - kFlagsUpdate = 0x12, - kEntryDelete = 0x13, - kClearEntries = 0x14, - kExecuteRpc = 0x20, - kRpcResponse = 0x21 - }; - enum DataType { - kBoolean = 0x00, - kDouble = 0x01, - kString = 0x02, - kRaw = 0x03, - kBooleanArray = 0x10, - kDoubleArray = 0x11, - kStringArray = 0x12, - kRpcDef = 0x20 - }; - static constexpr uint32_t kClearAllMagic = 0xD06CB27Aul; - - Message3() = default; - Message3(MsgType type, const private_init&) : m_type(type) {} - - MsgType type() const { return m_type; } - bool Is(MsgType type) const { return type == m_type; } - - // Message data accessors. Callers are responsible for knowing what data is - // actually provided for a particular message. - std::string_view str() const { return m_str; } - std::span bytes() const { - return {reinterpret_cast(m_str.data()), m_str.size()}; - } - const Value& value() const { return m_value; } - unsigned int id() const { return m_id; } - unsigned int flags() const { return m_flags; } - unsigned int seq_num_uid() const { return m_seq_num_uid; } - - void SetValue(const Value& value) { m_value = value; } - - // Create messages without data - static Message3 KeepAlive() { return {kKeepAlive, {}}; } - static Message3 ServerHelloDone() { return {kServerHelloDone, {}}; } - static Message3 ClientHelloDone() { return {kClientHelloDone, {}}; } - static Message3 ClearEntries() { return {kClearEntries, {}}; } - - // Create messages with data - static Message3 ProtoUnsup(unsigned int proto_rev = 0x0300u) { - Message3 msg{kProtoUnsup, {}}; - msg.m_id = proto_rev; - return msg; - } - static Message3 ClientHello(std::string_view self_id, - unsigned int proto_rev = 0x0300u) { - Message3 msg{kClientHello, {}}; - msg.m_str = self_id; - msg.m_id = proto_rev; - return msg; - } - static Message3 ServerHello(unsigned int flags, std::string_view self_id) { - Message3 msg{kServerHello, {}}; - msg.m_str = self_id; - msg.m_flags = flags; - return msg; - } - static Message3 EntryAssign(std::string_view name, unsigned int id, - unsigned int seq_num, const Value& value, - unsigned int flags) { - Message3 msg{kEntryAssign, {}}; - msg.m_str = name; - msg.m_value = value; - msg.m_id = id; - msg.m_flags = flags; - msg.m_seq_num_uid = seq_num; - return msg; - } - static Message3 EntryUpdate(unsigned int id, unsigned int seq_num, - const Value& value) { - Message3 msg{kEntryUpdate, {}}; - msg.m_value = value; - msg.m_id = id; - msg.m_seq_num_uid = seq_num; - return msg; - } - static Message3 FlagsUpdate(unsigned int id, unsigned int flags) { - Message3 msg{kFlagsUpdate, {}}; - msg.m_id = id; - msg.m_flags = flags; - return msg; - } - static Message3 EntryDelete(unsigned int id) { - Message3 msg{kEntryDelete, {}}; - msg.m_id = id; - return msg; - } - static Message3 ExecuteRpc(unsigned int id, unsigned int uid, - std::span params) { - Message3 msg{kExecuteRpc, {}}; - msg.m_str.assign(reinterpret_cast(params.data()), - params.size()); - msg.m_id = id; - msg.m_seq_num_uid = uid; - return msg; - } - static Message3 RpcResponse(unsigned int id, unsigned int uid, - std::span result) { - Message3 msg{kRpcResponse, {}}; - msg.m_str.assign(reinterpret_cast(result.data()), - result.size()); - msg.m_id = id; - msg.m_seq_num_uid = uid; - return msg; - } - - private: - MsgType m_type{kUnknown}; - - // Message data. Use varies by message type. - std::string m_str; - Value m_value; - unsigned int m_id{0}; // also used for proto_rev - unsigned int m_flags{0}; - unsigned int m_seq_num_uid{0}; -}; - -} // namespace nt::net3 diff --git a/ntcore/src/main/native/cpp/net3/SequenceNumber.h b/ntcore/src/main/native/cpp/net3/SequenceNumber.h deleted file mode 100644 index d8bf995172..0000000000 --- a/ntcore/src/main/native/cpp/net3/SequenceNumber.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#include - -namespace nt::net3 { - -/* A sequence number per RFC 1982 */ -class SequenceNumber { - public: - SequenceNumber() = default; - explicit SequenceNumber(unsigned int value) : m_value(value) {} - unsigned int value() const { return m_value; } - - SequenceNumber& operator++() { - ++m_value; - if (m_value > 0xffff) { - m_value = 0; - } - return *this; - } - SequenceNumber operator++(int) { - SequenceNumber tmp(*this); - operator++(); - return tmp; - } - - friend auto operator<=>(const SequenceNumber& lhs, - const SequenceNumber& rhs) = default; - - private: - unsigned int m_value{0}; -}; - -} // namespace nt::net3 diff --git a/ntcore/src/main/native/cpp/net3/UvStreamConnection3.cpp b/ntcore/src/main/native/cpp/net3/UvStreamConnection3.cpp deleted file mode 100644 index efc45348b0..0000000000 --- a/ntcore/src/main/native/cpp/net3/UvStreamConnection3.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include "UvStreamConnection3.h" - -#include -#include - -using namespace nt; -using namespace nt::net3; - -static constexpr size_t kMaxPoolSize = 16; - -UvStreamConnection3::UvStreamConnection3(wpi::uv::Stream& stream) - : m_stream{stream}, m_os{m_buffers, [this] { return AllocBuf(); }} {} - -UvStreamConnection3::~UvStreamConnection3() { - for (auto&& buf : m_buf_pool) { - buf.Deallocate(); - } -} - -void UvStreamConnection3::Flush() { - if (m_buffers.empty()) { - return; - } - ++m_sendsActive; - m_stream.Write(m_buffers, [selfweak = weak_from_this()](auto bufs, auto) { - if (auto self = selfweak.lock()) { -#ifdef __SANITIZE_ADDRESS__ - size_t numToPool = 0; -#else - size_t numToPool = - (std::min)(bufs.size(), kMaxPoolSize - self->m_buf_pool.size()); - self->m_buf_pool.insert(self->m_buf_pool.end(), bufs.begin(), - bufs.begin() + numToPool); -#endif - for (auto&& buf : bufs.subspan(numToPool)) { - buf.Deallocate(); - } - if (self->m_sendsActive > 0) { - --self->m_sendsActive; - } - } - }); - m_buffers.clear(); - m_os.reset(); - m_lastFlushTime = wpi::Now(); -} - -void UvStreamConnection3::Disconnect(std::string_view reason) { - m_reason = reason; - m_stream.Close(); -} - -void UvStreamConnection3::FinishSend() {} - -wpi::uv::Buffer UvStreamConnection3::AllocBuf() { - if (!m_buf_pool.empty()) { - auto buf = m_buf_pool.back(); - m_buf_pool.pop_back(); - return buf; - } - return wpi::uv::Buffer::Allocate(kAllocSize); -} diff --git a/ntcore/src/main/native/cpp/net3/UvStreamConnection3.h b/ntcore/src/main/native/cpp/net3/UvStreamConnection3.h deleted file mode 100644 index 6cb81eea00..0000000000 --- a/ntcore/src/main/native/cpp/net3/UvStreamConnection3.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "net3/WireConnection3.h" - -namespace wpi::uv { -class Stream; -} // namespace wpi::uv - -namespace nt::net3 { - -class UvStreamConnection3 final - : public WireConnection3, - public std::enable_shared_from_this { - static constexpr size_t kAllocSize = 4096; - - public: - explicit UvStreamConnection3(wpi::uv::Stream& stream); - ~UvStreamConnection3() override; - UvStreamConnection3(const UvStreamConnection3&) = delete; - UvStreamConnection3& operator=(const UvStreamConnection3&) = delete; - - bool Ready() const final { return m_sendsActive == 0; } - - Writer Send() final { return {m_os, *this}; } - - void Flush() final; - - uint64_t GetLastFlushTime() const final { return m_lastFlushTime; } - - void StopRead() final { - if (m_readActive) { - m_stream.StopRead(); - m_readActive = false; - } - } - void StartRead() final { - if (!m_readActive) { - m_stream.StartRead(); - m_readActive = true; - } - } - - void Disconnect(std::string_view reason) final; - - std::string_view GetDisconnectReason() const { return m_reason; } - - wpi::uv::Stream& GetStream() { return m_stream; } - - private: - void FinishSend() final; - - wpi::uv::Buffer AllocBuf(); - - wpi::uv::Stream& m_stream; - wpi::SmallVector m_buffers; - std::vector m_buf_pool; - wpi::raw_uv_ostream m_os; - std::string m_reason; - uint64_t m_lastFlushTime = 0; - int m_sendsActive = 0; - bool m_readActive = true; -}; - -} // namespace nt::net3 diff --git a/ntcore/src/main/native/cpp/net3/WireConnection3.h b/ntcore/src/main/native/cpp/net3/WireConnection3.h deleted file mode 100644 index 0d62c8fc89..0000000000 --- a/ntcore/src/main/native/cpp/net3/WireConnection3.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#include - -#include - -namespace wpi { -class raw_ostream; -} // namespace wpi - -namespace nt::net3 { - -class Writer; - -class WireConnection3 { - friend class Writer; - - public: - virtual ~WireConnection3() = default; - - virtual bool Ready() const = 0; - - virtual Writer Send() = 0; - - virtual void Flush() = 0; - - virtual uint64_t GetLastFlushTime() const = 0; // in microseconds - - virtual void StopRead() = 0; - virtual void StartRead() = 0; - - virtual void Disconnect(std::string_view reason) = 0; - - protected: - virtual void FinishSend() = 0; -}; - -class Writer { - public: - Writer(wpi::raw_ostream& os, WireConnection3& wire) - : m_os{&os}, m_wire{&wire} {} - Writer(const Writer&) = delete; - Writer(Writer&& rhs) : m_os{rhs.m_os}, m_wire{rhs.m_wire} { - rhs.m_os = nullptr; - rhs.m_wire = nullptr; - } - ~Writer() { - if (m_wire) { - m_wire->FinishSend(); - } - } - Writer& operator=(const Writer&) = delete; - Writer& operator=(Writer&& rhs) { - m_os = rhs.m_os; - m_wire = rhs.m_wire; - rhs.m_os = nullptr; - rhs.m_wire = nullptr; - return *this; - } - - wpi::raw_ostream& stream() { return *m_os; } - - private: - wpi::raw_ostream* m_os; - WireConnection3* m_wire; -}; - -} // namespace nt::net3 diff --git a/ntcore/src/main/native/cpp/net3/WireDecoder3.cpp b/ntcore/src/main/native/cpp/net3/WireDecoder3.cpp deleted file mode 100644 index dea6349b01..0000000000 --- a/ntcore/src/main/native/cpp/net3/WireDecoder3.cpp +++ /dev/null @@ -1,458 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include "WireDecoder3.h" - -#include -#include -#include -#include - -#include -#include - -#include "Message3.h" - -using namespace nt; -using namespace nt::net3; - -static uint8_t Read8(std::span* in) { - uint8_t val = in->front(); - *in = wpi::drop_front(*in); - return val; -} - -std::optional WireDecoder3::SimpleValueReader::Read16( - std::span* in) { - while (!in->empty()) { - m_value <<= 8; - m_value |= in->front() & 0xff; - *in = wpi::drop_front(*in); - if (++m_count >= 2) { - uint16_t val = static_cast(m_value); - m_count = 0; - m_value = 0; - return val; - } - } - return std::nullopt; -} - -std::optional WireDecoder3::SimpleValueReader::Read32( - std::span* in) { - while (!in->empty()) { - m_value <<= 8; - m_value |= in->front() & 0xff; - *in = wpi::drop_front(*in); - if (++m_count >= 4) { - uint32_t val = static_cast(m_value); - m_count = 0; - m_value = 0; - return val; - } - } - return std::nullopt; -} - -std::optional WireDecoder3::SimpleValueReader::Read64( - std::span* in) { - while (!in->empty()) { - m_value <<= 8; - m_value |= in->front() & 0xff; - *in = wpi::drop_front(*in); - if (++m_count >= 8) { - uint64_t val = m_value; - m_count = 0; - m_value = 0; - return val; - } - } - return std::nullopt; -} - -std::optional WireDecoder3::SimpleValueReader::ReadDouble( - std::span* in) { - if (auto val = Read64(in)) { - return std::bit_cast(val.value()); - } else { - return std::nullopt; - } -} - -void WireDecoder3::DoExecute(std::span* in) { - while (!in->empty()) { - switch (m_state) { - case kStart: { - uint8_t msgType = Read8(in); - switch (msgType) { - case Message3::kKeepAlive: - m_out.KeepAlive(); - break; - case Message3::kClientHello: - m_state = kClientHello_1ProtoRev; - break; - case Message3::kProtoUnsup: - m_state = kProtoUnsup_1ProtoRev; - break; - case Message3::kServerHello: - m_state = kServerHello_1Flags; - break; - case Message3::kServerHelloDone: - m_out.ServerHelloDone(); - break; - case Message3::kClientHelloDone: - m_out.ClientHelloDone(); - break; - case Message3::kEntryAssign: - m_state = kEntryAssign_1Name; - break; - case Message3::kEntryUpdate: - m_state = kEntryUpdate_1Id; - break; - case Message3::kFlagsUpdate: - m_state = kFlagsUpdate_1Id; - break; - case Message3::kEntryDelete: - m_state = kEntryDelete_1Id; - break; - case Message3::kClearEntries: - m_state = kClearEntries_1Magic; - break; - case Message3::kExecuteRpc: - m_state = kExecuteRpc_1Id; - break; - case Message3::kRpcResponse: - m_state = kRpcResponse_1Id; - break; - default: - EmitError(fmt::format("unrecognized message type: {}", - static_cast(msgType))); - return; - } - break; - } - case kClientHello_1ProtoRev: - if (auto val = m_simpleReader.Read16(in)) { - if (val < 0x0300u) { - m_state = kStart; - m_out.ClientHello("", val.value()); - } else { - m_state = kClientHello_2Id; - m_id = val.value(); - } - } - break; - case kClientHello_2Id: - if (auto val = ReadString(in)) { - m_state = kStart; - m_out.ClientHello(val.value(), m_id); - } - break; - case kProtoUnsup_1ProtoRev: - if (auto val = m_simpleReader.Read16(in)) { - m_state = kStart; - m_out.ProtoUnsup(val.value()); - } - break; - case kServerHello_1Flags: { - m_state = kServerHello_2Id; - m_flags = Read8(in); - break; - } - case kServerHello_2Id: - if (auto val = ReadString(in)) { - m_state = kStart; - m_out.ServerHello(m_flags, val.value()); - } - break; - case kEntryAssign_1Name: - if (auto val = ReadString(in)) { - m_state = kEntryAssign_2Type; - m_str = std::move(val.value()); - } - break; - case kEntryAssign_2Type: - if (auto val = ReadType(in)) { - m_state = kEntryAssign_3Id; - m_valueReader = ValueReader{val.value()}; - } - break; - case kEntryAssign_3Id: - if (auto val = m_simpleReader.Read16(in)) { - m_state = kEntryAssign_4SeqNum; - m_id = val.value(); - } - break; - case kEntryAssign_4SeqNum: - if (auto val = m_simpleReader.Read16(in)) { - m_state = kEntryAssign_5Flags; - m_seq_num_uid = val.value(); - } - break; - case kEntryAssign_5Flags: { - m_state = kEntryAssign_6Value; - m_flags = Read8(in); - break; - } - case kEntryAssign_6Value: - if (auto val = ReadValue(in)) { - m_state = kStart; - m_out.EntryAssign(m_str, m_id, m_seq_num_uid, val.value(), m_flags); - } - break; - case kEntryUpdate_1Id: - if (auto val = m_simpleReader.Read16(in)) { - m_state = kEntryUpdate_2SeqNum; - m_id = val.value(); - } - break; - case kEntryUpdate_2SeqNum: - if (auto val = m_simpleReader.Read16(in)) { - m_state = kEntryUpdate_3Type; - m_seq_num_uid = val.value(); - } - break; - case kEntryUpdate_3Type: - if (auto val = ReadType(in)) { - m_state = kEntryUpdate_4Value; - m_valueReader = ValueReader{val.value()}; - } - break; - case kEntryUpdate_4Value: - if (auto val = ReadValue(in)) { - m_state = kStart; - m_out.EntryUpdate(m_id, m_seq_num_uid, val.value()); - } - break; - case kFlagsUpdate_1Id: - if (auto val = m_simpleReader.Read16(in)) { - m_state = kFlagsUpdate_2Flags; - m_id = val.value(); - } - break; - case kFlagsUpdate_2Flags: { - m_state = kStart; - m_out.FlagsUpdate(m_id, Read8(in)); - break; - } - case kEntryDelete_1Id: - if (auto val = m_simpleReader.Read16(in)) { - m_state = kStart; - m_out.EntryDelete(val.value()); - } - break; - case kClearEntries_1Magic: - if (auto val = m_simpleReader.Read32(in)) { - m_state = kStart; - if (val.value() == Message3::kClearAllMagic) { - m_out.ClearEntries(); - } else { - EmitError("received incorrect CLEAR_ENTRIES magic value"); - } - break; - } - break; - case kExecuteRpc_1Id: - if (auto val = m_simpleReader.Read16(in)) { - m_state = kExecuteRpc_2Uid; - m_id = val.value(); - } - break; - case kExecuteRpc_2Uid: - if (auto val = m_simpleReader.Read16(in)) { - m_state = kExecuteRpc_3Params; - m_seq_num_uid = val.value(); - } - break; - case kExecuteRpc_3Params: - if (auto val = ReadRaw(in)) { - m_state = kStart; - m_out.ExecuteRpc(m_id, m_seq_num_uid, val.value()); - } - break; - case kRpcResponse_1Id: - if (auto val = m_simpleReader.Read16(in)) { - m_state = kRpcResponse_2Uid; - m_id = val.value(); - } - break; - case kRpcResponse_2Uid: - if (auto val = m_simpleReader.Read16(in)) { - m_state = kRpcResponse_3Result; - m_seq_num_uid = val.value(); - } - break; - case kRpcResponse_3Result: - if (auto val = ReadRaw(in)) { - m_state = kStart; - m_out.RpcResponse(m_id, m_seq_num_uid, val.value()); - } - break; - case kError: - return; - } - } -} - -std::optional WireDecoder3::ReadString( - std::span* in) { - // string length - if (!m_stringReader.len) { - if (auto val = m_ulebReader.ReadOne(in)) { - m_stringReader.SetLen(val.value()); - m_stringReader.buf.clear(); - } else { - return std::nullopt; - } - } - - // string data; nolint to avoid clang-tidy false positive - size_t toCopy = - (std::min)(in->size(), - static_cast(m_stringReader.len.value() - - m_stringReader.buf.size())); // NOLINT - m_stringReader.buf.append(reinterpret_cast(in->data()), toCopy); - *in = wpi::drop_front(*in, toCopy); - if (m_stringReader.buf.size() >= m_stringReader.len) { - m_stringReader.len.reset(); - return std::move(m_stringReader.buf); - } - return std::nullopt; -} - -std::optional> WireDecoder3::ReadRaw( - std::span* in) { - // string length - if (!m_rawReader.len) { - if (auto val = m_ulebReader.ReadOne(in)) { - m_rawReader.SetLen(val.value()); - m_rawReader.buf.clear(); - } else { - return std::nullopt; - } - } - - // string data - size_t toCopy = (std::min)( - static_cast(in->size()), - static_cast(m_rawReader.len.value() - m_rawReader.buf.size())); - m_rawReader.buf.insert(m_rawReader.buf.end(), in->begin(), - in->begin() + toCopy); - *in = wpi::drop_front(*in, toCopy); - if (m_rawReader.buf.size() >= m_rawReader.len) { - m_rawReader.len.reset(); - return std::move(m_rawReader.buf); - } - return std::nullopt; -} - -std::optional WireDecoder3::ReadType(std::span* in) { - // Convert from byte value to enum - switch (Read8(in)) { - case Message3::kBoolean: - return NT_BOOLEAN; - case Message3::kDouble: - return NT_DOUBLE; - case Message3::kString: - return NT_STRING; - case Message3::kRaw: - return NT_RAW; - case Message3::kBooleanArray: - return NT_BOOLEAN_ARRAY; - case Message3::kDoubleArray: - return NT_DOUBLE_ARRAY; - case Message3::kStringArray: - return NT_STRING_ARRAY; - case Message3::kRpcDef: - return NT_RPC; - default: - return EmitError("unrecognized value type"); - } -} - -std::optional WireDecoder3::ReadValue(std::span* in) { - while (!in->empty()) { - switch (m_valueReader.type) { - case NT_BOOLEAN: - return Value::MakeBoolean(Read8(in) != 0); - case NT_DOUBLE: - if (auto val = m_simpleReader.ReadDouble(in)) { - return Value::MakeDouble(val.value()); - } - break; - case NT_STRING: - if (auto val = ReadString(in)) { - return Value::MakeString(std::move(val.value())); - } - break; - case NT_RAW: - case NT_RPC: - if (auto val = ReadRaw(in)) { - return Value::MakeRaw(std::move(val.value())); - } - break; -#if 0 - case NT_RPC: - if (auto val = ReadRaw(in)) { - return Value::MakeRpc(std::move(val.value())); - } - break; -#endif - case NT_BOOLEAN_ARRAY: - // size - if (!m_valueReader.haveSize) { - m_valueReader.SetSize(Read8(in)); - break; - } - - // array values - while (!in->empty() && m_valueReader.ints.size() < m_valueReader.size) { - m_valueReader.ints.emplace_back(Read8(in) ? 1 : 0); - } - if (m_valueReader.ints.size() == m_valueReader.size) { - return Value::MakeBooleanArray(std::move(m_valueReader.ints)); - } - break; - case NT_DOUBLE_ARRAY: - // size - if (!m_valueReader.haveSize) { - m_valueReader.SetSize(Read8(in)); - break; - } - - // array values - while (!in->empty() && - m_valueReader.doubles.size() < m_valueReader.size) { - if (auto val = m_simpleReader.ReadDouble(in)) { - m_valueReader.doubles.emplace_back(std::move(val.value())); - } - } - if (m_valueReader.doubles.size() == m_valueReader.size) { - return Value::MakeDoubleArray(std::move(m_valueReader.doubles)); - } - break; - case NT_STRING_ARRAY: - // size - if (!m_valueReader.haveSize) { - m_valueReader.SetSize(Read8(in)); - break; - } - - // array values - while (!in->empty() && - m_valueReader.strings.size() < m_valueReader.size) { - if (auto val = ReadString(in)) { - m_valueReader.strings.emplace_back(std::move(val.value())); - } - } - if (m_valueReader.strings.size() == m_valueReader.size) { - return Value::MakeStringArray(std::move(m_valueReader.strings)); - } - break; - default: - return EmitError("invalid type when trying to read value"); - } - } - return std::nullopt; -} diff --git a/ntcore/src/main/native/cpp/net3/WireDecoder3.h b/ntcore/src/main/native/cpp/net3/WireDecoder3.h deleted file mode 100644 index 48064f7998..0000000000 --- a/ntcore/src/main/native/cpp/net3/WireDecoder3.h +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#include - -#include -#include -#include -#include -#include - -#include - -#include "ntcore_c.h" - -namespace nt { -class Value; -} // namespace nt - -namespace nt::net3 { - -class MessageHandler3 { - public: - virtual ~MessageHandler3() = default; - - virtual void KeepAlive() = 0; - virtual void ServerHelloDone() = 0; - virtual void ClientHelloDone() = 0; - virtual void ClearEntries() = 0; - virtual void ProtoUnsup(unsigned int proto_rev) = 0; - virtual void ClientHello(std::string_view self_id, - unsigned int proto_rev) = 0; - virtual void ServerHello(unsigned int flags, std::string_view self_id) = 0; - virtual void EntryAssign(std::string_view name, unsigned int id, - unsigned int seq_num, const Value& value, - unsigned int flags) = 0; - virtual void EntryUpdate(unsigned int id, unsigned int seq_num, - const Value& value) = 0; - virtual void FlagsUpdate(unsigned int id, unsigned int flags) = 0; - virtual void EntryDelete(unsigned int id) = 0; - virtual void ExecuteRpc(unsigned int id, unsigned int uid, - std::span params) = 0; - virtual void RpcResponse(unsigned int id, unsigned int uid, - std::span result) = 0; -}; - -/* Decodes NT3 protocol into native representation. */ -class WireDecoder3 { - public: - explicit WireDecoder3(MessageHandler3& out) : m_out{out} {} - - /** - * Executes the decoder. All input data will be consumed unless an error - * occurs. - * @param in input data (updated during parse) - * @return false if error occurred - */ - bool Execute(std::span* in) { - DoExecute(in); - return m_state != kError; - } - - void SetError(std::string_view message) { EmitError(message); } - std::string GetError() const { return m_error; } - - private: - class SimpleValueReader { - public: - std::optional Read16(std::span* in); - std::optional Read32(std::span* in); - std::optional Read64(std::span* in); - std::optional ReadDouble(std::span* in); - - private: - uint64_t m_value = 0; - int m_count = 0; - }; - - struct StringReader { - void SetLen(uint64_t len_) { - len = len_; - buf.clear(); - } - - std::optional len; - std::string buf; - }; - - struct RawReader { - void SetLen(uint64_t len_) { - len = len_; - buf.clear(); - } - - std::optional len; - std::vector buf; - }; - - struct ValueReader { - ValueReader() = default; - explicit ValueReader(NT_Type type_) : type{type_} {} - - void SetSize(uint32_t size_) { - haveSize = true; - size = size_; - ints.clear(); - doubles.clear(); - strings.clear(); - } - - NT_Type type = NT_UNASSIGNED; - bool haveSize = false; - uint32_t size = 0; - std::vector ints; - std::vector doubles; - std::vector strings; - }; - - MessageHandler3& m_out; - - // primary (message) decode state - enum { - kStart, - kClientHello_1ProtoRev, - kClientHello_2Id, - kProtoUnsup_1ProtoRev, - kServerHello_1Flags, - kServerHello_2Id, - kEntryAssign_1Name, - kEntryAssign_2Type, - kEntryAssign_3Id, - kEntryAssign_4SeqNum, - kEntryAssign_5Flags, - kEntryAssign_6Value, - kEntryUpdate_1Id, - kEntryUpdate_2SeqNum, - kEntryUpdate_3Type, - kEntryUpdate_4Value, - kFlagsUpdate_1Id, - kFlagsUpdate_2Flags, - kEntryDelete_1Id, - kClearEntries_1Magic, - kExecuteRpc_1Id, - kExecuteRpc_2Uid, - kExecuteRpc_3Params, - kRpcResponse_1Id, - kRpcResponse_2Uid, - kRpcResponse_3Result, - kError - } m_state = kStart; - - // detail decoders - wpi::Uleb128Reader m_ulebReader; - SimpleValueReader m_simpleReader; - StringReader m_stringReader; - RawReader m_rawReader; - ValueReader m_valueReader; - - std::string m_error; - - std::string m_str; - unsigned int m_id{0}; // also used for proto_rev - unsigned int m_flags{0}; - unsigned int m_seq_num_uid{0}; - - void DoExecute(std::span* in); - - std::nullopt_t EmitError(std::string_view msg) { - m_state = kError; - m_error = msg; - return std::nullopt; - } - - std::optional ReadString(std::span* in); - std::optional> ReadRaw(std::span* in); - std::optional ReadType(std::span* in); - std::optional ReadValue(std::span* in); -}; - -} // namespace nt::net3 diff --git a/ntcore/src/main/native/cpp/net3/WireEncoder3.cpp b/ntcore/src/main/native/cpp/net3/WireEncoder3.cpp deleted file mode 100644 index 0ac2bd38ec..0000000000 --- a/ntcore/src/main/native/cpp/net3/WireEncoder3.cpp +++ /dev/null @@ -1,321 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include "WireEncoder3.h" - -#include - -#include -#include -#include -#include - -#include "Message3.h" - -using namespace nt; -using namespace nt::net3; - -static void Write8(wpi::raw_ostream& os, uint8_t val) { - os << val; -} - -static void Write16(wpi::raw_ostream& os, uint16_t val) { - uint8_t buf[2]; - wpi::support::endian::write16be(buf, val); - os << buf; -} - -static void Write32(wpi::raw_ostream& os, uint32_t val) { - uint8_t buf[4]; - wpi::support::endian::write32be(buf, val); - os << buf; -} - -static void WriteDouble(wpi::raw_ostream& os, double val) { - uint8_t buf[8]; - wpi::support::endian::write64be(buf, std::bit_cast(val)); - os << buf; -} - -static void WriteString(wpi::raw_ostream& os, std::string_view str) { - wpi::WriteUleb128(os, str.size()); - os << str; -} - -static void WriteRaw(wpi::raw_ostream& os, std::span str) { - wpi::WriteUleb128(os, str.size()); - os << str; -} - -static bool WriteType(wpi::raw_ostream& os, NT_Type type) { - char ch; - // Convert from enum to actual byte value. - switch (type) { - case NT_BOOLEAN: - ch = Message3::kBoolean; - break; - case NT_INTEGER: - case NT_FLOAT: - case NT_DOUBLE: - ch = Message3::kDouble; - break; - case NT_STRING: - ch = Message3::kString; - break; - case NT_RAW: - ch = Message3::kRaw; - break; - case NT_BOOLEAN_ARRAY: - ch = Message3::kBooleanArray; - break; - case NT_INTEGER_ARRAY: - case NT_FLOAT_ARRAY: - case NT_DOUBLE_ARRAY: - ch = Message3::kDoubleArray; - break; - case NT_STRING_ARRAY: - ch = Message3::kStringArray; - break; - case NT_RPC: - ch = Message3::kRpcDef; - break; - default: - return false; - } - os << ch; - return true; -} - -static bool WriteValue(wpi::raw_ostream& os, const Value& value) { - switch (value.type()) { - case NT_BOOLEAN: - Write8(os, value.GetBoolean() ? 1 : 0); - break; - case NT_INTEGER: - WriteDouble(os, value.GetInteger()); - break; - case NT_FLOAT: - WriteDouble(os, value.GetFloat()); - break; - case NT_DOUBLE: - WriteDouble(os, value.GetDouble()); - break; - case NT_STRING: - WriteString(os, value.GetString()); - break; - case NT_RAW: - WriteRaw(os, value.GetRaw()); - break; - case NT_RPC: - WriteRaw(os, value.GetRaw()); - break; - case NT_BOOLEAN_ARRAY: { - auto v = value.GetBooleanArray(); - size_t size = v.size(); - if (size > 0xff) { - size = 0xff; // size is only 1 byte, truncate - } - Write8(os, size); - - for (size_t i = 0; i < size; ++i) { - Write8(os, v[i] ? 1 : 0); - } - break; - } - case NT_INTEGER_ARRAY: { - auto v = value.GetIntegerArray(); - size_t size = v.size(); - if (size > 0xff) { - size = 0xff; // size is only 1 byte, truncate - } - Write8(os, size); - - for (size_t i = 0; i < size; ++i) { - WriteDouble(os, v[i]); - } - break; - } - case NT_FLOAT_ARRAY: { - auto v = value.GetFloatArray(); - size_t size = v.size(); - if (size > 0xff) { - size = 0xff; // size is only 1 byte, truncate - } - Write8(os, size); - - for (size_t i = 0; i < size; ++i) { - WriteDouble(os, v[i]); - } - break; - } - case NT_DOUBLE_ARRAY: { - auto v = value.GetDoubleArray(); - size_t size = v.size(); - if (size > 0xff) { - size = 0xff; // size is only 1 byte, truncate - } - Write8(os, size); - - for (size_t i = 0; i < size; ++i) { - WriteDouble(os, v[i]); - } - break; - } - case NT_STRING_ARRAY: { - auto v = value.GetStringArray(); - size_t size = v.size(); - if (size > 0xff) { - size = 0xff; // size is only 1 byte, truncate - } - Write8(os, size); - - for (size_t i = 0; i < size; ++i) { - WriteString(os, v[i]); - } - break; - } - default: - return false; - } - return true; -} - -void nt::net3::WireEncodeKeepAlive(wpi::raw_ostream& os) { - Write8(os, Message3::kKeepAlive); -} - -void nt::net3::WireEncodeServerHelloDone(wpi::raw_ostream& os) { - Write8(os, Message3::kServerHelloDone); -} - -void nt::net3::WireEncodeClientHelloDone(wpi::raw_ostream& os) { - Write8(os, Message3::kClientHelloDone); -} - -void nt::net3::WireEncodeClearEntries(wpi::raw_ostream& os) { - Write8(os, Message3::kClearEntries); - Write32(os, Message3::kClearAllMagic); -} - -void nt::net3::WireEncodeProtoUnsup(wpi::raw_ostream& os, - unsigned int proto_rev) { - Write8(os, Message3::kProtoUnsup); - Write16(os, proto_rev); -} - -void nt::net3::WireEncodeClientHello(wpi::raw_ostream& os, - std::string_view self_id, - unsigned int proto_rev) { - Write8(os, Message3::kClientHello); - Write16(os, proto_rev); - WriteString(os, self_id); -} - -void nt::net3::WireEncodeServerHello(wpi::raw_ostream& os, unsigned int flags, - std::string_view self_id) { - Write8(os, Message3::kServerHello); - Write8(os, flags); - WriteString(os, self_id); -} - -bool nt::net3::WireEncodeEntryAssign(wpi::raw_ostream& os, - std::string_view name, unsigned int id, - unsigned int seq_num, const Value& value, - unsigned int flags) { - Write8(os, Message3::kEntryAssign); - WriteString(os, name); - WriteType(os, value.type()); - Write16(os, id); - Write16(os, seq_num); - Write8(os, flags); - return WriteValue(os, value); -} - -bool nt::net3::WireEncodeEntryUpdate(wpi::raw_ostream& os, unsigned int id, - unsigned int seq_num, const Value& value) { - Write8(os, Message3::kEntryUpdate); - Write16(os, id); - Write16(os, seq_num); - WriteType(os, value.type()); - return WriteValue(os, value); -} - -void nt::net3::WireEncodeFlagsUpdate(wpi::raw_ostream& os, unsigned int id, - unsigned int flags) { - Write8(os, Message3::kFlagsUpdate); - Write16(os, id); - Write8(os, flags); -} - -void nt::net3::WireEncodeEntryDelete(wpi::raw_ostream& os, unsigned int id) { - Write8(os, Message3::kEntryDelete); - Write16(os, id); -} - -void nt::net3::WireEncodeExecuteRpc(wpi::raw_ostream& os, unsigned int id, - unsigned int uid, - std::span params) { - Write8(os, Message3::kExecuteRpc); - Write16(os, id); - Write16(os, uid); - WriteRaw(os, params); -} - -void nt::net3::WireEncodeRpcResponse(wpi::raw_ostream& os, unsigned int id, - unsigned int uid, - std::span result) { - Write8(os, Message3::kRpcResponse); - Write16(os, id); - Write16(os, uid); - WriteRaw(os, result); -} - -bool nt::net3::WireEncode(wpi::raw_ostream& os, const Message3& msg) { - switch (msg.type()) { - case Message3::kKeepAlive: - WireEncodeKeepAlive(os); - break; - case Message3::kServerHelloDone: - WireEncodeServerHelloDone(os); - break; - case Message3::kClientHelloDone: - WireEncodeClientHelloDone(os); - break; - case Message3::kClientHello: - WireEncodeClientHello(os, msg.str(), msg.id()); - break; - case Message3::kProtoUnsup: - WireEncodeProtoUnsup(os, msg.id()); - break; - case Message3::kServerHello: - WireEncodeServerHello(os, msg.flags(), msg.str()); - break; - case Message3::kEntryAssign: - return WireEncodeEntryAssign(os, msg.str(), msg.id(), msg.seq_num_uid(), - msg.value(), msg.flags()); - case Message3::kEntryUpdate: - return WireEncodeEntryUpdate(os, msg.id(), msg.seq_num_uid(), - msg.value()); - case Message3::kFlagsUpdate: - WireEncodeFlagsUpdate(os, msg.id(), msg.flags()); - break; - case Message3::kEntryDelete: - WireEncodeEntryDelete(os, msg.id()); - break; - case Message3::kClearEntries: - WireEncodeClearEntries(os); - break; - case Message3::kExecuteRpc: - WireEncodeExecuteRpc(os, msg.id(), msg.seq_num_uid(), msg.bytes()); - break; - case Message3::kRpcResponse: - WireEncodeRpcResponse(os, msg.id(), msg.seq_num_uid(), msg.bytes()); - break; - case Message3::kUnknown: - return true; // ignore - default: - return false; - } - return true; -} diff --git a/ntcore/src/main/native/cpp/net3/WireEncoder3.h b/ntcore/src/main/native/cpp/net3/WireEncoder3.h deleted file mode 100644 index 66be9aedd4..0000000000 --- a/ntcore/src/main/native/cpp/net3/WireEncoder3.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#include - -#include -#include - -namespace wpi { -class raw_ostream; -} // namespace wpi - -namespace nt { -class Value; -} // namespace nt - -namespace nt::net3 { - -class Message3; - -// encoders for messages (avoids need to construct a Message struct) -void WireEncodeKeepAlive(wpi::raw_ostream& os); -void WireEncodeServerHelloDone(wpi::raw_ostream& os); -void WireEncodeClientHelloDone(wpi::raw_ostream& os); -void WireEncodeClearEntries(wpi::raw_ostream& os); -void WireEncodeProtoUnsup(wpi::raw_ostream& os, unsigned int proto_rev); -void WireEncodeClientHello(wpi::raw_ostream& os, std::string_view self_id, - unsigned int proto_rev); -void WireEncodeServerHello(wpi::raw_ostream& os, unsigned int flags, - std::string_view self_id); -bool WireEncodeEntryAssign(wpi::raw_ostream& os, std::string_view name, - unsigned int id, unsigned int seq_num, - const Value& value, unsigned int flags); -bool WireEncodeEntryUpdate(wpi::raw_ostream& os, unsigned int id, - unsigned int seq_num, const Value& value); -void WireEncodeFlagsUpdate(wpi::raw_ostream& os, unsigned int id, - unsigned int flags); -void WireEncodeEntryDelete(wpi::raw_ostream& os, unsigned int id); -void WireEncodeExecuteRpc(wpi::raw_ostream& os, unsigned int id, - unsigned int uid, std::span params); -void WireEncodeRpcResponse(wpi::raw_ostream& os, unsigned int id, - unsigned int uid, std::span result); - -bool WireEncode(wpi::raw_ostream& os, const Message3& msg); - -} // namespace nt::net3 diff --git a/ntcore/src/main/native/cpp/ntcore_c.cpp b/ntcore/src/main/native/cpp/ntcore_c.cpp index ff93c25062..610985abe8 100644 --- a/ntcore/src/main/native/cpp/ntcore_c.cpp +++ b/ntcore/src/main/native/cpp/ntcore_c.cpp @@ -527,22 +527,18 @@ void NT_StopLocal(NT_Inst inst) { } void NT_StartServer(NT_Inst inst, const struct WPI_String* persist_filename, - const struct WPI_String* listen_address, unsigned int port3, - unsigned int port4) { + const struct WPI_String* listen_address, + unsigned int port) { nt::StartServer(inst, wpi::to_string_view(persist_filename), - wpi::to_string_view(listen_address), port3, port4); + wpi::to_string_view(listen_address), port); } void NT_StopServer(NT_Inst inst) { nt::StopServer(inst); } -void NT_StartClient3(NT_Inst inst, const struct WPI_String* identity) { - nt::StartClient3(inst, wpi::to_string_view(identity)); -} - -void NT_StartClient4(NT_Inst inst, const struct WPI_String* identity) { - nt::StartClient4(inst, wpi::to_string_view(identity)); +void NT_StartClient(NT_Inst inst, const struct WPI_String* identity) { + nt::StartClient(inst, wpi::to_string_view(identity)); } void NT_StopClient(NT_Inst inst) { diff --git a/ntcore/src/main/native/cpp/ntcore_cpp.cpp b/ntcore/src/main/native/cpp/ntcore_cpp.cpp index 3cb3ce4fd7..b796e08146 100644 --- a/ntcore/src/main/native/cpp/ntcore_cpp.cpp +++ b/ntcore/src/main/native/cpp/ntcore_cpp.cpp @@ -633,10 +633,9 @@ void StopLocal(NT_Inst inst) { } void StartServer(NT_Inst inst, std::string_view persist_filename, - std::string_view listen_address, unsigned int port3, - unsigned int port4) { + std::string_view listen_address, unsigned int port) { if (auto ii = InstanceImpl::GetTyped(inst, Handle::kInstance)) { - ii->StartServer(persist_filename, listen_address, port3, port4); + ii->StartServer(persist_filename, listen_address, port); } } @@ -646,15 +645,9 @@ void StopServer(NT_Inst inst) { } } -void StartClient3(NT_Inst inst, std::string_view identity) { +void StartClient(NT_Inst inst, std::string_view identity) { if (auto ii = InstanceImpl::GetTyped(inst, Handle::kInstance)) { - ii->StartClient3(identity); - } -} - -void StartClient4(NT_Inst inst, std::string_view identity) { - if (auto ii = InstanceImpl::GetTyped(inst, Handle::kInstance)) { - ii->StartClient4(identity); + ii->StartClient(identity); } } diff --git a/ntcore/src/main/native/cpp/server/ServerClient3.cpp b/ntcore/src/main/native/cpp/server/ServerClient3.cpp deleted file mode 100644 index 0841b46618..0000000000 --- a/ntcore/src/main/native/cpp/server/ServerClient3.cpp +++ /dev/null @@ -1,482 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include "ServerClient3.h" - -#include -#include - -#include - -#include "Log.h" -#include "Types_internal.h" -#include "net3/WireEncoder3.h" -#include "server/ServerImpl.h" -#include "server/ServerPublisher.h" -#include "server/ServerTopic.h" - -using namespace nt::server; - -// maximum amount of time the wire can be not ready to send another -// transmission before we close the connection -static constexpr uint32_t kWireMaxNotReadyUs = 1000000; - -bool ServerClient3::TopicData3::UpdateFlags(ServerTopic* topic) { - unsigned int newFlags = topic->persistent ? NT_PERSISTENT : 0; - bool updated = flags != newFlags; - flags = newFlags; - return updated; -} - -bool ServerClient3::ProcessIncomingBinary(std::span data) { - if (!m_decoder.Execute(&data)) { - m_wire.Disconnect(m_decoder.GetError()); - } - return false; -} - -void ServerClient3::SendValue(ServerTopic* topic, const Value& value, - net::ValueSendMode mode) { - if (m_state != kStateRunning) { - if (mode == net::ValueSendMode::kImm) { - mode = net::ValueSendMode::kAll; - } - } else if (m_local) { - mode = net::ValueSendMode::kImm; // always send local immediately - } - TopicData3* topic3 = GetTopic3(topic); - bool added = false; - - switch (mode) { - case net::ValueSendMode::kDisabled: // do nothing - break; - case net::ValueSendMode::kImm: // send immediately - ++topic3->seqNum; - if (topic3->sentAssign) { - net3::WireEncodeEntryUpdate(m_wire.Send().stream(), topic->id, - topic3->seqNum.value(), value); - } else { - net3::WireEncodeEntryAssign(m_wire.Send().stream(), topic->name, - topic->id, topic3->seqNum.value(), value, - topic3->flags); - topic3->sentAssign = true; - } - if (m_local) { - Flush(); - } - break; - case net::ValueSendMode::kNormal: { - // replace, or append if not present - wpi::DenseMap::iterator it; - std::tie(it, added) = - m_outgoingValueMap.try_emplace(topic->id, m_outgoing.size()); - if (!added && it->second < m_outgoing.size()) { - auto& msg = m_outgoing[it->second]; - if (msg.Is(net3::Message3::kEntryUpdate) || - msg.Is(net3::Message3::kEntryAssign)) { - if (msg.id() == topic->id) { // should always be true - msg.SetValue(value); - break; - } - } - } - } - // fallthrough - case net::ValueSendMode::kAll: // append to outgoing - if (!added) { - m_outgoingValueMap[topic->id] = m_outgoing.size(); - } - ++topic3->seqNum; - if (topic3->sentAssign) { - m_outgoing.emplace_back(net3::Message3::EntryUpdate( - topic->id, topic3->seqNum.value(), value)); - } else { - m_outgoing.emplace_back(net3::Message3::EntryAssign( - topic->name, topic->id, topic3->seqNum.value(), value, - topic3->flags)); - topic3->sentAssign = true; - } - break; - } -} - -void ServerClient3::SendAnnounce(ServerTopic* topic, - std::optional pubuid) { - // ignore if we've not yet built the subscriber - if (m_subscribers.empty()) { - return; - } - - // subscribe to all non-special topics - if (!topic->special) { - topic->clients[this].AddSubscriber(m_subscribers[0].get()); - m_storage.UpdateMetaTopicSub(topic); - } - - // NT3 requires a value to send the assign message, so the assign message - // will get sent when the first value is sent (by SendValue). -} - -void ServerClient3::SendUnannounce(ServerTopic* topic) { - auto it = m_topics3.find(topic); - if (it == m_topics3.end()) { - return; // never sent to client - } - bool sentAssign = it->second.sentAssign; - m_topics3.erase(it); - if (!sentAssign) { - return; // never sent to client - } - - // map to NT3 delete message - if (m_local && m_state == kStateRunning) { - net3::WireEncodeEntryDelete(m_wire.Send().stream(), topic->id); - Flush(); - } else { - m_outgoing.emplace_back(net3::Message3::EntryDelete(topic->id)); - } -} - -void ServerClient3::SendPropertiesUpdate(ServerTopic* topic, - const wpi::json& update, bool ack) { - if (ack) { - return; // we don't ack in NT3 - } - auto it = m_topics3.find(topic); - if (it == m_topics3.end()) { - return; // never sent to client - } - TopicData3* topic3 = &it->second; - // Don't send flags update unless we've already sent an assign message. - // The assign message will contain the updated flags when we eventually - // send it. - if (topic3->UpdateFlags(topic) && topic3->sentAssign) { - if (m_local && m_state == kStateRunning) { - net3::WireEncodeFlagsUpdate(m_wire.Send().stream(), topic->id, - topic3->flags); - Flush(); - } else { - m_outgoing.emplace_back( - net3::Message3::FlagsUpdate(topic->id, topic3->flags)); - } - } -} - -void ServerClient3::SendOutgoing(uint64_t curTimeMs, bool flush) { - if (m_outgoing.empty() || m_state != kStateRunning) { - return; // nothing to do - } - - // rate limit frequency of transmissions - if (curTimeMs < (m_lastSendMs + kMinPeriodMs)) { - return; - } - - if (!m_wire.Ready()) { - uint64_t lastFlushTime = m_wire.GetLastFlushTime(); - uint64_t now = wpi::Now(); - if (lastFlushTime != 0 && now > (lastFlushTime + kWireMaxNotReadyUs)) { - m_wire.Disconnect("transmit stalled"); - } - return; - } - - auto out = m_wire.Send(); - for (auto&& msg : m_outgoing) { - net3::WireEncode(out.stream(), msg); - } - m_wire.Flush(); - m_outgoing.resize(0); - m_outgoingValueMap.clear(); - m_lastSendMs = curTimeMs; -} - -void ServerClient3::KeepAlive() { - DEBUG4("KeepAlive({})", m_id); - if (m_state != kStateRunning) { - m_decoder.SetError("received unexpected KeepAlive message"); - return; - } - // ignore -} - -void ServerClient3::ServerHelloDone() { - DEBUG4("ServerHelloDone({})", m_id); - m_decoder.SetError("received unexpected ServerHelloDone message"); -} - -void ServerClient3::ClientHelloDone() { - DEBUG4("ClientHelloDone({})", m_id); - if (m_state != kStateServerHelloComplete) { - m_decoder.SetError("received unexpected ClientHelloDone message"); - return; - } - m_state = kStateRunning; -} - -void ServerClient3::ClearEntries() { - DEBUG4("ClearEntries({})", m_id); - if (m_state != kStateRunning) { - m_decoder.SetError("received unexpected ClearEntries message"); - return; - } - - for (auto topic3it : m_topics3) { - ServerTopic* topic = topic3it.first; - - // make sure we send assign the next time - topic3it.second.sentAssign = false; - - // unpublish from this client (if it was previously published) - if (topic3it.second.published) { - topic3it.second.published = false; - auto publisherIt = m_publishers.find(topic3it.second.pubuid); - if (publisherIt != m_publishers.end()) { - // remove publisher from topic - topic->RemovePublisher(this, publisherIt->second.get()); - - // remove publisher from client - m_publishers.erase(publisherIt); - - // update meta data - m_storage.UpdateMetaTopicPub(topic); - UpdateMetaClientPub(); - } - } - - // set retained=false - m_storage.SetProperties(this, topic, {{"retained", false}}); - } -} - -void ServerClient3::ProtoUnsup(unsigned int proto_rev) { - DEBUG4("ProtoUnsup({})", m_id); - m_decoder.SetError("received unexpected ProtoUnsup message"); -} - -void ServerClient3::ClientHello(std::string_view self_id, - unsigned int proto_rev) { - DEBUG4("ClientHello({}, '{}', {:04x})", m_id, self_id, proto_rev); - if (m_state != kStateInitial) { - m_decoder.SetError("received unexpected ClientHello message"); - return; - } - if (proto_rev != 0x0300) { - net3::WireEncodeProtoUnsup(m_wire.Send().stream(), 0x0300); - Flush(); - m_decoder.SetError( - fmt::format("unsupported protocol version {:04x}", proto_rev)); - return; - } - // create a unique name including client id - m_name = fmt::format("{}-NT3@{}", self_id, m_connInfo); - m_connected(m_name, 0x0300); - m_connected = nullptr; // no longer required - - // create client meta topics - m_metaPub = m_storage.CreateMetaTopic(fmt::format("$clientpub${}", m_name)); - m_metaSub = m_storage.CreateMetaTopic(fmt::format("$clientsub${}", m_name)); - - // subscribe and send initial assignments - auto& sub = m_subscribers[0]; - std::string prefix; - PubSubOptions options; - options.prefixMatch = true; - sub = std::make_unique( - GetName(), std::span{{prefix}}, 0, options); - m_periodMs = net::UpdatePeriodCalc(m_periodMs, sub->GetPeriodMs()); - m_setPeriodic(m_periodMs); - - { - auto out = m_wire.Send(); - net3::WireEncodeServerHello(out.stream(), 0, "server"); - m_storage.ForEachTopic([&](ServerTopic* topic) { - if (topic && !topic->special && topic->IsPublished() && - topic->lastValue) { - DEBUG4("client {}: initial announce of '{}' (id {})", m_id, topic->name, - topic->id); - topic->clients[this].AddSubscriber(sub.get()); - m_storage.UpdateMetaTopicSub(topic); - - TopicData3* topic3 = GetTopic3(topic); - ++topic3->seqNum; - net3::WireEncodeEntryAssign(out.stream(), topic->name, topic->id, - topic3->seqNum.value(), topic->lastValue, - topic3->flags); - topic3->sentAssign = true; - } - }); - net3::WireEncodeServerHelloDone(out.stream()); - } - Flush(); - m_state = kStateServerHelloComplete; - - // update meta topics - UpdateMetaClientPub(); - UpdateMetaClientSub(); -} - -void ServerClient3::ServerHello(unsigned int flags, std::string_view self_id) { - DEBUG4("ServerHello({}, {}, {})", m_id, flags, self_id); - m_decoder.SetError("received unexpected ServerHello message"); -} - -void ServerClient3::EntryAssign(std::string_view name, unsigned int id, - unsigned int seq_num, const Value& value, - unsigned int flags) { - DEBUG4("EntryAssign({}, {}, {}, {}, {})", m_id, id, seq_num, - static_cast(value.type()), flags); - if (id != 0xffff) { - DEBUG3("ignored EntryAssign from {} with non-0xffff id {}", m_id, id); - return; - } - - // convert from NT3 info - auto typeStr = TypeToString(value.type()); - wpi::json properties = wpi::json::object(); - properties["retained"] = true; // treat all NT3 published topics as retained - properties["cached"] = true; // treat all NT3 published topics as cached - if ((flags & NT_PERSISTENT) != 0) { - properties["persistent"] = true; - } - - // create topic - auto topic = m_storage.CreateTopic(this, name, typeStr, properties); - TopicData3* topic3 = GetTopic3(topic); - if (topic3->published || topic3->sentAssign) { - WARN("ignoring client {} duplicate publish of '{}'", m_id, name); - return; - } - ++topic3->seqNum; - topic3->published = true; - topic3->pubuid = m_nextPubUid++; - topic3->sentAssign = true; - - // create publisher - auto [publisherIt, isNew] = m_publishers.try_emplace( - topic3->pubuid, - std::make_unique(GetName(), topic, topic3->pubuid)); - if (!isNew) { - return; // shouldn't happen, but just in case... - } - - // add publisher to topic - topic->AddPublisher(this, publisherIt->getSecond().get()); - - // update meta data - m_storage.UpdateMetaTopicPub(topic); - UpdateMetaClientPub(); - - // acts as an announce + data update - SendAnnounce(topic, topic3->pubuid); - m_storage.SetValue(this, topic, value); - - // respond with assign message with assigned topic ID - if (m_local && m_state == kStateRunning) { - net3::WireEncodeEntryAssign(m_wire.Send().stream(), topic->name, topic->id, - topic3->seqNum.value(), value, topic3->flags); - } else { - m_outgoing.emplace_back(net3::Message3::EntryAssign( - topic->name, topic->id, topic3->seqNum.value(), value, topic3->flags)); - } -} - -void ServerClient3::EntryUpdate(unsigned int id, unsigned int seq_num, - const Value& value) { - DEBUG4("EntryUpdate({}, {}, {}, {})", m_id, id, seq_num, - static_cast(value.type())); - if (m_state != kStateRunning) { - m_decoder.SetError("received unexpected EntryUpdate message"); - return; - } - - ServerTopic* topic = m_storage.GetTopic(id); - if (!topic || !topic->IsPublished()) { - DEBUG3("ignored EntryUpdate from {} on non-existent topic {}", m_id, id); - return; - } - - TopicData3* topic3 = GetTopic3(topic); - if (!topic3->published) { - topic3->published = true; - topic3->pubuid = m_nextPubUid++; - - // create publisher - auto [publisherIt, isNew] = m_publishers.try_emplace( - topic3->pubuid, - std::make_unique(GetName(), topic, topic3->pubuid)); - if (isNew) { - // add publisher to topic - topic->AddPublisher(this, publisherIt->getSecond().get()); - - // update meta data - m_storage.UpdateMetaTopicPub(topic); - UpdateMetaClientPub(); - } - } - topic3->seqNum = net3::SequenceNumber{seq_num}; - - m_storage.SetValue(this, topic, value); -} - -void ServerClient3::FlagsUpdate(unsigned int id, unsigned int flags) { - DEBUG4("FlagsUpdate({}, {}, {})", m_id, id, flags); - if (m_state != kStateRunning) { - m_decoder.SetError("received unexpected FlagsUpdate message"); - return; - } - ServerTopic* topic = m_storage.GetTopic(id); - if (!topic || !topic->IsPublished()) { - DEBUG3("ignored FlagsUpdate from {} on non-existent topic {}", m_id, id); - return; - } - if (topic->special) { - DEBUG3("ignored FlagsUpdate from {} on special topic {}", m_id, id); - return; - } - m_storage.SetFlags(this, topic, flags); -} - -void ServerClient3::EntryDelete(unsigned int id) { - DEBUG4("EntryDelete({}, {})", m_id, id); - if (m_state != kStateRunning) { - m_decoder.SetError("received unexpected EntryDelete message"); - return; - } - ServerTopic* topic = m_storage.GetTopic(id); - if (!topic || !topic->IsPublished()) { - DEBUG3("ignored EntryDelete from {} on non-existent topic {}", m_id, id); - return; - } - if (topic->special) { - DEBUG3("ignored EntryDelete from {} on special topic {}", m_id, id); - return; - } - - auto topic3it = m_topics3.find(topic); - if (topic3it != m_topics3.end()) { - // make sure we send assign the next time - topic3it->second.sentAssign = false; - - // unpublish from this client (if it was previously published) - if (topic3it->second.published) { - topic3it->second.published = false; - auto publisherIt = m_publishers.find(topic3it->second.pubuid); - if (publisherIt != m_publishers.end()) { - // remove publisher from topic - topic->RemovePublisher(this, publisherIt->second.get()); - - // remove publisher from client - m_publishers.erase(publisherIt); - - // update meta data - m_storage.UpdateMetaTopicPub(topic); - UpdateMetaClientPub(); - } - } - } - - // set retained=false - m_storage.SetProperties(this, topic, {{"retained", false}}); -} diff --git a/ntcore/src/main/native/cpp/server/ServerClient3.h b/ntcore/src/main/native/cpp/server/ServerClient3.h deleted file mode 100644 index 190ba6e00f..0000000000 --- a/ntcore/src/main/native/cpp/server/ServerClient3.h +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#include -#include - -#include "ServerClient.h" -#include "net/ClientMessageQueue.h" -#include "net3/Message3.h" -#include "net3/SequenceNumber.h" -#include "net3/WireConnection3.h" -#include "net3/WireDecoder3.h" -#include "server/Functions.h" - -namespace nt::server { - -class ServerClient3 final : public ServerClient, private net3::MessageHandler3 { - public: - ServerClient3(std::string_view connInfo, bool local, - net3::WireConnection3& wire, Connected3Func connected, - SetPeriodicFunc setPeriodic, ServerStorage& storage, int id, - wpi::Logger& logger) - : ServerClient{"", connInfo, local, setPeriodic, storage, id, logger}, - m_connected{std::move(connected)}, - m_wire{wire}, - m_decoder{*this}, - m_incoming{logger} {} - - bool ProcessIncomingText(std::string_view data) final { return false; } - bool ProcessIncomingBinary(std::span data) final; - - bool ProcessIncomingMessages(size_t max) final { return false; } - - void SendValue(ServerTopic* topic, const Value& value, - net::ValueSendMode mode) final; - void SendAnnounce(ServerTopic* topic, std::optional pubuid) final; - void SendUnannounce(ServerTopic* topic) final; - void SendPropertiesUpdate(ServerTopic* topic, const wpi::json& update, - bool ack) final; - void SendOutgoing(uint64_t curTimeMs, bool flush) final; - - void Flush() final { m_wire.Flush(); } - - private: - // MessageHandler3 interface - void KeepAlive() final; - void ServerHelloDone() final; - void ClientHelloDone() final; - void ClearEntries() final; - void ProtoUnsup(unsigned int proto_rev) final; - void ClientHello(std::string_view self_id, unsigned int proto_rev) final; - void ServerHello(unsigned int flags, std::string_view self_id) final; - void EntryAssign(std::string_view name, unsigned int id, unsigned int seq_num, - const Value& value, unsigned int flags) final; - void EntryUpdate(unsigned int id, unsigned int seq_num, - const Value& value) final; - void FlagsUpdate(unsigned int id, unsigned int flags) final; - void EntryDelete(unsigned int id) final; - void ExecuteRpc(unsigned int id, unsigned int uid, - std::span params) final {} - void RpcResponse(unsigned int id, unsigned int uid, - std::span result) final {} - - Connected3Func m_connected; - net3::WireConnection3& m_wire; - - enum State { kStateInitial, kStateServerHelloComplete, kStateRunning }; - State m_state{kStateInitial}; - net3::WireDecoder3 m_decoder; - - net::NetworkIncomingClientQueue m_incoming; - std::vector m_outgoing; - wpi::DenseMap m_outgoingValueMap; - int64_t m_nextPubUid{1}; - uint64_t m_lastSendMs{0}; - - struct TopicData3 { - explicit TopicData3(ServerTopic* topic) { UpdateFlags(topic); } - - unsigned int flags{0}; - net3::SequenceNumber seqNum; - bool sentAssign{false}; - bool published{false}; - int64_t pubuid{0}; - - bool UpdateFlags(ServerTopic* topic); - }; - wpi::DenseMap m_topics3; - TopicData3* GetTopic3(ServerTopic* topic) { - return &m_topics3.try_emplace(topic, topic).first->second; - } -}; - -} // namespace nt::server diff --git a/ntcore/src/main/native/cpp/server/ServerImpl.cpp b/ntcore/src/main/native/cpp/server/ServerImpl.cpp index 3c92488c97..1856407dcd 100644 --- a/ntcore/src/main/native/cpp/server/ServerImpl.cpp +++ b/ntcore/src/main/native/cpp/server/ServerImpl.cpp @@ -16,7 +16,6 @@ #include "Log.h" #include "server/MessagePackWriter.h" -#include "server/ServerClient3.h" #include "server/ServerClient4.h" #include "server/ServerClientLocal.h" @@ -60,20 +59,6 @@ std::pair ServerImpl::AddClient(std::string_view name, return {std::move(dedupName), index}; } -int ServerImpl::AddClient3(std::string_view connInfo, bool local, - net3::WireConnection3& wire, - Connected3Func connected, - SetPeriodicFunc setPeriodic) { - size_t index = GetEmptyClientSlot(); - - m_clients[index] = std::make_unique( - connInfo, local, wire, std::move(connected), std::move(setPeriodic), - m_storage, index, m_logger); - - DEBUG3("AddClient3('{}') -> {}", connInfo, index); - return index; -} - std::shared_ptr ServerImpl::RemoveClient(int clientId) { DEBUG3("RemoveClient({})", clientId); auto& client = m_clients[clientId]; diff --git a/ntcore/src/main/native/cpp/server/ServerImpl.h b/ntcore/src/main/native/cpp/server/ServerImpl.h index a7ee99f1d5..0cacafcb63 100644 --- a/ntcore/src/main/native/cpp/server/ServerImpl.h +++ b/ntcore/src/main/native/cpp/server/ServerImpl.h @@ -61,9 +61,6 @@ class ServerImpl final { std::string_view connInfo, bool local, net::WireConnection& wire, SetPeriodicFunc setPeriodic); - int AddClient3(std::string_view connInfo, bool local, - net3::WireConnection3& wire, Connected3Func connected, - SetPeriodicFunc setPeriodic); std::shared_ptr RemoveClient(int clientId); void ConnectionsChanged(const std::vector& conns) { diff --git a/ntcore/src/main/native/include/networktables/NetworkTableInstance.h b/ntcore/src/main/native/include/networktables/NetworkTableInstance.h index bd522f7016..64772199a7 100644 --- a/ntcore/src/main/native/include/networktables/NetworkTableInstance.h +++ b/ntcore/src/main/native/include/networktables/NetworkTableInstance.h @@ -74,8 +74,7 @@ class NetworkTableInstance final { enum NetworkMode { kNetModeNone = NT_NET_MODE_NONE, kNetModeServer = NT_NET_MODE_SERVER, - kNetModeClient3 = NT_NET_MODE_CLIENT3, - kNetModeClient4 = NT_NET_MODE_CLIENT4, + kNetModeClient = NT_NET_MODE_CLIENT, kNetModeLocal = NT_NET_MODE_LOCAL }; @@ -95,14 +94,9 @@ class NetworkTableInstance final { }; /** - * The default port that network tables operates on for NT3. + * The default port that network tables operates on. */ - static constexpr unsigned int kDefaultPort3 = NT_DEFAULT_PORT3; - - /** - * The default port that network tables operates on for NT4. - */ - static constexpr unsigned int kDefaultPort4 = NT_DEFAULT_PORT4; + static constexpr unsigned int kDefaultPort = NT_DEFAULT_PORT; /** * Construct invalid instance. @@ -611,14 +605,12 @@ class NetworkTableInstance final { * null terminated) * @param listen_address the address to listen on, or null to listen on any * address (UTF-8 string, null terminated) - * @param port3 port to communicate over (NT3) - * @param port4 port to communicate over (NT4) + * @param port port to communicate over */ void StartServer(std::string_view persist_filename = "networktables.json", const char* listen_address = "", - unsigned int port3 = kDefaultPort3, - unsigned int port4 = kDefaultPort4) { - ::nt::StartServer(m_handle, persist_filename, listen_address, port3, port4); + unsigned int port = kDefaultPort) { + ::nt::StartServer(m_handle, persist_filename, listen_address, port); } /** @@ -627,23 +619,13 @@ class NetworkTableInstance final { void StopServer() { ::nt::StopServer(m_handle); } /** - * Starts a NT3 client. Use SetServer or SetServerTeam to set the server name + * Starts a client. Use SetServer or SetServerTeam to set the server name * and port. * * @param identity network identity to advertise (cannot be empty string) */ - void StartClient3(std::string_view identity) { - ::nt::StartClient3(m_handle, identity); - } - - /** - * Starts a NT4 client. Use SetServer or SetServerTeam to set the server name - * and port. - * - * @param identity network identity to advertise (cannot be empty string) - */ - void StartClient4(std::string_view identity) { - ::nt::StartClient4(m_handle, identity); + void StartClient(std::string_view identity) { + ::nt::StartClient(m_handle, identity); } /** diff --git a/ntcore/src/main/native/include/ntcore_c.h b/ntcore/src/main/native/include/ntcore_c.h index 4489b4f382..ab384757e6 100644 --- a/ntcore/src/main/native/include/ntcore_c.h +++ b/ntcore/src/main/native/include/ntcore_c.h @@ -43,11 +43,8 @@ typedef NT_Handle NT_Topic; typedef NT_Handle NT_Subscriber; typedef NT_Handle NT_Publisher; -/** Default network tables port number (NT3) */ -#define NT_DEFAULT_PORT3 1735 - -/** Default network tables port number (NT4) */ -#define NT_DEFAULT_PORT4 5810 +/** Default network tables port number */ +#define NT_DEFAULT_PORT 5810 /** NetworkTables data types. */ enum NT_Type { @@ -90,8 +87,7 @@ enum NT_LogLevel { enum NT_NetworkMode { NT_NET_MODE_NONE = 0x00, /* not running */ NT_NET_MODE_SERVER = 0x01, /* running in server mode */ - NT_NET_MODE_CLIENT3 = 0x02, /* running in NT3 client mode */ - NT_NET_MODE_CLIENT4 = 0x04, /* running in NT4 client mode */ + NT_NET_MODE_CLIENT = 0x04, /* running in client mode */ NT_NET_MODE_STARTING = 0x08, /* flag for starting (either client or server) */ NT_NET_MODE_LOCAL = 0x10, /* running in local-only mode */ }; @@ -190,7 +186,7 @@ struct NT_TopicInfo { /** NetworkTables Connection Information */ struct NT_ConnectionInfo { /** - * The remote identifier (as set on the remote node by NT_StartClient4(). + * The remote identifier (as set on the remote node by NT_StartClient(). */ struct WPI_String remote_id; @@ -1119,12 +1115,10 @@ void NT_StopLocal(NT_Inst inst); * null terminated) * @param listen_address the address to listen on, or null to listen on any * address. (UTF-8 string, null terminated) - * @param port3 port to communicate over (NT3) - * @param port4 port to communicate over (NT4) + * @param port port to communicate over */ void NT_StartServer(NT_Inst inst, const struct WPI_String* persist_filename, - const struct WPI_String* listen_address, unsigned int port3, - unsigned int port4); + const struct WPI_String* listen_address, unsigned int port); /** * Stops the server if it is running. @@ -1134,22 +1128,13 @@ void NT_StartServer(NT_Inst inst, const struct WPI_String* persist_filename, void NT_StopServer(NT_Inst inst); /** - * Starts a NT3 client. Use NT_SetServer or NT_SetServerTeam to set the server + * Starts a client. Use NT_SetServer or NT_SetServerTeam to set the server * name and port. * * @param inst instance handle * @param identity network identity to advertise (cannot be empty string) */ -void NT_StartClient3(NT_Inst inst, const struct WPI_String* identity); - -/** - * Starts a NT4 client. Use NT_SetServer or NT_SetServerTeam to set the server - * name and port. - * - * @param inst instance handle - * @param identity network identity to advertise (cannot be empty string) - */ -void NT_StartClient4(NT_Inst inst, const struct WPI_String* identity); +void NT_StartClient(NT_Inst inst, const struct WPI_String* identity); /** * Stops the client if it is running. diff --git a/ntcore/src/main/native/include/ntcore_cpp.h b/ntcore/src/main/native/include/ntcore_cpp.h index b64106ecff..f46ef2e335 100644 --- a/ntcore/src/main/native/include/ntcore_cpp.h +++ b/ntcore/src/main/native/include/ntcore_cpp.h @@ -120,7 +120,7 @@ struct TopicInfo { struct ConnectionInfo { /** * The remote identifier (as set on the remote node by - * NetworkTableInstance::StartClient4() or nt::StartClient4()). + * NetworkTableInstance::StartClient() or nt::StartClient()). */ std::string remote_id; @@ -1057,12 +1057,10 @@ void StopLocal(NT_Inst inst); * null terminated) * @param listen_address the address to listen on, or null to listen on any * address. (UTF-8 string) - * @param port3 port to communicate over (NT3) - * @param port4 port to communicate over (NT4) + * @param port port to communicate over */ void StartServer(NT_Inst inst, std::string_view persist_filename, - std::string_view listen_address, unsigned int port3, - unsigned int port4); + std::string_view listen_address, unsigned int port); /** * Stops the server if it is running. @@ -1072,22 +1070,13 @@ void StartServer(NT_Inst inst, std::string_view persist_filename, void StopServer(NT_Inst inst); /** - * Starts a NT3 client. Use SetServer or SetServerTeam to set the server name + * Starts a client. Use SetServer or SetServerTeam to set the server name * and port. * * @param inst instance handle * @param identity network identity to advertise (cannot be empty string) */ -void StartClient3(NT_Inst inst, std::string_view identity); - -/** - * Starts a NT4 client. Use SetServer or SetServerTeam to set the server name - * and port. - * - * @param inst instance handle - * @param identity network identity to advertise (cannot be empty string) - */ -void StartClient4(NT_Inst inst, std::string_view identity); +void StartClient(NT_Inst inst, std::string_view identity); /** * Stops the client if it is running. diff --git a/ntcore/src/test/java/edu/wpi/first/networktables/ConnectionListenerTest.java b/ntcore/src/test/java/edu/wpi/first/networktables/ConnectionListenerTest.java index 9fac048e2e..bd386c0dca 100644 --- a/ntcore/src/test/java/edu/wpi/first/networktables/ConnectionListenerTest.java +++ b/ntcore/src/test/java/edu/wpi/first/networktables/ConnectionListenerTest.java @@ -39,8 +39,8 @@ class ConnectionListenerTest { /** Connect to the server. */ private void connect(int port) { - m_serverInst.startServer("connectionlistenertest.json", "127.0.0.1", 0, port); - m_clientInst.startClient4("client"); + m_serverInst.startServer("connectionlistenertest.json", "127.0.0.1", port); + m_clientInst.startClient("client"); m_clientInst.setServer("127.0.0.1", port); // wait for client to report it's connected, then wait another 0.1 sec @@ -113,7 +113,7 @@ class ConnectionListenerTest { @ParameterizedTest @ValueSource(strings = {"127.0.0.1", "127.0.0.1 ", " 127.0.0.1 "}) void testThreaded(String address) { - m_serverInst.startServer("connectionlistenertest.json", address, 0, threadedPort); + m_serverInst.startServer("connectionlistenertest.json", address, threadedPort); List events = new ArrayList<>(); final int handle = m_serverInst.addConnectionListener( @@ -125,7 +125,7 @@ class ConnectionListenerTest { }); // trigger a connect event - m_clientInst.startClient4("client"); + m_clientInst.startClient("client"); m_clientInst.setServer(address, threadedPort); threadedPort++; diff --git a/ntcore/src/test/java/edu/wpi/first/networktables/LoggerTest.java b/ntcore/src/test/java/edu/wpi/first/networktables/LoggerTest.java index c562291994..052ac6c11e 100644 --- a/ntcore/src/test/java/edu/wpi/first/networktables/LoggerTest.java +++ b/ntcore/src/test/java/edu/wpi/first/networktables/LoggerTest.java @@ -31,13 +31,13 @@ class LoggerTest { List msgs = new ArrayList<>(); m_clientInst.addLogger(LogMessage.kInfo, 100, msgs::add); - m_clientInst.startClient4("client"); + m_clientInst.startClient("client"); m_clientInst.setServer("127.0.0.1", 10000); // wait for client to report it's started, then wait another 0.1 sec try { int count = 0; - while (!m_clientInst.getNetworkMode().contains(NetworkTableInstance.NetworkMode.kClient4)) { + while (!m_clientInst.getNetworkMode().contains(NetworkTableInstance.NetworkMode.kClient)) { Thread.sleep(100); count++; if (count > 30) { diff --git a/ntcore/src/test/java/edu/wpi/first/networktables/TimeSyncTest.java b/ntcore/src/test/java/edu/wpi/first/networktables/TimeSyncTest.java index 9048ef4401..70c95ccd5a 100644 --- a/ntcore/src/test/java/edu/wpi/first/networktables/TimeSyncTest.java +++ b/ntcore/src/test/java/edu/wpi/first/networktables/TimeSyncTest.java @@ -37,7 +37,7 @@ class TimeSyncTest { try (var poller = new NetworkTableListenerPoller(m_inst)) { poller.addTimeSyncListener(false); - m_inst.startServer("timesynctest.json", "127.0.0.1", 0, 10030); + m_inst.startServer("timesynctest.json", "127.0.0.1", 10030); var offset = m_inst.getServerTimeOffset(); assertTrue(offset.isPresent()); assertEquals(0L, offset.getAsLong()); @@ -61,19 +61,8 @@ class TimeSyncTest { } @Test - void testClient3() { - m_inst.startClient3("client"); - var offset = m_inst.getServerTimeOffset(); - assertFalse(offset.isPresent()); - - m_inst.stopClient(); - offset = m_inst.getServerTimeOffset(); - assertFalse(offset.isPresent()); - } - - @Test - void testClient4() { - m_inst.startClient4("client"); + void testClient() { + m_inst.startClient("client"); var offset = m_inst.getServerTimeOffset(); assertFalse(offset.isPresent()); diff --git a/ntcore/src/test/java/edu/wpi/first/networktables/TopicListenerTest.java b/ntcore/src/test/java/edu/wpi/first/networktables/TopicListenerTest.java index 9f1d67f574..3038c356d3 100644 --- a/ntcore/src/test/java/edu/wpi/first/networktables/TopicListenerTest.java +++ b/ntcore/src/test/java/edu/wpi/first/networktables/TopicListenerTest.java @@ -33,8 +33,8 @@ class TopicListenerTest { } private void connect() { - m_serverInst.startServer("topiclistenertest.json", "127.0.0.1", 0, 10010); - m_clientInst.startClient4("client"); + m_serverInst.startServer("topiclistenertest.json", "127.0.0.1", 10010); + m_clientInst.startClient("client"); m_clientInst.setServer("127.0.0.1", 10010); // Use connection listener to ensure we've connected diff --git a/ntcore/src/test/native/cpp/ConnectionListenerTest.cpp b/ntcore/src/test/native/cpp/ConnectionListenerTest.cpp index b5ae9daf86..ebceeb7e59 100644 --- a/ntcore/src/test/native/cpp/ConnectionListenerTest.cpp +++ b/ntcore/src/test/native/cpp/ConnectionListenerTest.cpp @@ -23,18 +23,16 @@ class ConnectionListenerTest : public ::testing::Test { nt::DestroyInstance(client_inst); } - void Connect(const char* address, unsigned int port3, unsigned int port4); + void Connect(const char* address, unsigned int port4); protected: NT_Inst server_inst; NT_Inst client_inst; }; -void ConnectionListenerTest::Connect(const char* address, unsigned int port3, - unsigned int port4) { - nt::StartServer(server_inst, "connectionlistenertest.ini", address, port3, - port4); - nt::StartClient4(client_inst, "client"); +void ConnectionListenerTest::Connect(const char* address, unsigned int port4) { + nt::StartServer(server_inst, "connectionlistenertest.ini", address, port4); + nt::StartClient(client_inst, "client"); nt::SetServer(client_inst, address, port4); // wait for client to report it's connected, then wait another 0.1 sec @@ -57,7 +55,7 @@ TEST_F(ConnectionListenerTest, Polled) { ASSERT_NE(handle, 0u); // trigger a connect event - Connect("127.0.0.1", 0, 10020); + Connect("127.0.0.1", 10020); // get the event bool timed_out = false; @@ -98,7 +96,7 @@ TEST_P(ConnectionListenerVariantTest, Threaded) { }); // trigger a connect event - Connect(GetParam().first, 0, 20001 + GetParam().second); + Connect(GetParam().first, 20001 + GetParam().second); bool timed_out = false; ASSERT_TRUE(wpi::WaitForObject(handle, 1.0, &timed_out)); diff --git a/ntcore/src/test/native/cpp/LoggerTest.cpp b/ntcore/src/test/native/cpp/LoggerTest.cpp index 38aaab1901..ee621baab2 100644 --- a/ntcore/src/test/native/cpp/LoggerTest.cpp +++ b/ntcore/src/test/native/cpp/LoggerTest.cpp @@ -27,7 +27,7 @@ class LoggerTest : public ::testing::Test { void LoggerTest::Generate() { // generate info message - nt::StartClient4(m_inst, ""); + nt::StartClient(m_inst, ""); // generate error message nt::Publish(nt::Handle(nt::Handle{m_inst}.GetInst(), 5, nt::Handle::kTopic), diff --git a/ntcore/src/test/native/cpp/TestPrinters.cpp b/ntcore/src/test/native/cpp/TestPrinters.cpp index 708573f74b..f918e80a73 100644 --- a/ntcore/src/test/native/cpp/TestPrinters.cpp +++ b/ntcore/src/test/native/cpp/TestPrinters.cpp @@ -7,7 +7,6 @@ #include "Handle.h" #include "PubSubOptions.h" #include "net/Message.h" -#include "net3/Message3.h" #include "networktables/NetworkTableValue.h" #include "ntcore_cpp.h" @@ -54,59 +53,6 @@ void PrintTo(const Handle& handle, std::ostream* os) { *os << ", " << handle.GetInst() << ", " << handle.GetIndex() << '}'; } -void PrintTo(const net3::Message3& msg, std::ostream* os) { - *os << "Message{"; - switch (msg.type()) { - case net3::Message3::kKeepAlive: - *os << "kKeepAlive"; - break; - case net3::Message3::kClientHello: - *os << "kClientHello"; - break; - case net3::Message3::kProtoUnsup: - *os << "kProtoUnsup"; - break; - case net3::Message3::kServerHelloDone: - *os << "kServerHelloDone"; - break; - case net3::Message3::kServerHello: - *os << "kServerHello"; - break; - case net3::Message3::kClientHelloDone: - *os << "kClientHelloDone"; - break; - case net3::Message3::kEntryAssign: - *os << "kEntryAssign"; - break; - case net3::Message3::kEntryUpdate: - *os << "kEntryUpdate"; - break; - case net3::Message3::kFlagsUpdate: - *os << "kFlagsUpdate"; - break; - case net3::Message3::kEntryDelete: - *os << "kEntryDelete"; - break; - case net3::Message3::kClearEntries: - *os << "kClearEntries"; - break; - case net3::Message3::kExecuteRpc: - *os << "kExecuteRpc"; - break; - case net3::Message3::kRpcResponse: - *os << "kRpcResponse"; - break; - default: - *os << "UNKNOWN"; - break; - } - *os << ": str=\"" << msg.str() << "\", id=" << msg.id() - << ", flags=" << msg.flags() << ", seq_num_uid=" << msg.seq_num_uid() - << ", value="; - PrintTo(msg.value(), os); - *os << '}'; -} - void PrintTo(const Value& value, std::ostream* os) { *os << "Value{"; switch (value.type()) { diff --git a/ntcore/src/test/native/cpp/TimeSyncTest.cpp b/ntcore/src/test/native/cpp/TimeSyncTest.cpp index 1820b37ff4..283e7b768b 100644 --- a/ntcore/src/test/native/cpp/TimeSyncTest.cpp +++ b/ntcore/src/test/native/cpp/TimeSyncTest.cpp @@ -26,7 +26,7 @@ TEST_F(TimeSyncTest, TestServer) { nt::NetworkTableListenerPoller poller{m_inst}; poller.AddTimeSyncListener(false); - m_inst.StartServer("timesynctest.json", "127.0.0.1", 0, 10030); + m_inst.StartServer("timesynctest.json", "127.0.0.1", 10030); auto offset = m_inst.GetServerTimeOffset(); ASSERT_TRUE(offset); ASSERT_EQ(0, *offset); @@ -50,18 +50,8 @@ TEST_F(TimeSyncTest, TestServer) { ASSERT_FALSE(data->valid); } -TEST_F(TimeSyncTest, TestClient3) { - m_inst.StartClient3("client"); - auto offset = m_inst.GetServerTimeOffset(); - ASSERT_FALSE(offset); - - m_inst.StopClient(); - offset = m_inst.GetServerTimeOffset(); - ASSERT_FALSE(offset); -} - -TEST_F(TimeSyncTest, TestClient4) { - m_inst.StartClient4("client"); +TEST_F(TimeSyncTest, TestClient) { + m_inst.StartClient("client"); auto offset = m_inst.GetServerTimeOffset(); ASSERT_FALSE(offset); diff --git a/ntcore/src/test/native/cpp/TopicListenerTest.cpp b/ntcore/src/test/native/cpp/TopicListenerTest.cpp index 8511b3b4da..8e3d34544e 100644 --- a/ntcore/src/test/native/cpp/TopicListenerTest.cpp +++ b/ntcore/src/test/native/cpp/TopicListenerTest.cpp @@ -50,8 +50,8 @@ class TopicListenerTest : public ::testing::Test { }; void TopicListenerTest::Connect(unsigned int port) { - nt::StartServer(m_serverInst, "topiclistenertest.json", "127.0.0.1", 0, port); - nt::StartClient4(m_clientInst, "client"); + nt::StartServer(m_serverInst, "topiclistenertest.json", "127.0.0.1", port); + nt::StartClient(m_clientInst, "client"); nt::SetServer(m_clientInst, "127.0.0.1", port); // Use connection listener to ensure we've connected diff --git a/ntcore/src/test/native/cpp/net3/MessageMatcher3.cpp b/ntcore/src/test/native/cpp/net3/MessageMatcher3.cpp deleted file mode 100644 index d595c6ac1b..0000000000 --- a/ntcore/src/test/native/cpp/net3/MessageMatcher3.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include "MessageMatcher3.h" - -namespace nt::net3 { - -bool MessageMatcher::MatchAndExplain( - Message3 msg, ::testing::MatchResultListener* listener) const { - bool match = true; - if (msg.str() != goodmsg.str()) { - *listener << "str mismatch "; - match = false; - } - if ((!msg.value() && goodmsg.value()) || (msg.value() && !goodmsg.value()) || - (msg.value() && goodmsg.value() && msg.value() != goodmsg.value())) { - *listener << "value mismatch "; - match = false; - } - if (msg.id() != goodmsg.id()) { - *listener << "id mismatch "; - match = false; - } - if (msg.flags() != goodmsg.flags()) { - *listener << "flags mismatch"; - match = false; - } - if (msg.seq_num_uid() != goodmsg.seq_num_uid()) { - *listener << "seq_num_uid mismatch"; - match = false; - } - return match; -} - -void MessageMatcher::DescribeTo(::std::ostream* os) const { - PrintTo(goodmsg, os); -} - -void MessageMatcher::DescribeNegationTo(::std::ostream* os) const { - *os << "is not equal to "; - PrintTo(goodmsg, os); -} - -} // namespace nt::net3 diff --git a/ntcore/src/test/native/cpp/net3/MessageMatcher3.h b/ntcore/src/test/native/cpp/net3/MessageMatcher3.h deleted file mode 100644 index 6b1e770dc5..0000000000 --- a/ntcore/src/test/native/cpp/net3/MessageMatcher3.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#include -#include -#include - -#include "../TestPrinters.h" -#include "gmock/gmock.h" -#include "net3/Message3.h" - -namespace nt::net3 { - -class MessageMatcher : public ::testing::MatcherInterface { - public: - explicit MessageMatcher(Message3 goodmsg_) : goodmsg(std::move(goodmsg_)) {} - - bool MatchAndExplain(Message3 msg, - ::testing::MatchResultListener* listener) const override; - void DescribeTo(::std::ostream* os) const override; - void DescribeNegationTo(::std::ostream* os) const override; - - private: - Message3 goodmsg; -}; - -inline ::testing::Matcher MessageEq(Message3 goodmsg) { - return ::testing::MakeMatcher(new MessageMatcher(std::move(goodmsg))); -} - -} // namespace nt::net3 diff --git a/ntcore/src/test/native/cpp/net3/MockWireConnection3.h b/ntcore/src/test/native/cpp/net3/MockWireConnection3.h deleted file mode 100644 index f788df1b52..0000000000 --- a/ntcore/src/test/native/cpp/net3/MockWireConnection3.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#include - -#include -#include - -#include - -#include "gmock/gmock.h" -#include "net3/WireConnection3.h" - -namespace nt::net3 { - -class MockWireConnection3 : public WireConnection3 { - public: - MockWireConnection3() : m_os{m_data} {} - - MOCK_METHOD(bool, Ready, (), (const, override)); - - Writer Send() override { return {m_os, *this}; } - - MOCK_METHOD(void, Data, (std::span data)); - - MOCK_METHOD(void, Flush, (), (override)); - - MOCK_METHOD(uint64_t, GetLastFlushTime, (), (const, override)); - - MOCK_METHOD(void, StopRead, (), (override)); - MOCK_METHOD(void, StartRead, (), (override)); - - MOCK_METHOD(void, Disconnect, (std::string_view reason), (override)); - - protected: - void FinishSend() override { - Data(m_data); - m_data.resize(0); - } - - private: - std::vector m_data; - wpi::raw_uvector_ostream m_os; -}; - -} // namespace nt::net3 diff --git a/ntcore/src/test/native/cpp/net3/WireDecoder3Test.cpp b/ntcore/src/test/native/cpp/net3/WireDecoder3Test.cpp deleted file mode 100644 index af40483db0..0000000000 --- a/ntcore/src/test/native/cpp/net3/WireDecoder3Test.cpp +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "../TestPrinters.h" -#include "../ValueMatcher.h" -#include "gmock/gmock.h" -#include "net3/WireDecoder3.h" -#include "networktables/NetworkTableValue.h" - -using namespace std::string_view_literals; -using testing::_; -using testing::MockFunction; -using testing::StrictMock; - -namespace nt { - -class MockMessageHandler3 : public net3::MessageHandler3 { - public: - MOCK_METHOD0(KeepAlive, void()); - MOCK_METHOD0(ServerHelloDone, void()); - MOCK_METHOD0(ClientHelloDone, void()); - MOCK_METHOD0(ClearEntries, void()); - MOCK_METHOD1(ProtoUnsup, void(unsigned int proto_rev)); - MOCK_METHOD2(ClientHello, - void(std::string_view self_id, unsigned int proto_rev)); - MOCK_METHOD2(ServerHello, void(unsigned int flags, std::string_view self_id)); - MOCK_METHOD5(EntryAssign, void(std::string_view name, unsigned int id, - unsigned int seq_num, const Value& value, - unsigned int flags)); - MOCK_METHOD3(EntryUpdate, - void(unsigned int id, unsigned int seq_num, const Value& value)); - MOCK_METHOD2(FlagsUpdate, void(unsigned int id, unsigned int flags)); - MOCK_METHOD1(EntryDelete, void(unsigned int id)); - MOCK_METHOD3(ExecuteRpc, void(unsigned int id, unsigned int uid, - std::span params)); - MOCK_METHOD3(RpcResponse, void(unsigned int id, unsigned int uid, - std::span result)); -}; - -class WireDecoder3Test : public ::testing::Test { - protected: - StrictMock handler; - net3::WireDecoder3 decoder{handler}; - - void DecodeComplete(std::span in) { - decoder.Execute(&in); - EXPECT_TRUE(in.empty()); - ASSERT_EQ(decoder.GetError(), ""); - } -}; - -TEST_F(WireDecoder3Test, KeepAlive) { - EXPECT_CALL(handler, KeepAlive()); - DecodeComplete("\x00"_us); -} - -TEST_F(WireDecoder3Test, ClientHello) { - EXPECT_CALL(handler, ClientHello(std::string_view{"hello"}, 0x0300u)); - DecodeComplete("\x01\x03\x00\x05hello"_us); -} - -TEST_F(WireDecoder3Test, ProtoUnsup) { - EXPECT_CALL(handler, ProtoUnsup(0x0300u)); - EXPECT_CALL(handler, ProtoUnsup(0x0200u)); - DecodeComplete("\x02\x03\x00\x02\x02\x00"_us); -} - -TEST_F(WireDecoder3Test, ServerHelloDone) { - EXPECT_CALL(handler, ServerHelloDone()); - DecodeComplete("\x03"_us); -} - -TEST_F(WireDecoder3Test, ServerHello) { - EXPECT_CALL(handler, ServerHello(0x03, std::string_view{"hello"})); - DecodeComplete("\x04\x03\x05hello"_us); -} - -TEST_F(WireDecoder3Test, ClientHelloDone) { - EXPECT_CALL(handler, ClientHelloDone()); - DecodeComplete("\x05"_us); -} - -TEST_F(WireDecoder3Test, FlagsUpdate) { - EXPECT_CALL(handler, FlagsUpdate(0x5678, 0x03)); - DecodeComplete("\x12\x56\x78\x03"_us); -} - -TEST_F(WireDecoder3Test, EntryDelete) { - EXPECT_CALL(handler, EntryDelete(0x5678)); - DecodeComplete("\x13\x56\x78"_us); -} - -TEST_F(WireDecoder3Test, ClearEntries) { - EXPECT_CALL(handler, ClearEntries()); - DecodeComplete("\x14\xd0\x6c\xb2\x7a"_us); -} - -TEST_F(WireDecoder3Test, ClearEntriesInvalid) { - auto in = "\x14\xd0\x6c\xb2\x7b"_us; - decoder.Execute(&in); - EXPECT_EQ(decoder.GetError(), "received incorrect CLEAR_ENTRIES magic value"); -} - -TEST_F(WireDecoder3Test, ExecuteRpc) { - EXPECT_CALL(handler, ExecuteRpc(0x5678, 0x1234, wpi::SpanEq("hello"_us))); - DecodeComplete("\x20\x56\x78\x12\x34\x05hello"_us); -} - -TEST_F(WireDecoder3Test, RpcResponse) { - EXPECT_CALL(handler, RpcResponse(0x5678, 0x1234, wpi::SpanEq("hello"_us))); - DecodeComplete("\x21\x56\x78\x12\x34\x05hello"_us); -} - -TEST_F(WireDecoder3Test, UnknownMessage) { - auto in = "\x23"_us; - decoder.Execute(&in); - EXPECT_EQ(decoder.GetError(), "unrecognized message type: 35"); -} - -TEST_F(WireDecoder3Test, EntryAssignBoolean) { - EXPECT_CALL(handler, EntryAssign("test"sv, 0x5678, 0x1234, - Value::MakeBoolean(true), 0x9a)); - DecodeComplete("\x10\x04test\x00\x56\x78\x12\x34\x9a\x01"_us); -} - -TEST_F(WireDecoder3Test, EntryAssignDouble) { - EXPECT_CALL(handler, EntryAssign("test"sv, 0x5678, 0x1234, - Value::MakeDouble(2.3e5), 0x9a)); - DecodeComplete( - "\x10\x04test\x01\x56\x78\x12\x34" - "\x9a\x41\x0c\x13\x80\x00\x00\x00\x00"_us); -} - -TEST_F(WireDecoder3Test, EntryUpdateBoolean) { - EXPECT_CALL(handler, EntryUpdate(0x5678, 0x1234, Value::MakeBoolean(true))); - DecodeComplete("\x11\x56\x78\x12\x34\x00\x01"_us); -} - -TEST_F(WireDecoder3Test, EntryUpdateDouble) { - // values except min and max from - // http://www.binaryconvert.com/result_double.html - EXPECT_CALL(handler, EntryUpdate(0x5678, 0x1234, Value::MakeDouble(0.0))); - DecodeComplete("\x11\x56\x78\x12\x34\x01\x00\x00\x00\x00\x00\x00\x00\x00"_us); - EXPECT_CALL(handler, EntryUpdate(0x5678, 0x1234, Value::MakeDouble(2.3e5))); - DecodeComplete("\x11\x56\x78\x12\x34\x01\x41\x0c\x13\x80\x00\x00\x00\x00"_us); - EXPECT_CALL( - handler, - EntryUpdate(0x5678, 0x1234, - Value::MakeDouble(std::numeric_limits::infinity()))); - DecodeComplete("\x11\x56\x78\x12\x34\x01\x7f\xf0\x00\x00\x00\x00\x00\x00"_us); - EXPECT_CALL(handler, EntryUpdate(0x5678, 0x1234, Value::MakeDouble(DBL_MIN))); - DecodeComplete("\x11\x56\x78\x12\x34\x01\x00\x10\x00\x00\x00\x00\x00\x00"_us); - EXPECT_CALL(handler, EntryUpdate(0x5678, 0x1234, Value::MakeDouble(DBL_MAX))); - DecodeComplete("\x11\x56\x78\x12\x34\x01\x7f\xef\xff\xff\xff\xff\xff\xff"_us); -} - -TEST_F(WireDecoder3Test, EntryUpdateString) { - EXPECT_CALL(handler, - EntryUpdate(0x5678, 0x1234, Value::MakeString("hello"sv))); - DecodeComplete("\x11\x56\x78\x12\x34\x02\x05hello"_us); -} - -TEST_F(WireDecoder3Test, EntryUpdateString2) { - std::vector in{0x11, 0x56, 0x78, 0x12, 0x34, 0x02, 0x7f}; - in.insert(in.end(), 127, '*'); - std::string out(127, '*'); - EXPECT_CALL(handler, - EntryUpdate(0x5678, 0x1234, Value::MakeString(std::move(out)))); - DecodeComplete(in); -} - -TEST_F(WireDecoder3Test, EntryUpdateStringLarge) { - std::vector in{0x11, 0x56, 0x78, 0x12, 0x34, 0x02, 0x80, 0x01}; - in.insert(in.end(), 127, '*'); - in.push_back('x'); - - std::string out(127, '*'); - out.push_back('x'); - - EXPECT_CALL(handler, - EntryUpdate(0x5678, 0x1234, Value::MakeString(std::move(out)))); - DecodeComplete(in); -} - -TEST_F(WireDecoder3Test, EntryUpdateStringHuge) { - std::vector in{0x11, 0x56, 0x78, 0x12, 0x34, 0x02, 0x81, 0x80, 0x04}; - in.insert(in.end(), 65534, '*'); - in.insert(in.end(), 3, 'x'); - - std::string out(65534, '*'); - out.append(3, 'x'); - - EXPECT_CALL(handler, - EntryUpdate(0x5678, 0x1234, Value::MakeString(std::move(out)))); - DecodeComplete(in); -} - -TEST_F(WireDecoder3Test, EntryUpdateRaw) { - EXPECT_CALL(handler, EntryUpdate(0x5678, 0x1234, Value::MakeRaw("hello"_us))); - DecodeComplete("\x11\x56\x78\x12\x34\x03\x05hello"_us); -} - -TEST_F(WireDecoder3Test, EntryUpdateBooleanArray) { - EXPECT_CALL(handler, - EntryUpdate(0x5678, 0x1234, - Value::MakeBooleanArray({false, true, false}))); - DecodeComplete("\x11\x56\x78\x12\x34\x10\x03\x00\x01\x00"_us); -} - -TEST_F(WireDecoder3Test, EntryUpdateBooleanArrayLarge) { - std::vector in{0x11, 0x56, 0x78, 0x12, 0x34, 0x10, 0xff}; - in.insert(in.end(), 255, 0); - std::vector out(255, 0); - EXPECT_CALL(handler, EntryUpdate(0x5678, 0x1234, - Value::MakeBooleanArray(std::move(out)))); - DecodeComplete(in); -} - -TEST_F(WireDecoder3Test, EntryUpdateDoubleArray) { - EXPECT_CALL(handler, - EntryUpdate(0x5678, 0x1234, Value::MakeDoubleArray({0.5, 0.25}))); - DecodeComplete( - "\x11\x56\x78\x12\x34\x11\x02" - "\x3f\xe0\x00\x00\x00\x00\x00\x00" - "\x3f\xd0\x00\x00\x00\x00\x00\x00"_us); -} - -TEST_F(WireDecoder3Test, EntryUpdateDoubleArrayLarge) { - std::vector in{0x11, 0x56, 0x78, 0x12, 0x34, 0x11, 0xff}; - in.insert(in.end(), 255 * 8, 0); - std::vector out(255, 0.0); - EXPECT_CALL(handler, EntryUpdate(0x5678, 0x1234, - Value::MakeDoubleArray(std::move(out)))); - DecodeComplete(in); -} - -TEST_F(WireDecoder3Test, EntryUpdateStringArray) { - EXPECT_CALL(handler, EntryUpdate(0x5678, 0x1234, - Value::MakeStringArray({"hello", "bye"}))); - DecodeComplete( - "\x11\x56\x78\x12\x34\x12\x02\x05hello\x03" - "bye"_us); -} - -TEST_F(WireDecoder3Test, EntryUpdateStringArrayLarge) { - std::vector in{0x11, 0x56, 0x78, 0x12, 0x34, 0x12, 0xff}; - in.insert(in.end(), 255, 0); - std::vector out(255, ""); - EXPECT_CALL(handler, EntryUpdate(0x5678, 0x1234, - Value::MakeStringArray(std::move(out)))); - DecodeComplete(in); -} - -TEST_F(WireDecoder3Test, EntryUpdateRpc) { - // RPC values are decoded as raw - EXPECT_CALL(handler, EntryUpdate(0x5678, 0x1234, Value::MakeRaw("hello"_us))); - DecodeComplete("\x11\x56\x78\x12\x34\x20\x05hello"_us); -} - -TEST_F(WireDecoder3Test, EntryUpdateTypeError) { - auto in = "\x11\x56\x78\x12\x34\x30\x11"_us; - decoder.Execute(&in); - ASSERT_EQ(decoder.GetError(), "unrecognized value type"); -} - -} // namespace nt diff --git a/ntcore/src/test/native/cpp/net3/WireEncoder3Test.cpp b/ntcore/src/test/native/cpp/net3/WireEncoder3Test.cpp deleted file mode 100644 index 96c39a1243..0000000000 --- a/ntcore/src/test/native/cpp/net3/WireEncoder3Test.cpp +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "../TestPrinters.h" -#include "net3/Message3.h" -#include "net3/WireEncoder3.h" -#include "networktables/NetworkTableValue.h" - -using namespace std::string_view_literals; - -namespace nt { - -class WireEncoder3Test : public ::testing::Test { - protected: - std::vector out; - wpi::raw_uvector_ostream os{out}; -}; - -TEST_F(WireEncoder3Test, Unknown) { - net3::WireEncode(os, net3::Message3{}); - ASSERT_TRUE(out.empty()); -} - -TEST_F(WireEncoder3Test, KeepAlive) { - net3::WireEncode(os, net3::Message3::KeepAlive()); - ASSERT_THAT(out, wpi::SpanEq("\x00"_us)); -} - -TEST_F(WireEncoder3Test, ClientHello) { - net3::WireEncode(os, net3::Message3::ClientHello("hello")); - ASSERT_THAT(out, wpi::SpanEq("\x01\x03\x00\x05hello"_us)); -} - -TEST_F(WireEncoder3Test, ProtoUnsup) { - net3::WireEncode(os, net3::Message3::ProtoUnsup()); - net3::WireEncode(os, net3::Message3::ProtoUnsup(0x0200u)); - ASSERT_THAT(out, wpi::SpanEq("\x02\x03\x00\x02\x02\x00"_us)); -} - -TEST_F(WireEncoder3Test, ServerHelloDone) { - net3::WireEncode(os, net3::Message3::ServerHelloDone()); - ASSERT_THAT(out, wpi::SpanEq("\x03"_us)); -} - -TEST_F(WireEncoder3Test, ServerHello) { - net3::WireEncode(os, net3::Message3::ServerHello(0x03, "hello")); - ASSERT_THAT(out, wpi::SpanEq("\x04\x03\x05hello"_us)); -} - -TEST_F(WireEncoder3Test, ClientHelloDone) { - net3::WireEncode(os, net3::Message3::ClientHelloDone()); - ASSERT_THAT(out, wpi::SpanEq("\x05"_us)); -} - -TEST_F(WireEncoder3Test, FlagsUpdate) { - net3::WireEncode(os, net3::Message3::FlagsUpdate(0x5678, 0x03)); - ASSERT_THAT(out, wpi::SpanEq("\x12\x56\x78\x03"_us)); -} - -TEST_F(WireEncoder3Test, EntryDelete) { - net3::WireEncode(os, net3::Message3::EntryDelete(0x5678)); - ASSERT_THAT(out, wpi::SpanEq("\x13\x56\x78"_us)); -} - -TEST_F(WireEncoder3Test, ClearEntries) { - net3::WireEncode(os, net3::Message3::ClearEntries()); - ASSERT_THAT(out, wpi::SpanEq("\x14\xd0\x6c\xb2\x7a"_us)); -} - -TEST_F(WireEncoder3Test, ExecuteRpc) { - net3::WireEncode(os, net3::Message3::ExecuteRpc(0x5678, 0x1234, "hello"_us)); - ASSERT_THAT(out, wpi::SpanEq("\x20\x56\x78\x12\x34\x05hello"_us)); -} - -TEST_F(WireEncoder3Test, RpcResponse) { - net3::WireEncode(os, net3::Message3::RpcResponse(0x5678, 0x1234, "hello"_us)); - ASSERT_THAT(out, wpi::SpanEq("\x21\x56\x78\x12\x34\x05hello"_us)); -} - -TEST_F(WireEncoder3Test, EntryAssignBoolean) { - net3::WireEncode(os, - net3::Message3::EntryAssign("test"sv, 0x5678, 0x1234, - Value::MakeBoolean(true), 0x9a)); - ASSERT_THAT(out, wpi::SpanEq("\x10\x04test\x00\x56\x78\x12\x34\x9a\x01"_us)); -} - -TEST_F(WireEncoder3Test, EntryAssignDouble) { - net3::WireEncode(os, - net3::Message3::EntryAssign("test"sv, 0x5678, 0x1234, - Value::MakeDouble(2.3e5), 0x9a)); - ASSERT_THAT(out, wpi::SpanEq("\x10\x04test\x01\x56\x78\x12\x34" - "\x9a\x41\x0c\x13\x80\x00\x00\x00\x00"_us)); -} - -TEST_F(WireEncoder3Test, EntryUpdateBoolean) { - net3::WireEncode(os, net3::Message3::EntryUpdate(0x5678, 0x1234, - Value::MakeBoolean(true))); - ASSERT_THAT(out, wpi::SpanEq("\x11\x56\x78\x12\x34\x00\x01"_us)); -} - -TEST_F(WireEncoder3Test, EntryUpdateDouble) { - // values except min and max from - // http://www.binaryconvert.com/result_double.html - net3::WireEncode( - os, net3::Message3::EntryUpdate(0x5678, 0x1234, Value::MakeDouble(0.0))); - ASSERT_THAT( - out, wpi::SpanEq( - "\x11\x56\x78\x12\x34\x01\x00\x00\x00\x00\x00\x00\x00\x00"_us)); - - out.clear(); - net3::WireEncode(os, net3::Message3::EntryUpdate(0x5678, 0x1234, - Value::MakeDouble(2.3e5))); - ASSERT_THAT( - out, wpi::SpanEq( - "\x11\x56\x78\x12\x34\x01\x41\x0c\x13\x80\x00\x00\x00\x00"_us)); - - out.clear(); - net3::WireEncode( - os, net3::Message3::EntryUpdate( - 0x5678, 0x1234, - Value::MakeDouble(std::numeric_limits::infinity()))); - ASSERT_THAT( - out, wpi::SpanEq( - "\x11\x56\x78\x12\x34\x01\x7f\xf0\x00\x00\x00\x00\x00\x00"_us)); - - out.clear(); - net3::WireEncode(os, net3::Message3::EntryUpdate(0x5678, 0x1234, - Value::MakeDouble(DBL_MIN))); - ASSERT_THAT( - out, wpi::SpanEq( - "\x11\x56\x78\x12\x34\x01\x00\x10\x00\x00\x00\x00\x00\x00"_us)); - - out.clear(); - net3::WireEncode(os, net3::Message3::EntryUpdate(0x5678, 0x1234, - Value::MakeDouble(DBL_MAX))); - ASSERT_THAT( - out, wpi::SpanEq( - "\x11\x56\x78\x12\x34\x01\x7f\xef\xff\xff\xff\xff\xff\xff"_us)); -} - -TEST_F(WireEncoder3Test, EntryUpdateString) { - net3::WireEncode(os, net3::Message3::EntryUpdate( - 0x5678, 0x1234, Value::MakeString("hello"sv))); - ASSERT_THAT(out, wpi::SpanEq("\x11\x56\x78\x12\x34\x02\x05hello"_us)); -} - -TEST_F(WireEncoder3Test, EntryUpdateString2) { - std::vector ex{0x11, 0x56, 0x78, 0x12, 0x34, 0x02, 0x7f}; - ex.insert(ex.end(), 127, '*'); - std::string in(127, '*'); - net3::WireEncode(os, net3::Message3::EntryUpdate( - 0x5678, 0x1234, Value::MakeString(std::move(in)))); - ASSERT_THAT(out, ex); -} - -TEST_F(WireEncoder3Test, EntryUpdateStringLarge) { - std::vector ex{0x11, 0x56, 0x78, 0x12, 0x34, 0x02, 0x80, 0x01}; - ex.insert(ex.end(), 127, '*'); - ex.push_back('x'); - - std::string in(127, '*'); - in.push_back('x'); - - net3::WireEncode(os, net3::Message3::EntryUpdate( - 0x5678, 0x1234, Value::MakeString(std::move(in)))); - ASSERT_THAT(out, ex); -} - -TEST_F(WireEncoder3Test, EntryUpdateStringHuge) { - std::vector ex{0x11, 0x56, 0x78, 0x12, 0x34, 0x02, 0x81, 0x80, 0x04}; - ex.insert(ex.end(), 65534, '*'); - ex.insert(ex.end(), 3, 'x'); - - std::string in(65534, '*'); - in.append(3, 'x'); - - net3::WireEncode(os, net3::Message3::EntryUpdate( - 0x5678, 0x1234, Value::MakeString(std::move(in)))); - ASSERT_THAT(out, ex); -} - -TEST_F(WireEncoder3Test, EntryUpdateRaw) { - net3::WireEncode(os, net3::Message3::EntryUpdate(0x5678, 0x1234, - Value::MakeRaw("hello"_us))); - ASSERT_THAT(out, wpi::SpanEq("\x11\x56\x78\x12\x34\x03\x05hello"_us)); -} - -TEST_F(WireEncoder3Test, EntryUpdateBooleanArray) { - net3::WireEncode( - os, net3::Message3::EntryUpdate( - 0x5678, 0x1234, Value::MakeBooleanArray({false, true, false}))); - ASSERT_THAT(out, wpi::SpanEq("\x11\x56\x78\x12\x34\x10\x03\x00\x01\x00"_us)); -} - -TEST_F(WireEncoder3Test, EntryUpdateBooleanArrayLarge) { - std::vector ex{0x11, 0x56, 0x78, 0x12, 0x34, 0x10, 0xff}; - ex.insert(ex.end(), 255, 0); - std::vector in(255, 0); - net3::WireEncode( - os, net3::Message3::EntryUpdate(0x5678, 0x1234, - Value::MakeBooleanArray(std::move(in)))); - ASSERT_THAT(out, ex); -} - -TEST_F(WireEncoder3Test, EntryUpdateBooleanArrayTrunc) { - std::vector ex{0x11, 0x56, 0x78, 0x12, 0x34, 0x10, 0xff}; - ex.insert(ex.end(), 255, 0); - std::vector in(256, 0); - net3::WireEncode( - os, net3::Message3::EntryUpdate(0x5678, 0x1234, - Value::MakeBooleanArray(std::move(in)))); - ASSERT_THAT(out, ex); -} - -TEST_F(WireEncoder3Test, EntryUpdateDoubleArray) { - net3::WireEncode( - os, net3::Message3::EntryUpdate(0x5678, 0x1234, - Value::MakeDoubleArray({0.5, 0.25}))); - ASSERT_THAT(out, wpi::SpanEq("\x11\x56\x78\x12\x34\x11\x02" - "\x3f\xe0\x00\x00\x00\x00\x00\x00" - "\x3f\xd0\x00\x00\x00\x00\x00\x00"_us)); -} - -TEST_F(WireEncoder3Test, EntryUpdateDoubleArrayLarge) { - std::vector ex{0x11, 0x56, 0x78, 0x12, 0x34, 0x11, 0xff}; - ex.insert(ex.end(), 255 * 8, 0); - std::vector in(255, 0.0); - net3::WireEncode( - os, net3::Message3::EntryUpdate(0x5678, 0x1234, - Value::MakeDoubleArray(std::move(in)))); - ASSERT_THAT(out, ex); -} - -TEST_F(WireEncoder3Test, EntryUpdateDoubleArrayTrunc) { - std::vector ex{0x11, 0x56, 0x78, 0x12, 0x34, 0x11, 0xff}; - ex.insert(ex.end(), 255 * 8, 0); - std::vector in(256, 0.0); - net3::WireEncode( - os, net3::Message3::EntryUpdate(0x5678, 0x1234, - Value::MakeDoubleArray(std::move(in)))); - ASSERT_THAT(out, ex); -} - -TEST_F(WireEncoder3Test, EntryUpdateStringArray) { - net3::WireEncode( - os, net3::Message3::EntryUpdate( - 0x5678, 0x1234, Value::MakeStringArray({"hello", "bye"}))); - ASSERT_THAT(out, wpi::SpanEq("\x11\x56\x78\x12\x34\x12\x02\x05hello\x03" - "bye"_us)); -} - -TEST_F(WireEncoder3Test, EntryUpdateStringArrayLarge) { - std::vector ex{0x11, 0x56, 0x78, 0x12, 0x34, 0x12, 0xff}; - ex.insert(ex.end(), 255, 0); - std::vector in(255, ""); - net3::WireEncode( - os, net3::Message3::EntryUpdate(0x5678, 0x1234, - Value::MakeStringArray(std::move(in)))); - ASSERT_THAT(out, ex); -} - -TEST_F(WireEncoder3Test, EntryUpdateStringArrayTrunc) { - std::vector ex{0x11, 0x56, 0x78, 0x12, 0x34, 0x12, 0xff}; - ex.insert(ex.end(), 255, 0); - std::vector in(256, ""); - net3::WireEncode( - os, net3::Message3::EntryUpdate(0x5678, 0x1234, - Value::MakeStringArray(std::move(in)))); - ASSERT_THAT(out, ex); -} - -} // namespace nt diff --git a/ntcoreffi/src/main/native/symbols.txt b/ntcoreffi/src/main/native/symbols.txt index 906da957f8..cd15300bfe 100644 --- a/ntcoreffi/src/main/native/symbols.txt +++ b/ntcoreffi/src/main/native/symbols.txt @@ -208,8 +208,7 @@ NT_SetTopicPersistent NT_SetTopicProperties NT_SetTopicProperty NT_SetTopicRetained -NT_StartClient3 -NT_StartClient4 +NT_StartClient NT_StartConnectionDataLog NT_StartDSClient NT_StartEntryDataLog diff --git a/outlineviewer/src/main/native/cpp/main.cpp b/outlineviewer/src/main/native/cpp/main.cpp index 72c2b64742..768cf4ce6e 100644 --- a/outlineviewer/src/main/native/cpp/main.cpp +++ b/outlineviewer/src/main/native/cpp/main.cpp @@ -50,7 +50,7 @@ static std::string MakeTitle(NT_Inst inst, nt::Event event) { auto numClients = nt::GetConnections(inst).size(); return fmt::format("OutlineViewer - {} Client{} Connected", numClients, (numClients == 1 ? "" : "s")); - } else if (mode & NT_NET_MODE_CLIENT3 || mode & NT_NET_MODE_CLIENT4) { + } else if (mode & NT_NET_MODE_CLIENT) { if (event.Is(NT_EVENT_CONNECTED)) { return fmt::format("OutlineViewer - Connected ({})", event.GetConnectionInfo()->remote_ip); diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/PreferencesTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/PreferencesTest.java index 7b11a90ff7..21a27a2e8f 100644 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/PreferencesTest.java +++ b/wpilibj/src/test/java/edu/wpi/first/wpilibj/PreferencesTest.java @@ -52,7 +52,7 @@ class PreferencesTest { fail(ex); } - m_inst.startServer(filepath.toString(), "", 0, 0); + m_inst.startServer(filepath.toString(), "", 0); try { int count = 0; while (m_inst.getNetworkMode().contains(NetworkTableInstance.NetworkMode.kStarting)) {