Sundry tweaks to aos/vision libs

Change-Id: Ia5578dcf2d42ac53b81af239bf329eb084fcf1d9
diff --git a/aos/vision/events/BUILD b/aos/vision/events/BUILD
index 2b5b9e7..9c55a1c 100644
--- a/aos/vision/events/BUILD
+++ b/aos/vision/events/BUILD
@@ -1,5 +1,5 @@
 load('/tools/build_rules/gtk_dependent', 'gtk_dependent_cc_binary', 'gtk_dependent_cc_library')
-package(default_visibility = ["//visibility:public"])
+package(default_visibility = ['//visibility:public'])
 
 cc_library(
   name = 'epoll_events',
@@ -12,12 +12,14 @@
   ],
 )
 
-cc_library(name = "socket_types",
-    hdrs = ["socket_types.h"],
-    deps = [
-        "//aos/vision/events:tcp_server",
-        "//aos/vision/image:image_types",
-    ],
+cc_library(
+  name = 'socket_types',
+  hdrs = ['socket_types.h'],
+  deps = [
+    '//aos/vision/events:tcp_server',
+    '//aos/vision/image:image_types',
+    '//third_party/protobuf:protobuf',
+  ],
 )
 
 cc_library(
@@ -59,10 +61,10 @@
 )
 
 gtk_dependent_cc_library(
-  name = "gtk_event",
-  srcs = ["gtk_event.cc"],
+  name = 'gtk_event',
+  srcs = ['gtk_event.cc'],
   deps = [
-    ":epoll_events",
+    ':epoll_events',
     '@usr_repo//:gtk+-3.0',
   ],
 )
diff --git a/aos/vision/events/epoll_events.cc b/aos/vision/events/epoll_events.cc
index e4f789f..d49043c 100644
--- a/aos/vision/events/epoll_events.cc
+++ b/aos/vision/events/epoll_events.cc
@@ -36,7 +36,7 @@
 
     for (int i = 0; i < number_events; i++) {
       EpollEvent *event = static_cast<EpollEvent *>(events[i].data.ptr);
-      if ((events[i].events & ~(EPOLLIN | EPOLLPRI)) != 0) {
+      if ((events[i].events & ~(EPOLLIN | EPOLLPRI | EPOLLERR)) != 0) {
         LOG(FATAL, "unexpected epoll events set in %x on %d\n",
             events[i].events, event->fd());
       }
diff --git a/aos/vision/events/epoll_events.h b/aos/vision/events/epoll_events.h
index ee288c4..3b7d75a 100644
--- a/aos/vision/events/epoll_events.h
+++ b/aos/vision/events/epoll_events.h
@@ -44,7 +44,7 @@
     // Duplicate above to allow Done to change itself.
     if (time_ < monotonic_clock::epoch()) return -1;
     if (time_ <= now) {
-      return -1;// Recalculate(now);
+      return -1;
     }
 
     if (time_ - now > ::std::chrono::milliseconds(INT_MAX)) {
diff --git a/aos/vision/events/gtk_event.cc b/aos/vision/events/gtk_event.cc
index e8b43aa..0c518e0 100644
--- a/aos/vision/events/gtk_event.cc
+++ b/aos/vision/events/gtk_event.cc
@@ -1,9 +1,9 @@
-#include <gtk/gtk.h>
 #include <gdk/gdk.h>
-#include <thread>
+#include <gtk/gtk.h>
 #include <sys/epoll.h>
-#include <mutex>
 #include <condition_variable>
+#include <mutex>
+#include <thread>
 
 #include "aos/vision/events/epoll_events.h"
 
@@ -43,16 +43,19 @@
   std::thread t([&]() {
     std::unique_lock<std::mutex> lk(m);
     while (true) {
-      cv.wait(lk, [&all_events_handled]{return all_events_handled;});
+      cv.wait(lk, [&all_events_handled] { return all_events_handled; });
       // Wait for handle_cb to be done.
-      number_events = PCHECK(epoll_wait(epoll_fd(), events, kNumberOfEvents, timeout));
+      number_events =
+          PCHECK(epoll_wait(epoll_fd(), events, kNumberOfEvents, timeout));
       all_events_handled = false;
       // Trigger handle_cb on main_thread to avoid concurrency.
-      gdk_threads_add_idle(+[](gpointer user_data) -> gboolean {
-        auto& handle_cb = *reinterpret_cast<HandleCBType*>(user_data);
-        handle_cb();
-        return G_SOURCE_REMOVE;
-      }, &handle_cb);
+      gdk_threads_add_idle(
+          +[](gpointer user_data) -> gboolean {
+            auto &handle_cb = *reinterpret_cast<HandleCBType *>(user_data);
+            handle_cb();
+            return G_SOURCE_REMOVE;
+          },
+          &handle_cb);
     }
   });
   gtk_main();
diff --git a/aos/vision/events/socket_types.h b/aos/vision/events/socket_types.h
index 2432cb9..d377214 100644
--- a/aos/vision/events/socket_types.h
+++ b/aos/vision/events/socket_types.h
@@ -3,6 +3,8 @@
 
 #include <poll.h>
 #include <stdint.h>
+#include <sys/socket.h>
+#include <sys/types.h>
 
 #include "aos/vision/events/tcp_server.h"
 #include "aos/vision/image/image_types.h"
@@ -32,7 +34,12 @@
     char buf[512];
     while (true) {
       count = read(fd(), &buf, sizeof buf);
-      if (count <= 0) return;
+      if (count <= 0) {
+        if (errno != EAGAIN) {
+          CloseConnection();
+          return;
+        }
+      }
     }
   }
 
@@ -46,14 +53,15 @@
   void Emit(vision::DataRef data) {
     data_len len;
     len.len = data.size();
-    int res = write(fd(), len.buf, sizeof len.buf);
+    int res = send(fd(), len.buf, sizeof len.buf, MSG_NOSIGNAL);
     if (res == -1) {
-      printf("Emit Error on write\n");
+      CloseConnection();
+      return;
     }
     size_t write_count = 0;
     while (write_count < data.size()) {
-      int len =
-          write(fd(), &data.data()[write_count], data.size() - write_count);
+      int len = send(fd(), &data.data()[write_count], data.size() - write_count,
+                     MSG_NOSIGNAL);
       if (len == -1) {
         if (errno == EAGAIN) {
           struct pollfd waiting;
@@ -61,7 +69,7 @@
           waiting.events = POLLOUT;
           poll(&waiting, 1, -1);
         } else {
-          close(fd());
+          CloseConnection();
           return;
         }
       } else {
@@ -70,6 +78,13 @@
       if (write_count != data.size()) printf("wrote: %d\n", len);
     }
   }
+
+ private:
+  void CloseConnection() {
+    loop()->Delete(this);
+    close(fd());
+    delete this;
+  }
 };
 
 }  // namespace events
diff --git a/aos/vision/events/tcp_client.cc b/aos/vision/events/tcp_client.cc
index 41485f9..4ac45af 100644
--- a/aos/vision/events/tcp_client.cc
+++ b/aos/vision/events/tcp_client.cc
@@ -30,7 +30,7 @@
   return 0;
 }
 
-int OpenClient(const char *hostname, int portno) {
+int OpenClient(const std::string &hostname, int portno) {
   int sockfd;
   struct sockaddr_in serveraddr;
   struct hostent *server;
@@ -38,9 +38,9 @@
   PCHECK(sockfd = socket(AF_INET, SOCK_STREAM, 0));
 
   /* gethostbyname: get the server's DNS entry */
-  server = gethostbyname(hostname);
+  server = gethostbyname(hostname.c_str());
   if (server == NULL) {
-    fprintf(stderr, "ERROR, no such host as %s\n", hostname);
+    fprintf(stderr, "ERROR, no such host as %s\n", hostname.c_str());
     exit(-1);
   }
 
@@ -60,7 +60,7 @@
 }
 }  // namespace
 
-TcpClient::TcpClient(const char *hostname, int portno)
+TcpClient::TcpClient(const std::string &hostname, int portno)
     : EpollEvent(OpenClient(hostname, portno)) {}
 
 }  // namespace events
