39#include "blocxx/BLOCXX_config.h"
52#if !defined(BLOCXX_WIN32)
55#include <sys/socket.h>
57#include <netinet/in.h>
63#define INVALID_SOCKET -1
77#if defined(BLOCXX_WIN32)
79 , m_shuttingDown(false)
81 m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
96#if defined(BLOCXX_WIN32)
98 , m_shuttingDown(false)
100 m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
120#if defined(BLOCXX_WIN32)
121 ::CloseHandle(m_event);
129#if defined(BLOCXX_WIN32)
134 st.networkevents = FD_ACCEPT;
144 int queueSize,
const String& listenAddr,
148 doListen(port, queueSize,listenAddr, reuseAddr);
151#if defined(BLOCXX_WIN32)
155 int queueSize,
const String& listenAddr,
162#ifdef BLOCXX_HAVE_IPV6
165 sock_ipv6 = ::socket(AF_INET6, SOCK_STREAM, 0);
170 case EPROTONOSUPPORT:
174 m_sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
185 m_sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
189 BLOCXX_THROW(SocketException, Format(
"ServerSocketImpl: %1",
193 unsigned long cmdArg = 1;
194 if (::ioctlsocket(
m_sockfd, FIONBIO, &cmdArg) == SOCKET_ERROR)
196 BLOCXX_THROW(SocketException, Format(
"ServerSocketImpl: %1",
203 ::setsockopt(
m_sockfd, SOL_SOCKET, SO_REUSEADDR,
204 (
const char*)&reuse,
sizeof(reuse));
212#ifdef BLOCXX_HAVE_IPV6
216 ServerSocketImpl::doListenIPv6( port, queueSize, listenAddr, reuseAddr);
226 memset(&inetAddr, 0,
sizeof(inetAddr));
227 reinterpret_cast<sockaddr_in*
>(&inetAddr)->sin_family = AF_INET;
228 reinterpret_cast<sockaddr_in*
>(&inetAddr)->sin_port =
hton16(port);
231 reinterpret_cast<sockaddr_in*
>(&inetAddr)->sin_addr.s_addr =
hton32(INADDR_ANY);
236 reinterpret_cast<sockaddr_in*
>(&inetAddr)->sin_addr.s_addr =
237 reinterpret_cast<const sockaddr_in*
>(addr.getInetAddress())->sin_addr.s_addr;
239 if (::bind(
m_sockfd,
reinterpret_cast<sockaddr*
>(&inetAddr),
sizeof(inetAddr)) == -1)
242 BLOCXX_THROW(SocketException, Format(
"ServerSocketImpl: %1",
245 if (::listen(
m_sockfd, queueSize) == -1)
248 BLOCXX_THROW(SocketException, Format(
"ServerSocketImpl: %1",
255#ifdef BLOCXX_HAVE_IPV6
257ServerSocketImpl::doListenIPv6(UInt16 port,
int queueSize,
const String& listenAddr)
261 memset(&inetAddr, 0,
sizeof(inetAddr));
262 reinterpret_cast<sockaddr_in6*
>(&inetAddr)->sin6_family = AF_INET6;
263 reinterpret_cast<sockaddr_in6*
>(&inetAddr)->sin6_port =
hton16(port);
267 memcpy(
reinterpret_cast<sockaddr_in6*
>(&inetAddr)->sin6_addr.s6_addr, &in6addr_any,
sizeof(
struct in6_addr));
272 if(!inet_pton(AF_INET6, listenAddr.c_str(), (
void*)&
reinterpret_cast<sockaddr_in6*
>(&inetAddr)->sin6_addr))
276 memset(&hints, 0,
sizeof(hints));
277 hints.ai_socktype = SOCK_STREAM;
278 hints.ai_family = AF_INET6;
279 if(getaddrinfo(listenAddr.c_str(), NULL, &hints, &addrinfos))
282 BLOCXX_THROW(SocketException, Format(
"ServerSocketImpl:: doListen(): getaddrinfo() %1",
285 memcpy(
reinterpret_cast<sockaddr_in6*
>(&inetAddr), addrinfos->ai_addr, addrinfos->ai_addrlen);
286 freeaddrinfo(addrinfos);
289 if (::bind(
m_sockfd,
reinterpret_cast<sockaddr*
>(&inetAddr),
sizeof(inetAddr)) == -1)
292 BLOCXX_THROW(SocketException, Format(
"ServerSocketImpl: %1",
295 if (::listen(
m_sockfd, queueSize) == -1)
298 BLOCXX_THROW(SocketException, Format(
"ServerSocketImpl: %1",
310waitForAcceptIO(
SocketHandle_t fd, HANDLE eventArg,
const Timeout& timeOutSecs,
313 TimeoutTimer timer(timeOutSecs);
315 if (networkEvents != -1L)
317 if(::WSAEventSelect(fd, eventArg, networkEvents) != 0)
320 Format(
"WSAEventSelect failed in waitForAcceptIO: %1",
326 switch(::WaitForSingleObject(eventArg, timer.asDWORDMs()))
329 ::ResetEvent(eventArg);
353 BLOCXX_THROW(SocketException,
"ServerSocketImpl::accept: NONE");
357 if(::WSAEventSelect(
m_sockfd, m_event, FD_ACCEPT) != 0)
360 Format(
"WSAEventSelect failed in accept: %1",
372 clntlen =
sizeof(clntInetAddr);
374 reinterpret_cast<struct sockaddr*
>(&clntInetAddr), &clntlen);
381 if (::WSAGetLastError() != WSAEWOULDBLOCK)
383 BLOCXX_THROW(SocketException, Format(
"ServerSocketImpl: %1",
388 cc = waitForAcceptIO(
m_sockfd, m_event, timeoutSecs, FD_ACCEPT);
397 BLOCXX_THROW(SocketException,
"Error while waiting for network events");
399 BLOCXX_THROW(SocketException,
"Shutdown event was signaled");
401 BLOCXX_THROW(SocketTimeoutException,
"Timed out waiting for a connection");
406 if(::WSAEventSelect(clntfd, NULL, 0) != 0)
409 Format(
"WSAEventSelect failed in accept: %1",
414 unsigned long cmdArg = 0;
415 if (::ioctlsocket(clntfd, FIONBIO, &cmdArg) == SOCKET_ERROR)
417 BLOCXX_THROW(SocketException, Format(
"ServerSocketImpl: %1",
432 int queueSize,
const String& listenAddr,
439#ifdef BLOCXX_HAVE_IPV6
442 sock_ipv6 = ::socket(AF_INET6, SOCK_STREAM, 0);
447 case EPROTONOSUPPORT:
452 m_sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
462 int ipv6_proto = IPPROTO_IPV6;
467 ::setsockopt(
m_sockfd, ipv6_proto, IPV6_V6ONLY, &ipv6_only,
sizeof(ipv6_only));
471 m_sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
478 if (::fcntl(
m_sockfd, F_SETFD, FD_CLOEXEC) == -1)
482 "close-on-exec flag on listen socket");
486 int fdflags = ::fcntl(
m_sockfd, F_GETFL, 0);
487 ::fcntl(
m_sockfd, F_SETFL, fdflags | O_NONBLOCK);
499#if defined(BLOCXX_NCR)
500 ::setsockopt(
m_sockfd, SOL_SOCKET, SO_REUSEADDR, (
char*)&reuse,
sizeof(reuse));
502 ::setsockopt(
m_sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse,
sizeof(reuse));
510#ifdef BLOCXX_HAVE_IPV6
513 ServerSocketImpl::doListenIPv6( port, queueSize, listenAddr );
524 memset(&inetAddr, 0,
sizeof(inetAddr));
525 reinterpret_cast<sockaddr_in*
>(&inetAddr)->sin_family = AF_INET;
526 reinterpret_cast<sockaddr_in*
>(&inetAddr)->sin_port =
hton16(port);
529 reinterpret_cast<sockaddr_in*
>(&inetAddr)->sin_addr.s_addr =
hton32(INADDR_ANY);
534 reinterpret_cast<sockaddr_in*
>(&inetAddr)->sin_addr.s_addr =
535 reinterpret_cast<const sockaddr_in*
>(addr.
getInetAddress())->sin_addr.s_addr;
537 if (::bind(
m_sockfd,
reinterpret_cast<sockaddr*
>(&inetAddr),
sizeof(inetAddr)) == -1)
542 if (::listen(
m_sockfd, queueSize) == -1)
551#ifdef BLOCXX_HAVE_IPV6
554ServerSocketImpl::doListenIPv6(UInt16 port,
int queueSize,
const String& listenAddr)
558 memset(&inetAddr, 0,
sizeof(inetAddr));
559 reinterpret_cast<sockaddr_in6*
>(&inetAddr)->sin6_family = AF_INET6;
560 reinterpret_cast<sockaddr_in6*
>(&inetAddr)->sin6_port =
hton16(port);
564 memcpy(
reinterpret_cast<sockaddr_in6*
>(&inetAddr)->sin6_addr.s6_addr, &in6addr_any,
sizeof(
struct in6_addr));
569 if(!inet_pton(AF_INET6, listenAddr.
c_str(), (
void*)&
reinterpret_cast<sockaddr_in6*
>(&inetAddr)->sin6_addr))
573 memset(&hints, 0,
sizeof(hints));
574 hints.ai_socktype = SOCK_STREAM;
575 hints.ai_family = AF_INET6;
576 if(getaddrinfo(listenAddr.
c_str(), NULL, &hints, &addrinfos))
581 memcpy(
reinterpret_cast<sockaddr_in6*
>(&inetAddr), addrinfos->ai_addr, addrinfos->ai_addrlen);
582 freeaddrinfo(addrinfos);
585 if (::bind(
m_sockfd,
reinterpret_cast<sockaddr*
>(&inetAddr),
sizeof(inetAddr)) == -1)
590 if (::listen(
m_sockfd, queueSize) == -1)
605 m_sockfd = ::socket(PF_UNIX,SOCK_STREAM, 0);
611 if (::fcntl(
m_sockfd, F_SETFD, FD_CLOEXEC) == -1)
615 "close-on-exec flag on listen socket");
620 int fdflags = ::fcntl(
m_sockfd, F_GETFL, 0);
621 ::fcntl(
m_sockfd, F_SETFL, fdflags | O_NONBLOCK);
628#if defined(BLOCXX_NCR)
629 ::setsockopt(
m_sockfd, SOL_SOCKET, SO_REUSEADDR, (
char *)&reuse,
sizeof(reuse));
631 ::setsockopt(
m_sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse,
sizeof(reuse));
634 String lockfilename = filename +
".lock";
639 Format(
"ServerSocketImpl::doListen(): Unable to open or create Unix Domain Socket lock: %1",
640 lockfilename).c_str());
646 Format(
"ServerSocketImpl::doListen(): Unable to lock Unix Domain Socket: %1",
656 Format(
"ServerSocketImpl::doListen(): Unable to unlink Unix Domain Socket: %1",
661#if defined(BLOCXX_NCR)
672 if (::chmod(filename.
c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) == -1)
677 if (::listen(
m_sockfd, queueSize) == -1)
707 struct sockaddr_un clntUnixAddr;
708 struct sockaddr* pSA(0);
711 pSA =
reinterpret_cast<struct sockaddr*
>(&clntInetAddr);
712 clntlen =
sizeof(clntInetAddr);
716 pSA =
reinterpret_cast<struct sockaddr*
>(&clntUnixAddr);
717 clntlen =
sizeof(clntUnixAddr);
729 if (errno == EWOULDBLOCK
730 || errno == ECONNABORTED
737 "between select() and accept()");
748 int fdflags = ::fcntl(clntfd, F_GETFL, 0);
751 if ((fdflags & O_NONBLOCK) == O_NONBLOCK)
753 ::fcntl(clntfd, F_SETFL, fdflags ^ O_NONBLOCK);
781#if defined(BLOCXX_WIN32)
792 Format(
"ServerSocketImpl::close(): Unable to unlink Unix Domain Socket: %1",
797 String lockfilename = filename +
".lock";
801 Format(
"ServerSocketImpl::close(): Failed to unlock Unix Domain Socket: %1",
802 lockfilename).c_str());
808 Format(
"ServerSocketImpl::close(): Unable to unlink Unix Domain Socket lock: %1",
809 lockfilename).c_str());
825 struct sockaddr *p_addr;
827 memset(&ss, 0,
sizeof(ss));
829 p_addr =
reinterpret_cast<struct sockaddr*
>(&ss);
830 if (getsockname(
m_sockfd, p_addr, &len) == -1)
836#if !defined(BLOCXX_WIN32)
839 struct sockaddr_un addr;
840 memset(&addr, 0,
sizeof(addr));
842 if (getsockname(
m_sockfd,
reinterpret_cast<struct sockaddr*
>(&addr), &len) == -1)
#define BLOCXX_ASSERT(CON)
BLOCXX_ASSERT works similar to the assert() macro, but instead of calling abort(),...
#define BLOCXX_THROW(exType, msg)
Throw an exception using FILE and LINE.
#define BLOCXX_THROW_ERRNO_MSG(exType, msg)
Throw an exception using FILE, LINE, errno and strerror(errno)
int unlock()
Release a lock on the file.
int tryLock(ELockType type=E_WRITE_LOCK)
Acquire a kernel lock on the file.
int close()
Close the underlying file object.
void doListenIPv4(UInt16 port, int queueSize, const String &listenAddr)
void doListen(UInt16 port, SocketFlags::ESSLFlag isSSL, int queueSize=10, const String &listenAddr=SocketAddress::ALL_LOCAL_ADDRESSES, SocketFlags::EReuseAddrFlag reuseAddr=SocketFlags::E_REUSE_ADDR)
SocketAddress m_localAddress
SocketFlags::ESSLFlag m_isSSL
Socket accept(const Timeout &timeout)
void doListenUDS(const String &filename, int queueSize=10, bool reuseAddr=true)
Select_t getSelectObj() const
ServerSocketImpl(SSLServerCtxRef sslCtx)
void assignFromNativeForm(const UnixSocketAddress_t *address, size_t len)
AddressType getType() const
size_t getNativeFormSize() const
const SocketAddress_t * getNativeForm() const
const InetSocketAddress_t * getInetAddress() const
Get a pointer to the InetSocketAddress_t precondition: getType() == INET.
static SocketAddress allocEmptyAddress(AddressType type)
Allocate an empty SocketAddress.
static const char *const ALL_LOCAL_ADDRESSES
static SocketAddress getByName(const String &host, unsigned short port=0)
Do a DNS lookup on a hostname and return an SocketAddress for that host.
const String toString() const
Returns the IP address and the port with a colon in between.
static SocketAddress getUDS(const String &filename)
This String class is an abstract data type that represents as NULL terminated string of characters.
const char * c_str() const
static void testCancel()
Test if this thread has been cancelled.
A timeout can be absolute, which means that it will happen at the specified DateTime.
BLOCXX_COMMON_API bool exists(const String &path)
BLOCXX_COMMON_API bool removeFile(const String &path)
Remove the given file.
BLOCXX_COMMON_API File openOrCreateFile(const String &path)
Opens or creates the file for the given name.
int waitForIO(SocketHandle_t fd, int timeOutSecs, SocketFlags::EWaitDirectionFlag waitFlag)
Wait for input or output on a socket.
String lastErrorMsg(bool socketError)
sockaddr_in InetSocketAddress_t