Mercurial > code
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 } |