38 #include <system_error> 60 int err = (
listen_fd_ = socket(AF_INET, SOCK_STREAM, 0));
63 throw std::system_error(std::error_code(errno, std::generic_category()),
"Failed to create socket endpoint");
66 setsockopt(
listen_fd_, SOL_SOCKET, SO_REUSEADDR, &flag,
sizeof(
int));
67 setsockopt(
listen_fd_, SOL_SOCKET, SO_KEEPALIVE, &flag,
sizeof(
int));
77 throw std::system_error(std::error_code(errno, std::generic_category()),
"Error creating self-pipe");
87 throw std::system_error(std::error_code(errno, std::generic_category()),
"fcntl-F_GETFL");
90 if (fcntl(
self_pipe_[0], F_SETFL, flags) == -1)
92 throw std::system_error(std::error_code(errno, std::generic_category()),
"fcntl-F_SETFL");
98 throw std::system_error(std::error_code(errno, std::generic_category()),
"fcntl-F_GETFL");
101 if (fcntl(
self_pipe_[1], F_SETFL, flags) == -1)
103 throw std::system_error(std::error_code(errno, std::generic_category()),
"fcntl-F_SETFL");
115 throw std::system_error(std::error_code(errno, std::generic_category()),
"Writing to self-pipe failed.");
128 struct sockaddr_in server_addr;
129 server_addr.sin_family = AF_INET;
132 server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
133 server_addr.sin_port = htons(
port_);
134 int err =
::bind(
listen_fd_, (
struct sockaddr*)&server_addr,
sizeof(server_addr));
137 std::ostringstream ss;
138 ss <<
"Failed to bind socket for port " <<
port_ <<
" to address. Reason: " << strerror(errno);
139 throw std::system_error(std::error_code(errno, std::generic_category()), ss.str());
152 std::ostringstream ss;
153 ss <<
"Failed to start listen on port " <<
port_;
154 throw std::system_error(std::error_code(errno, std::generic_category()), ss.str());
161 struct sockaddr_storage client_addr;
162 socklen_t addrlen =
sizeof(client_addr);
163 int client_fd = accept(
listen_fd_, (
struct sockaddr*)&client_addr, &addrlen);
166 std::ostringstream ss;
167 ss <<
"Failed to accept connection request on port " <<
port_;
168 throw std::system_error(std::error_code(errno, std::generic_category()), ss.str());
186 URCL_LOG_WARN(
"Connection attempt on port %d while maximum number of clients (%d) is already connected. Closing " 201 URCL_LOG_ERROR(
"select() failed. Shutting down socket event handler.");
229 for (
int i = 0; i <=
maxfd_; i++)
282 if (errno == ECONNRESET)
284 URCL_LOG_DEBUG(
"client from FD %s sent a connection reset package.", fd);
314 bool TCPServer::write(
const int fd,
const uint8_t* buf,
const size_t buf_len,
size_t& written)
318 size_t remaining = buf_len;
321 while (written < buf_len)
323 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(...)
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, char *buffer)> message_callback_
std::function< void(const int)> new_connection_callback_