Checking in debug_view, some extra missing utils, and the y2016 target_sender code.

Change-Id: I241947265da8f332c39862f4d0ddcdc2d29c7b68
diff --git a/aos/vision/events/BUILD b/aos/vision/events/BUILD
index c3400fe..e003dc9 100644
--- a/aos/vision/events/BUILD
+++ b/aos/vision/events/BUILD
@@ -11,6 +11,14 @@
   ],
 )
 
+cc_library(name = "socket_types",
+    hdrs = ["socket_types.h"],
+    deps = [
+        "//aos/vision/events:tcp_server",
+        "//aos/vision/image:image_types",
+    ],
+)
+
 cc_library(
   name = 'intrusive_free_list',
   hdrs = ['intrusive_free_list.h'],
diff --git a/aos/vision/events/socket_types.h b/aos/vision/events/socket_types.h
new file mode 100644
index 0000000..2432cb9
--- /dev/null
+++ b/aos/vision/events/socket_types.h
@@ -0,0 +1,78 @@
+#ifndef _AOS_VISION_EVENTS_SOCKET_TYPES_H_
+#define _AOS_VISION_EVENTS_SOCKET_TYPES_H_
+
+#include <poll.h>
+#include <stdint.h>
+
+#include "aos/vision/events/tcp_server.h"
+#include "aos/vision/image/image_types.h"
+#include "google/protobuf/message.h"
+
+namespace aos {
+namespace events {
+
+// Simple TCP client connection that sends messages prefixed by length.
+// Useful to broadcast to a message all connected clients.
+class DataSocket : public events::SocketConnection {
+ public:
+  // Aliasing cast.
+  union data_len {
+    uint32_t len;
+    char buf[4];
+  };
+
+  DataSocket(events::TCPServerBase *serv, int fd)
+      : events::SocketConnection(serv, fd) {}
+
+  ~DataSocket() { printf("Closed connection on descriptor %d\n", fd()); }
+
+  void ReadEvent() override {
+    // Ignore reads, but don't leave them pending.
+    ssize_t count;
+    char buf[512];
+    while (true) {
+      count = read(fd(), &buf, sizeof buf);
+      if (count <= 0) return;
+    }
+  }
+
+  void Emit(const google::protobuf::Message &data) {
+    std::string d;
+    if (data.SerializeToString(&d)) {
+      Emit(d);
+    }
+  }
+
+  void Emit(vision::DataRef data) {
+    data_len len;
+    len.len = data.size();
+    int res = write(fd(), len.buf, sizeof len.buf);
+    if (res == -1) {
+      printf("Emit Error on write\n");
+    }
+    size_t write_count = 0;
+    while (write_count < data.size()) {
+      int len =
+          write(fd(), &data.data()[write_count], data.size() - write_count);
+      if (len == -1) {
+        if (errno == EAGAIN) {
+          struct pollfd waiting;
+          waiting.fd = fd();
+          waiting.events = POLLOUT;
+          poll(&waiting, 1, -1);
+        } else {
+          close(fd());
+          return;
+        }
+      } else {
+        write_count += len;
+      }
+      if (write_count != data.size()) printf("wrote: %d\n", len);
+    }
+  }
+};
+
+}  // namespace events
+}  // namespace aos
+
+#endif  // _AOS_VISION_EVENTS_SOCKET_TYPES_H_
diff --git a/aos/vision/events/udp.cc b/aos/vision/events/udp.cc
index 2d3d1d1..b5367f6 100644
--- a/aos/vision/events/udp.cc
+++ b/aos/vision/events/udp.cc
@@ -5,24 +5,24 @@
 #include "aos/common/logging/logging.h"
 
 namespace aos {
-namespace vision {
+namespace events {
 
-TXUdpSocket::TXUdpSocket(const char *ip_addr, int port)
+TXUdpSocket::TXUdpSocket(const std::string &ip_addr, int port)
     : fd_(PCHECK(socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))) {
   sockaddr_in destination_in;
   memset(&destination_in, 0, sizeof(destination_in));
   destination_in.sin_family = AF_INET;
   destination_in.sin_port = htons(port);
-  if (inet_aton(ip_addr, &destination_in.sin_addr) == 0) {
-    LOG(FATAL, "invalid IP address %s\n", ip_addr);
+  if (inet_aton(ip_addr.c_str(), &destination_in.sin_addr) == 0) {
+    LOG(FATAL, "invalid IP address %s\n", ip_addr.c_str());
   }
 
   PCHECK(connect(fd_.get(), reinterpret_cast<sockaddr *>(&destination_in),
                  sizeof(destination_in)));
 }
 
-int TXUdpSocket::Send(const void *data, int size) {
-  return PCHECK(send(fd_.get(), static_cast<const char *>(data), size, 0));
+int TXUdpSocket::Send(const char *data, int size) {
+  return PCHECK(send(fd_.get(), data, size, 0));
 }
 
 RXUdpSocket::RXUdpSocket(int port)
@@ -42,5 +42,5 @@
   return PCHECK(recv(fd_.get(), static_cast<char *>(data), size, 0));
 }
 
-}  // namespace vision
+}  // namespace events
 }  // namespace aos
diff --git a/aos/vision/events/udp.h b/aos/vision/events/udp.h
index a12a8bf..ed4a8e7 100644
--- a/aos/vision/events/udp.h
+++ b/aos/vision/events/udp.h
@@ -1,27 +1,28 @@
-#ifndef AOS_VISION_IMAGE_UDP_H_
-#define AOS_VISION_IMAGE_UDP_H_
+#ifndef AOS_VISION_EVENTS_UDP_H_
+#define AOS_VISION_EVENTS_UDP_H_
 
 #include <arpa/inet.h>
-#include <sys/socket.h>
 #include <math.h>
+#include <sys/socket.h>
 #include <unistd.h>
+#include <string>
 #include <vector>
 
 #include "aos/common/macros.h"
 #include "aos/common/scoped_fd.h"
 
 namespace aos {
-namespace vision {
+namespace events {
 
 // Simple wrapper around a transmitting UDP socket.
 //
 // LOG(FATAL)s for all errors, including from Send.
 class TXUdpSocket {
  public:
-  TXUdpSocket(const char *ip_addr, int port);
+  TXUdpSocket(const std::string &ip_addr, int port);
 
   // Returns the number of bytes actually sent.
-  int Send(const void *data, int size);
+  int Send(const char *data, int size);
 
  private:
   ScopedFD fd_;
@@ -45,7 +46,7 @@
   DISALLOW_COPY_AND_ASSIGN(RXUdpSocket);
 };
 
-}  // namespace vision
+}  // namespace events
 }  // namespace aos
 
-#endif  // AOS_VISION_IMAGE_UDP_H_
+#endif  // AOS_VISION_EVENTS_UDP_H_
diff --git a/aos/vision/events/udp_test.cc b/aos/vision/events/udp_test.cc
index 87046ba..7e77b68 100644
--- a/aos/vision/events/udp_test.cc
+++ b/aos/vision/events/udp_test.cc
@@ -3,7 +3,7 @@
 #include "gtest/gtest.h"
 
 namespace aos {
-namespace vision {
+namespace events {
 
 TEST(UDPTest, SendRecv) {
   RXUdpSocket rx(1109);
@@ -19,5 +19,5 @@
   EXPECT_EQ(txdata[3], rxdata[3]);
 }
 
-}  // namespace vision
+}  // namespace events
 }  // namespace aos