blob: 830a389e92f7d6768d8765b561f4c2a6f69c6c23 [file] [log] [blame]
// 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