ftpiiu_plugin/include/socket.h

187 lines
4.7 KiB
C
Raw Normal View History

2020-04-05 21:16:16 +02:00
// ftpd is a server implementation based on the following:
// - RFC 959 (https://tools.ietf.org/html/rfc959)
// - RFC 3659 (https://tools.ietf.org/html/rfc3659)
// - suggested implementation details from https://cr.yp.to/ftp/filesystem.html
//
// Copyright (C) 2020 Michael Theall
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include "ioBuffer.h"
#include "sockAddr.h"
#include <chrono>
#include <memory>
2020-04-17 22:32:39 +02:00
#ifdef NDS
struct pollfd
{
int fd;
int events;
int revents;
};
using socklen_t = int;
using nfds_t = unsigned int;
extern "C" int poll (struct pollfd *fds_, nfds_t nfds_, int timeout_);
#define POLLIN (1 << 0)
#define POLLPRI (1 << 1)
#define POLLOUT (1 << 2)
#define POLLERR (1 << 3)
#define POLLHUP (1 << 4)
#else
#include <poll.h>
#endif
2020-04-05 21:16:16 +02:00
class Socket;
using UniqueSocket = std::unique_ptr<Socket>;
using SharedSocket = std::shared_ptr<Socket>;
2020-04-06 07:36:03 +02:00
/// \brief Socket object
2020-04-05 21:16:16 +02:00
class Socket
{
public:
2020-04-06 07:36:03 +02:00
/// \brief Poll info
2020-04-05 21:16:16 +02:00
struct PollInfo
{
2020-04-06 07:36:03 +02:00
/// \brief Socket to poll
2020-04-05 21:16:16 +02:00
std::reference_wrapper<Socket> socket;
2020-04-06 07:36:03 +02:00
/// \brief Input events
2020-04-05 21:16:16 +02:00
int events;
2020-04-06 07:36:03 +02:00
/// \brief Output events
2020-04-05 21:16:16 +02:00
int revents;
};
~Socket ();
2020-04-06 07:36:03 +02:00
/// \brief Accept connection
2020-04-05 21:16:16 +02:00
UniqueSocket accept ();
2020-04-06 07:36:03 +02:00
/// \brief Whether socket is at out-of-band mark
2020-04-05 21:16:16 +02:00
int atMark ();
2020-04-06 07:36:03 +02:00
/// \brief Bind socket to address
/// \param addr_ Address to bind
2020-04-05 21:16:16 +02:00
bool bind (SockAddr const &addr_);
2020-04-06 07:36:03 +02:00
/// \brief Connect to a peer
/// \param addr_ Peer address
2020-04-05 21:16:16 +02:00
bool connect (SockAddr const &addr_);
2020-04-06 07:36:03 +02:00
/// \brief Listen for connections
/// \param backlog_ Queue size for incoming connections
2020-04-05 21:16:16 +02:00
bool listen (int backlog_);
2020-04-06 07:36:03 +02:00
/// \brief Shutdown socket
/// \param how_ Type of shutdown (\sa ::shutdown)
2020-04-05 21:16:16 +02:00
bool shutdown (int how_);
2020-04-06 07:36:03 +02:00
/// \brief Set linger option
/// \param enable_ Whether to enable linger
/// \param time_ Linger timeout
2020-04-05 21:16:16 +02:00
bool setLinger (bool enable_, std::chrono::seconds time_);
2020-04-06 07:36:03 +02:00
/// \brief Set non-blocking
/// \param nonBlocking_ Whether to set non-blocking
2020-04-05 21:16:16 +02:00
bool setNonBlocking (bool nonBlocking_ = true);
2020-04-06 07:36:03 +02:00
/// \brief Set reuse address in subsequent bind
/// \param reuse_ Whether to reuse address
2020-04-05 21:16:16 +02:00
bool setReuseAddress (bool reuse_ = true);
2020-04-06 07:36:03 +02:00
/// \brief Set recv buffer size
/// \param size_ Buffer size
2020-04-05 21:16:16 +02:00
bool setRecvBufferSize (std::size_t size_);
2020-04-06 07:36:03 +02:00
/// \brief Set send buffer size
/// \param size_ Buffer size
2020-04-05 21:16:16 +02:00
bool setSendBufferSize (std::size_t size_);
2020-04-06 07:36:03 +02:00
/// \brief Read data
/// \param buffer_ Output buffer
/// \param size_ Size to read
/// \param oob_ Whether to read from out-of-band
2020-05-19 03:45:46 +02:00
std::make_signed_t<std::size_t> read (void *buffer_, std::size_t size_, bool oob_ = false);
2020-04-06 07:36:03 +02:00
/// \brief Read data
/// \param buffer_ Output buffer
/// \param oob_ Whether to read from out-of-band
2020-05-19 03:45:46 +02:00
std::make_signed_t<std::size_t> read (IOBuffer &buffer_, bool oob_ = false);
2020-04-06 07:36:03 +02:00
/// \brief Write data
/// \param buffer_ Input buffer
/// \param size_ Size to write
2020-05-19 03:45:46 +02:00
std::make_signed_t<std::size_t> write (void const *buffer_, std::size_t size_);
2020-04-06 07:36:03 +02:00
/// \brief Write data
/// \param buffer_ Input buffer
/// \param size_ Size to write
2020-05-19 03:45:46 +02:00
std::make_signed_t<std::size_t> write (IOBuffer &buffer_);
2020-04-05 21:16:16 +02:00
2020-04-06 07:36:03 +02:00
/// \brief Local name
2020-04-05 21:16:16 +02:00
SockAddr const &sockName () const;
2020-04-06 07:36:03 +02:00
/// \brief Peer name
2020-04-05 21:16:16 +02:00
SockAddr const &peerName () const;
2020-04-06 07:36:03 +02:00
/// \brief Create socket
2020-04-05 21:16:16 +02:00
static UniqueSocket create ();
2020-04-06 07:36:03 +02:00
/// \brief Poll sockets
/// \param info_ Poll info
/// \param count_ Number of poll entries
/// \param timeout_ Poll timeout
2020-04-05 21:16:16 +02:00
static int poll (PollInfo *info_, std::size_t count_, std::chrono::milliseconds timeout_);
private:
Socket () = delete;
2020-04-06 07:36:03 +02:00
/// \brief Parameterized constructor
/// \param fd_ Socket fd
2020-04-05 21:16:16 +02:00
Socket (int fd_);
2020-04-06 07:36:03 +02:00
/// \brief Parameterized constructor
/// \param fd_ Socket fd
/// \param sockName_ Local name
/// \param peerName_ Peer name
2020-04-05 21:16:16 +02:00
Socket (int fd_, SockAddr const &sockName_, SockAddr const &peerName_);
Socket (Socket const &that_) = delete;
Socket (Socket &&that_) = delete;
Socket &operator= (Socket const &that_) = delete;
Socket &operator= (Socket &&that_) = delete;
2020-04-06 07:36:03 +02:00
/// \param Local name
2020-04-05 21:16:16 +02:00
SockAddr m_sockName;
2020-04-06 07:36:03 +02:00
/// \param Peer name
2020-04-05 21:16:16 +02:00
SockAddr m_peerName;
2020-04-06 07:36:03 +02:00
/// \param Socket fd
2020-04-05 21:16:16 +02:00
int const m_fd;
2020-04-06 07:36:03 +02:00
/// \param Whether listening
2020-04-05 21:16:16 +02:00
bool m_listening : 1;
2020-04-06 07:36:03 +02:00
/// \param Whether connected
2020-04-05 21:16:16 +02:00
bool m_connected : 1;
};