40 # include <netinet/in.h>
41 # include <netinet/tcp.h>
43 # include <sys/wait.h>
52 #include <sys/types.h>
61 #define LISTEN_BACKLOG 5
77 for (
auto&& r :
Resolver(host, port, AI_PASSIVE)) {
79 int fd = socket(r.ai_family, socktype, r.ai_protocol);
83 #if !defined __WIN32__ && defined F_SETFD && defined FD_CLOEXEC
88 (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
96 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
97 reinterpret_cast<char*
>(&on),
135 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
136 reinterpret_cast<char*
>(&on),
145 if (::bind(fd, r.ai_addr, r.ai_addrlen) == 0) {
164 if (bind_errno == WSAEACCES) bind_errno = EADDRINUSE;
166 if (bind_errno == EADDRINUSE) {
168 cerr << host <<
':' << port <<
" already in use\n";
175 if (bind_errno == EACCES) {
176 cerr <<
"Can't bind to privileged port " << port <<
'\n';
188 if (listen_errno == EADDRINUSE) {
203 TcpServer::TcpServer(
const std::string& host,
212 TcpServer::accept_connection()
229 FD_SET(listener, &fds);
230 if (select(listener + 1, &fds,
nullptr,
nullptr,
nullptr) > 0) {
237 while (waitpid(-1, &status, WNOHANG) > 0) {
238 if (
verbose) cout <<
"Connection closed.\n";
243 struct sockaddr_storage client_address;
244 SOCKLEN_T client_address_size =
sizeof(client_address);
245 int connection = accept(listener,
246 reinterpret_cast<sockaddr*
>(&client_address),
247 &client_address_size);
249 if (connection < 0) {
252 if (accept_errno == WSAEINTR) {
264 cout << host <<
':' << port <<
" connected\n";
266 cout <<
"Unknown host connected\n";
273 TcpServer::~TcpServer()
286 signal(SIGTERM, SIG_DFL);
303 signal(SIGTERM, sigterm_handler);
307 int connected_socket = accept_connection();
313 handle_one_connection(connected_socket);
314 close(connected_socket);
322 int fork_errno = errno;
323 close(connected_socket);
327 close(connected_socket);
331 cerr <<
"Caught unknown exception\n";
336 #elif defined __WIN32__
344 static const int* pShutdownSocket = NULL;
348 CtrlHandler(DWORD fdwCtrlType)
350 switch (fdwCtrlType) {
352 case CTRL_CLOSE_EVENT:
356 case CTRL_LOGOFF_EVENT:
357 case CTRL_SHUTDOWN_EVENT:
361 cout <<
"Shutting down...\n";
363 case CTRL_BREAK_EVENT:
367 cout <<
"Ctrl+Break: aborting process\n";
370 cerr <<
"unexpected CtrlHandler: " << fdwCtrlType <<
'\n';
377 if (!pShutdownSocket || closesocket(*pShutdownSocket) == SOCKET_ERROR) {
383 pShutdownSocket = NULL;
390 thread_param(TcpServer* s,
int c) : server(s), connected_socket(c) {}
392 int connected_socket;
396 static unsigned __stdcall
397 run_thread(
void* param_)
399 thread_param* param(
reinterpret_cast<thread_param*
>(param_));
400 int socket = param->connected_socket;
402 TcpServer* tcp_server = param->server;
403 tcp_server->handle_one_connection(socket);
406 if (tcp_server->get_verbose()) cout <<
"Connection closed.\n";
421 pShutdownSocket = &listener;
422 if (!::SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE))
427 int connected_socket = accept_connection();
428 if (connected_socket == -1)
435 thread_param* param =
new thread_param(
this, connected_socket);
436 HANDLE hthread = (HANDLE)_beginthreadex(NULL, 0, ::run_thread,
441 closesocket(connected_socket);
449 CloseHandle(hthread);
453 cerr <<
"Caught unknown exception\n";
459 # error Neither HAVE_FORK nor __WIN32__ are defined.
463 TcpServer::run_once()
466 int fd = accept_connection();
467 handle_one_connection(fd);
All exceptions thrown by Xapian are subclasses of Xapian::Error.
std::string get_description() const
Return a string describing this object.
Indicates a problem communicating with a remote database.
Hierarchy of classes which Xapian can throw as exceptions.
Resolve hostnames and ip addresses.
include <fcntl.h>, but working around broken platforms.
include <netdb.h>, with portability workarounds.
include <sysexits.h> with portability workarounds.
include <sys/select.h> with portability workarounds.
include <sys/socket.h> with portability workarounds.
<unistd.h>, but with compat.
int pretty_ip6(const void *p, char *buf)
Socket handling utilities.
constexpr size_t PRETTY_IP6_LEN
static int create_listener(const std::string &host, int port, bool tcp_nodelay)
Create a listening socket ready to accept connections.
Generic TCP/IP socket based server base class.