-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Introducing UDP listener. #5473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0509ee3
eca712d
37232e4
3c7e6f6
6389f68
bd240a5
3a973f1
6803aee
eed7d49
0bcfbb8
a1afecf
c375b54
8e49e6b
0749e32
7ae3884
4c25d18
e85347d
17ba123
cd8930e
f128673
b83ff51
e8003b2
84b6e68
a84a96d
ee78778
9bcfacf
4f8de99
bc2695a
3c1f89a
ce18742
972819a
3de381d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -114,6 +114,59 @@ class ListenerCallbacks { | |
| virtual void onNewConnection(ConnectionPtr&& new_connection) PURE; | ||
| }; | ||
|
|
||
| /** | ||
| * Utility struct that encapsulates the information from a udp socket's | ||
| * recvfrom/recvmmsg call. | ||
| * | ||
| * TODO(conqerAtapple): Maybe this belongs inside the UdpListenerCallbacks | ||
| * class. | ||
| */ | ||
| struct UdpData { | ||
|
||
| Address::InstanceConstSharedPtr local_address_; | ||
| Address::InstanceConstSharedPtr peer_address_; // TODO(conquerAtapple): Fix ownership semantics. | ||
| Buffer::InstancePtr buffer_; | ||
| // TODO(conquerAtapple): | ||
| // Add UdpReader here so that the callback handler can | ||
| // then use the reader to do multiple reads(recvmmsg) once the OS notifies it | ||
| // has data. We could also just return a `ReaderFactory` that returns either a | ||
| // `recvfrom` reader (with peer information) or a `read/recvmmsg` reader. This | ||
| // is still being flushed out (Jan, 2019). | ||
| }; | ||
|
|
||
| /** | ||
| * Udp listener callbacks. | ||
| */ | ||
| class UdpListenerCallbacks { | ||
|
||
| public: | ||
| enum class ErrorCode { SyscallError, UnknownError }; | ||
|
|
||
| virtual ~UdpListenerCallbacks() = default; | ||
|
|
||
| /** | ||
| * Called whenever data is received by the underlying udp socket. | ||
| * | ||
| * @param data UdpData from the underlying socket. | ||
| */ | ||
| virtual void onData(const UdpData& data) PURE; | ||
|
|
||
| /** | ||
| * Called when the underlying socket is ready for write. | ||
| * | ||
| * @param socket Underlying server socket for the listener. | ||
| * | ||
| * TODO(conqerAtapple): Maybe we need a UdpWriter here instead of Socket. | ||
| */ | ||
| virtual void onWriteReady(const Socket& socket) PURE; | ||
|
|
||
| /** | ||
| * Called when there is an error event. | ||
| * | ||
| * @param error_code ErrorCode for the error event. | ||
| * @param error_number System error number. | ||
| */ | ||
| virtual void onError(const ErrorCode& error_code, int error_number) PURE; | ||
| }; | ||
|
|
||
|
||
| /** | ||
| * An abstract socket listener. Free the listener to stop listening on the socket. | ||
| */ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ | |
| #include "common/network/connection_impl.h" | ||
| #include "common/network/dns_impl.h" | ||
| #include "common/network/listener_impl.h" | ||
| #include "common/network/udp_listener_impl.h" | ||
|
|
||
| #include "event2/event.h" | ||
|
|
||
|
|
@@ -119,6 +120,12 @@ DispatcherImpl::createListener(Network::Socket& socket, Network::ListenerCallbac | |
| hand_off_restored_destination_connections)}; | ||
| } | ||
|
|
||
| Network::ListenerPtr DispatcherImpl::createUdpListener(Network::Socket& socket, | ||
| Network::UdpListenerCallbacks& cb) { | ||
| ASSERT(isThreadSafe()); | ||
| return Network::ListenerPtr{new Network::UdpListenerImpl(*this, socket, cb)}; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: |
||
| } | ||
|
|
||
| TimerPtr DispatcherImpl::createTimer(TimerCb cb) { | ||
| ASSERT(isThreadSafe()); | ||
| return scheduler_->createTimer(cb); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| #include "common/network/base_listener_impl.h" | ||
|
|
||
| #include <sys/un.h> | ||
|
|
||
| #include "envoy/common/exception.h" | ||
|
|
||
| #include "common/common/assert.h" | ||
| #include "common/common/empty_string.h" | ||
| #include "common/common/fmt.h" | ||
| #include "common/event/dispatcher_impl.h" | ||
| #include "common/event/file_event_impl.h" | ||
| #include "common/network/address_impl.h" | ||
|
|
||
| #include "event2/listener.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Network { | ||
|
|
||
| Address::InstanceConstSharedPtr BaseListenerImpl::getLocalAddress(int fd) { | ||
| return Address::addressFromFd(fd); | ||
| } | ||
|
|
||
| BaseListenerImpl::BaseListenerImpl(Event::DispatcherImpl& dispatcher, Socket& socket) | ||
| : local_address_(nullptr), dispatcher_(dispatcher), socket_(socket) { | ||
| const auto ip = socket.localAddress()->ip(); | ||
|
|
||
| // Only use the listen socket's local address for new connections if it is not the all hosts | ||
| // address (e.g., 0.0.0.0 for IPv4). | ||
| if (!(ip && ip->isAnyAddress())) { | ||
| local_address_ = socket.localAddress(); | ||
| } | ||
| } | ||
|
|
||
| } // namespace Network | ||
| } // namespace Envoy |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| #pragma once | ||
|
|
||
| #include "envoy/network/listener.h" | ||
|
|
||
| #include "common/event/dispatcher_impl.h" | ||
| #include "common/event/libevent.h" | ||
| #include "common/network/listen_socket_impl.h" | ||
|
|
||
| #include "event2/event.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Network { | ||
|
|
||
| /** | ||
| * Base libevent implementation of Network::Listener. | ||
| */ | ||
| class BaseListenerImpl : public Listener { | ||
| public: | ||
| BaseListenerImpl(Event::DispatcherImpl& dispatcher, Socket& socket); | ||
|
|
||
| protected: | ||
| virtual Address::InstanceConstSharedPtr getLocalAddress(int fd); | ||
|
|
||
| Address::InstanceConstSharedPtr local_address_; | ||
| Event::DispatcherImpl& dispatcher_; | ||
| Socket& socket_; | ||
| }; | ||
|
|
||
| } // namespace Network | ||
| } // namespace Envoy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering whether we will ever want to support proxying datagrams over Unix domain sockets, in addition to over UDP. (Analogous to current Envoy support for pipes vs. TCP connections.) If so, then it might be more general to name this createDatagramListener. Or maybe UDS datagrams aren't worth supporting, in which case current name SGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mpwarres Does gQUIC currently use Unix domain sockets for proxying datagrams? I vaguely recall hearing about a potential experiment with them in a QUIC talk.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that I'm aware. We have used SOCK_DGRAM + shared memory to allow GFEs (speaking QUIC) to efficiently front for other (non QUIC speaking) servers, but AIUI there the datagrams were just for coordinating shared memory use, not for carrying QUIC traffic. Not sure if @ianswett may have mentioned this in one of his talks, perhaps this one, though I don't see it in the slides. The comment I posted upthread was more hypothetical--I don't have a concrete use case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a strong opinion on this, though
createDatagramListener()does seem more generic.