| // 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. |
| #ifndef KUDU_UTIL_NET_SOCKET_H |
| #define KUDU_UTIL_NET_SOCKET_H |
| |
| #include <cstddef> |
| #include <cstdint> |
| |
| #include "kudu/gutil/macros.h" |
| #include "kudu/util/status.h" |
| |
| struct iovec; |
| |
| namespace kudu { |
| |
| class MonoDelta; |
| class MonoTime; |
| class Sockaddr; |
| |
| class Socket { |
| public: |
| static const int FLAG_NONBLOCKING = 0x1; |
| |
| // Create a new invalid Socket object. |
| Socket(); |
| |
| // Start managing a socket. |
| explicit Socket(int fd); |
| Socket(Socket&& other) noexcept; |
| |
| // Close the socket. Errors will be ignored. |
| virtual ~Socket(); |
| |
| // Close the Socket, checking for errors. |
| virtual Status Close(); |
| |
| // call shutdown() on the socket |
| Status Shutdown(bool shut_read, bool shut_write); |
| |
| // Start managing a socket. |
| void Reset(int fd); |
| |
| // Stop managing the socket and return it. |
| int Release(); |
| |
| // Get the raw file descriptor, or -1 if there is no file descriptor being |
| // managed. |
| int GetFd() const; |
| |
| // Returns true if the error is temporary and will go away if we retry on |
| // the socket. |
| static bool IsTemporarySocketError(int err); |
| |
| // Init the socket for use with the given family (eg AF_INET or AF_UNIX). |
| Status Init(int family, int flags); // See FLAG_NONBLOCKING |
| |
| // Set or clear TCP_NODELAY |
| Status SetNoDelay(bool enabled); |
| |
| // Set or clear TCP_CORK |
| Status SetTcpCork(bool enabled); |
| |
| // Set or clear O_NONBLOCK |
| Status SetNonBlocking(bool enabled); |
| Status IsNonBlocking(bool* is_nonblock) const; |
| |
| // Set SO_SENDTIMEO to the specified value. Should only be used for blocking sockets. |
| Status SetSendTimeout(const MonoDelta& timeout); |
| |
| // Set SO_RCVTIMEO to the specified value. Should only be used for blocking sockets. |
| Status SetRecvTimeout(const MonoDelta& timeout); |
| |
| // Sets SO_REUSEADDR to 'flag'. Should be used prior to Bind(). |
| Status SetReuseAddr(bool flag); |
| |
| // Sets SO_REUSEPORT to 'flag'. Should be used prior to Bind(). |
| Status SetReusePort(bool flag); |
| |
| // Convenience method to invoke the common sequence: |
| // 1) SetReuseAddr(true) |
| // 2) Bind() |
| // 3) Listen() |
| Status BindAndListen(const Sockaddr &sockaddr, int listen_queue_size); |
| |
| // Start listening for new connections, with the given backlog size. |
| // Requires that the socket has already been bound using Bind(). |
| Status Listen(int listen_queue_size); |
| |
| // Call getsockname to get the address of this socket. |
| Status GetSocketAddress(Sockaddr *cur_addr) const; |
| |
| // Call getpeername to get the address of the connected peer. |
| // It is virtual so that tests can override. |
| virtual Status GetPeerAddress(Sockaddr *cur_addr) const; |
| |
| // Return true if this socket is determined to be a loopback connection |
| // (i.e. the local and remote peer share an IP address). |
| // |
| // If any error occurs while determining this, returns false. |
| bool IsLoopbackConnection() const; |
| |
| // Call bind() to bind the socket to a given address. |
| // If bind() fails and indicates that the requested port is already in use, |
| // generates an informative log message by calling 'lsof' if available. |
| Status Bind(const Sockaddr& bind_addr); |
| |
| // Call accept(2) to get a new connection. |
| Status Accept(Socket *new_conn, Sockaddr *remote, int flags); |
| |
| // start connecting this socket to a remote address. |
| Status Connect(const Sockaddr &remote); |
| |
| // get the error status using getsockopt(2) |
| Status GetSockError() const; |
| |
| // Write up to 'amt' bytes from 'buf' to the socket. The number of bytes |
| // actually written will be stored in 'nwritten'. If an error is returned, |
| // the value of 'nwritten' is undefined. |
| virtual Status Write(const uint8_t *buf, int32_t amt, int32_t *nwritten); |
| |
| // Vectorized Write. |
| // If there is an error, that error needs to be resolved before calling again. |
| // If there was no error, but not all the bytes were written, the unwritten |
| // bytes must be retried. See writev(2) for more information. |
| virtual Status Writev(const struct ::iovec *iov, int iov_len, int64_t *nwritten); |
| |
| // Blocking Write call, returns IOError unless full buffer is sent. |
| // Underlying Socket expected to be in blocking mode. Fails if any Write() sends 0 bytes. |
| // Returns OK if buflen bytes were sent, otherwise IOError. |
| // Upon return, nwritten will contain the number of bytes actually written. |
| // See also writen() from Stevens (2004) or Kerrisk (2010) |
| Status BlockingWrite(const uint8_t *buf, size_t buflen, size_t *nwritten, |
| const MonoTime& deadline); |
| |
| virtual Status Recv(uint8_t *buf, int32_t amt, int32_t *nread); |
| |
| // Blocking Recv call, returns IOError unless requested amt bytes are read. |
| // Underlying Socket expected to be in blocking mode. Fails if any Recv() reads 0 bytes. |
| // Returns OK if amt bytes were read, otherwise IOError. |
| // Upon return, nread will contain the number of bytes actually read. |
| // See also readn() from Stevens (2004) or Kerrisk (2010) |
| Status BlockingRecv(uint8_t *buf, size_t amt, size_t *nread, const MonoTime& deadline); |
| |
| // Enable TCP keepalive for the underlying socket. A TCP keepalive probe will be sent |
| // to the remote end after the connection has been idle for 'idle_time_s' seconds. |
| // It will retry sending probes up to 'num_retries' number of times until an ACK is |
| // heard from peer. 'retry_time_s' is the sleep time in seconds between successive |
| // keepalive probes. |
| Status SetTcpKeepAlive(int idle_time_s, int retry_time_s, int num_retries); |
| |
| private: |
| // Called internally from SetSend/RecvTimeout(). |
| Status SetTimeout(int opt, const char* optname, const MonoDelta& timeout); |
| |
| // Called internally during socket setup. |
| Status SetCloseOnExec(); |
| |
| // Bind the socket to a local address before making an outbound connection, |
| // based on the value of FLAGS_local_ip_for_outbound_sockets. |
| Status BindForOutgoingConnection(); |
| |
| // Set an option on the socket. |
| template<typename T> |
| Status SetSockOpt(int level, int option, const T& value); |
| |
| int fd_; |
| |
| DISALLOW_COPY_AND_ASSIGN(Socket); |
| }; |
| |
| } // namespace kudu |
| |
| #endif |