Add a barebones websocket server for vision debug

Change-Id: Ifc1a2fc1ae7f1312d28923e33e90eb43ac43e0c4
diff --git a/y2019/vision/server/server.cc b/y2019/vision/server/server.cc
new file mode 100644
index 0000000..cc6d260
--- /dev/null
+++ b/y2019/vision/server/server.cc
@@ -0,0 +1,95 @@
+#include <memory>
+#include <set>
+
+#include "aos/init.h"
+#include "aos/logging/logging.h"
+#include "aos/time/time.h"
+#include "internal/Embedded.h"
+#include "seasocks/PrintfLogger.h"
+#include "seasocks/Server.h"
+#include "seasocks/StringUtil.h"
+#include "seasocks/WebSocket.h"
+
+namespace y2019 {
+namespace vision {
+
+class WebsocketHandler : public seasocks::WebSocket::Handler {
+ public:
+  WebsocketHandler();
+  void onConnect(seasocks::WebSocket* connection) override;
+  void onData(seasocks::WebSocket* connection, const char* data) override;
+  void onDisconnect(seasocks::WebSocket* connection) override;
+
+ private:
+  std::set<seasocks::WebSocket *> connections_;
+};
+
+WebsocketHandler::WebsocketHandler() {
+}
+
+void WebsocketHandler::onConnect(seasocks::WebSocket *connection) {
+  connections_.insert(connection);
+  LOG(INFO, "Connected: %s : %s\n", connection->getRequestUri().c_str(),
+      seasocks::formatAddress(connection->getRemoteAddress()).c_str());
+}
+
+void WebsocketHandler::onData(seasocks::WebSocket * /*connection*/,
+                              const char *data) {
+  LOG(INFO, "Got data: %s\n", data);
+}
+
+void WebsocketHandler::onDisconnect(seasocks::WebSocket *connection) {
+  connections_.erase(connection);
+  LOG(INFO, "Disconnected: %s : %s\n", connection->getRequestUri().c_str(),
+      seasocks::formatAddress(connection->getRemoteAddress()).c_str());
+}
+
+// TODO(Brian): Put this somewhere shared.
+class SeasocksLogger : public seasocks::PrintfLogger {
+ public:
+  SeasocksLogger(Level min_level_to_log) : PrintfLogger(min_level_to_log) {}
+  void log(Level level, const char* message) override;
+};
+
+void SeasocksLogger::log(Level level, const char *message) {
+  // Convert Seasocks error codes to AOS.
+  log_level aos_level;
+  switch (level) {
+    case seasocks::Logger::INFO:
+      aos_level = INFO;
+      break;
+    case seasocks::Logger::WARNING:
+      aos_level = WARNING;
+      break;
+    case seasocks::Logger::ERROR:
+    case seasocks::Logger::SEVERE:
+      aos_level = ERROR;
+      break;
+    case seasocks::Logger::DEBUG:
+    case seasocks::Logger::ACCESS:
+    default:
+      aos_level = DEBUG;
+      break;
+  }
+  LOG(aos_level, "Seasocks: %s\n", message);
+}
+
+}  // namespace vision
+}  // namespace y2019
+
+int main(int, char *[]) {
+  // Make sure to reference this to force the linker to include it.
+  findEmbeddedContent("");
+
+  aos::InitNRT();
+
+  seasocks::Server server(::std::shared_ptr<seasocks::Logger>(
+      new y2019::vision::SeasocksLogger(seasocks::Logger::INFO)));
+
+  auto websocket_handler = std::make_shared<y2019::vision::WebsocketHandler>();
+
+  server.addWebSocketHandler("/ws", websocket_handler);
+  server.serve("/home/admin/robot_code/www", 1180);
+
+  return 0;
+}