| /** @file |
| |
| This file implements an I/O Processor for network I/O |
| |
| @section license License |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you 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. |
| |
| */ |
| #pragma once |
| |
| #include "ProxyProtocol.h" |
| #include "I_Net.h" |
| |
| #include <string_view> |
| #include <optional> |
| |
| #include "tscore/ink_inet.h" |
| #include "I_Action.h" |
| #include "I_VConnection.h" |
| #include "I_Event.h" |
| #include "tscore/List.h" |
| #include "I_IOBuffer.h" |
| #include "I_Socks.h" |
| #include "ts/apidefs.h" |
| #include "YamlSNIConfig.h" |
| #include "tscpp/util/TextView.h" |
| #include "tscore/IpMap.h" |
| |
| #define CONNECT_SUCCESS 1 |
| #define CONNECT_FAILURE 0 |
| |
| #define SSL_EVENT_SERVER 0 |
| #define SSL_EVENT_CLIENT 1 |
| |
| // Indicator the context for a NetVConnection |
| typedef enum { |
| NET_VCONNECTION_UNSET = 0, |
| NET_VCONNECTION_IN, // Client <--> ATS, Client-Side |
| NET_VCONNECTION_OUT, // ATS <--> Server, Server-Side |
| } NetVConnectionContext_t; |
| |
| /** Holds client options for NetVConnection. |
| |
| This class holds various options a user can specify for |
| NetVConnection. Various clients need many slightly different |
| features. This is an attempt to prevent out of control growth of |
| the connection method signatures. Only options of interest need to |
| be explicitly set -- the rest get sensible default values. |
| |
| @note Binding addresses is a bit complex. It is not currently |
| possible to bind indiscriminately across protocols, which means |
| any connection must commit to IPv4 or IPv6. For this reason the |
| connection logic will look at the address family of @a local_addr |
| even if @a addr_binding is @c ANY_ADDR and bind to any address in |
| that protocol. If it's not an IP protocol, IPv4 will be used. |
| */ |
| struct NetVCOptions { |
| typedef NetVCOptions self; ///< Self reference type. |
| |
| /// Values for valid IP protocols. |
| enum ip_protocol_t { |
| USE_TCP, ///< TCP protocol. |
| USE_UDP ///< UDP protocol. |
| }; |
| |
| /// IP (TCP or UDP) protocol to use on socket. |
| ip_protocol_t ip_proto; |
| |
| /** IP address family. |
| |
| This is used for inbound connections only if @c local_ip is not |
| set, which is sometimes more convenient for the client. This |
| defaults to @c AF_INET so if the client sets neither this nor @c |
| local_ip then IPv4 is used. |
| |
| For outbound connections this is ignored and the family of the |
| remote address used. |
| |
| @note This is (inconsistently) called "domain" and "protocol" in |
| other places. "family" is used here because that's what the |
| standard IP data structures use. |
| |
| */ |
| uint16_t ip_family; |
| |
| /** The set of ways in which the local address should be bound. |
| |
| The protocol is set by the contents of @a local_addr regardless |
| of this value. @c ANY_ADDR will override only the address. |
| |
| @note The difference between @c INTF_ADDR and @c FOREIGN_ADDR is |
| whether transparency is enabled on the socket. It is the |
| client's responsibility to set this correctly based on whether |
| the address in @a local_addr is associated with an interface on |
| the local system ( @c INTF_ADDR ) or is owned by a foreign |
| system ( @c FOREIGN_ADDR ). A binding style of @c ANY_ADDR |
| causes the value in @a local_addr to be ignored. |
| |
| The IP address and port are separate because most clients treat |
| these independently. For the same reason @c IpAddr is used |
| to be clear that it contains no port data. |
| |
| @see local_addr |
| @see addr_binding |
| */ |
| enum addr_bind_style { |
| ANY_ADDR, ///< Bind to any available local address (don't care, default). |
| INTF_ADDR, ///< Bind to interface address in @a local_addr. |
| FOREIGN_ADDR ///< Bind to foreign address in @a local_addr. |
| }; |
| |
| /** Local address for the connection. |
| |
| For outbound connections this must have the same family as the |
| remote address (which is not stored in this structure). For |
| inbound connections the family of this value overrides @a |
| ip_family if set. |
| |
| @note Ignored if @a addr_binding is @c ANY_ADDR. |
| @see addr_binding |
| @see ip_family |
| */ |
| IpAddr local_ip; |
| |
| /** Local port for connection. |
| Set to 0 for "don't care" (default). |
| */ |
| uint16_t local_port; |
| |
| /// How to bind the local address. |
| /// @note Default is @c ANY_ADDR. |
| addr_bind_style addr_binding; |
| |
| /// Make the socket blocking on I/O (default: @c false) |
| bool f_blocking; |
| /// Make socket block on connect (default: @c false) |
| bool f_blocking_connect; |
| |
| // Use TCP Fast Open on this socket. The connect(2) call will be omitted. |
| bool f_tcp_fastopen = false; |
| |
| /// Control use of SOCKS. |
| /// Set to @c NO_SOCKS to disable use of SOCKS. Otherwise SOCKS is |
| /// used if available. |
| unsigned char socks_support; |
| /// Version of SOCKS to use. |
| unsigned char socks_version; |
| |
| int socket_recv_bufsize; |
| int socket_send_bufsize; |
| |
| /// Configuration options for sockets. |
| /// @note These are not identical to internal socket options but |
| /// specifically defined for configuration. These are mask values |
| /// and so must be powers of 2. |
| uint32_t sockopt_flags; |
| /// Value for TCP no delay for @c sockopt_flags. |
| static uint32_t const SOCK_OPT_NO_DELAY = 1; |
| /// Value for keep alive for @c sockopt_flags. |
| static uint32_t const SOCK_OPT_KEEP_ALIVE = 2; |
| /// Value for linger on for @c sockopt_flags |
| static uint32_t const SOCK_OPT_LINGER_ON = 4; |
| /// Value for TCP Fast open @c sockopt_flags |
| static uint32_t const SOCK_OPT_TCP_FAST_OPEN = 8; |
| /// Value for SO_MARK @c sockopt_flags |
| static uint32_t const SOCK_OPT_PACKET_MARK = 16; |
| /// Value for IP_TOS @c sockopt_flags |
| static uint32_t const SOCK_OPT_PACKET_TOS = 32; |
| /// Value for TCP_NOTSENT_LOWAT @c sockopt_flags |
| static uint32_t const SOCK_OPT_TCP_NOTSENT_LOWAT = 64; |
| |
| uint32_t packet_mark; |
| uint32_t packet_tos; |
| uint32_t packet_notsent_lowat; |
| |
| EventType etype; |
| |
| /** ALPN protocol-lists. The format is OpenSSL protocol-lists format (vector of 8-bit length-prefixed, byte strings) |
| https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_alpn_protos.html |
| */ |
| std::string_view alpn_protos; |
| /** Server name to use for SNI data on an outbound connection. |
| */ |
| ats_scoped_str sni_servername; |
| /** FQDN used to connect to the origin. May be different |
| * than sni_servername if pristine host headers are used |
| */ |
| ats_scoped_str ssl_servername; |
| |
| /** Server host name from client's request to use for SNI data on an outbound connection. |
| */ |
| ats_scoped_str sni_hostname; |
| |
| /** Outbound sni policy which overrides proxy.ssl.client.sni_policy |
| */ |
| ats_scoped_str outbound_sni_policy; |
| |
| /** |
| * Client certificate to use in response to OS's certificate request |
| */ |
| ats_scoped_str ssl_client_cert_name; |
| /* |
| * File containing private key matching certificate |
| */ |
| const char *ssl_client_private_key_name = nullptr; |
| /* |
| * File containing CA certs for verifying origin's cert |
| */ |
| const char *ssl_client_ca_cert_name = nullptr; |
| /* |
| * Directory containing CA certs for verifying origin's cert |
| */ |
| const char *ssl_client_ca_cert_path = nullptr; |
| |
| bool tls_upstream = false; |
| |
| /** |
| * Set to DISABLED, PERFMISSIVE, or ENFORCED |
| * Controls how the server certificate verification is handled |
| */ |
| YamlSNIConfig::Policy verifyServerPolicy = YamlSNIConfig::Policy::DISABLED; |
| |
| /** |
| * Bit mask of which features of the server certificate should be checked |
| * Currently SIGNATURE and NAME |
| */ |
| YamlSNIConfig::Property verifyServerProperties = YamlSNIConfig::Property::NONE; |
| |
| /// Reset all values to defaults. |
| void reset(); |
| |
| void set_sock_param(int _recv_bufsize, int _send_bufsize, unsigned long _opt_flags, unsigned long _packet_mark = 0, |
| unsigned long _packet_tos = 0, unsigned long _packet_notsent_lowat = 0); |
| |
| NetVCOptions() { reset(); } |
| ~NetVCOptions() {} |
| |
| /** Set the SNI server name. |
| A local copy is made of @a name. |
| */ |
| self & |
| set_sni_servername(const char *name, size_t len) |
| { |
| IpEndpoint ip; |
| |
| // Literal IPv4 and IPv6 addresses are not permitted in "HostName".(rfc6066#section-3) |
| if (name && len && ats_ip_pton(std::string_view(name, len), &ip) != 0) { |
| sni_servername = ats_strndup(name, len); |
| } else { |
| sni_servername = nullptr; |
| } |
| return *this; |
| } |
| |
| self & |
| set_ssl_client_cert_name(const char *name) |
| { |
| if (name) { |
| ssl_client_cert_name = ats_strdup(name); |
| } else { |
| ssl_client_cert_name = nullptr; |
| } |
| return *this; |
| } |
| |
| self & |
| set_ssl_servername(const char *name) |
| { |
| if (name) { |
| ssl_servername = ats_strdup(name); |
| } else { |
| ssl_servername = nullptr; |
| } |
| return *this; |
| } |
| |
| self & |
| set_sni_hostname(const char *name, size_t len) |
| { |
| IpEndpoint ip; |
| |
| // Literal IPv4 and IPv6 addresses are not permitted in "HostName".(rfc6066#section-3) |
| if (name && len && ats_ip_pton(std::string_view(name, len), &ip) != 0) { |
| sni_hostname = ats_strndup(name, len); |
| } else { |
| sni_hostname = nullptr; |
| } |
| return *this; |
| } |
| |
| self & |
| operator=(self const &that) |
| { |
| if (&that != this) { |
| /* |
| * It is odd but necessary to null the scoped string pointer here |
| * and then explicitly call release on them in the string assignments |
| * below. |
| * We a memcpy from that to this. This will put that's string pointers into |
| * this's memory. Therefore we must first explicitly null out |
| * this's original version of the string. The release after the |
| * memcpy removes the extra reference to that's copy of the string |
| * Removing the release will eventually cause a double free crash |
| */ |
| sni_servername = nullptr; // release any current name. |
| ssl_servername = nullptr; |
| sni_hostname = nullptr; |
| ssl_client_cert_name = nullptr; |
| memcpy(static_cast<void *>(this), &that, sizeof(self)); |
| if (that.sni_servername) { |
| sni_servername.release(); // otherwise we'll free the source string. |
| this->sni_servername = ats_strdup(that.sni_servername); |
| } |
| if (that.ssl_servername) { |
| ssl_servername.release(); // otherwise we'll free the source string. |
| this->ssl_servername = ats_strdup(that.ssl_servername); |
| } |
| if (that.sni_hostname) { |
| sni_hostname.release(); // otherwise we'll free the source string. |
| this->sni_hostname = ats_strdup(that.sni_hostname); |
| } |
| if (that.ssl_client_cert_name) { |
| this->ssl_client_cert_name.release(); // otherwise we'll free the source string. |
| this->ssl_client_cert_name = ats_strdup(that.ssl_client_cert_name); |
| } |
| } |
| return *this; |
| } |
| |
| std::string_view get_family_string() const; |
| |
| std::string_view get_proto_string() const; |
| |
| /// @name Debugging |
| //@{ |
| /// Convert @a s to its string equivalent. |
| static const char *toString(addr_bind_style s); |
| //@} |
| |
| // noncopyable |
| NetVCOptions(const NetVCOptions &) = delete; |
| }; |
| |
| inline void |
| NetVCOptions::reset() |
| { |
| ip_proto = USE_TCP; |
| ip_family = AF_INET; |
| local_ip.invalidate(); |
| local_port = 0; |
| addr_binding = ANY_ADDR; |
| f_blocking = false; |
| f_blocking_connect = false; |
| socks_support = NORMAL_SOCKS; |
| socks_version = SOCKS_DEFAULT_VERSION; |
| socket_recv_bufsize = |
| #if defined(RECV_BUF_SIZE) |
| RECV_BUF_SIZE; |
| #else |
| 0; |
| #endif |
| socket_send_bufsize = 0; |
| sockopt_flags = 0; |
| packet_mark = 0; |
| packet_tos = 0; |
| packet_notsent_lowat = 0; |
| |
| etype = ET_NET; |
| |
| sni_servername = nullptr; |
| ssl_servername = nullptr; |
| sni_hostname = nullptr; |
| ssl_client_cert_name = nullptr; |
| ssl_client_private_key_name = nullptr; |
| outbound_sni_policy = nullptr; |
| } |
| |
| inline void |
| NetVCOptions::set_sock_param(int _recv_bufsize, int _send_bufsize, unsigned long _opt_flags, unsigned long _packet_mark, |
| unsigned long _packet_tos, unsigned long _packet_notsent_lowat) |
| { |
| socket_recv_bufsize = _recv_bufsize; |
| socket_send_bufsize = _send_bufsize; |
| sockopt_flags = _opt_flags; |
| packet_mark = _packet_mark; |
| packet_tos = _packet_tos; |
| packet_notsent_lowat = _packet_notsent_lowat; |
| } |
| |
| /** |
| A VConnection for a network socket. Abstraction for a net connection. |
| Similar to a socket descriptor VConnections are IO handles to |
| streams. In one sense, they serve a purpose similar to file |
| descriptors. Unlike file descriptors, VConnections allow for a |
| stream IO to be done based on a single read or write call. |
| |
| */ |
| class NetVConnection : public VConnection, public PluginUserArgs<TS_USER_ARGS_VCONN> |
| { |
| public: |
| /** |
| Initiates read. Thread safe, may be called when not handling |
| an event from the NetVConnection, or the NetVConnection creation |
| callback. |
| |
| Callbacks: non-reentrant, c's lock taken during callbacks. |
| |
| <table> |
| <tr><td>c->handleEvent(VC_EVENT_READ_READY, vio)</td><td>data added to buffer</td></tr> |
| <tr><td>c->handleEvent(VC_EVENT_READ_COMPLETE, vio)</td><td>finished reading nbytes of data</td></tr> |
| <tr><td>c->handleEvent(VC_EVENT_EOS, vio)</td><td>the stream has been shutdown</td></tr> |
| <tr><td>c->handleEvent(VC_EVENT_ERROR, vio)</td><td>error</td></tr> |
| </table> |
| |
| The vio returned during callbacks is the same as the one returned |
| by do_io_read(). The vio can be changed only during call backs |
| from the vconnection. |
| |
| @param c continuation to be called back after (partial) read |
| @param nbytes no of bytes to read, if unknown set to INT64_MAX |
| @param buf buffer to put the data into |
| @return vio |
| |
| */ |
| VIO *do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf) override = 0; |
| |
| /** |
| Initiates write. Thread-safe, may be called when not handling |
| an event from the NetVConnection, or the NetVConnection creation |
| callback. |
| |
| Callbacks: non-reentrant, c's lock taken during callbacks. |
| |
| <table> |
| <tr> |
| <td>c->handleEvent(VC_EVENT_WRITE_READY, vio)</td> |
| <td>signifies data has written from the reader or there are no bytes available for the reader to write.</td> |
| </tr> |
| <tr> |
| <td>c->handleEvent(VC_EVENT_WRITE_COMPLETE, vio)</td> |
| <td>signifies the amount of data indicated by nbytes has been read from the buffer</td> |
| </tr> |
| <tr> |
| <td>c->handleEvent(VC_EVENT_ERROR, vio)</td> |
| <td>signified that error occurred during write.</td> |
| </tr> |
| </table> |
| |
| The vio returned during callbacks is the same as the one returned |
| by do_io_write(). The vio can be changed only during call backs |
| from the vconnection. The vconnection deallocates the reader |
| when it is destroyed. |
| |
| @param c continuation to be called back after (partial) write |
| @param nbytes no of bytes to write, if unknown must be set to INT64_MAX |
| @param buf source of data |
| @param owner |
| @return vio pointer |
| |
| */ |
| VIO *do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner = false) override = 0; |
| |
| /** |
| Closes the vconnection. A state machine MUST call do_io_close() |
| when it has finished with a VConnection. do_io_close() indicates |
| that the VConnection can be deallocated. After a close has been |
| called, the VConnection and underlying processor must NOT send |
| any more events related to this VConnection to the state machine. |
| Likewise, state machine must not access the VConnection or |
| any returned VIOs after calling close. lerrno indicates whether |
| a close is a normal close or an abort. The difference between |
| a normal close and an abort depends on the underlying type of |
| the VConnection. Passing VIO::CLOSE for lerrno indicates a |
| normal close while passing VIO::ABORT indicates an abort. |
| |
| @param lerrno VIO:CLOSE for regular close or VIO::ABORT for aborts |
| |
| */ |
| void do_io_close(int lerrno = -1) override = 0; |
| |
| /** |
| Shuts down read side, write side, or both. do_io_shutdown() can |
| be used to terminate one or both sides of the VConnection. The |
| howto is one of IO_SHUTDOWN_READ, IO_SHUTDOWN_WRITE, |
| IO_SHUTDOWN_READWRITE. Once a side of a VConnection is shutdown, |
| no further I/O can be done on that side of the connections and |
| the underlying processor MUST NOT send any further events |
| (INCLUDING TIMEOUT EVENTS) to the state machine. The state machine |
| MUST NOT use any VIOs from a shutdown side of a connection. |
| Even if both sides of a connection are shutdown, the state |
| machine MUST still call do_io_close() when it wishes the |
| VConnection to be deallocated. |
| |
| @param howto IO_SHUTDOWN_READ, IO_SHUTDOWN_WRITE, IO_SHUTDOWN_READWRITE |
| |
| */ |
| void do_io_shutdown(ShutdownHowTo_t howto) override = 0; |
| |
| /** |
| Return the server name that is appropriate for the network VC type |
| */ |
| virtual const char * |
| get_server_name() const |
| { |
| return nullptr; |
| } |
| |
| //////////////////////////////////////////////////////////// |
| // Set the timeouts associated with this connection. // |
| // active_timeout is for the total elapsed time of // |
| // the connection. // |
| // inactivity_timeout is the elapsed time from the time // |
| // a read or a write was scheduled during which the // |
| // connection was unable to sink/provide data. // |
| // calling these functions repeatedly resets the timeout. // |
| // These functions are NOT THREAD-SAFE, and may only be // |
| // called when handing an event from this NetVConnection,// |
| // or the NetVConnection creation callback. // |
| //////////////////////////////////////////////////////////// |
| |
| /** |
| Sets time after which SM should be notified. |
| |
| Sets the amount of time (in nanoseconds) after which the state |
| machine using the NetVConnection should receive a |
| VC_EVENT_ACTIVE_TIMEOUT event. The timeout is value is ignored |
| if neither the read side nor the write side of the connection |
| is currently active. The timer is reset if the function is |
| called repeatedly This call can be used by SMs to make sure |
| that it does not keep any connections open for a really long |
| time. |
| |
| Timeout semantics: |
| |
| Should a timeout occur, the state machine for the read side of |
| the NetVConnection is signaled first assuming that a read has |
| been initiated on the NetVConnection and that the read side of |
| the NetVConnection has not been shutdown. Should either of the |
| two conditions not be met, the NetProcessor will attempt to |
| signal the write side. If a timeout is sent to the read side |
| state machine and its handler, return EVENT_DONE, a timeout |
| will not be sent to the write side. Should the return from the |
| handler not be EVENT_DONE and the write side state machine is |
| different (in terms of pointer comparison) from the read side |
| state machine, the NetProcessor will try to signal the write |
| side state machine as well. To signal write side, a write must |
| have been initiated on it and the write must not have been |
| shutdown. |
| |
| Receiving a timeout is only a notification that the timer has |
| expired. The NetVConnection is still usable. Further timeouts |
| of the type signaled will not be generated unless the timeout |
| is reset via the set_active_timeout() or set_inactivity_timeout() |
| interfaces. |
| |
| */ |
| virtual void set_active_timeout(ink_hrtime timeout_in) = 0; |
| |
| /** |
| Sets time after which SM should be notified if the requested |
| IO could not be performed. Sets the amount of time (in nanoseconds), |
| if the NetVConnection is idle on both the read or write side, |
| after which the state machine using the NetVConnection should |
| receive a VC_EVENT_INACTIVITY_TIMEOUT event. Either read or |
| write traffic will cause timer to be reset. Calling this function |
| again also resets the timer. The timeout is value is ignored |
| if neither the read side nor the write side of the connection |
| is currently active. See section on timeout semantics above. |
| |
| */ |
| virtual void set_inactivity_timeout(ink_hrtime timeout_in) = 0; |
| virtual void set_default_inactivity_timeout(ink_hrtime timeout_in) = 0; |
| virtual bool is_default_inactivity_timeout() = 0; |
| |
| /** |
| Clears the active timeout. No active timeouts will be sent until |
| set_active_timeout() is used to reset the active timeout. |
| |
| */ |
| virtual void cancel_active_timeout() = 0; |
| |
| /** |
| Clears the inactivity timeout. No inactivity timeouts will be |
| sent until set_inactivity_timeout() is used to reset the |
| inactivity timeout. |
| |
| */ |
| virtual void cancel_inactivity_timeout() = 0; |
| |
| /** Set the action to use a continuation. |
| The action continuation will be called with an event if there is no pending I/O operation |
| to receive the event. |
| |
| Pass @c nullptr to disable. |
| |
| @internal Subclasses should implement this if they support actions. This abstract class does |
| not. If the subclass doesn't have an action this method is silently ignored. |
| */ |
| virtual void |
| set_action(Continuation *) |
| { |
| return; |
| } |
| |
| virtual void add_to_keep_alive_queue() = 0; |
| |
| virtual void remove_from_keep_alive_queue() = 0; |
| |
| virtual bool add_to_active_queue() = 0; |
| |
| /** @return the current active_timeout value in nanosecs */ |
| virtual ink_hrtime get_active_timeout() = 0; |
| |
| /** @return current inactivity_timeout value in nanosecs */ |
| virtual ink_hrtime get_inactivity_timeout() = 0; |
| |
| /** Force an @a event if a write operation empties the write buffer. |
| |
| This event will be sent to the VIO, the same place as other IO events. |
| Use an @a event value of 0 to cancel the trap. |
| |
| The event is sent only the next time the write buffer is emptied, not |
| every future time. The event is sent only if otherwise no event would |
| be generated. |
| */ |
| virtual void trapWriteBufferEmpty(int event = VC_EVENT_WRITE_READY); |
| |
| /** Returns local sockaddr storage. */ |
| sockaddr const *get_local_addr(); |
| IpEndpoint const &get_local_endpoint(); |
| |
| /** Returns local port. */ |
| uint16_t get_local_port(); |
| |
| /** Returns remote sockaddr storage. */ |
| sockaddr const *get_remote_addr(); |
| IpEndpoint const &get_remote_endpoint(); |
| |
| /** Returns remote port. */ |
| uint16_t get_remote_port(); |
| |
| /** Set the context of NetVConnection. |
| * The context is ONLY set once and will not be changed. |
| * |
| * @param context The context to be set. |
| */ |
| void |
| set_context(NetVConnectionContext_t context) |
| { |
| ink_assert(NET_VCONNECTION_UNSET == netvc_context); |
| netvc_context = context; |
| } |
| |
| /** Get the context. |
| * @return the context of current NetVConnection |
| */ |
| NetVConnectionContext_t |
| get_context() const |
| { |
| return netvc_context; |
| } |
| |
| /** |
| * Returns true if the network protocol |
| * supports a client provided SNI value |
| */ |
| virtual bool |
| support_sni() const |
| { |
| return false; |
| } |
| |
| virtual const char * |
| get_sni_servername() const |
| { |
| return nullptr; |
| } |
| |
| virtual bool |
| peer_provided_cert() const |
| { |
| return false; |
| } |
| |
| virtual int |
| provided_cert() const |
| { |
| return 0; |
| } |
| |
| /** Structure holding user options. */ |
| NetVCOptions options; |
| |
| /** Attempt to push any changed options down */ |
| virtual void apply_options() = 0; |
| |
| // |
| // Private |
| // |
| |
| // The following variable used to obtain host addr when transparency |
| // is enabled by SocksProxy |
| SocksAddrType socks_addr; |
| |
| unsigned int attributes = 0; |
| EThread *thread = nullptr; |
| |
| /// PRIVATE: The public interface is VIO::reenable() |
| void reenable(VIO *vio) override = 0; |
| |
| /// PRIVATE: The public interface is VIO::reenable() |
| void reenable_re(VIO *vio) override = 0; |
| |
| /// PRIVATE |
| ~NetVConnection() override {} |
| /** |
| PRIVATE: instances of NetVConnection cannot be created directly |
| by the state machines. The objects are created by NetProcessor |
| calls like accept connect_re() etc. The constructor is public |
| just to avoid compile errors. |
| |
| */ |
| NetVConnection(); |
| |
| virtual SOCKET get_socket() = 0; |
| |
| /** Set the TCP congestion control algorithm */ |
| virtual int set_tcp_congestion_control(int side) = 0; |
| |
| /** Set local sock addr struct. */ |
| virtual void set_local_addr() = 0; |
| |
| /** Set remote sock addr struct. */ |
| virtual void set_remote_addr() = 0; |
| |
| /** Set remote sock addr struct. */ |
| virtual void set_remote_addr(const sockaddr *) = 0; |
| |
| /** Set the MPTCP state for this connection */ |
| virtual void set_mptcp_state() = 0; |
| |
| // for InkAPI |
| bool |
| get_is_internal_request() const |
| { |
| return is_internal_request; |
| } |
| |
| void |
| set_is_internal_request(bool val = false) |
| { |
| is_internal_request = val; |
| } |
| |
| /// Get the transparency state. |
| bool |
| get_is_transparent() const |
| { |
| return is_transparent; |
| } |
| |
| /// Get the MPTCP state of the VC. |
| std::optional<bool> |
| get_mptcp_state() const |
| { |
| return mptcp_state; |
| } |
| |
| /// Set the transparency state. |
| void |
| set_is_transparent(bool state = true) |
| { |
| is_transparent = state; |
| } |
| |
| /// Get the proxy protocol enabled flag |
| bool |
| get_is_proxy_protocol() const |
| { |
| return is_proxy_protocol; |
| } |
| /// Set the proxy protocol enabled flag on the port |
| void |
| set_is_proxy_protocol(bool state = true) |
| { |
| is_proxy_protocol = state; |
| } |
| |
| virtual int |
| populate_protocol(std::string_view *results, int n) const |
| { |
| return 0; |
| } |
| |
| virtual const char * |
| protocol_contains(std::string_view prefix) const |
| { |
| return nullptr; |
| } |
| |
| // noncopyable |
| NetVConnection(const NetVConnection &) = delete; |
| NetVConnection &operator=(const NetVConnection &) = delete; |
| |
| ProxyProtocolVersion |
| get_proxy_protocol_version() const |
| { |
| return pp_info.version; |
| } |
| |
| sockaddr const *get_proxy_protocol_addr(const ProxyProtocolData) const; |
| |
| sockaddr const * |
| get_proxy_protocol_src_addr() const |
| { |
| return get_proxy_protocol_addr(ProxyProtocolData::SRC); |
| } |
| |
| uint16_t |
| get_proxy_protocol_src_port() const |
| { |
| return ats_ip_port_host_order(this->get_proxy_protocol_addr(ProxyProtocolData::SRC)); |
| } |
| |
| sockaddr const * |
| get_proxy_protocol_dst_addr() const |
| { |
| return get_proxy_protocol_addr(ProxyProtocolData::DST); |
| } |
| |
| uint16_t |
| get_proxy_protocol_dst_port() const |
| { |
| return ats_ip_port_host_order(this->get_proxy_protocol_addr(ProxyProtocolData::DST)); |
| }; |
| |
| void set_proxy_protocol_info(const ProxyProtocol &src); |
| const ProxyProtocol &get_proxy_protocol_info() const; |
| |
| bool has_proxy_protocol(IOBufferReader *); |
| bool has_proxy_protocol(char *, int64_t *); |
| |
| protected: |
| IpEndpoint local_addr; |
| IpEndpoint remote_addr; |
| ProxyProtocol pp_info; |
| |
| bool got_local_addr = false; |
| bool got_remote_addr = false; |
| |
| bool is_internal_request = false; |
| /// Set if this connection is transparent. |
| bool is_transparent = false; |
| /// Set if proxy protocol is enabled |
| bool is_proxy_protocol = false; |
| /// This is essentially a tri-state, we leave it undefined to mean no MPTCP support |
| std::optional<bool> mptcp_state; |
| /// Set if the next write IO that empties the write buffer should generate an event. |
| int write_buffer_empty_event = 0; |
| /// NetVConnection Context. |
| NetVConnectionContext_t netvc_context = NET_VCONNECTION_UNSET; |
| }; |
| |
| inline NetVConnection::NetVConnection() : VConnection(nullptr) |
| |
| { |
| ink_zero(local_addr); |
| ink_zero(remote_addr); |
| } |
| |
| inline void |
| NetVConnection::trapWriteBufferEmpty(int event) |
| { |
| write_buffer_empty_event = event; |
| } |