1 module async.net.tcpstream; 2 3 import std.socket; 4 import std.datetime; 5 6 abstract class TcpStream 7 { 8 this(Socket socket) 9 { 10 _socket = socket; 11 _socket.blocking = false; 12 } 13 14 @property bool reusePort() 15 { 16 return _reusePort; 17 } 18 19 @property bool reusePort(bool enabled) 20 { 21 _reusePort = enabled; 22 23 _socket.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, _reusePort); 24 25 version (Posix) 26 { 27 import core.sys.posix.sys.socket; 28 _socket.setOption(SocketOptionLevel.SOCKET, cast(SocketOption)SO_REUSEPORT, _reusePort); 29 } 30 31 version (Windows) 32 { 33 if (!_reusePort) 34 { 35 import core.sys.windows.winsock2; 36 _socket.setOption(SocketOptionLevel.SOCKET, cast(SocketOption)SO_EXCLUSIVEADDRUSE, true); 37 } 38 } 39 40 return _reusePort; 41 } 42 43 @property bool blocking() 44 { 45 return _blocking; 46 } 47 48 @property bool blocking(bool enabled) 49 { 50 _blocking = enabled; 51 _socket.blocking = _blocking; 52 53 return _blocking; 54 } 55 56 @property int fd() 57 { 58 return _socket.handle(); 59 } 60 61 @property Address remoteAddress() 62 { 63 return _socket.remoteAddress(); 64 } 65 66 @property Address localAddress() 67 { 68 return _socket.localAddress(); 69 } 70 71 @property bool isAlive() 72 { 73 return _socket.isAlive(); 74 } 75 76 int getOption(SocketOptionLevel level, SocketOption option, void[] result) @trusted 77 { 78 return _socket.getOption(level, option, result); 79 } 80 81 int getOption(SocketOptionLevel level, SocketOption option, out int result) @trusted 82 { 83 return _socket.getOption(level, option, result); 84 } 85 86 int getOption(SocketOptionLevel level, SocketOption option, out Linger result) @trusted 87 { 88 return _socket.getOption(level, option, result); 89 } 90 91 void getOption(SocketOptionLevel level, SocketOption option, out Duration result) @trusted 92 { 93 return _socket.getOption(level, option, result); 94 } 95 96 void setOption(SocketOptionLevel level, SocketOption option, void[] value) @trusted 97 { 98 _socket.setOption(level, option, value); 99 } 100 101 void setOption(SocketOptionLevel level, SocketOption option, int value) @trusted 102 { 103 _socket.setOption(level, option, value); 104 } 105 106 void setOption(SocketOptionLevel level, SocketOption option, Linger value) @trusted 107 { 108 _socket.setOption(level, option, value); 109 } 110 111 void setOption(SocketOptionLevel level, SocketOption option, Duration value) @trusted 112 { 113 _socket.setOption(level, option, value); 114 } 115 116 void setKeepAlive(int time, int interval) @trusted 117 { 118 version (Windows) 119 { 120 tcp_keepalive options; 121 options.onoff = 1; 122 options.keepalivetime = time * 1000; 123 options.keepaliveinterval = interval * 1000; 124 uint cbBytesReturned; 125 if (WSAIoctl(_socket.handle(), SIO_KEEPALIVE_VALS, &options, options.sizeof, null, 0, &cbBytesReturned, null, null) != 0) 126 { 127 //throw new SocketOSException("Error setting keep-alive."); 128 } 129 } 130 else 131 static if (is(typeof(TCP_KEEPIDLE)) && is(typeof(TCP_KEEPINTVL))) 132 { 133 setOption(SocketOptionLevel.TCP, cast(SocketOption) TCP_KEEPIDLE, time); 134 setOption(SocketOptionLevel.TCP, cast(SocketOption) TCP_KEEPINTVL, interval); 135 setOption(SocketOptionLevel.SOCKET, SocketOption.KEEPALIVE, true); 136 } 137 else 138 { 139 //throw new SocketFeatureException("Setting keep-alive options is not supported on this platform."); 140 } 141 } 142 143 protected: 144 145 Socket _socket; 146 147 bool _reusePort = false; 148 bool _blocking = false; 149 }