comparison C++/modules/Socket/Socket.cpp @ 334:0b576ee64d45

* Create brand new hierarchy * Rename DynLib to Dynlib * Remove some warnings
author David Demelier <markand@malikania.fr>
date Sun, 08 Mar 2015 14:26:33 +0100
parents C++/Socket.cpp@cba77da58496
children 486767e1d165
comparison
equal deleted inserted replaced
333:412ca7a5e1ea 334:0b576ee64d45
1 /*
2 * Socket.cpp -- portable C++ socket wrappers
3 *
4 * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <cstring>
20
21 #include "Socket.h"
22 #include "SocketAddress.h"
23
24 /* --------------------------------------------------------
25 * System dependent code
26 * -------------------------------------------------------- */
27
28 #if defined(_WIN32)
29
30 std::string Socket::syserror(int errn)
31 {
32 LPSTR str = nullptr;
33 std::string errmsg = "Unknown error";
34
35 FormatMessageA(
36 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
37 NULL,
38 errn,
39 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
40 (LPSTR)&str, 0, NULL);
41
42
43 if (str) {
44 errmsg = std::string(str);
45 LocalFree(str);
46 }
47
48 return errmsg;
49 }
50
51 #else
52
53 #include <cerrno>
54
55 std::string Socket::syserror(int errn)
56 {
57 return strerror(errn);
58 }
59
60 #endif
61
62 std::string Socket::syserror()
63 {
64 #if defined(_WIN32)
65 return syserror(WSAGetLastError());
66 #else
67 return syserror(errno);
68 #endif
69 }
70
71 /* --------------------------------------------------------
72 * SocketError class
73 * -------------------------------------------------------- */
74
75 SocketError::SocketError(Code code, std::string function)
76 : m_code(code)
77 , m_function(std::move(function))
78 , m_error(Socket::syserror())
79 {
80 }
81
82 SocketError::SocketError(Code code, std::string function, int error)
83 : m_code(code)
84 , m_function(std::move(function))
85 , m_error(Socket::syserror(error))
86 {
87 }
88
89 SocketError::SocketError(Code code, std::string function, std::string error)
90 : m_code(code)
91 , m_function(std::move(function))
92 , m_error(std::move(error))
93 {
94 }
95
96 /* --------------------------------------------------------
97 * Socket class
98 * -------------------------------------------------------- */
99
100 #if defined(_WIN32)
101 std::mutex Socket::s_mutex;
102 std::atomic<bool> Socket::s_initialized{false};
103 #endif
104
105 Socket::Socket(int domain, int type, int protocol)
106 {
107 #if defined(_WIN32) && !defined(SOCKET_NO_WSA_INIT)
108 if (!s_initialized)
109 initialize();
110 #endif
111
112 m_handle = ::socket(domain, type, protocol);
113
114 if (m_handle == Invalid)
115 throw SocketError(SocketError::System, "socket");
116
117 m_state = SocketState::Opened;
118 }
119
120 void Socket::bind(const SocketAddress &address)
121 {
122 const auto &sa = address.address();
123 const auto addrlen = address.length();
124
125 if (::bind(m_handle, reinterpret_cast<const sockaddr *>(&sa), addrlen) == Error)
126 throw SocketError(SocketError::System, "bind");
127
128 m_state = SocketState::Bound;
129 }
130
131 void Socket::close()
132 {
133 #if defined(_WIN32)
134 ::closesocket(m_handle);
135 #else
136 ::close(m_handle);
137 #endif
138
139 m_state = SocketState::Closed;
140 }
141
142 void Socket::setBlockMode(bool block)
143 {
144 #if defined(O_NONBLOCK) && !defined(_WIN32)
145 int flags;
146
147 if ((flags = fcntl(m_handle, F_GETFL, 0)) == -1)
148 flags = 0;
149
150 if (block)
151 flags &= ~(O_NONBLOCK);
152 else
153 flags |= O_NONBLOCK;
154
155 if (fcntl(m_handle, F_SETFL, flags) == Error)
156 throw SocketError(SocketError::System, "setBlockMode");
157 #else
158 unsigned long flags = (block) ? 0 : 1;
159
160 if (ioctlsocket(m_handle, FIONBIO, &flags) == Error)
161 throw SocketError(SocketError::System, "setBlockMode");
162 #endif
163 }
164
165 bool operator==(const Socket &s1, const Socket &s2)
166 {
167 return s1.handle() == s2.handle();
168 }
169
170 bool operator<(const Socket &s1, const Socket &s2)
171 {
172 return s1.handle() < s2.handle();
173 }