1 /*
2 * OSCompatSocket.cpp - socket interfaces.
3 *
4 * Copyright (c) 2009 Higepon(Taro Minowa) <higepon@users.sourceforge.jp>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * $Id: OSCompatSocket.cpp 183 2008-07-04 06:19:28Z higepon $
30 */
31
32 #include "scheme.h"
33 #include "Object.h"
34 #include "Object-inl.h"
35 #include "Pair.h"
36 #include "Pair-inl.h"
37 #include "UTF8Codec.h"
38 #include "Transcoder.h"
39 #include "OSCompat.h"
40 #include "OSCompatSocket.h"
41
42 using namespace scheme;
43
Socket(int fd,enum Type type,const ucs4string & address)44 Socket::Socket(int fd, enum Type type, const ucs4string& address) :
45 socket_(fd),
46 lastError_(0),
47 address_(address),
48 type_(type),
49 isSSL_(false)
50 {
51 }
52
accept()53 Socket* Socket::accept()
54 {
55 MOSH_ASSERT(isOpen());
56 #ifdef MONA
57 struct sockaddr_in addr;
58 #else
59 struct sockaddr_storage addr;
60 #endif
61 socklen_t addrlen = sizeof(addr);
62
63 int fd = -1;
64 for (;;) {
65 fd = ::accept(socket_, (sockaddr*)&addr, &addrlen);
66 if (-1 == fd) {
67 if (errno == EINTR) {
68 continue;
69 } else {
70 setLastError();
71 return NULL;
72 }
73 } else {
74 break;
75 }
76 }
77 return new Socket(fd, Socket::SERVER, getAddressString((sockaddr*)&addr, addrlen));
78 }
79
isOpen() const80 bool Socket::isOpen() const
81 {
82 return socket_ != -1;
83 }
84
sslize()85 bool Socket::sslize()
86 {
87 #if HAVE_OPENSSL
88 if (isSSL_) {
89 return true;
90 }
91 ctx_ = SSL_CTX_new(SSLv23_client_method());
92 if (ctx_ == NULL) {
93 return false;
94 }
95 ssl_ = SSL_new(ctx_);
96 if (ssl_ == NULL) {
97 return false;
98 }
99
100 if (SSL_set_fd(ssl_, socket_) == 0) {
101 return false;
102 }
103 RAND_poll();
104 while (RAND_status() == 0) {
105 unsigned short rand_ret = rand() % 65536;
106 RAND_seed(&rand_ret, sizeof(rand_ret));
107 }
108 if (SSL_connect(ssl_) == -1) {
109 return false;
110 }
111 isSSL_ = true;
112 return true;
113 #else
114 return false;
115 #endif
116 }
117
shutdown(int how)118 void Socket::shutdown(int how)
119 {
120 if (!isOpen()) {
121 return;
122 }
123 ::shutdown(socket_, how);
124 }
125
close()126 void Socket::close()
127 {
128 if (!isOpen()) {
129 return;
130 }
131 #if HAVE_OPENSSL
132 if (isSSL()) {
133 SSL_shutdown(ssl_);
134 }
135 #endif
136 #ifdef _WIN32
137 ::shutdown(socket_, SD_SEND);
138 ::closesocket(socket_);
139 #elif defined(MONA)
140 ::closesocket(socket_);
141 #else
142 ::close(socket_);
143 #endif
144 #if HAVE_OPENSSL
145 if (isSSL()) {
146 SSL_free(ssl_);
147 SSL_CTX_free(ctx_);
148 }
149 #endif
150 socket_ = -1;
151
152 }
153
getLastErrorMessage() const154 ucs4string Socket::getLastErrorMessage() const
155 {
156 return getLastErrorMessageInternal(lastError_);
157 }
158
toString() const159 ucs4string Socket::toString() const
160 {
161 if (address_.empty()) {
162 return UC("<socket>");
163 } else {
164 ucs4string ret = UC("<socket ");
165 if (type_ == CLIENT) {
166 ret += UC("client ");
167 } else {
168 ret += UC("server ");
169 }
170 ret += address_;
171 ret += UC(">");
172 return ret;
173 }
174 }
175
176 /**
177 read from socket
178 @param data [in] buffer to read
179 @param size [in] size to read
180 @param flags [in] flags
181 @retval >=0 read size
182 @retval -1 error
183 */
receive(uint8_t * data,int size,int flags)184 int Socket::receive(uint8_t* data, int size, int flags)
185 {
186 if (isSSL()) {
187 #if HAVE_OPENSSL
188 return SSL_read(ssl_, data, size);
189 #else
190 MOSH_ASSERT(false);
191 return -1;
192 #endif
193 } else {
194 MOSH_ASSERT(isOpen());
195
196 for (;;) {
197 const int ret = recv(socket_, (char*)data, size, flags);
198 if (ret == -1 && errno == EINTR) {
199 continue;
200 }
201 setLastError();
202 return ret;
203 }
204 }
205 }
206
207 /**
208 write to socket
209 @param data [in] buffer to read
210 @param size [in] size to read
211 @param flags [in] flags
212 @retval >=0 written size
213 @retval -1 error
214 */
send(uint8_t * data,int size,int flags)215 int Socket::send(uint8_t* data, int size, int flags)
216 {
217 MOSH_ASSERT(isOpen());
218 if (isSSL()) {
219 #if HAVE_OPENSSL
220 return SSL_write(ssl_, data, size);
221 #else
222 MOSH_ASSERT(false);
223 return -1;
224 #endif
225 } else {
226 int rest = size;
227 int sizeSent = 0;
228 while (rest > 0) {
229 const int ret = ::send(socket_, (char*)data, size, flags);
230 if (ret == -1) {
231 if (errno == EINTR) {
232 continue;
233 } else {
234 setLastError();
235 return ret;
236 }
237 }
238 sizeSent += ret;
239 rest -= ret;
240 data += ret;
241 size -= ret;
242 }
243 return sizeSent;
244 }
245 }
246
247 // Factories
createClientSocket(const char * node,const char * service,int ai_family,int ai_socktype,int ai_flags,int ai_protocol,bool & isErrorOccured,ucs4string & errorMessage)248 Socket* Socket::createClientSocket(const char* node,
249 const char* service,
250 int ai_family,
251 int ai_socktype,
252 int ai_flags,
253 int ai_protocol,
254 bool& isErrorOccured,
255 ucs4string& errorMessage)
256 {
257 struct addrinfo hints;
258 memset(&hints, 0, sizeof(struct addrinfo));
259 hints.ai_family = ai_family;
260 hints.ai_socktype = ai_socktype;
261 hints.ai_flags = ai_flags;
262 hints.ai_protocol = ai_protocol;
263 hints.ai_canonname = NULL;
264 hints.ai_addr = NULL;
265 hints.ai_next = NULL;
266 struct addrinfo* result;
267 int ret;
268 // TODO server socket?
269 #ifndef MONA
270 MOSH_ASSERT(!((ai_flags & AI_PASSIVE) && node == NULL));
271 #endif
272
273 // check temporary failure
274 do {
275 ret = getaddrinfo(node, service, &hints, &result);
276 } while (EAI_AGAIN == ret);
277
278 if (ret != 0) {
279 isErrorOccured = true;
280 #ifdef _WIN32
281 errorMessage = getLastErrorMessageInternal(WSAGetLastError());
282 #elif defined(MONA)
283 char buf[128];
284 snprintf(buf, 128, "getaddrinfo returns %d", ret);
285 errorMessage = ucs4string::from_c_str(buf);
286 #else
287 errorMessage = ucs4string::from_c_str(gai_strerror(ret));
288 #endif
289 return NULL;
290 }
291
292 // there may be many addresses for one host
293 int lastError = 0;
294 for (struct addrinfo* p = result; p != NULL; p = p->ai_next) {
295 const int fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
296 if (-1 == fd) {
297 #ifdef _WIN32
298 lastError = WSAGetLastError();
299 #else
300 lastError = errno;
301 #endif
302 continue;
303 }
304 if (connect(fd, p->ai_addr, p->ai_addrlen) == 0) {
305
306 ucs4string addressString = getAddressString(p);
307 freeaddrinfo(result);
308 return new Socket(fd, Socket::CLIENT, addressString);
309 } else {
310 #ifdef _WIN32
311 lastError = WSAGetLastError();
312 #else
313 lastError = errno;
314 #endif
315 #ifdef _WIN32
316 ::shutdown(fd, SD_SEND);
317 ::closesocket(fd);
318 #elif defined(MONA)
319 ::closesocket(fd);
320 #else
321 ::close(fd);
322 #endif
323 }
324 }
325 freeaddrinfo(result);
326 isErrorOccured = true;
327 errorMessage = getLastErrorMessageInternal(lastError);
328 return NULL;
329 }
330 #if !defined(__CYGWIN__) && !defined(MONA)
331 extern ucs4string my_utf16ToUtf32(const std::wstring& s);
332 #endif
createServerSocket(const char * service,int ai_family,int ai_socktype,int ai_protocol,bool & isErrorOccured,ucs4string & errorMessage)333 Socket* Socket::createServerSocket(const char* service,
334 int ai_family,
335 int ai_socktype,
336 int ai_protocol,
337 bool& isErrorOccured,
338 ucs4string& errorMessage)
339 {
340 struct addrinfo hints;
341 memset(&hints, 0, sizeof(struct addrinfo));
342 hints.ai_family = ai_family;
343 hints.ai_socktype = ai_socktype;
344 #ifndef MONA
345 hints.ai_flags = AI_PASSIVE;
346 #endif
347 hints.ai_protocol = ai_protocol;
348 hints.ai_canonname = NULL;
349 hints.ai_addr = NULL;
350 hints.ai_next = NULL;
351 struct addrinfo* result;
352 int ret;
353
354 // check temporary failure
355 do {
356 ret = getaddrinfo(NULL, service, &hints, &result);
357 } while (EAI_AGAIN == ret);
358
359 if (ret != 0) {
360 isErrorOccured = true;
361 #ifdef _WIN32
362 errorMessage = my_utf16ToUtf32(gai_strerror(ret));
363 #elif defined(MONA)
364 errorMessage = ucs4string::from_c_str("should be port lwip_strerr");
365 #else
366 errorMessage = ucs4string::from_c_str(gai_strerror(ret));
367 #endif
368 return NULL;
369 }
370 // there may be many addresses for one host
371 int lastError = 0;
372 for (struct addrinfo* p = result; p != NULL; p = p->ai_next) {
373 const int fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
374 if (-1 == fd) {
375 lastError = errno;
376 continue;
377 }
378 // Mona's lwip doesn't support SO_REUSEADDR.
379 #ifndef MONA
380 int optValue = 1;
381 if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&optValue, sizeof(optValue)) == -1) {
382 #ifdef _WIN32
383 ::shutdown(fd, SD_SEND);
384 ::closesocket(fd);
385 lastError = WSAGetLastError();
386 #else
387 ::close(fd);
388 lastError = errno;
389 #endif
390 continue;
391 }
392 #endif
393
394 if (bind(fd, p->ai_addr, p->ai_addrlen) == -1) {
395 #ifdef _WIN32
396 ::shutdown(fd, SD_SEND);
397 ::closesocket(fd);
398 lastError = WSAGetLastError();
399 #elif defined(MONA)
400 ::closesocket(fd);
401 lastError = errno;
402 #else
403 ::close(fd);
404 lastError = errno;
405 #endif
406 continue;
407 }
408 const int TRADITIONAL_BACKLOG = 5;
409 if (p->ai_socktype == SOCK_STREAM ) {
410 if (listen(fd, TRADITIONAL_BACKLOG) == -1) {
411 #ifdef _WIN32
412 ::shutdown(fd, SD_SEND);
413 ::closesocket(fd);
414 lastError = WSAGetLastError();
415 #elif defined(MONA)
416 ::closesocket(fd);
417 lastError = errno;
418 #else
419 ::close(fd);
420 lastError = errno;
421 #endif
422
423 continue;
424 }
425 }
426 ucs4string addressString = getAddressString(p);
427 freeaddrinfo(result);
428 return new Socket(fd, Socket::SERVER, addressString);
429 }
430 freeaddrinfo(result);
431 isErrorOccured = true;
432 errorMessage = getLastErrorMessageInternal(lastError);
433 return NULL;
434 }
435
getAddressString(const struct sockaddr * addr,socklen_t addrlen)436 ucs4string Socket::getAddressString(const struct sockaddr* addr, socklen_t addrlen)
437 {
438 #ifdef MONA
439 return ucs4string::from_c_str("getAddressString not supported");
440 #else
441 int ret;
442 char host[NI_MAXHOST];
443 char serv[NI_MAXSERV];
444 do {
445 ret = getnameinfo(addr,
446 addrlen,
447 host, sizeof(host),
448 serv, sizeof(serv), NI_NUMERICSERV);
449 } while (EAI_AGAIN == ret);
450 char name[NI_MAXSERV + NI_MAXHOST + 1];
451 snprintf(name, sizeof(name), "%s:%s", host, serv);
452 return ucs4string::from_c_str(name);
453 #endif
454 }
getAddressString(const struct addrinfo * addr)455 ucs4string Socket::getAddressString(const struct addrinfo* addr)
456 {
457 return getAddressString(addr->ai_addr, addr->ai_addrlen);
458 }
459
setLastError()460 void Socket::setLastError()
461 {
462 #ifdef _WIN32
463 lastError_ = WSAGetLastError();
464 #else
465 lastError_ = errno;
466 #endif
467 }
468