Use sockets with new IP Address structs
This commit is contained in:
		| @@ -35,9 +35,6 @@ type information at compile-time, to transform from one type to another. It has | |||||||
| also different algorithms for iterating, searching and modifying template | also different algorithms for iterating, searching and modifying template | ||||||
| arguments. | arguments. | ||||||
| * `net`: URL-Parsing, network programming. | * `net`: URL-Parsing, network programming. | ||||||
| * `network`: Socket implementation. `network` is currently under rework. |  | ||||||
| After finishing the new socket implementation will land in the `net` package and |  | ||||||
| `network` will be deprecated. |  | ||||||
| * `os`: Platform-independent interfaces to operating system functionality. | * `os`: Platform-independent interfaces to operating system functionality. | ||||||
| * `range`: Generic functions and templates for D ranges. | * `range`: Generic functions and templates for D ranges. | ||||||
| * `test`: Test suite for unittest-blocks. | * `test`: Test suite for unittest-blocks. | ||||||
| @@ -167,7 +164,7 @@ parameter is used) | |||||||
|  |  | ||||||
| | DMD     | GCC       | | | DMD     | GCC       | | ||||||
| |:-------:|:---------:| | |:-------:|:---------:| | ||||||
| | 2.091.1 | gdc trunk | | | 2.096.0 | 10.3      | | ||||||
|  |  | ||||||
| ## Further characteristics | ## Further characteristics | ||||||
|  |  | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ import tanya.async.transport; | |||||||
| import tanya.async.watcher; | import tanya.async.watcher; | ||||||
| import tanya.container.array; | import tanya.container.array; | ||||||
| import tanya.memory.allocator; | import tanya.memory.allocator; | ||||||
| import tanya.network.socket; | import tanya.net.socket; | ||||||
|  |  | ||||||
| extern (C) nothrow @nogc | extern (C) nothrow @nogc | ||||||
| { | { | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ import tanya.async.watcher; | |||||||
| import tanya.container.array; | import tanya.container.array; | ||||||
| import tanya.container.buffer; | import tanya.container.buffer; | ||||||
| import tanya.memory.allocator; | import tanya.memory.allocator; | ||||||
| import tanya.network.socket; | import tanya.net.socket; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Transport for stream sockets. |  * Transport for stream sockets. | ||||||
|   | |||||||
| @@ -34,8 +34,9 @@ | |||||||
|  * |  * | ||||||
|  * void main() |  * void main() | ||||||
|  * { |  * { | ||||||
|  *     auto address = defaultAllocator.make!InternetAddress("127.0.0.1", cast(ushort) 8192); |  *     auto address = address4("127.0.0.1"); | ||||||
|  * |  *     auto endpoint = Endpoint(address.get, cast(ushort) 8192); | ||||||
|  |  *     | ||||||
|  *     version (Windows) |  *     version (Windows) | ||||||
|  *     { |  *     { | ||||||
|  *         auto sock = defaultAllocator.make!OverlappedStreamSocket(AddressFamily.inet); |  *         auto sock = defaultAllocator.make!OverlappedStreamSocket(AddressFamily.inet); | ||||||
| @@ -46,19 +47,18 @@ | |||||||
|  *         sock.blocking = false; |  *         sock.blocking = false; | ||||||
|  *     } |  *     } | ||||||
|  * |  * | ||||||
|  *     sock.bind(address); |  *     sock.bind(endpoint); | ||||||
|  *     sock.listen(5); |  *     sock.listen(5); | ||||||
|  * |  *     | ||||||
|  *     auto io = defaultAllocator.make!ConnectionWatcher(sock); |  *     auto io = defaultAllocator.make!ConnectionWatcher(sock); | ||||||
|  *     io.setProtocol!EchoProtocol; |  *     io.setProtocol!EchoProtocol; | ||||||
|  * |  *     | ||||||
|  *     defaultLoop.start(io); |  *     defaultLoop.start(io); | ||||||
|  *     defaultLoop.run(); |  *     defaultLoop.run(); | ||||||
|  * |  *     | ||||||
|  *     sock.shutdown(); |  *     sock.shutdown(); | ||||||
|  *     defaultAllocator.dispose(io); |  *     defaultAllocator.dispose(io); | ||||||
|  *     defaultAllocator.dispose(sock); |  *     defaultAllocator.dispose(sock); | ||||||
|  *     defaultAllocator.dispose(address); |  | ||||||
|  * } |  * } | ||||||
|  * --- |  * --- | ||||||
|  * |  * | ||||||
| @@ -78,7 +78,7 @@ import tanya.bitmanip; | |||||||
| import tanya.container.buffer; | import tanya.container.buffer; | ||||||
| import tanya.container.list; | import tanya.container.list; | ||||||
| import tanya.memory.allocator; | import tanya.memory.allocator; | ||||||
| import tanya.network.socket; | import tanya.net.socket; | ||||||
|  |  | ||||||
| version (DisableBackends) | version (DisableBackends) | ||||||
| { | { | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ | |||||||
| module tanya.async.protocol; | module tanya.async.protocol; | ||||||
|  |  | ||||||
| import tanya.async.transport; | import tanya.async.transport; | ||||||
| import tanya.network.socket; | import tanya.net.socket; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Common protocol interface. |  * Common protocol interface. | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ | |||||||
| module tanya.async.transport; | module tanya.async.transport; | ||||||
|  |  | ||||||
| import tanya.async.protocol; | import tanya.async.protocol; | ||||||
| import tanya.network.socket; | import tanya.net.socket; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Base transport interface. |  * Base transport interface. | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ import tanya.async.transport; | |||||||
| import tanya.container.buffer; | import tanya.container.buffer; | ||||||
| import tanya.container.list; | import tanya.container.list; | ||||||
| import tanya.memory.allocator; | import tanya.memory.allocator; | ||||||
| import tanya.network.socket; | import tanya.net.socket; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * A watcher is an opaque structure that you allocate and register to record |  * A watcher is an opaque structure that you allocate and register to record | ||||||
|   | |||||||
| @@ -142,3 +142,23 @@ String indexToName(uint index) @nogc nothrow @trusted | |||||||
|         return String(findNullTerminated(buffer)); |         return String(findNullTerminated(buffer)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * $(D_PSYMBOL AddressFamily) specifies a communication domain; this selects | ||||||
|  |  * the protocol family which will be used for communication. | ||||||
|  |  */ | ||||||
|  | enum AddressFamily : int | ||||||
|  | { | ||||||
|  |     unspec    = 0,     /// Unspecified. | ||||||
|  |     local     = 1,     /// Local to host (pipes and file-domain). | ||||||
|  |     unix      = local, /// POSIX name for PF_LOCAL. | ||||||
|  |     inet      = 2,     /// IP protocol family. | ||||||
|  |     ax25      = 3,     /// Amateur Radio AX.25. | ||||||
|  |     ipx       = 4,     /// Novell Internet Protocol. | ||||||
|  |     appletalk = 5,     /// Appletalk DDP. | ||||||
|  |     netrom    = 6,     /// Amateur radio NetROM. | ||||||
|  |     bridge    = 7,     /// Multiprotocol bridge. | ||||||
|  |     atmpvc    = 8,     /// ATM PVCs. | ||||||
|  |     x25       = 9,     /// Reserved for X.25 project. | ||||||
|  |     inet6     = 10,    /// IP version 6. | ||||||
|  | } | ||||||
|   | |||||||
| @@ -14,7 +14,6 @@ | |||||||
|  */ |  */ | ||||||
| module tanya.net.ip; | module tanya.net.ip; | ||||||
|  |  | ||||||
| import core.sys.posix.sys.socket; |  | ||||||
| import std.algorithm.comparison; | import std.algorithm.comparison; | ||||||
| import std.ascii; | import std.ascii; | ||||||
| import std.typecons; | import std.typecons; | ||||||
| @@ -1331,7 +1330,7 @@ struct Address | |||||||
|  */ |  */ | ||||||
| struct Endpoint | struct Endpoint | ||||||
| { | { | ||||||
|     private sa_family_t family = AF_UNSPEC; |     private AddressFamily family = AddressFamily.unspec; | ||||||
|     private ubyte[ushort.sizeof] service; |     private ubyte[ushort.sizeof] service; | ||||||
|     private Address4 address4; // Unused sin6_flowinfo if IPv6 |     private Address4 address4; // Unused sin6_flowinfo if IPv6 | ||||||
|     private Address6 address6; // Unused if IPv4 |     private Address6 address6; // Unused if IPv4 | ||||||
| @@ -1345,10 +1344,12 @@ struct Endpoint | |||||||
|      * Constructs an endpoint. |      * Constructs an endpoint. | ||||||
|      * |      * | ||||||
|      * Params: |      * Params: | ||||||
|  |      *     T = Address type (IPv4 or IPv6). | ||||||
|      *     address = IP address that should be associated with the endpoint. |      *     address = IP address that should be associated with the endpoint. | ||||||
|      *     port = Port number in network byte order. |      *     port = Port number in network byte order. | ||||||
|      */ |      */ | ||||||
|     this(Address address, const ushort port = anyPort) |     this(T)(T address, const ushort port = anyPort) | ||||||
|  |     if (is(T == Address) || is(T == Address4) || is(T == Address6)) | ||||||
|     { |     { | ||||||
|         this.address = address; |         this.address = address; | ||||||
|         this.port = port; |         this.port = port; | ||||||
| @@ -1357,7 +1358,7 @@ struct Endpoint | |||||||
|     /** |     /** | ||||||
|      * Returns: Port number in network byte order. |      * Returns: Port number in network byte order. | ||||||
|      */ |      */ | ||||||
|     @property ushort port() const @nogc nothrow pure @safe |     @property inout(ushort) port() inout const @nogc nothrow pure @safe | ||||||
|     { |     { | ||||||
|         return this.service[].toHostOrder!ushort(); |         return this.service[].toHostOrder!ushort(); | ||||||
|     } |     } | ||||||
| @@ -1374,13 +1375,13 @@ struct Endpoint | |||||||
|     /** |     /** | ||||||
|      * Returns: IP address associated with the endpoint. |      * Returns: IP address associated with the endpoint. | ||||||
|      */ |      */ | ||||||
|     @property Address address() @nogc nothrow pure @safe |     @property inout(Address) address() inout @nogc nothrow pure @safe | ||||||
|     { |     { | ||||||
|         if (this.family == AF_INET) |         if (this.family == AddressFamily.inet) | ||||||
|         { |         { | ||||||
|             return Address(this.address4); |             return Address(this.address4); | ||||||
|         } |         } | ||||||
|         else if (this.family == AF_INET6) |         else if (this.family == AddressFamily.inet6) | ||||||
|         { |         { | ||||||
|             return Address(this.address6); |             return Address(this.address6); | ||||||
|         } |         } | ||||||
| @@ -1395,14 +1396,26 @@ struct Endpoint | |||||||
|     { |     { | ||||||
|         if (address.isV4()) |         if (address.isV4()) | ||||||
|         { |         { | ||||||
|             this.family = AF_INET; |             this.address = address.toV4(); | ||||||
|             this.address4 = address.toV4(); |  | ||||||
|         } |         } | ||||||
|         else if (address.isV6()) |         else if (address.isV6()) | ||||||
|         { |         { | ||||||
|             this.family = AF_INET6; |             this.address = address.toV6(); | ||||||
|             this.address4 = Address4(0); |  | ||||||
|             this.address6 = address.toV6(); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /// ditto | ||||||
|  |     @property void address(Address4 address) @nogc nothrow pure @safe | ||||||
|  |     { | ||||||
|  |         this.family = AddressFamily.inet; | ||||||
|  |         this.address4 = address; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// ditto | ||||||
|  |     @property void address(Address6 address) @nogc nothrow pure @safe | ||||||
|  |     { | ||||||
|  |         this.family = AddressFamily.inet6; | ||||||
|  |         this.address4 = Address4(0); | ||||||
|  |         this.address6 = address; | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -17,4 +17,5 @@ module tanya.net; | |||||||
| public import tanya.net.iface; | public import tanya.net.iface; | ||||||
| public import tanya.net.inet; | public import tanya.net.inet; | ||||||
| public import tanya.net.ip; | public import tanya.net.ip; | ||||||
|  | public import tanya.net.socket; | ||||||
| public import tanya.net.uri; | public import tanya.net.uri; | ||||||
|   | |||||||
| @@ -7,37 +7,6 @@ | |||||||
|  * |  * | ||||||
|  * Current API supports only server-side TCP communication. |  * Current API supports only server-side TCP communication. | ||||||
|  * |  * | ||||||
|  * Here is an example of a cross-platform blocking server: |  | ||||||
|  * |  | ||||||
|  * --- |  | ||||||
|  * import std.stdio; |  | ||||||
|  * import tanya.memory; |  | ||||||
|  * import tanya.network; |  | ||||||
|  * |  | ||||||
|  * void main() |  | ||||||
|  * { |  | ||||||
|  *     auto socket = defaultAllocator.make!StreamSocket(AddressFamily.inet); |  | ||||||
|  *     auto address = defaultAllocator.make!InternetAddress("127.0.0.1", |  | ||||||
|  *                                                          cast(ushort) 8192); |  | ||||||
|  * |  | ||||||
|  *     socket.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true); |  | ||||||
|  *     socket.blocking = true; |  | ||||||
|  *     socket.bind(address); |  | ||||||
|  *     socket.listen(5); |  | ||||||
|  * |  | ||||||
|  *     auto client = socket.accept(); |  | ||||||
|  *     client.send(cast(const(ubyte)[]) "Test\n"); |  | ||||||
|  * |  | ||||||
|  *     ubyte[100] buf; |  | ||||||
|  *     auto response = client.receive(buf[]); |  | ||||||
|  * |  | ||||||
|  *     writeln(cast(const(char)[]) buf[0 .. response]); |  | ||||||
|  * |  | ||||||
|  *     defaultAllocator.dispose(client); |  | ||||||
|  *     defaultAllocator.dispose(socket); |  | ||||||
|  * } |  | ||||||
|  * --- |  | ||||||
|  * |  | ||||||
|  * For an example of an asynchronous server refer to the documentation of the |  * For an example of an asynchronous server refer to the documentation of the | ||||||
|  * $(D_PSYMBOL tanya.async.loop) module. |  * $(D_PSYMBOL tanya.async.loop) module. | ||||||
|  * |  * | ||||||
| @@ -48,7 +17,7 @@ | |||||||
|  * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/network/socket.d,
 |  * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/network/socket.d,
 | ||||||
|  *                 tanya/network/socket.d) |  *                 tanya/network/socket.d) | ||||||
|  */ |  */ | ||||||
| module tanya.network.socket; | module tanya.net.socket; | ||||||
| 
 | 
 | ||||||
| import core.stdc.errno; | import core.stdc.errno; | ||||||
| import core.time; | import core.time; | ||||||
| @@ -57,6 +26,8 @@ import tanya.bitmanip; | |||||||
| import tanya.memory.allocator; | import tanya.memory.allocator; | ||||||
| import tanya.meta.trait; | import tanya.meta.trait; | ||||||
| import tanya.os.error; | import tanya.os.error; | ||||||
|  | import tanya.net.iface; | ||||||
|  | import tanya.net.ip; | ||||||
| 
 | 
 | ||||||
| /// Value returned by socket operations on error.
 | /// Value returned by socket operations on error.
 | ||||||
| enum int socketError = -1; | enum int socketError = -1; | ||||||
| @@ -588,26 +559,6 @@ shared static this() | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** |  | ||||||
|  * $(D_PSYMBOL AddressFamily) specifies a communication domain; this selects |  | ||||||
|  * the protocol family which will be used for communication. |  | ||||||
|  */ |  | ||||||
| enum AddressFamily : int |  | ||||||
| { |  | ||||||
|     unspec    = 0,     /// Unspecified.
 |  | ||||||
|     local     = 1,     /// Local to host (pipes and file-domain).
 |  | ||||||
|     unix      = local, /// POSIX name for PF_LOCAL.
 |  | ||||||
|     inet      = 2,     /// IP protocol family.
 |  | ||||||
|     ax25      = 3,     /// Amateur Radio AX.25.
 |  | ||||||
|     ipx       = 4,     /// Novell Internet Protocol.
 |  | ||||||
|     appletalk = 5,     /// Appletalk DDP.
 |  | ||||||
|     netrom    = 6,     /// Amateur radio NetROM.
 |  | ||||||
|     bridge    = 7,     /// Multiprotocol bridge.
 |  | ||||||
|     atmpvc    = 8,     /// ATM PVCs.
 |  | ||||||
|     x25       = 9,     /// Reserved for X.25 project.
 |  | ||||||
|     inet6     = 10,    /// IP version 6.
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** | /** | ||||||
|  * $(D_PSYMBOL SocketException) should be thrown only if one of the socket functions |  * $(D_PSYMBOL SocketException) should be thrown only if one of the socket functions | ||||||
|  * $(D_PSYMBOL socketError) and sets $(D_PSYMBOL errno), because |  * $(D_PSYMBOL socketError) and sets $(D_PSYMBOL errno), because | ||||||
| @@ -1064,13 +1015,13 @@ class StreamSocket : Socket, ConnectionOrientedSocket | |||||||
|      * Associate a local address with this socket. |      * Associate a local address with this socket. | ||||||
|      * |      * | ||||||
|      * Params: |      * Params: | ||||||
|      *  address = Local address. |      *  endpoint = Local address. | ||||||
|      * |      * | ||||||
|      * Throws: $(D_PSYMBOL SocketException) if unable to bind. |      * Throws: $(D_PSYMBOL SocketException) if unable to bind. | ||||||
|      */ |      */ | ||||||
|     void bind(Address address) const @trusted @nogc |     void bind(const Endpoint endpoint) const @nogc | ||||||
|     { |     { | ||||||
|         if (.bind(handle_, address.name, address.length) == socketError) |         if (.bind(handle_, cast(const(sockaddr)*) &endpoint, Endpoint.sizeof)) | ||||||
|         { |         { | ||||||
|             throw defaultAllocator.make!SocketException("Unable to bind socket"); |             throw defaultAllocator.make!SocketException("Unable to bind socket"); | ||||||
|         } |         } | ||||||
| @@ -1268,157 +1219,6 @@ class ConnectedSocket : Socket, ConnectionOrientedSocket | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** |  | ||||||
|  * Socket address representation. |  | ||||||
|  */ |  | ||||||
| abstract class Address |  | ||||||
| { |  | ||||||
|     /** |  | ||||||
|      * Returns: Pointer to underlying $(D_PSYMBOL sockaddr) structure. |  | ||||||
|      */ |  | ||||||
|     abstract @property inout(sockaddr)* name() inout pure nothrow @nogc; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Returns: Actual size of underlying $(D_PSYMBOL sockaddr) structure. |  | ||||||
|      */ |  | ||||||
|     abstract @property inout(socklen_t) length() inout const pure nothrow @nogc; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| class InternetAddress : Address |  | ||||||
| { |  | ||||||
|     version (Windows) |  | ||||||
|     { |  | ||||||
|         /// Internal internet address representation.
 |  | ||||||
|         protected SOCKADDR_STORAGE storage; |  | ||||||
|     } |  | ||||||
|     else version (Posix) |  | ||||||
|     { |  | ||||||
|         /// Internal internet address representation.
 |  | ||||||
|         protected sockaddr_storage storage; |  | ||||||
|     } |  | ||||||
|     const ushort port_; |  | ||||||
| 
 |  | ||||||
|     enum ushort anyPort = 0; |  | ||||||
| 
 |  | ||||||
|     this(string host, const ushort port = anyPort) @nogc |  | ||||||
|     { |  | ||||||
|         if (getaddrinfoPointer is null || freeaddrinfoPointer is null) |  | ||||||
|         { |  | ||||||
|             throw make!SocketException(defaultAllocator, |  | ||||||
|                                        "Address info lookup is not available on this system"); |  | ||||||
|         } |  | ||||||
|         addrinfo* ai_res; |  | ||||||
|         this.port_ = port; |  | ||||||
| 
 |  | ||||||
|         // Make C-string from host.
 |  | ||||||
|         auto node = cast(char[]) allocator.allocate(host.length + 1); |  | ||||||
|         node[0 .. $ - 1] = host; |  | ||||||
|         node[$ - 1] = '\0'; |  | ||||||
|         scope (exit) |  | ||||||
|         { |  | ||||||
|             allocator.deallocate(node); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Convert port to a C-string.
 |  | ||||||
|         char[6] service = [0, 0, 0, 0, 0, 0]; |  | ||||||
|         const(char)* servicePointer; |  | ||||||
|         if (port) |  | ||||||
|         { |  | ||||||
|             ushort originalPort = port; |  | ||||||
|             ushort start; |  | ||||||
|             for (ushort j = 10, i = 4; i > 0; j *= 10, --i) |  | ||||||
|             { |  | ||||||
|                 ushort rest = originalPort % 10; |  | ||||||
|                 if (rest != 0) |  | ||||||
|                 { |  | ||||||
|                     service[i] = cast(char) (rest + '0'); |  | ||||||
|                     start = i; |  | ||||||
|                 } |  | ||||||
|                 originalPort /= 10; |  | ||||||
|             } |  | ||||||
|             servicePointer = service[start .. $].ptr; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         auto ret = getaddrinfoPointer(node.ptr, servicePointer, null, &ai_res); |  | ||||||
|         if (ret) |  | ||||||
|         { |  | ||||||
|             throw defaultAllocator.make!SocketException("Address info lookup failed"); |  | ||||||
|         } |  | ||||||
|         scope (exit) |  | ||||||
|         { |  | ||||||
|             freeaddrinfoPointer(ai_res); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         ubyte* dp = cast(ubyte*) &storage, sp = cast(ubyte*) ai_res.ai_addr; |  | ||||||
|         for (auto i = ai_res.ai_addrlen; i > 0; --i, *dp++, *sp++) |  | ||||||
|         { |  | ||||||
|             *dp = *sp; |  | ||||||
|         } |  | ||||||
|         if (ai_res.ai_family != AddressFamily.inet && ai_res.ai_family != AddressFamily.inet6) |  | ||||||
|         { |  | ||||||
|             throw defaultAllocator.make!SocketException("Wrong address family"); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     ///
 |  | ||||||
|     unittest |  | ||||||
|     { |  | ||||||
|         auto address = defaultAllocator.make!InternetAddress("127.0.0.1"); |  | ||||||
|         assert(address.port == InternetAddress.anyPort); |  | ||||||
|         assert(address.name !is null); |  | ||||||
|         assert(address.family == AddressFamily.inet); |  | ||||||
| 
 |  | ||||||
|         defaultAllocator.dispose(address); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Returns: Pointer to underlying $(D_PSYMBOL sockaddr) structure. |  | ||||||
|      */ |  | ||||||
|     override @property inout(sockaddr)* name() inout pure nothrow @nogc |  | ||||||
|     { |  | ||||||
|         return cast(sockaddr*) &storage; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Returns: Actual size of underlying $(D_PSYMBOL sockaddr) structure. |  | ||||||
|      */ |  | ||||||
|     override @property inout(socklen_t) length() inout const pure nothrow @nogc |  | ||||||
|     { |  | ||||||
|         // FreeBSD wants to know the exact length of the address on bind.
 |  | ||||||
|         switch (family) |  | ||||||
|         { |  | ||||||
|             case AddressFamily.inet: |  | ||||||
|                 return sockaddr_in.sizeof; |  | ||||||
|             case AddressFamily.inet6: |  | ||||||
|                 return sockaddr_in6.sizeof; |  | ||||||
|             default: |  | ||||||
|                 assert(false); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Returns: Family of this address. |  | ||||||
|      */ |  | ||||||
|     @property inout(AddressFamily) family() inout const pure nothrow @nogc |  | ||||||
|     { |  | ||||||
|         return cast(AddressFamily) storage.ss_family; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @property inout(ushort) port() inout const pure nothrow @nogc |  | ||||||
|     { |  | ||||||
|         return port_; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     ///
 |  | ||||||
|     unittest |  | ||||||
|     { |  | ||||||
|         auto address = defaultAllocator.make!InternetAddress("127.0.0.1", |  | ||||||
|                                                              cast(ushort) 1234); |  | ||||||
|         assert(address.port == 1234); |  | ||||||
|         defaultAllocator.dispose(address); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** | /** | ||||||
|  * Checks if the last error is a serious error or just a special |  * Checks if the last error is a serious error or just a special | ||||||
|  * behaviour error of non-blocking sockets (for example an error |  * behaviour error of non-blocking sockets (for example an error | ||||||
| @@ -1,17 +0,0 @@ | |||||||
| /* This Source Code Form is subject to the terms of the Mozilla Public |  | ||||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this |  | ||||||
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Network programming. |  | ||||||
|  * |  | ||||||
|  * Copyright: Eugene Wissner 2016-2020. |  | ||||||
|  * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, |  | ||||||
|  *                  Mozilla Public License, v. 2.0). |  | ||||||
|  * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) |  | ||||||
|  * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/network/package.d, |  | ||||||
|  *                 tanya/network/package.d) |  | ||||||
|  */ |  | ||||||
| module tanya.network; |  | ||||||
|  |  | ||||||
| public import tanya.network.socket; |  | ||||||
		Reference in New Issue
	
	Block a user