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. 29 version (FreeBSD) { 30 enum connresetOnPeerShutdown = true; 31 } else version (OSX) { 32 enum connresetOnPeerShutdown = true; 33 } else { 34 enum connresetOnPeerShutdown = false; 35 } 36 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 */ 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 85 bool isSocketCloseErrno(typeof(getSocketErrno()) errno) { 86 return (errno == EPIPE || errno == ECONNRESET || errno == ENOTCONN); 87 } 88 } 89 90 string socketErrnoString(uint errno) { 91 version (Windows) { 92 return sysErrorString(errno); 93 } else { 94 return to!string(strerror(errno)); 95 } 96 }