• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /* FIXME: "posix" files shouldn't be depending on _GNU_SOURCE */
20 #ifndef _GNU_SOURCE
21 #define _GNU_SOURCE
22 #endif
23 
24 #ifndef SO_RXQ_OVFL
25 #define SO_RXQ_OVFL 40
26 #endif
27 
28 #include <grpc/support/port_platform.h>
29 
30 #include "src/core/lib/iomgr/port.h"
31 
32 #ifdef GRPC_POSIX_SOCKET_UDP_SERVER
33 
34 #include "src/core/lib/iomgr/udp_server.h"
35 
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <limits.h>
39 #include <netinet/in.h>
40 #include <netinet/tcp.h>
41 #include <string.h>
42 #include <sys/socket.h>
43 #include <sys/stat.h>
44 #include <sys/types.h>
45 #include <unistd.h>
46 
47 #include <string>
48 #include <vector>
49 
50 #include "absl/container/inlined_vector.h"
51 #include "absl/strings/str_cat.h"
52 
53 #include <grpc/grpc.h>
54 #include <grpc/support/alloc.h>
55 #include <grpc/support/log.h>
56 #include <grpc/support/string_util.h>
57 #include <grpc/support/sync.h>
58 #include <grpc/support/time.h>
59 #include "src/core/lib/channel/channel_args.h"
60 #include "src/core/lib/gpr/string.h"
61 #include "src/core/lib/gprpp/memory.h"
62 #include "src/core/lib/iomgr/error.h"
63 #include "src/core/lib/iomgr/ev_posix.h"
64 #include "src/core/lib/iomgr/executor.h"
65 #include "src/core/lib/iomgr/resolve_address.h"
66 #include "src/core/lib/iomgr/sockaddr.h"
67 #include "src/core/lib/iomgr/sockaddr_utils.h"
68 #include "src/core/lib/iomgr/socket_factory_posix.h"
69 #include "src/core/lib/iomgr/socket_utils_posix.h"
70 #include "src/core/lib/iomgr/unix_sockets_posix.h"
71 
72 /* A listener which implements basic features of Listening on a port for
73  * I/O events*/
74 class GrpcUdpListener {
75  public:
76   GrpcUdpListener(grpc_udp_server* server, int fd,
77                   const grpc_resolved_address* addr);
78   ~GrpcUdpListener();
79 
80   /* Called when grpc server starts to listening on the grpc_fd. */
81   void StartListening(const std::vector<grpc_pollset*>* pollsets,
82                       GrpcUdpHandlerFactory* handler_factory);
83 
84   /* Called when data is available to read from the socket.
85    * Return true if there is more data to read from fd. */
86   void OnRead(grpc_error* error, void* do_read_arg);
87 
88   /* Called when the socket is writeable. The given closure should be scheduled
89    * when the socket becomes blocked next time. */
90   void OnCanWrite(grpc_error* error, void* do_write_arg);
91 
92   /* Called when the grpc_fd is about to be orphaned (and the FD closed). */
93   void OnFdAboutToOrphan();
94 
95   /* Called to orphan fd of this listener.*/
96   void OrphanFd();
97 
98   /* Called when this listener is going to be destroyed. */
99   void OnDestroy();
100 
fd() const101   int fd() const { return fd_; }
102 
103  protected:
emfd() const104   grpc_fd* emfd() const { return emfd_; }
105 
mutex()106   gpr_mu* mutex() { return &mutex_; }
107 
108  private:
109   /* event manager callback when reads are ready */
110   static void on_read(void* arg, grpc_error* error);
111   static void on_write(void* arg, grpc_error* error);
112 
113   static void do_read(void* arg, grpc_error* error);
114   static void do_write(void* arg, grpc_error* error);
115   // Wrapper of grpc_fd_notify_on_write() with a grpc_closure callback
116   // interface.
117   static void fd_notify_on_write_wrapper(void* arg, grpc_error* error);
118 
119   static void shutdown_fd(void* args, grpc_error* error);
120 
121   int fd_;
122   grpc_fd* emfd_;
123   grpc_udp_server* server_;
124   grpc_resolved_address addr_;
125   grpc_closure read_closure_;
126   grpc_closure write_closure_;
127   // To be called when corresponding QuicGrpcServer closes all active
128   // connections.
129   grpc_closure orphan_fd_closure_;
130   grpc_closure destroyed_closure_;
131   // To be scheduled on another thread to actually read/write.
132   grpc_closure do_read_closure_;
133   grpc_closure do_write_closure_;
134   grpc_closure notify_on_write_closure_;
135   // True if orphan_cb is trigered.
136   bool orphan_notified_;
137   // True if grpc_fd_notify_on_write() is called after on_write() call.
138   bool notify_on_write_armed_;
139   // True if fd has been shutdown.
140   bool already_shutdown_;
141   // Object actually handles I/O events. Assigned in StartListening().
142   GrpcUdpHandler* udp_handler_ = nullptr;
143   // To be notified on destruction.
144   GrpcUdpHandlerFactory* handler_factory_ = nullptr;
145   // Required to access above fields.
146   gpr_mu mutex_;
147 };
148 
GrpcUdpListener(grpc_udp_server * server,int fd,const grpc_resolved_address * addr)149 GrpcUdpListener::GrpcUdpListener(grpc_udp_server* server, int fd,
150                                  const grpc_resolved_address* addr)
151     : fd_(fd),
152       server_(server),
153       orphan_notified_(false),
154       already_shutdown_(false) {
155   std::string addr_str = grpc_sockaddr_to_string(addr, true);
156   std::string name = absl::StrCat("udp-server-listener:", addr_str);
157   emfd_ = grpc_fd_create(fd, name.c_str(), true);
158   memcpy(&addr_, addr, sizeof(grpc_resolved_address));
159   GPR_ASSERT(emfd_);
160   gpr_mu_init(&mutex_);
161 }
162 
~GrpcUdpListener()163 GrpcUdpListener::~GrpcUdpListener() { gpr_mu_destroy(&mutex_); }
164 
165 /* the overall server */
166 struct grpc_udp_server {
167   gpr_mu mu;
168 
169   /* factory to use for creating and binding sockets, or NULL */
170   grpc_socket_factory* socket_factory;
171 
172   /* active port count: how many ports are actually still listening */
173   size_t active_ports;
174   /* destroyed port count: how many ports are completely destroyed */
175   size_t destroyed_ports;
176 
177   /* is this server shutting down? (boolean) */
178   int shutdown;
179 
180   /* An array of listeners */
181   absl::InlinedVector<GrpcUdpListener, 16> listeners;
182 
183   /* factory for use to create udp listeners */
184   GrpcUdpHandlerFactory* handler_factory;
185 
186   /* shutdown callback */
187   grpc_closure* shutdown_complete;
188 
189   /* all pollsets interested in new connections. The object pointed at is not
190    * owned by this struct. */
191   const std::vector<grpc_pollset*>* pollsets;
192   /* opaque object to pass to callbacks */
193   void* user_data;
194 
195   /* latch has_so_reuseport during server creation */
196   bool so_reuseport;
197 };
198 
get_socket_factory(const grpc_channel_args * args)199 static grpc_socket_factory* get_socket_factory(const grpc_channel_args* args) {
200   if (args) {
201     const grpc_arg* arg = grpc_channel_args_find(args, GRPC_ARG_SOCKET_FACTORY);
202     if (arg) {
203       GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
204       return static_cast<grpc_socket_factory*>(arg->value.pointer.p);
205     }
206   }
207   return nullptr;
208 }
209 
grpc_udp_server_create(const grpc_channel_args * args)210 grpc_udp_server* grpc_udp_server_create(const grpc_channel_args* args) {
211   grpc_udp_server* s = new grpc_udp_server();
212   gpr_mu_init(&s->mu);
213   s->socket_factory = get_socket_factory(args);
214   if (s->socket_factory) {
215     grpc_socket_factory_ref(s->socket_factory);
216   }
217   s->active_ports = 0;
218   s->destroyed_ports = 0;
219   s->shutdown = 0;
220   s->so_reuseport = grpc_is_socket_reuse_port_supported();
221   return s;
222 }
223 
224 // static
shutdown_fd(void * args,grpc_error * error)225 void GrpcUdpListener::shutdown_fd(void* args, grpc_error* error) {
226   if (args == nullptr) {
227     // No-op if shutdown args are null.
228     return;
229   }
230   auto sp = static_cast<GrpcUdpListener*>(args);
231   gpr_mu_lock(sp->mutex());
232   gpr_log(GPR_DEBUG, "shutdown fd %d", sp->fd_);
233   grpc_fd_shutdown(sp->emfd_, GRPC_ERROR_REF(error));
234   sp->already_shutdown_ = true;
235   if (!sp->notify_on_write_armed_) {
236     // Re-arm write notification to notify listener with error. This is
237     // necessary to decrement active_ports.
238     sp->notify_on_write_armed_ = true;
239     grpc_fd_notify_on_write(sp->emfd_, &sp->write_closure_);
240   }
241   gpr_mu_unlock(sp->mutex());
242 }
243 
finish_shutdown(grpc_udp_server * s)244 static void finish_shutdown(grpc_udp_server* s) {
245   if (s->shutdown_complete != nullptr) {
246     grpc_core::ExecCtx::Run(DEBUG_LOCATION, s->shutdown_complete,
247                             GRPC_ERROR_NONE);
248   }
249 
250   gpr_mu_destroy(&s->mu);
251 
252   gpr_log(GPR_DEBUG, "Destroy all listeners.");
253   for (size_t i = 0; i < s->listeners.size(); ++i) {
254     s->listeners[i].OnDestroy();
255   }
256 
257   if (s->socket_factory) {
258     grpc_socket_factory_unref(s->socket_factory);
259   }
260 
261   delete s;
262 }
263 
destroyed_port(void * server,grpc_error *)264 static void destroyed_port(void* server, grpc_error* /*error*/) {
265   grpc_udp_server* s = static_cast<grpc_udp_server*>(server);
266   gpr_mu_lock(&s->mu);
267   s->destroyed_ports++;
268   if (s->destroyed_ports == s->listeners.size()) {
269     gpr_mu_unlock(&s->mu);
270     finish_shutdown(s);
271   } else {
272     gpr_mu_unlock(&s->mu);
273   }
274 }
275 
276 /* called when all listening endpoints have been shutdown, so no further
277    events will be received on them - at this point it's safe to destroy
278    things */
deactivated_all_ports(grpc_udp_server * s)279 static void deactivated_all_ports(grpc_udp_server* s) {
280   /* delete ALL the things */
281   gpr_mu_lock(&s->mu);
282 
283   GPR_ASSERT(s->shutdown);
284 
285   if (s->listeners.empty()) {
286     gpr_mu_unlock(&s->mu);
287     finish_shutdown(s);
288     return;
289   }
290   for (size_t i = 0; i < s->listeners.size(); ++i) {
291     s->listeners[i].OrphanFd();
292   }
293   gpr_mu_unlock(&s->mu);
294 }
295 
OrphanFd()296 void GrpcUdpListener::OrphanFd() {
297   gpr_log(GPR_DEBUG, "Orphan fd %d, emfd %p", fd_, emfd_);
298   grpc_unlink_if_unix_domain_socket(&addr_);
299 
300   GRPC_CLOSURE_INIT(&destroyed_closure_, destroyed_port, server_,
301                     grpc_schedule_on_exec_ctx);
302   /* Because at this point, all listening sockets have been shutdown already, no
303    * need to call OnFdAboutToOrphan() to notify the handler again. */
304   grpc_fd_orphan(emfd_, &destroyed_closure_, nullptr, "udp_listener_shutdown");
305 }
306 
grpc_udp_server_destroy(grpc_udp_server * s,grpc_closure * on_done)307 void grpc_udp_server_destroy(grpc_udp_server* s, grpc_closure* on_done) {
308   gpr_mu_lock(&s->mu);
309 
310   GPR_ASSERT(!s->shutdown);
311   s->shutdown = 1;
312 
313   s->shutdown_complete = on_done;
314 
315   gpr_log(GPR_DEBUG, "start to destroy udp_server");
316   /* shutdown all fd's */
317   if (s->active_ports) {
318     for (size_t i = 0; i < s->listeners.size(); ++i) {
319       GrpcUdpListener* sp = &s->listeners[i];
320       sp->OnFdAboutToOrphan();
321     }
322     gpr_mu_unlock(&s->mu);
323   } else {
324     gpr_mu_unlock(&s->mu);
325     deactivated_all_ports(s);
326   }
327 }
328 
OnFdAboutToOrphan()329 void GrpcUdpListener::OnFdAboutToOrphan() {
330   gpr_mu_lock(&mutex_);
331   grpc_unlink_if_unix_domain_socket(&addr_);
332 
333   GRPC_CLOSURE_INIT(&destroyed_closure_, destroyed_port, server_,
334                     grpc_schedule_on_exec_ctx);
335   if (!orphan_notified_ && udp_handler_ != nullptr) {
336     /* Signals udp_handler that the FD is about to be closed and
337      * should no longer be used. */
338     GRPC_CLOSURE_INIT(&orphan_fd_closure_, shutdown_fd, this,
339                       grpc_schedule_on_exec_ctx);
340     gpr_log(GPR_DEBUG, "fd %d about to be orphaned", fd_);
341     udp_handler_->OnFdAboutToOrphan(&orphan_fd_closure_, server_->user_data);
342     orphan_notified_ = true;
343   }
344   gpr_mu_unlock(&mutex_);
345 }
346 
bind_socket(grpc_socket_factory * socket_factory,int sockfd,const grpc_resolved_address * addr)347 static int bind_socket(grpc_socket_factory* socket_factory, int sockfd,
348                        const grpc_resolved_address* addr) {
349   return (socket_factory != nullptr)
350              ? grpc_socket_factory_bind(socket_factory, sockfd, addr)
351              : bind(sockfd,
352                     reinterpret_cast<grpc_sockaddr*>(
353                         const_cast<char*>(addr->addr)),
354                     addr->len);
355 }
356 
357 /* Prepare a recently-created socket for listening. */
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)358 static int prepare_socket(grpc_socket_factory* socket_factory, int fd,
359                           const grpc_resolved_address* addr, int rcv_buf_size,
360                           int snd_buf_size, bool so_reuseport) {
361   grpc_resolved_address sockname_temp;
362   grpc_sockaddr* addr_ptr =
363       reinterpret_cast<grpc_sockaddr*>(const_cast<char*>(addr->addr));
364 
365   if (fd < 0) {
366     goto error;
367   }
368 
369   if (grpc_set_socket_nonblocking(fd, 1) != GRPC_ERROR_NONE) {
370     gpr_log(GPR_ERROR, "Unable to set nonblocking %d: %s", fd, strerror(errno));
371     goto error;
372   }
373   if (grpc_set_socket_cloexec(fd, 1) != GRPC_ERROR_NONE) {
374     gpr_log(GPR_ERROR, "Unable to set cloexec %d: %s", fd, strerror(errno));
375     goto error;
376   }
377 
378   if (grpc_set_socket_ip_pktinfo_if_possible(fd) != GRPC_ERROR_NONE) {
379     gpr_log(GPR_ERROR, "Unable to set ip_pktinfo.");
380     goto error;
381   } else if (addr_ptr->sa_family == AF_INET6) {
382     if (grpc_set_socket_ipv6_recvpktinfo_if_possible(fd) != GRPC_ERROR_NONE) {
383       gpr_log(GPR_ERROR, "Unable to set ipv6_recvpktinfo.");
384       goto error;
385     }
386   }
387 
388   if (grpc_set_socket_sndbuf(fd, snd_buf_size) != GRPC_ERROR_NONE) {
389     gpr_log(GPR_ERROR, "Failed to set send buffer size to %d bytes",
390             snd_buf_size);
391     goto error;
392   }
393 
394   if (grpc_set_socket_rcvbuf(fd, rcv_buf_size) != GRPC_ERROR_NONE) {
395     gpr_log(GPR_ERROR, "Failed to set receive buffer size to %d bytes",
396             rcv_buf_size);
397     goto error;
398   }
399 
400   {
401     int get_overflow = 1;
402     if (0 != setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
403                         sizeof(get_overflow))) {
404       gpr_log(GPR_INFO, "Failed to set socket overflow support");
405     }
406   }
407 
408   if (so_reuseport && !grpc_is_unix_socket(addr) &&
409       grpc_set_socket_reuse_port(fd, 1) != GRPC_ERROR_NONE) {
410     gpr_log(GPR_ERROR, "Failed to set SO_REUSEPORT for fd %d", fd);
411     goto error;
412   }
413 
414   if (bind_socket(socket_factory, fd, addr) < 0) {
415     std::string addr_str = grpc_sockaddr_to_string(addr, false);
416     gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str.c_str(), strerror(errno));
417     goto error;
418   }
419 
420   sockname_temp.len = static_cast<socklen_t>(sizeof(struct sockaddr_storage));
421 
422   if (getsockname(fd, reinterpret_cast<grpc_sockaddr*>(sockname_temp.addr),
423                   &sockname_temp.len) < 0) {
424     gpr_log(GPR_ERROR, "Unable to get the address socket %d is bound to: %s",
425             fd, strerror(errno));
426     goto error;
427   }
428 
429   return grpc_sockaddr_get_port(&sockname_temp);
430 
431 error:
432   if (fd >= 0) {
433     close(fd);
434   }
435   return -1;
436 }
437 
438 // static
do_read(void * arg,grpc_error * error)439 void GrpcUdpListener::do_read(void* arg, grpc_error* error) {
440   GrpcUdpListener* sp = static_cast<GrpcUdpListener*>(arg);
441   GPR_ASSERT(error == GRPC_ERROR_NONE);
442   /* TODO: the reason we hold server->mu here is merely to prevent fd
443    * shutdown while we are reading. However, it blocks do_write(). Switch to
444    * read lock if available. */
445   gpr_mu_lock(sp->mutex());
446   /* Tell the registered callback that data is available to read. */
447   if (!sp->already_shutdown_ && sp->udp_handler_->Read()) {
448     /* There maybe more packets to read. Schedule read_more_cb_ closure to run
449      * after finishing this event loop. */
450     grpc_core::Executor::Run(&sp->do_read_closure_, GRPC_ERROR_NONE,
451                              grpc_core::ExecutorType::DEFAULT,
452                              grpc_core::ExecutorJobType::LONG);
453   } else {
454     /* Finish reading all the packets, re-arm the notification event so we can
455      * get another chance to read. Or fd already shutdown, re-arm to get a
456      * notification with shutdown error. */
457     grpc_fd_notify_on_read(sp->emfd_, &sp->read_closure_);
458   }
459   gpr_mu_unlock(sp->mutex());
460 }
461 
462 // static
on_read(void * arg,grpc_error * error)463 void GrpcUdpListener::on_read(void* arg, grpc_error* error) {
464   GrpcUdpListener* sp = static_cast<GrpcUdpListener*>(arg);
465   sp->OnRead(error, arg);
466 }
467 
OnRead(grpc_error * error,void * do_read_arg)468 void GrpcUdpListener::OnRead(grpc_error* error, void* do_read_arg) {
469   if (error != GRPC_ERROR_NONE) {
470     gpr_mu_lock(&server_->mu);
471     if (0 == --server_->active_ports && server_->shutdown) {
472       gpr_mu_unlock(&server_->mu);
473       deactivated_all_ports(server_);
474     } else {
475       gpr_mu_unlock(&server_->mu);
476     }
477     return;
478   }
479 
480   /* Read once. If there is more data to read, off load the work to another
481    * thread to finish. */
482   if (udp_handler_->Read()) {
483     /* There maybe more packets to read. Schedule read_more_cb_ closure to run
484      * after finishing this event loop. */
485     GRPC_CLOSURE_INIT(&do_read_closure_, do_read, do_read_arg, nullptr);
486     grpc_core::Executor::Run(&do_read_closure_, GRPC_ERROR_NONE,
487                              grpc_core::ExecutorType::DEFAULT,
488                              grpc_core::ExecutorJobType::LONG);
489   } else {
490     /* Finish reading all the packets, re-arm the notification event so we can
491      * get another chance to read. Or fd already shutdown, re-arm to get a
492      * notification with shutdown error. */
493     grpc_fd_notify_on_read(emfd_, &read_closure_);
494   }
495 }
496 
497 // static
498 // Wrapper of grpc_fd_notify_on_write() with a grpc_closure callback interface.
fd_notify_on_write_wrapper(void * arg,grpc_error *)499 void GrpcUdpListener::fd_notify_on_write_wrapper(void* arg,
500                                                  grpc_error* /*error*/) {
501   GrpcUdpListener* sp = static_cast<GrpcUdpListener*>(arg);
502   gpr_mu_lock(sp->mutex());
503   if (!sp->notify_on_write_armed_) {
504     grpc_fd_notify_on_write(sp->emfd_, &sp->write_closure_);
505     sp->notify_on_write_armed_ = true;
506   }
507   gpr_mu_unlock(sp->mutex());
508 }
509 
510 // static
do_write(void * arg,grpc_error * error)511 void GrpcUdpListener::do_write(void* arg, grpc_error* error) {
512   GrpcUdpListener* sp = static_cast<GrpcUdpListener*>(arg);
513   gpr_mu_lock(sp->mutex());
514   if (sp->already_shutdown_) {
515     // If fd has been shutdown, don't write any more and re-arm notification.
516     grpc_fd_notify_on_write(sp->emfd_, &sp->write_closure_);
517   } else {
518     sp->notify_on_write_armed_ = false;
519     /* Tell the registered callback that the socket is writeable. */
520     GPR_ASSERT(error == GRPC_ERROR_NONE);
521     GRPC_CLOSURE_INIT(&sp->notify_on_write_closure_, fd_notify_on_write_wrapper,
522                       arg, grpc_schedule_on_exec_ctx);
523     sp->udp_handler_->OnCanWrite(sp->server_->user_data,
524                                  &sp->notify_on_write_closure_);
525   }
526   gpr_mu_unlock(sp->mutex());
527 }
528 
529 // static
on_write(void * arg,grpc_error * error)530 void GrpcUdpListener::on_write(void* arg, grpc_error* error) {
531   GrpcUdpListener* sp = static_cast<GrpcUdpListener*>(arg);
532   sp->OnCanWrite(error, arg);
533 }
534 
OnCanWrite(grpc_error * error,void * do_write_arg)535 void GrpcUdpListener::OnCanWrite(grpc_error* error, void* do_write_arg) {
536   if (error != GRPC_ERROR_NONE) {
537     gpr_mu_lock(&server_->mu);
538     if (0 == --server_->active_ports && server_->shutdown) {
539       gpr_mu_unlock(&server_->mu);
540       deactivated_all_ports(server_);
541     } else {
542       gpr_mu_unlock(&server_->mu);
543     }
544     return;
545   }
546 
547   /* Schedule actual write in another thread. */
548   GRPC_CLOSURE_INIT(&do_write_closure_, do_write, do_write_arg, nullptr);
549 
550   grpc_core::Executor::Run(&do_write_closure_, GRPC_ERROR_NONE,
551                            grpc_core::ExecutorType::DEFAULT,
552                            grpc_core::ExecutorJobType::LONG);
553 }
554 
add_socket_to_server(grpc_udp_server * s,int fd,const grpc_resolved_address * addr,int rcv_buf_size,int snd_buf_size)555 static int add_socket_to_server(grpc_udp_server* s, int fd,
556                                 const grpc_resolved_address* addr,
557                                 int rcv_buf_size, int snd_buf_size) {
558   gpr_log(GPR_DEBUG, "add socket %d to server", fd);
559 
560   int port = prepare_socket(s->socket_factory, fd, addr, rcv_buf_size,
561                             snd_buf_size, s->so_reuseport);
562   if (port >= 0) {
563     gpr_mu_lock(&s->mu);
564     s->listeners.emplace_back(s, fd, addr);
565     gpr_log(GPR_DEBUG,
566             "add socket %d to server for port %d, %zu listener(s) in total", fd,
567             port, s->listeners.size());
568     gpr_mu_unlock(&s->mu);
569   }
570   return port;
571 }
572 
grpc_udp_server_add_port(grpc_udp_server * s,grpc_resolved_address * addr,int rcv_buf_size,int snd_buf_size,GrpcUdpHandlerFactory * handler_factory,size_t num_listeners)573 int grpc_udp_server_add_port(grpc_udp_server* s, grpc_resolved_address* addr,
574                              int rcv_buf_size, int snd_buf_size,
575                              GrpcUdpHandlerFactory* handler_factory,
576                              size_t num_listeners) {
577   if (num_listeners > 1 && !s->so_reuseport) {
578     gpr_log(GPR_ERROR,
579             "Try to have multiple listeners on same port, but SO_REUSEPORT is "
580             "not supported. Only create 1 listener.");
581   }
582   std::string addr_str = grpc_sockaddr_to_string(addr, true);
583   gpr_log(GPR_DEBUG, "add address: %s to server", addr_str.c_str());
584 
585   int allocated_port1 = -1;
586   int allocated_port2 = -1;
587   int fd;
588   grpc_dualstack_mode dsmode;
589   grpc_resolved_address addr6_v4mapped;
590   grpc_resolved_address wild4;
591   grpc_resolved_address wild6;
592   grpc_resolved_address addr4_copy;
593   grpc_resolved_address* allocated_addr = nullptr;
594   grpc_resolved_address sockname_temp;
595   int port = 0;
596 
597   /* Check if this is a wildcard port, and if so, try to keep the port the same
598      as some previously created listener. */
599   if (grpc_sockaddr_get_port(addr) == 0) {
600     /* Loop through existing listeners to find the port in use. */
601     for (size_t i = 0; i < s->listeners.size(); ++i) {
602       sockname_temp.len =
603           static_cast<socklen_t>(sizeof(struct sockaddr_storage));
604       if (0 == getsockname(s->listeners[i].fd(),
605                            reinterpret_cast<grpc_sockaddr*>(sockname_temp.addr),
606                            &sockname_temp.len)) {
607         port = grpc_sockaddr_get_port(&sockname_temp);
608         if (port > 0) {
609           /* Found such a port, update |addr| to reflects this port. */
610           allocated_addr = static_cast<grpc_resolved_address*>(
611               gpr_malloc(sizeof(grpc_resolved_address)));
612           memcpy(allocated_addr, addr, sizeof(grpc_resolved_address));
613           grpc_sockaddr_set_port(allocated_addr, port);
614           addr = allocated_addr;
615           break;
616         }
617       }
618     }
619   }
620 
621   if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
622     addr = &addr6_v4mapped;
623   }
624 
625   s->handler_factory = handler_factory;
626   for (size_t i = 0; i < num_listeners; ++i) {
627     /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
628     if (grpc_sockaddr_is_wildcard(addr, &port)) {
629       grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
630 
631       /* Try listening on IPv6 first. */
632       addr = &wild6;
633       // TODO(rjshade): Test and propagate the returned grpc_error*:
634       GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory(
635           s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd));
636       allocated_port1 =
637           add_socket_to_server(s, fd, addr, rcv_buf_size, snd_buf_size);
638       if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
639         if (port == 0) {
640           /* This is the first time to bind to |addr|. If its port is still
641            * wildcard port, update |addr| with the ephermeral port returned by
642            * kernel. Thus |addr| can have a specific port in following
643            * iterations. */
644           grpc_sockaddr_set_port(addr, allocated_port1);
645           port = allocated_port1;
646         } else if (allocated_port1 >= 0) {
647           /* The following successfully created socket should have same port as
648            * the first one. */
649           GPR_ASSERT(port == allocated_port1);
650         }
651         /* A dualstack socket is created, no need to create corresponding IPV4
652          * socket. */
653         continue;
654       }
655 
656       /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
657       if (port == 0 && allocated_port1 > 0) {
658         /* |port| hasn't been assigned to an emphemeral port yet, |wild4| must
659          * have a wildcard port. Update it with the emphemeral port created
660          * during binding.*/
661         grpc_sockaddr_set_port(&wild4, allocated_port1);
662         port = allocated_port1;
663       }
664       /* |wild4| should have been updated with an emphemeral port by now. Use
665        * this IPV4 address to create a IPV4 socket. */
666       addr = &wild4;
667     }
668 
669     // TODO(rjshade): Test and propagate the returned grpc_error*:
670     GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory(
671         s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd));
672     if (fd < 0) {
673       gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
674     }
675     if (dsmode == GRPC_DSMODE_IPV4 &&
676         grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
677       addr = &addr4_copy;
678     }
679     allocated_port2 =
680         add_socket_to_server(s, fd, addr, rcv_buf_size, snd_buf_size);
681     if (port == 0) {
682       /* Update |addr| with the ephermeral port returned by kernel. So |addr|
683        * can have a specific port in following iterations. */
684       grpc_sockaddr_set_port(addr, allocated_port2);
685       port = allocated_port2;
686     } else if (allocated_port2 >= 0) {
687       GPR_ASSERT(port == allocated_port2);
688     }
689   }
690 
691   gpr_free(allocated_addr);
692   return port;
693 }
694 
grpc_udp_server_get_fd(grpc_udp_server * s,unsigned port_index)695 int grpc_udp_server_get_fd(grpc_udp_server* s, unsigned port_index) {
696   if (port_index >= s->listeners.size()) {
697     return -1;
698   }
699 
700   return s->listeners[port_index].fd();
701 }
702 
grpc_udp_server_start(grpc_udp_server * udp_server,const std::vector<grpc_pollset * > * pollsets,void * user_data)703 void grpc_udp_server_start(grpc_udp_server* udp_server,
704                            const std::vector<grpc_pollset*>* pollsets,
705                            void* user_data) {
706   gpr_log(GPR_DEBUG, "grpc_udp_server_start");
707   gpr_mu_lock(&udp_server->mu);
708   GPR_ASSERT(udp_server->active_ports == 0);
709   udp_server->pollsets = pollsets;
710   udp_server->user_data = user_data;
711 
712   for (auto& listener : udp_server->listeners) {
713     listener.StartListening(pollsets, udp_server->handler_factory);
714   }
715 
716   gpr_mu_unlock(&udp_server->mu);
717 }
718 
StartListening(const std::vector<grpc_pollset * > * pollsets,GrpcUdpHandlerFactory * handler_factory)719 void GrpcUdpListener::StartListening(const std::vector<grpc_pollset*>* pollsets,
720                                      GrpcUdpHandlerFactory* handler_factory) {
721   gpr_mu_lock(&mutex_);
722   handler_factory_ = handler_factory;
723   udp_handler_ = handler_factory->CreateUdpHandler(emfd_, server_->user_data);
724   for (grpc_pollset* pollset : *pollsets) {
725     grpc_pollset_add_fd(pollset, emfd_);
726   }
727   GRPC_CLOSURE_INIT(&read_closure_, on_read, this, grpc_schedule_on_exec_ctx);
728   grpc_fd_notify_on_read(emfd_, &read_closure_);
729 
730   GRPC_CLOSURE_INIT(&write_closure_, on_write, this, grpc_schedule_on_exec_ctx);
731   notify_on_write_armed_ = true;
732   grpc_fd_notify_on_write(emfd_, &write_closure_);
733 
734   /* Registered for both read and write callbacks: increment active_ports
735    * twice to account for this, and delay free-ing of memory until both
736    * on_read and on_write have fired. */
737   server_->active_ports += 2;
738   gpr_mu_unlock(&mutex_);
739 }
740 
OnDestroy()741 void GrpcUdpListener::OnDestroy() {
742   if (udp_handler_ != nullptr) {
743     handler_factory_->DestroyUdpHandler(udp_handler_);
744   }
745 }
746 
747 #endif
748