Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc-cloned / deps / grpc / src / core / lib / iomgr / udp_server.cc
diff --git a/legacy-libs/grpc-cloned/deps/grpc/src/core/lib/iomgr/udp_server.cc b/legacy-libs/grpc-cloned/deps/grpc/src/core/lib/iomgr/udp_server.cc
new file mode 100644 (file)
index 0000000..3e85394
--- /dev/null
@@ -0,0 +1,748 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/* FIXME: "posix" files shouldn't be depending on _GNU_SOURCE */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#ifndef SO_RXQ_OVFL
+#define SO_RXQ_OVFL 40
+#endif
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/iomgr/port.h"
+
+#ifdef GRPC_POSIX_SOCKET
+
+#include "src/core/lib/iomgr/udp_server.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/time.h>
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gprpp/inlined_vector.h"
+#include "src/core/lib/gprpp/memory.h"
+#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/iomgr/ev_posix.h"
+#include "src/core/lib/iomgr/executor.h"
+#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
+#include "src/core/lib/iomgr/socket_factory_posix.h"
+#include "src/core/lib/iomgr/socket_utils_posix.h"
+#include "src/core/lib/iomgr/unix_sockets_posix.h"
+
+/* A listener which implements basic features of Listening on a port for
+ * I/O events*/
+class GrpcUdpListener {
+ public:
+  GrpcUdpListener(grpc_udp_server* server, int fd,
+                  const grpc_resolved_address* addr);
+  ~GrpcUdpListener();
+
+  /* Called when grpc server starts to listening on the grpc_fd. */
+  void StartListening(grpc_pollset** pollsets, size_t pollset_count,
+                      GrpcUdpHandlerFactory* handler_factory);
+
+  /* Called when data is available to read from the socket.
+   * Return true if there is more data to read from fd. */
+  void OnRead(grpc_error* error, void* do_read_arg);
+
+  /* Called when the socket is writeable. The given closure should be scheduled
+   * when the socket becomes blocked next time. */
+  void OnCanWrite(grpc_error* error, void* do_write_arg);
+
+  /* Called when the grpc_fd is about to be orphaned (and the FD closed). */
+  void OnFdAboutToOrphan();
+
+  /* Called to orphan fd of this listener.*/
+  void OrphanFd();
+
+  /* Called when this listener is going to be destroyed. */
+  void OnDestroy();
+
+  int fd() const { return fd_; }
+
+ protected:
+  grpc_fd* emfd() const { return emfd_; }
+
+  gpr_mu* mutex() { return &mutex_; }
+
+ private:
+  /* event manager callback when reads are ready */
+  static void on_read(void* arg, grpc_error* error);
+  static void on_write(void* arg, grpc_error* error);
+
+  static void do_read(void* arg, grpc_error* error);
+  static void do_write(void* arg, grpc_error* error);
+  // Wrapper of grpc_fd_notify_on_write() with a grpc_closure callback
+  // interface.
+  static void fd_notify_on_write_wrapper(void* arg, grpc_error* error);
+
+  static void shutdown_fd(void* args, grpc_error* error);
+
+  int fd_;
+  grpc_fd* emfd_;
+  grpc_udp_server* server_;
+  grpc_resolved_address addr_;
+  grpc_closure read_closure_;
+  grpc_closure write_closure_;
+  // To be called when corresponding QuicGrpcServer closes all active
+  // connections.
+  grpc_closure orphan_fd_closure_;
+  grpc_closure destroyed_closure_;
+  // To be scheduled on another thread to actually read/write.
+  grpc_closure do_read_closure_;
+  grpc_closure do_write_closure_;
+  grpc_closure notify_on_write_closure_;
+  // True if orphan_cb is trigered.
+  bool orphan_notified_;
+  // True if grpc_fd_notify_on_write() is called after on_write() call.
+  bool notify_on_write_armed_;
+  // True if fd has been shutdown.
+  bool already_shutdown_;
+  // Object actually handles I/O events. Assigned in StartListening().
+  GrpcUdpHandler* udp_handler_ = nullptr;
+  // To be notified on destruction.
+  GrpcUdpHandlerFactory* handler_factory_ = nullptr;
+  // Required to access above fields.
+  gpr_mu mutex_;
+};
+
+GrpcUdpListener::GrpcUdpListener(grpc_udp_server* server, int fd,
+                                 const grpc_resolved_address* addr)
+    : fd_(fd),
+      server_(server),
+      orphan_notified_(false),
+      already_shutdown_(false) {
+  char* addr_str;
+  char* name;
+  grpc_sockaddr_to_string(&addr_str, addr, 1);
+  gpr_asprintf(&name, "udp-server-listener:%s", addr_str);
+  gpr_free(addr_str);
+  emfd_ = grpc_fd_create(fd, name, true);
+  memcpy(&addr_, addr, sizeof(grpc_resolved_address));
+  GPR_ASSERT(emfd_);
+  gpr_free(name);
+  gpr_mu_init(&mutex_);
+}
+
+GrpcUdpListener::~GrpcUdpListener() { gpr_mu_destroy(&mutex_); }
+
+/* the overall server */
+struct grpc_udp_server {
+  gpr_mu mu;
+
+  /* factory to use for creating and binding sockets, or NULL */
+  grpc_socket_factory* socket_factory;
+
+  /* active port count: how many ports are actually still listening */
+  size_t active_ports;
+  /* destroyed port count: how many ports are completely destroyed */
+  size_t destroyed_ports;
+
+  /* is this server shutting down? (boolean) */
+  int shutdown;
+
+  /* An array of listeners */
+  grpc_core::InlinedVector<GrpcUdpListener, 16> listeners;
+
+  /* factory for use to create udp listeners */
+  GrpcUdpHandlerFactory* handler_factory;
+
+  /* shutdown callback */
+  grpc_closure* shutdown_complete;
+
+  /* all pollsets interested in new connections */
+  grpc_pollset** pollsets;
+  /* number of pollsets in the pollsets array */
+  size_t pollset_count;
+  /* opaque object to pass to callbacks */
+  void* user_data;
+
+  /* latch has_so_reuseport during server creation */
+  bool so_reuseport;
+};
+
+static grpc_socket_factory* get_socket_factory(const grpc_channel_args* args) {
+  if (args) {
+    const grpc_arg* arg = grpc_channel_args_find(args, GRPC_ARG_SOCKET_FACTORY);
+    if (arg) {
+      GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
+      return static_cast<grpc_socket_factory*>(arg->value.pointer.p);
+    }
+  }
+  return nullptr;
+}
+
+grpc_udp_server* grpc_udp_server_create(const grpc_channel_args* args) {
+  grpc_udp_server* s = grpc_core::New<grpc_udp_server>();
+  gpr_mu_init(&s->mu);
+  s->socket_factory = get_socket_factory(args);
+  if (s->socket_factory) {
+    grpc_socket_factory_ref(s->socket_factory);
+  }
+  s->active_ports = 0;
+  s->destroyed_ports = 0;
+  s->shutdown = 0;
+  s->so_reuseport = grpc_is_socket_reuse_port_supported();
+  return s;
+}
+
+// static
+void GrpcUdpListener::shutdown_fd(void* args, grpc_error* error) {
+  if (args == nullptr) {
+    // No-op if shutdown args are null.
+    return;
+  }
+  auto sp = static_cast<GrpcUdpListener*>(args);
+  gpr_mu_lock(sp->mutex());
+  gpr_log(GPR_DEBUG, "shutdown fd %d", sp->fd_);
+  grpc_fd_shutdown(sp->emfd_, GRPC_ERROR_REF(error));
+  sp->already_shutdown_ = true;
+  if (!sp->notify_on_write_armed_) {
+    // Re-arm write notification to notify listener with error. This is
+    // necessary to decrement active_ports.
+    sp->notify_on_write_armed_ = true;
+    grpc_fd_notify_on_write(sp->emfd_, &sp->write_closure_);
+  }
+  gpr_mu_unlock(sp->mutex());
+}
+
+static void finish_shutdown(grpc_udp_server* s) {
+  if (s->shutdown_complete != nullptr) {
+    GRPC_CLOSURE_SCHED(s->shutdown_complete, GRPC_ERROR_NONE);
+  }
+
+  gpr_mu_destroy(&s->mu);
+
+  gpr_log(GPR_DEBUG, "Destroy all listeners.");
+  for (size_t i = 0; i < s->listeners.size(); ++i) {
+    s->listeners[i].OnDestroy();
+  }
+
+  if (s->socket_factory) {
+    grpc_socket_factory_unref(s->socket_factory);
+  }
+
+  grpc_core::Delete(s);
+}
+
+static void destroyed_port(void* server, grpc_error* error) {
+  grpc_udp_server* s = static_cast<grpc_udp_server*>(server);
+  gpr_mu_lock(&s->mu);
+  s->destroyed_ports++;
+  if (s->destroyed_ports == s->listeners.size()) {
+    gpr_mu_unlock(&s->mu);
+    finish_shutdown(s);
+  } else {
+    gpr_mu_unlock(&s->mu);
+  }
+}
+
+/* called when all listening endpoints have been shutdown, so no further
+   events will be received on them - at this point it's safe to destroy
+   things */
+static void deactivated_all_ports(grpc_udp_server* s) {
+  /* delete ALL the things */
+  gpr_mu_lock(&s->mu);
+
+  GPR_ASSERT(s->shutdown);
+
+  if (s->listeners.size() == 0) {
+    gpr_mu_unlock(&s->mu);
+    finish_shutdown(s);
+    return;
+  }
+  for (size_t i = 0; i < s->listeners.size(); ++i) {
+    s->listeners[i].OrphanFd();
+  }
+  gpr_mu_unlock(&s->mu);
+}
+
+void GrpcUdpListener::OrphanFd() {
+  gpr_log(GPR_DEBUG, "Orphan fd %d, emfd %p", fd_, emfd_);
+  grpc_unlink_if_unix_domain_socket(&addr_);
+
+  GRPC_CLOSURE_INIT(&destroyed_closure_, destroyed_port, server_,
+                    grpc_schedule_on_exec_ctx);
+  /* Because at this point, all listening sockets have been shutdown already, no
+   * need to call OnFdAboutToOrphan() to notify the handler again. */
+  grpc_fd_orphan(emfd_, &destroyed_closure_, nullptr, "udp_listener_shutdown");
+}
+
+void grpc_udp_server_destroy(grpc_udp_server* s, grpc_closure* on_done) {
+  gpr_mu_lock(&s->mu);
+
+  GPR_ASSERT(!s->shutdown);
+  s->shutdown = 1;
+
+  s->shutdown_complete = on_done;
+
+  gpr_log(GPR_DEBUG, "start to destroy udp_server");
+  /* shutdown all fd's */
+  if (s->active_ports) {
+    for (size_t i = 0; i < s->listeners.size(); ++i) {
+      GrpcUdpListener* sp = &s->listeners[i];
+      sp->OnFdAboutToOrphan();
+    }
+    gpr_mu_unlock(&s->mu);
+  } else {
+    gpr_mu_unlock(&s->mu);
+    deactivated_all_ports(s);
+  }
+}
+
+void GrpcUdpListener::OnFdAboutToOrphan() {
+  gpr_mu_lock(&mutex_);
+  grpc_unlink_if_unix_domain_socket(&addr_);
+
+  GRPC_CLOSURE_INIT(&destroyed_closure_, destroyed_port, server_,
+                    grpc_schedule_on_exec_ctx);
+  if (!orphan_notified_ && udp_handler_ != nullptr) {
+    /* Signals udp_handler that the FD is about to be closed and
+     * should no longer be used. */
+    GRPC_CLOSURE_INIT(&orphan_fd_closure_, shutdown_fd, this,
+                      grpc_schedule_on_exec_ctx);
+    gpr_log(GPR_DEBUG, "fd %d about to be orphaned", fd_);
+    udp_handler_->OnFdAboutToOrphan(&orphan_fd_closure_, server_->user_data);
+    orphan_notified_ = true;
+  }
+  gpr_mu_unlock(&mutex_);
+}
+
+static int bind_socket(grpc_socket_factory* socket_factory, int sockfd,
+                       const grpc_resolved_address* addr) {
+  return (socket_factory != nullptr)
+             ? grpc_socket_factory_bind(socket_factory, sockfd, addr)
+             : bind(sockfd,
+                    reinterpret_cast<grpc_sockaddr*>(
+                        const_cast<char*>(addr->addr)),
+                    addr->len);
+}
+
+/* Prepare a recently-created socket for listening. */
+static int prepare_socket(grpc_socket_factory* socket_factory, int fd,
+                          const grpc_resolved_address* addr, int rcv_buf_size,
+                          int snd_buf_size, bool so_reuseport) {
+  grpc_resolved_address sockname_temp;
+  grpc_sockaddr* addr_ptr =
+      reinterpret_cast<grpc_sockaddr*>(const_cast<char*>(addr->addr));
+
+  if (fd < 0) {
+    goto error;
+  }
+
+  if (grpc_set_socket_nonblocking(fd, 1) != GRPC_ERROR_NONE) {
+    gpr_log(GPR_ERROR, "Unable to set nonblocking %d: %s", fd, strerror(errno));
+    goto error;
+  }
+  if (grpc_set_socket_cloexec(fd, 1) != GRPC_ERROR_NONE) {
+    gpr_log(GPR_ERROR, "Unable to set cloexec %d: %s", fd, strerror(errno));
+    goto error;
+  }
+
+  if (grpc_set_socket_ip_pktinfo_if_possible(fd) != GRPC_ERROR_NONE) {
+    gpr_log(GPR_ERROR, "Unable to set ip_pktinfo.");
+    goto error;
+  } else if (addr_ptr->sa_family == AF_INET6) {
+    if (grpc_set_socket_ipv6_recvpktinfo_if_possible(fd) != GRPC_ERROR_NONE) {
+      gpr_log(GPR_ERROR, "Unable to set ipv6_recvpktinfo.");
+      goto error;
+    }
+  }
+
+  if (grpc_set_socket_sndbuf(fd, snd_buf_size) != GRPC_ERROR_NONE) {
+    gpr_log(GPR_ERROR, "Failed to set send buffer size to %d bytes",
+            snd_buf_size);
+    goto error;
+  }
+
+  if (grpc_set_socket_rcvbuf(fd, rcv_buf_size) != GRPC_ERROR_NONE) {
+    gpr_log(GPR_ERROR, "Failed to set receive buffer size to %d bytes",
+            rcv_buf_size);
+    goto error;
+  }
+
+  {
+    int get_overflow = 1;
+    if (0 != setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
+                        sizeof(get_overflow))) {
+      gpr_log(GPR_INFO, "Failed to set socket overflow support");
+    }
+  }
+
+  if (so_reuseport && !grpc_is_unix_socket(addr) &&
+      grpc_set_socket_reuse_port(fd, 1) != GRPC_ERROR_NONE) {
+    gpr_log(GPR_ERROR, "Failed to set SO_REUSEPORT for fd %d", fd);
+    goto error;
+  }
+
+  if (bind_socket(socket_factory, fd, addr) < 0) {
+    char* addr_str;
+    grpc_sockaddr_to_string(&addr_str, addr, 0);
+    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
+    gpr_free(addr_str);
+    goto error;
+  }
+
+  sockname_temp.len = static_cast<socklen_t>(sizeof(struct sockaddr_storage));
+
+  if (getsockname(fd, reinterpret_cast<grpc_sockaddr*>(sockname_temp.addr),
+                  &sockname_temp.len) < 0) {
+    gpr_log(GPR_ERROR, "Unable to get the address socket %d is bound to: %s",
+            fd, strerror(errno));
+    goto error;
+  }
+
+  return grpc_sockaddr_get_port(&sockname_temp);
+
+error:
+  if (fd >= 0) {
+    close(fd);
+  }
+  return -1;
+}
+
+// static
+void GrpcUdpListener::do_read(void* arg, grpc_error* error) {
+  GrpcUdpListener* sp = static_cast<GrpcUdpListener*>(arg);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
+  /* TODO: the reason we hold server->mu here is merely to prevent fd
+   * shutdown while we are reading. However, it blocks do_write(). Switch to
+   * read lock if available. */
+  gpr_mu_lock(sp->mutex());
+  /* Tell the registered callback that data is available to read. */
+  if (!sp->already_shutdown_ && sp->udp_handler_->Read()) {
+    /* There maybe more packets to read. Schedule read_more_cb_ closure to run
+     * after finishing this event loop. */
+    GRPC_CLOSURE_SCHED(&sp->do_read_closure_, GRPC_ERROR_NONE);
+  } else {
+    /* Finish reading all the packets, re-arm the notification event so we can
+     * get another chance to read. Or fd already shutdown, re-arm to get a
+     * notification with shutdown error. */
+    grpc_fd_notify_on_read(sp->emfd_, &sp->read_closure_);
+  }
+  gpr_mu_unlock(sp->mutex());
+}
+
+// static
+void GrpcUdpListener::on_read(void* arg, grpc_error* error) {
+  GrpcUdpListener* sp = static_cast<GrpcUdpListener*>(arg);
+  sp->OnRead(error, arg);
+}
+
+void GrpcUdpListener::OnRead(grpc_error* error, void* do_read_arg) {
+  if (error != GRPC_ERROR_NONE) {
+    gpr_mu_lock(&server_->mu);
+    if (0 == --server_->active_ports && server_->shutdown) {
+      gpr_mu_unlock(&server_->mu);
+      deactivated_all_ports(server_);
+    } else {
+      gpr_mu_unlock(&server_->mu);
+    }
+    return;
+  }
+
+  /* Read once. If there is more data to read, off load the work to another
+   * thread to finish. */
+  if (udp_handler_->Read()) {
+    /* There maybe more packets to read. Schedule read_more_cb_ closure to run
+     * after finishing this event loop. */
+    GRPC_CLOSURE_INIT(
+        &do_read_closure_, do_read, do_read_arg,
+        grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::LONG));
+    GRPC_CLOSURE_SCHED(&do_read_closure_, GRPC_ERROR_NONE);
+  } else {
+    /* Finish reading all the packets, re-arm the notification event so we can
+     * get another chance to read. Or fd already shutdown, re-arm to get a
+     * notification with shutdown error. */
+    grpc_fd_notify_on_read(emfd_, &read_closure_);
+  }
+}
+
+// static
+// Wrapper of grpc_fd_notify_on_write() with a grpc_closure callback interface.
+void GrpcUdpListener::fd_notify_on_write_wrapper(void* arg, grpc_error* error) {
+  GrpcUdpListener* sp = static_cast<GrpcUdpListener*>(arg);
+  gpr_mu_lock(sp->mutex());
+  if (!sp->notify_on_write_armed_) {
+    grpc_fd_notify_on_write(sp->emfd_, &sp->write_closure_);
+    sp->notify_on_write_armed_ = true;
+  }
+  gpr_mu_unlock(sp->mutex());
+}
+
+// static
+void GrpcUdpListener::do_write(void* arg, grpc_error* error) {
+  GrpcUdpListener* sp = static_cast<GrpcUdpListener*>(arg);
+  gpr_mu_lock(sp->mutex());
+  if (sp->already_shutdown_) {
+    // If fd has been shutdown, don't write any more and re-arm notification.
+    grpc_fd_notify_on_write(sp->emfd_, &sp->write_closure_);
+  } else {
+    sp->notify_on_write_armed_ = false;
+    /* Tell the registered callback that the socket is writeable. */
+    GPR_ASSERT(error == GRPC_ERROR_NONE);
+    GRPC_CLOSURE_INIT(&sp->notify_on_write_closure_, fd_notify_on_write_wrapper,
+                      arg, grpc_schedule_on_exec_ctx);
+    sp->udp_handler_->OnCanWrite(sp->server_->user_data,
+                                 &sp->notify_on_write_closure_);
+  }
+  gpr_mu_unlock(sp->mutex());
+}
+
+// static
+void GrpcUdpListener::on_write(void* arg, grpc_error* error) {
+  GrpcUdpListener* sp = static_cast<GrpcUdpListener*>(arg);
+  sp->OnCanWrite(error, arg);
+}
+
+void GrpcUdpListener::OnCanWrite(grpc_error* error, void* do_write_arg) {
+  if (error != GRPC_ERROR_NONE) {
+    gpr_mu_lock(&server_->mu);
+    if (0 == --server_->active_ports && server_->shutdown) {
+      gpr_mu_unlock(&server_->mu);
+      deactivated_all_ports(server_);
+    } else {
+      gpr_mu_unlock(&server_->mu);
+    }
+    return;
+  }
+
+  /* Schedule actual write in another thread. */
+  GRPC_CLOSURE_INIT(
+      &do_write_closure_, do_write, do_write_arg,
+      grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::LONG));
+
+  GRPC_CLOSURE_SCHED(&do_write_closure_, GRPC_ERROR_NONE);
+}
+
+static int add_socket_to_server(grpc_udp_server* s, int fd,
+                                const grpc_resolved_address* addr,
+                                int rcv_buf_size, int snd_buf_size) {
+  gpr_log(GPR_DEBUG, "add socket %d to server", fd);
+
+  int port = prepare_socket(s->socket_factory, fd, addr, rcv_buf_size,
+                            snd_buf_size, s->so_reuseport);
+  if (port >= 0) {
+    gpr_mu_lock(&s->mu);
+    s->listeners.emplace_back(s, fd, addr);
+    gpr_log(GPR_DEBUG,
+            "add socket %d to server for port %d, %zu listener(s) in total", fd,
+            port, s->listeners.size());
+    gpr_mu_unlock(&s->mu);
+  }
+  return port;
+}
+
+int grpc_udp_server_add_port(grpc_udp_server* s,
+                             const grpc_resolved_address* addr,
+                             int rcv_buf_size, int snd_buf_size,
+                             GrpcUdpHandlerFactory* handler_factory,
+                             size_t num_listeners) {
+  if (num_listeners > 1 && !s->so_reuseport) {
+    gpr_log(GPR_ERROR,
+            "Try to have multiple listeners on same port, but SO_REUSEPORT is "
+            "not supported. Only create 1 listener.");
+  }
+  char* addr_str;
+  grpc_sockaddr_to_string(&addr_str, addr, 1);
+  gpr_log(GPR_DEBUG, "add address: %s to server", addr_str);
+  gpr_free(addr_str);
+
+  int allocated_port1 = -1;
+  int allocated_port2 = -1;
+  int fd;
+  grpc_dualstack_mode dsmode;
+  grpc_resolved_address addr6_v4mapped;
+  grpc_resolved_address wild4;
+  grpc_resolved_address wild6;
+  grpc_resolved_address addr4_copy;
+  grpc_resolved_address* allocated_addr = nullptr;
+  grpc_resolved_address sockname_temp;
+  int port = 0;
+
+  /* Check if this is a wildcard port, and if so, try to keep the port the same
+     as some previously created listener. */
+  if (grpc_sockaddr_get_port(addr) == 0) {
+    /* Loop through existing listeners to find the port in use. */
+    for (size_t i = 0; i < s->listeners.size(); ++i) {
+      sockname_temp.len =
+          static_cast<socklen_t>(sizeof(struct sockaddr_storage));
+      if (0 == getsockname(s->listeners[i].fd(),
+                           reinterpret_cast<grpc_sockaddr*>(sockname_temp.addr),
+                           &sockname_temp.len)) {
+        port = grpc_sockaddr_get_port(&sockname_temp);
+        if (port > 0) {
+          /* Found such a port, update |addr| to reflects this port. */
+          allocated_addr = static_cast<grpc_resolved_address*>(
+              gpr_malloc(sizeof(grpc_resolved_address)));
+          memcpy(allocated_addr, addr, sizeof(grpc_resolved_address));
+          grpc_sockaddr_set_port(allocated_addr, port);
+          addr = allocated_addr;
+          break;
+        }
+      }
+    }
+  }
+
+  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
+    addr = &addr6_v4mapped;
+  }
+
+  s->handler_factory = handler_factory;
+  for (size_t i = 0; i < num_listeners; ++i) {
+    /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
+    if (grpc_sockaddr_is_wildcard(addr, &port)) {
+      grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
+
+      /* Try listening on IPv6 first. */
+      addr = &wild6;
+      // TODO(rjshade): Test and propagate the returned grpc_error*:
+      GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory(
+          s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd));
+      allocated_port1 =
+          add_socket_to_server(s, fd, addr, rcv_buf_size, snd_buf_size);
+      if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
+        if (port == 0) {
+          /* This is the first time to bind to |addr|. If its port is still
+           * wildcard port, update |addr| with the ephermeral port returned by
+           * kernel. Thus |addr| can have a specific port in following
+           * iterations. */
+          grpc_sockaddr_set_port(addr, allocated_port1);
+          port = allocated_port1;
+        } else if (allocated_port1 >= 0) {
+          /* The following successfully created socket should have same port as
+           * the first one. */
+          GPR_ASSERT(port == allocated_port1);
+        }
+        /* A dualstack socket is created, no need to create corresponding IPV4
+         * socket. */
+        continue;
+      }
+
+      /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
+      if (port == 0 && allocated_port1 > 0) {
+        /* |port| hasn't been assigned to an emphemeral port yet, |wild4| must
+         * have a wildcard port. Update it with the emphemeral port created
+         * during binding.*/
+        grpc_sockaddr_set_port(&wild4, allocated_port1);
+        port = allocated_port1;
+      }
+      /* |wild4| should have been updated with an emphemeral port by now. Use
+       * this IPV4 address to create a IPV4 socket. */
+      addr = &wild4;
+    }
+
+    // TODO(rjshade): Test and propagate the returned grpc_error*:
+    GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory(
+        s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd));
+    if (fd < 0) {
+      gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
+    }
+    if (dsmode == GRPC_DSMODE_IPV4 &&
+        grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
+      addr = &addr4_copy;
+    }
+    allocated_port2 =
+        add_socket_to_server(s, fd, addr, rcv_buf_size, snd_buf_size);
+    if (port == 0) {
+      /* Update |addr| with the ephermeral port returned by kernel. So |addr|
+       * can have a specific port in following iterations. */
+      grpc_sockaddr_set_port(addr, allocated_port2);
+      port = allocated_port2;
+    } else if (allocated_port2 >= 0) {
+      GPR_ASSERT(port == allocated_port2);
+    }
+  }
+
+  gpr_free(allocated_addr);
+  return port;
+}
+
+int grpc_udp_server_get_fd(grpc_udp_server* s, unsigned port_index) {
+  if (port_index >= s->listeners.size()) {
+    return -1;
+  }
+
+  return s->listeners[port_index].fd();
+}
+
+void grpc_udp_server_start(grpc_udp_server* s, grpc_pollset** pollsets,
+                           size_t pollset_count, void* user_data) {
+  gpr_log(GPR_DEBUG, "grpc_udp_server_start");
+  gpr_mu_lock(&s->mu);
+  GPR_ASSERT(s->active_ports == 0);
+  s->pollsets = pollsets;
+  s->user_data = user_data;
+
+  for (size_t i = 0; i < s->listeners.size(); ++i) {
+    s->listeners[i].StartListening(pollsets, pollset_count, s->handler_factory);
+  }
+
+  gpr_mu_unlock(&s->mu);
+}
+
+void GrpcUdpListener::StartListening(grpc_pollset** pollsets,
+                                     size_t pollset_count,
+                                     GrpcUdpHandlerFactory* handler_factory) {
+  gpr_mu_lock(&mutex_);
+  handler_factory_ = handler_factory;
+  udp_handler_ = handler_factory->CreateUdpHandler(emfd_, server_->user_data);
+  for (size_t i = 0; i < pollset_count; i++) {
+    grpc_pollset_add_fd(pollsets[i], emfd_);
+  }
+  GRPC_CLOSURE_INIT(&read_closure_, on_read, this, grpc_schedule_on_exec_ctx);
+  grpc_fd_notify_on_read(emfd_, &read_closure_);
+
+  GRPC_CLOSURE_INIT(&write_closure_, on_write, this, grpc_schedule_on_exec_ctx);
+  notify_on_write_armed_ = true;
+  grpc_fd_notify_on_write(emfd_, &write_closure_);
+
+  /* Registered for both read and write callbacks: increment active_ports
+   * twice to account for this, and delay free-ing of memory until both
+   * on_read and on_write have fired. */
+  server_->active_ports += 2;
+  gpr_mu_unlock(&mutex_);
+}
+
+void GrpcUdpListener::OnDestroy() {
+  if (udp_handler_ != nullptr) {
+    handler_factory_->DestroyUdpHandler(udp_handler_);
+  }
+}
+
+#endif