39 #include <system_error> 61 int err = (
listen_fd_ = socket(AF_INET, SOCK_STREAM, 0));
64 throw std::system_error(std::error_code(errno, std::generic_category()),
"Failed to create socket endpoint");
67 setsockopt(
listen_fd_, SOL_SOCKET, SO_REUSEADDR, &flag,
sizeof(
int));
68 setsockopt(
listen_fd_, SOL_SOCKET, SO_KEEPALIVE, &flag,
sizeof(
int));
78 throw std::system_error(std::error_code(errno, std::generic_category()),
"Error creating self-pipe");
88 throw std::system_error(std::error_code(errno, std::generic_category()),
"fcntl-F_GETFL");
91 if (fcntl(
self_pipe_[0], F_SETFL, flags) == -1)
93 throw std::system_error(std::error_code(errno, std::generic_category()),
"fcntl-F_SETFL");
99 throw std::system_error(std::error_code(errno, std::generic_category()),
"fcntl-F_GETFL");
102 if (fcntl(
self_pipe_[1], F_SETFL, flags) == -1)
104 throw std::system_error(std::error_code(errno, std::generic_category()),
"fcntl-F_SETFL");
116 throw std::system_error(std::error_code(errno, std::generic_category()),
"Writing to self-pipe failed.");
129 struct sockaddr_in server_addr;
130 server_addr.sin_family = AF_INET;
133 server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
134 server_addr.sin_port = htons(
port_);
135 int err =
::bind(
listen_fd_, (
struct sockaddr*)&server_addr,
sizeof(server_addr));
138 std::ostringstream ss;
139 ss <<
"Failed to bind socket for port " <<
port_ <<
" to address. Reason: " << strerror(errno);
140 throw std::system_error(std::error_code(errno, std::generic_category()), ss.str());
153 std::ostringstream ss;
154 ss <<
"Failed to start listen on port " <<
port_;
155 throw std::system_error(std::error_code(errno, std::generic_category()), ss.str());
162 struct sockaddr_storage client_addr;
163 socklen_t addrlen =
sizeof(client_addr);
164 int client_fd = accept(
listen_fd_, (
struct sockaddr*)&client_addr, &addrlen);
167 std::ostringstream ss;
168 ss <<
"Failed to accept connection request on port " <<
port_;
169 throw std::system_error(std::error_code(errno, std::generic_category()), ss.str());
187 URCL_LOG_WARN(
"Connection attempt on port %d while maximum number of clients (%d) is already connected. Closing " 202 URCL_LOG_ERROR(
"select() failed. Shutting down socket event handler.");
230 for (
int i = 0; i <=
maxfd_; i++)
283 if (errno == ECONNRESET)
285 URCL_LOG_DEBUG(
"client from FD %s sent a connection reset package.", fd);
315 bool TCPServer::write(
const int fd,
const uint8_t* buf,
const size_t buf_len,
size_t& written)
319 size_t remaining = buf_len;
322 while (written < buf_len)
324 ssize_t sent = ::send(fd, buf + written, remaining, 0);
#define URCL_LOG_ERROR(...)
std::thread worker_thread_
std::vector< int > client_fds_
void spin()
Event handler. Blocks until activity on any client or connection attempt.
std::atomic< int > listen_fd_
void start()
Start event handling.
void handleDisconnect(const int fd)
void readData(const int fd)
read data from socket
void shutdown()
Shut down the event listener thread. After calling this, no events will be handled anymore...
char input_buffer_[INPUT_BUFFER_SIZE]
std::function< void(const int)> disconnect_callback_
std::atomic< bool > keep_running_
void worker()
Runs spin() as long as keep_running_ is set to true.
uint32_t max_clients_allowed_
#define URCL_LOG_DEBUG(...)
std::function< void(const int, char *buffer, int nbytesrecv)> message_callback_
bool write(const int fd, const uint8_t *buf, const size_t buf_len, size_t &written)
Writes to a client.
#define URCL_LOG_WARN(...)
static const int INPUT_BUFFER_SIZE
void handleConnect()
Handles connection events.
std::function< void(const int)> new_connection_callback_