TCP server for the vision library.

Change-Id: Id73304cabe3f746d72d51cc7dfe5adbe61c20c16
diff --git a/aos/vision/events/tcp_server.h b/aos/vision/events/tcp_server.h
new file mode 100644
index 0000000..3116f55
--- /dev/null
+++ b/aos/vision/events/tcp_server.h
@@ -0,0 +1,77 @@
+#ifndef _AOS_VISION_EVENTS_TCP_SERVER_H_
+#define _AOS_VISION_EVENTS_TCP_SERVER_H_
+
+#include "aos/vision/events/epoll_events.h"
+#include "aos/vision/events/intrusive_free_list.h"
+
+#include <memory>
+#include <vector>
+
+namespace aos {
+namespace events {
+
+// Non-templatized base class of TCP server.
+// TCPServer implements Construct which specializes the client connection
+// based on the specific use-case.
+template <class T>
+class TCPServer;
+class SocketConnection;
+class TCPServerBase : public EpollEvent {
+ public:
+  TCPServerBase(int fd) : EpollEvent(fd) {}
+  ~TCPServerBase();
+
+ protected:
+  // Listens on port portno. File descriptor to
+  // accept on is returned.
+  static int SocketBindListenOnPort(int portno);
+
+ private:
+  virtual SocketConnection *Construct(int child_fd) = 0;
+  void ReadEvent() override;
+  friend class SocketConnection;
+  template <class T>
+  friend class TCPServer;
+  intrusive_free_list<SocketConnection> free_list;
+};
+
+// Base class for client connections. Clients are responsible for
+// deleting themselves once the connection is broken. This will remove
+// the entry from the free list.
+class SocketConnection : public EpollEvent,
+                         public intrusive_free_list<SocketConnection>::element {
+ public:
+  SocketConnection(TCPServerBase *server, int fd)
+      : EpollEvent(fd), element(&server->free_list, this) {}
+};
+
+// T should be a subclass of SocketConnection.
+template <class T>
+class TCPServer : public TCPServerBase {
+ public:
+  TCPServer(int port) : TCPServerBase(SocketBindListenOnPort(port)) {}
+  SocketConnection *Construct(int child_fd) override {
+    return new T(this, child_fd);
+  }
+
+  static std::unique_ptr<TCPServer<T>> Make(int port) {
+    return std::unique_ptr<TCPServer<T>>(new TCPServer<T>(port));
+  }
+
+  // Call blk on each entry of the free-list. This is used to send a message
+  // to all clients.
+  template <typename EachBlock>
+  void Broadcast(const EachBlock &blk) {
+    auto a = free_list.begin();
+    while (a) {
+      auto client = static_cast<T *>(a);
+      blk(client);
+      a = a->next();
+    }
+  }
+};
+
+}  // namespace events
+}  // namespace aos
+
+#endif  // _AOS_VISION_EVENTS_TCP_SERVER_H_