diff --git a/aos/vision/events/tcp_client.h b/aos/vision/events/tcp_client.h
index 7ce01f7..74f1418 100644
--- a/aos/vision/events/tcp_client.h
+++ b/aos/vision/events/tcp_client.h
@@ -4,6 +4,7 @@
 #include "aos/vision/events/epoll_events.h"
 
 #include <memory>
+#include <string>
 
 namespace aos {
 namespace events {
@@ -11,7 +12,7 @@
 // Handles the client connection logic to hostname:portno
 class TcpClient : public EpollEvent {
  public:
-  TcpClient(const char *hostname, int portno);
+  TcpClient(const std::string &hostname, int portno);
 
   // Implement ReadEvent from EpollEvent to use this class.
 };
diff --git a/aos/vision/events/udp.cc b/aos/vision/events/udp.cc
index b5367f6..4c0437b 100644
--- a/aos/vision/events/udp.cc
+++ b/aos/vision/events/udp.cc
@@ -22,7 +22,8 @@
 }
 
 int TXUdpSocket::Send(const char *data, int size) {
-  return PCHECK(send(fd_.get(), data, size, 0));
+  // Don't fail on send. If no one is connected that is fine.
+  return send(fd_.get(), data, size, 0);
 }
 
 RXUdpSocket::RXUdpSocket(int port)