#include "Socket.h"
namespace HttpServer
{
int Socket::Startup()
{
#ifdef WIN32
unsigned short version = MAKEWORD(2, 2);
::WSADATA wsaData = {0};
return ::WSAStartup(version, &wsaData);
#elif POSIX
return 0;
#else
#error "Undefine platform"
#endif
}
int Socket::Cleanup()
{
#ifdef WIN32
return ::WSACleanup();
#elif POSIX
return 0;
#else
#error "Undefine platform"
#endif
}
Socket::Socket(): socket_handle(~0)
{
}
Socket::Socket(const System::native_socket_type handle) : socket_handle(handle)
{
}
Socket::Socket(const Socket &obj) : socket_handle(obj.socket_handle)
{
}
Socket::Socket(Socket &&that) : socket_handle(that.socket_handle)
{
that.socket_handle = ~0;
}
System::native_socket_type Socket::open()
{
close();
socket_handle = ::socket(AF_INET, SOCK_STREAM, 0);
return socket_handle;
}
int Socket::close()
{
if (is_open() )
{
#ifdef WIN32
int result = ::closesocket(socket_handle);
#elif POSIX
int result = ::close(socket_handle);
#else
#error "Undefine platform"
#endif
if (0 == result)
{
socket_handle = ~0;
}
return result;
}
return ~0;
}
int Socket::bind(const int port) const
{
::sockaddr_in sock_addr = {0};
sock_addr.sin_family = AF_INET;
sock_addr.sin_port = htons(port);
sock_addr.sin_addr.s_addr = ::htonl(INADDR_ANY);
return ::bind(socket_handle, reinterpret_cast(&sock_addr), sizeof(sockaddr_in) );
}
int Socket::listen() const
{
return ::listen(socket_handle, SOMAXCONN);
}
Socket Socket::accept() const
{
#ifdef WIN32
System::native_socket_type client_socket = ::accept(socket_handle, static_cast(nullptr), static_cast(nullptr) );
#elif POSIX
System::native_socket_type client_socket = ::accept(socket_handle, static_cast(nullptr), static_cast(nullptr) );
#else
#error "Undefine platform"
#endif
return Socket(client_socket);
}
Socket Socket::nonblock_accept() const
{
System::native_socket_type client_socket = ~0;
#ifdef WIN32
WSAPOLLFD event = {0};
event.fd = socket_handle;
event.events = POLLRDNORM;
if (1 == ::WSAPoll(&event, 1, ~0) && event.revents | POLLRDNORM)
{
client_socket = ::accept(socket_handle, static_cast(nullptr), static_cast(nullptr) );
}
#elif POSIX
struct ::pollfd event = {0};
event.fd = socket_handle;
event.events = POLLIN;
if (1 == ::poll(&event, 1, ~0) && event.revents | POLLIN)
{
client_socket = ::accept(socket_handle, static_cast(nullptr), static_cast(nullptr) );
}
#else
#error "Undefine platform"
#endif
return Socket(client_socket);
}
Socket Socket::nonblock_accept(const std::chrono::milliseconds &timeWait) const
{
System::native_socket_type client_socket = ~0;
#ifdef WIN32
WSAPOLLFD event = {0};
event.fd = socket_handle;
event.events = POLLRDNORM;
if (1 == ::WSAPoll(&event, 1, timeWait.count() ) && event.revents | POLLRDNORM)
{
client_socket = ::accept(socket_handle, static_cast(nullptr), static_cast(nullptr) );
}
#elif POSIX
struct ::pollfd event = {0};
event.fd = socket_handle;
event.events = POLLIN;
if (1 == ::poll(&event, 1, timeWait.count() ) && event.revents | POLLIN)
{
client_socket = ::accept(socket_handle, static_cast(nullptr), static_cast(nullptr) );
}
#else
#error "Undefine platform"
#endif
return Socket(client_socket);
}
int Socket::shutdown() const
{
if (is_open() )
{
#ifdef WIN32
return ::shutdown(socket_handle, SD_BOTH);
#elif POSIX
return ::shutdown(socket_handle, SHUT_RDWR);
#else
#error "Undefine platform"
#endif
}
return -1;
}
bool Socket::nonblock(const bool isNonBlock) const
{
#ifdef WIN32
unsigned long value = isNonBlock;
return 0 == ::ioctlsocket(socket_handle, FIONBIO, &value);
#elif POSIX
return -1 != ::fcntl(socket_handle, F_SETFL, isNonBlock ? O_NONBLOCK : O_SYNC);
#else
#error "Undefine platform"
#endif
}
/* bool Socket::is_nonblock() const
{
#ifdef WIN32
#elif POSIX
int flags = ::fcntl(socket_handle, F_GETFL, 0);
return (flags != -1) && (flags & O_NONBLOCK);
#else
#error "Undefine platform"
#endif
}*/
size_t Socket::recv(std::vector &buf) const
{
#ifdef WIN32
return ::recv(socket_handle, buf.data(), buf.size(), 0);
#elif POSIX
return ::recv(socket_handle, buf.data(), buf.size(), MSG_NOSIGNAL);
#else
#error "Undefine platform"
#endif
}
size_t Socket::nonblock_recv(std::vector &buf, const std::chrono::milliseconds &timeWait) const
{
size_t recv_len = ~0;
#ifdef WIN32
WSAPOLLFD event = {0};
event.fd = socket_handle;
event.events = POLLRDNORM;
if (1 == ::WSAPoll(&event, 1, timeWait.count() ) && event.revents | POLLRDNORM)
{
recv_len = ::recv(socket_handle, buf.data(), buf.size(), 0);
}
#elif POSIX
struct ::pollfd event = {0};
event.fd = socket_handle;
event.events = POLLIN;
if (1 == ::poll(&event, 1, timeWait.count() ) && event.revents | POLLIN)
{
recv_len = ::recv(socket_handle, buf.data(), buf.size(), MSG_NOSIGNAL);
}
#else
#error "Undefine platform"
#endif
return recv_len;
}
size_t Socket::send(const std::string &buf) const
{
#ifdef WIN32
return ::send(socket_handle, buf.data(), buf.length(), 0);
#elif POSIX
return ::send(socket_handle, buf.data(), buf.length(), MSG_WAITALL | MSG_NOSIGNAL);
#else
#error "Undefine platform"
#endif
}
size_t Socket::send(const std::vector &buf, const size_t length) const
{
#ifdef WIN32
return ::send(socket_handle, buf.data(), length, 0);
#elif POSIX
return ::send(socket_handle, buf.data(), length, MSG_WAITALL | MSG_NOSIGNAL);
#else
#error "Undefine platform"
#endif
}
size_t Socket::nonblock_send(const std::string &buf, const std::chrono::milliseconds &timeWait) const
{
size_t send_len = ~0;
#ifdef WIN32
WSAPOLLFD event = {0};
event.fd = socket_handle;
event.events = POLLWRNORM;
if (1 == ::WSAPoll(&event, 1, timeWait.count() ) && event.revents | POLLWRNORM)
{
send_len = ::send(socket_handle, buf.data(), buf.length(), 0);
}
#elif POSIX
struct ::pollfd event = {0};
event.fd = socket_handle;
event.events = POLLOUT;
if (1 == ::poll(&event, 1, timeWait.count() ) && event.revents | POLLOUT)
{
send_len = ::send(socket_handle, buf.data(), buf.length(), MSG_NOSIGNAL);
}
#else
#error "Undefine platform"
#endif
return send_len;
}
size_t Socket::nonblock_send(const std::vector &buf, const size_t length, const std::chrono::milliseconds &timeWait) const
{
size_t send_len = ~0;
#ifdef WIN32
WSAPOLLFD event = {0};
event.fd = socket_handle;
event.events = POLLWRNORM;
if (1 == ::WSAPoll(&event, 1, timeWait.count() ) && event.revents | POLLWRNORM)
{
send_len = ::send(socket_handle, buf.data(), length, 0);
}
#elif POSIX
struct ::pollfd event = {0};
event.fd = socket_handle;
event.events = POLLOUT;
if (1 == ::poll(&event, 1, timeWait.count() ) && event.revents | POLLOUT)
{
send_len = ::send(socket_handle, buf.data(), length, MSG_WAITALL | MSG_NOSIGNAL);
}
#else
#error "Undefine platform"
#endif
return send_len;
}
Socket &Socket::operator=(const Socket s)
{
socket_handle = s.socket_handle;
return *this;
}
};