1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 /**
21 * Abstractions over OS-dependent socket functionality.
22 */
23 module thrift.internal.socket;
24
25 import std.conv : to;
26
27 // FreeBSD and OS X return -1 and set ECONNRESET if socket was closed by
28 // the other side, we need to check for that before throwing an exception.
version(FreeBSD)29 version (FreeBSD) {
30 enum connresetOnPeerShutdown = true;
31 } else version (OSX) {
32 enum connresetOnPeerShutdown = true;
33 } else {
34 enum connresetOnPeerShutdown = false;
35 }
36
version(Windows)37 version (Windows) {
38 import core.sys.windows.winsock2 : WSAGetLastError, WSAEINTR, WSAEWOULDBLOCK;
39 import std.windows.syserror : sysErrorString;
40
41 // These are unfortunately not defined in std.c.windows.winsock, see
42 // http://msdn.microsoft.com/en-us/library/ms740668.aspx.
43 enum WSAECONNRESET = 10054;
44 enum WSAENOTCONN = 10057;
45 enum WSAETIMEDOUT = 10060;
46 } else {
47 import core.stdc.errno : errno, EAGAIN, ECONNRESET, EINPROGRESS, EINTR,
48 ENOTCONN, EPIPE;
49 import core.stdc.string : strerror;
50 }
51
52 /*
53 * CONNECT_INPROGRESS_ERRNO: set by connect() for non-blocking sockets if the
54 * connection could not be immediately established.
55 * INTERRUPTED_ERRNO: set when blocking system calls are interrupted by
56 * signals or similar.
57 * TIMEOUT_ERRNO: set when a socket timeout has been exceeded.
58 * WOULD_BLOCK_ERRNO: set when send/recv would block on non-blocking sockets.
59 *
60 * isSocetCloseErrno(errno): returns true if errno indicates that the socket
61 * is logically in closed state now.
62 */
version(Windows)63 version (Windows) {
64 alias WSAGetLastError getSocketErrno;
65 enum CONNECT_INPROGRESS_ERRNO = WSAEWOULDBLOCK;
66 enum INTERRUPTED_ERRNO = WSAEINTR;
67 enum TIMEOUT_ERRNO = WSAETIMEDOUT;
68 enum WOULD_BLOCK_ERRNO = WSAEWOULDBLOCK;
69
70 bool isSocketCloseErrno(typeof(getSocketErrno()) errno) {
71 return (errno == WSAECONNRESET || errno == WSAENOTCONN);
72 }
73 } else {
74 alias errno getSocketErrno;
75 enum CONNECT_INPROGRESS_ERRNO = EINPROGRESS;
76 enum INTERRUPTED_ERRNO = EINTR;
77 enum WOULD_BLOCK_ERRNO = EAGAIN;
78
79 // TODO: The C++ TSocket implementation mentions that EAGAIN can also be
80 // set (undocumentedly) in out of resource conditions; it would be a good
81 // idea to contact the original authors of the C++ code for details and adapt
82 // the code accordingly.
83 enum TIMEOUT_ERRNO = EAGAIN;
84
isSocketCloseErrno(typeof (getSocketErrno ())errno)85 bool isSocketCloseErrno(typeof(getSocketErrno()) errno) {
86 return (errno == EPIPE || errno == ECONNRESET || errno == ENOTCONN);
87 }
88 }
89
socketErrnoString(uint errno)90 string socketErrnoString(uint errno) {
91 version (Windows) {
92 return sysErrorString(errno);
93 } else {
94 return to!string(strerror(errno));
95 }
96 }
97