Import foxglove schemas repo

This has to do a couple of things:
* Actually import the repo as an http_archive.
* Modify the cc_static_flatbuffer rule to allow it to handle a
  flatbuffer target with multiple fbs files.
* Move foxglove-related third_party files into one directory.

Change-Id: I0123fc8037b107019f9c29b781418c9a03639eca
Signed-off-by: James Kuszmaul <jabukuszmaul@gmail.com>
diff --git a/third_party/foxglove/BUILD b/third_party/foxglove/BUILD
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/foxglove/BUILD
diff --git a/third_party/foxglove/schemas/BUILD b/third_party/foxglove/schemas/BUILD
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/foxglove/schemas/BUILD
diff --git a/third_party/foxglove/schemas/schemas.BUILD b/third_party/foxglove/schemas/schemas.BUILD
new file mode 100644
index 0000000..a1a5d29
--- /dev/null
+++ b/third_party/foxglove/schemas/schemas.BUILD
@@ -0,0 +1,21 @@
+load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library", "DEFAULT_FLATC_ARGS")
+
+FLATC_ARGS = [arg for arg in DEFAULT_FLATC_ARGS if arg != "--require-explicit-ids"]
+
+flatbuffer_cc_library(
+    name = "schemas",
+    srcs = glob(["*.fbs"]),
+    flatc_args = FLATC_ARGS,
+    gen_reflections = True,
+    visibility = ["//visibility:public"],
+)
+
+load("@org_frc971//aos:flatbuffers.bzl", "cc_static_flatbuffer")
+
+[cc_static_flatbuffer(
+    name = filename[:-4] + "_schema",
+    bfbs_name = filename[:-4] + ".bfbs",
+    function = "foxglove::" + filename[:-4] + "Schema",
+    target = ":schemas_reflection_out",
+    visibility = ["//visibility:public"],
+) for filename in glob(["*.fbs"])]
diff --git a/third_party/foxglove/ws_protocol/BUILD b/third_party/foxglove/ws_protocol/BUILD
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/foxglove/ws_protocol/BUILD
diff --git a/third_party/foxglove/ws_protocol/foxglove_ws_protocol.BUILD b/third_party/foxglove/ws_protocol/foxglove_ws_protocol.BUILD
new file mode 100644
index 0000000..01d9a90
--- /dev/null
+++ b/third_party/foxglove/ws_protocol/foxglove_ws_protocol.BUILD
@@ -0,0 +1,19 @@
+# MIT License
+licenses(["notice"])
+
+cc_library(
+    name = "com_github_foxglove_ws-protocol",
+    hdrs = ["cpp/foxglove-websocket/include/foxglove/websocket/server.hpp"],
+    includes = ["cpp/foxglove-websocket/include/"],
+    visibility = ["//visibility:public"],
+    deps = [
+        "@com_github_nlohmann_json//:json",
+        "@com_github_zaphoyd_websocketpp",
+    ],
+)
+
+cc_binary(
+    name = "example_server",
+    srcs = ["cpp/examples/example_server.cpp"],
+    deps = [":com_github_foxglove_ws-protocol"],
+)
diff --git a/third_party/foxglove/ws_protocol/foxglove_ws_protocol.patch b/third_party/foxglove/ws_protocol/foxglove_ws_protocol.patch
new file mode 100644
index 0000000..39eb3da
--- /dev/null
+++ b/third_party/foxglove/ws_protocol/foxglove_ws_protocol.patch
@@ -0,0 +1,78 @@
+# Blue River-specific patches to be able to compile the websocket
+# server against boost and with our compilers/compiler flags.
+diff --git a/cpp/examples/example_server.cpp b/cpp/examples/example_server.cpp
+index c731072..e869e8f 100644
+--- a/cpp/examples/example_server.cpp
++++ b/cpp/examples/example_server.cpp
+@@ -44,7 +44,7 @@ int main() {
+   });
+
+   uint64_t i = 0;
+-  std::shared_ptr<asio::steady_timer> timer;
++  std::shared_ptr<boost::asio::steady_timer> timer;
+   std::function<void()> setTimer = [&] {
+     timer = server.getEndpoint().set_timer(200, [&](std::error_code const& ec) {
+       if (ec) {
+@@ -59,7 +59,7 @@ int main() {
+
+   setTimer();
+
+-  asio::signal_set signals(server.getEndpoint().get_io_service(), SIGINT);
++  boost::asio::signal_set signals(server.getEndpoint().get_io_service(), SIGINT);
+
+   signals.async_wait([&](std::error_code const& ec, int sig) {
+     if (ec) {
+diff --git a/cpp/foxglove-websocket/include/foxglove/websocket/server.hpp b/cpp/foxglove-websocket/include/foxglove/websocket/server.hpp
+index 16a5e83..8845971 100644
+--- a/cpp/foxglove-websocket/include/foxglove/websocket/server.hpp
++++ b/cpp/foxglove-websocket/include/foxglove/websocket/server.hpp
+@@ -1,6 +1,6 @@
+ #pragma once
+
+-#include <nlohmann/json.hpp>
++#include "single_include/nlohmann/json.hpp"
+ #include <websocketpp/config/asio_no_tls.hpp>
+ #include <websocketpp/server.hpp>
+
+@@ -84,6 +84,9 @@ public:
+   Server& operator=(Server&&) = delete;
+
+   void run();
++  size_t run_for(std::chrono::nanoseconds duration) {
++    return _server.get_io_service().run_for(duration);
++  }
+   void stop();
+
+   ChannelId addChannel(ChannelWithoutId channel);
+@@ -105,6 +108,10 @@ private:
+     std::unordered_map<SubscriptionId, ChannelId> subscriptions;
+     std::unordered_map<ChannelId, std::unordered_set<SubscriptionId>> subscriptionsByChannel;
+
++    ClientInfo(const std::string& name_, const ConnHandle& handle_)
++        : name(name_)
++        , handle(handle_) {}
++
+     ClientInfo(const ClientInfo&) = delete;
+     ClientInfo& operator=(const ClientInfo&) = delete;
+
+@@ -147,7 +154,7 @@ inline Server::Server(uint16_t port, std::string name)
+   _server.set_message_handler(std::bind(&Server::handleMessage, this, _1, _2));
+   _server.set_reuse_addr(true);
+   _server.set_listen_backlog(128);
+-  _server.listen(_port);
++  _server.listen(websocketpp::lib::asio::ip::tcp::v4(), _port);
+   _server.start_accept();
+ }
+
+@@ -174,10 +181,7 @@ inline void Server::handleConnectionOpened(ConnHandle hdl) {
+   _server.get_alog().write(
+     websocketpp::log::alevel::app,
+     "Client " + con->get_remote_endpoint() + " connected via " + con->get_resource());
+-  _clients.emplace(hdl, ClientInfo{
+-                          .name = con->get_remote_endpoint(),
+-                          .handle = hdl,
+-                        });
++  _clients.emplace(hdl, ClientInfo{con->get_remote_endpoint(), hdl});
+
+   con->send(json({
+                    {"op", "serverInfo"},