1 module yu.asyncsocket.transport; 2 3 import yu.eventloop; 4 public import yu.memory.allocator; 5 6 enum TransportType : short { 7 ACCEPT, 8 TCP, 9 UDP 10 } 11 12 __gshared size_t TCP_READ_BUFFER_SIZE = 16 * 1024; 13 __gshared size_t UDP_READ_BUFFER_SIZE = 16 * 1024; 14 15 abstract class AsyncTransport { 16 this(EventLoop loop, TransportType type) { 17 _loop = loop; 18 } 19 20 void close(); 21 bool start(); 22 @property bool isAlive() @trusted; 23 @property int fd(); 24 25 final @property transportType() { 26 return _type; 27 } 28 29 final @property eventLoop() { 30 return _loop; 31 } 32 33 protected: 34 EventLoop _loop; 35 TransportType _type; 36 } 37 38 static if (IOMode == IO_MODE.epoll) { 39 version (X86) { 40 41 enum SO_REUSEPORT = 15; 42 } else version (X86_64) { 43 enum SO_REUSEPORT = 15; 44 } else version (MIPS32) { 45 enum SO_REUSEPORT = 0x0200; 46 47 } else version (MIPS64) { 48 enum SO_REUSEPORT = 0x0200; 49 } else version (PPC) { 50 enum SO_REUSEPORT = 15; 51 } else version (PPC64) { 52 enum SO_REUSEPORT = 15; 53 } else version (ARM) { 54 enum SO_REUSEPORT = 15; 55 } 56 } else static if (IOMode == IO_MODE.kqueue) { 57 enum SO_REUSEPORT = 0x0200; 58 } 59 60 mixin template TransportSocketOption() { 61 import std.functional; 62 import std.datetime; 63 import core.stdc.stdint; 64 import std.socket; 65 66 version (Windows) import SOCKETOPTIONS = core.sys.windows.winsock2; 67 68 version (Posix) import SOCKETOPTIONS = core.sys.posix.sys.socket; 69 70 /// Get a socket option. 71 /// Returns: The number of bytes written to $(D result). 72 //returns the length, in bytes, of the actual result - very different from getsockopt() 73 pragma(inline) final int getOption(SocketOptionLevel level, SocketOption option, 74 void[] result) @trusted { 75 76 return _socket.getOption(level, option, result); 77 } 78 79 /// Common case of getting integer and boolean options. 80 pragma(inline) final int getOption(SocketOptionLevel level, 81 SocketOption option, ref int32_t result) @trusted { 82 return _socket.getOption(level, option, result); 83 } 84 85 /// Get the linger option. 86 pragma(inline) final int getOption(SocketOptionLevel level, SocketOption option, 87 ref Linger result) @trusted { 88 return _socket.getOption(level, option, result); 89 } 90 91 /// Get a timeout (duration) option. 92 pragma(inline) final void getOption(SocketOptionLevel level, 93 SocketOption option, ref Duration result) @trusted { 94 _socket.getOption(level, option, result); 95 } 96 97 /// Set a socket option. 98 pragma(inline) final void setOption(SocketOptionLevel level, SocketOption option, 99 void[] value) @trusted { 100 return _socket.setOption(forward!(level, option, value)); 101 } 102 103 /// Common case for setting integer and boolean options. 104 pragma(inline) final void setOption(SocketOptionLevel level, SocketOption option, 105 int32_t value) @trusted { 106 return _socket.setOption(forward!(level, option, value)); 107 } 108 109 /// Set the linger option. 110 pragma(inline) final void setOption(SocketOptionLevel level, SocketOption option, 111 Linger value) @trusted { 112 return _socket.setOption(forward!(level, option, value)); 113 } 114 115 pragma(inline) final void setOption(SocketOptionLevel level, SocketOption option, 116 Duration value) @trusted { 117 return _socket.setOption(forward!(level, option, value)); 118 } 119 120 // you should be yDel the Address 121 final @property @trusted Address remoteAddress() { 122 Address addr = createAddress(); 123 SOCKETOPTIONS.socklen_t nameLen = addr.nameLen; 124 if (Socket.ERROR == SOCKETOPTIONS.getpeername(_socket.handle, addr.name, &nameLen)) 125 throw new SocketOSException("Unable to obtain remote socket address"); 126 if (nameLen > addr.nameLen) 127 throw new SocketParameterException("Not enough socket address storage"); 128 assert(addr.addressFamily == _socket.addressFamily); 129 return addr; 130 } 131 132 // you should be yDel the Address 133 final @property @trusted Address localAddress() { 134 Address addr = createAddress(); 135 SOCKETOPTIONS.socklen_t nameLen = addr.nameLen; 136 if (Socket.ERROR == SOCKETOPTIONS.getsockname(_socket.handle, addr.name, &nameLen)) 137 throw new SocketOSException("Unable to obtain local socket address"); 138 if (nameLen > addr.nameLen) 139 throw new SocketParameterException("Not enough socket address storage"); 140 assert(addr.addressFamily == _socket.addressFamily); 141 return addr; 142 } 143 144 protected final Address createAddress() { 145 enum ushort DPORT = 0; 146 if (AddressFamily.INET == _socket.addressFamily) 147 return yNew!InternetAddress(DPORT); 148 else if (AddressFamily.INET6 == _socket.addressFamily) 149 return yNew!Internet6Address(DPORT); 150 else 151 throw new AddressException( 152 "NOT SUPPORT addressFamily. It only can be AddressFamily.INET or AddressFamily.INET6"); 153 } 154 }