Mercurial > code
view C++/modules/Socket/Socket.cpp @ 390:d7e6d7d1e102
Socket: get rid of SocketState
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 03 Jul 2015 13:02:05 +0200 |
parents | 743b3a1c71c8 |
children | d5ec1174b707 |
line wrap: on
line source
/* * Socket.cpp -- portable C++ socket wrappers * * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <cstring> #include "Socket.h" #include "SocketAddress.h" /* -------------------------------------------------------- * System dependent code * -------------------------------------------------------- */ #if defined(_WIN32) const SocketAbstract::Handle SocketAbstract::Invalid{INVALID_SOCKET}; const int SocketAbstract::Error{SOCKET_ERROR}; #else const int SocketAbstract::Invalid{-1}; const int SocketAbstract::Error{-1}; #endif #if defined(_WIN32) std::string SocketAbstract::syserror(int errn) { LPSTR str = nullptr; std::string errmsg = "Unknown error"; FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errn, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&str, 0, NULL); if (str) { errmsg = std::string(str); LocalFree(str); } return errmsg; } #else std::string SocketAbstract::syserror(int errn) { return strerror(errn); } #endif std::string SocketAbstract::syserror() { #if defined(_WIN32) return syserror(WSAGetLastError()); #else return syserror(errno); #endif } /* -------------------------------------------------------- * SocketError class * -------------------------------------------------------- */ SocketError::SocketError(Code code, std::string function) : m_code{code} , m_function{std::move(function)} , m_error{SocketAbstract::syserror()} { } SocketError::SocketError(Code code, std::string function, int error) : m_code{code} , m_function{std::move(function)} , m_error{SocketAbstract::syserror(error)} { } SocketError::SocketError(Code code, std::string function, std::string error) : m_code{code} , m_function{std::move(function)} , m_error{std::move(error)} { } /* -------------------------------------------------------- * SocketAbstract class * -------------------------------------------------------- */ #if defined(_WIN32) std::mutex SocketAbstract::s_mutex; std::atomic<bool> SocketAbstract::s_initialized{false}; #endif SocketAbstract::SocketAbstract(int domain, int type, int protocol) { #if defined(_WIN32) && !defined(SOCKET_NO_WSA_INIT) if (!s_initialized) { initialize(); } #endif m_handle = ::socket(domain, type, protocol); if (m_handle == Invalid) { throw SocketError{SocketError::System, "socket"}; } } SocketAbstract::SocketAbstract(SocketAbstract &&other) noexcept { m_handle = other.m_handle; // Invalidate other other.m_handle = -1; } SocketAbstract::~SocketAbstract() { close(); } void SocketAbstract::close() { if (m_handle != Invalid) { #if defined(_WIN32) ::closesocket(m_handle); #else ::close(m_handle); #endif m_handle = Invalid; } } void SocketAbstract::setBlockMode(bool block) { #if defined(O_NONBLOCK) && !defined(_WIN32) int flags; if ((flags = fcntl(m_handle, F_GETFL, 0)) == -1) { flags = 0; } if (block) { flags &= ~(O_NONBLOCK); } else { flags |= O_NONBLOCK; } if (fcntl(m_handle, F_SETFL, flags) == Error) { throw SocketError{SocketError::System, "setBlockMode"}; } #else unsigned long flags = (block) ? 0 : 1; if (ioctlsocket(m_handle, FIONBIO, &flags) == Error) { throw SocketError{SocketError::System, "setBlockMode"}; } #endif } SocketAbstract &SocketAbstract::operator=(SocketAbstract &&other) noexcept { m_handle = other.m_handle; // Invalidate other other.m_handle = Invalid; return *this; } bool operator==(const SocketAbstract &s1, const SocketAbstract &s2) { return s1.handle() == s2.handle(); } bool operator!=(const SocketAbstract &s1, const SocketAbstract &s2) { return s1.handle() != s2.handle(); } bool operator<(const SocketAbstract &s1, const SocketAbstract &s2) { return s1.handle() < s2.handle(); } bool operator>(const SocketAbstract &s1, const SocketAbstract &s2) { return s1.handle() > s2.handle(); } bool operator<=(const SocketAbstract &s1, const SocketAbstract &s2) { return s1.handle() <= s2.handle(); } bool operator>=(const SocketAbstract &s1, const SocketAbstract &s2) { return s1.handle() >= s2.handle(); }