Use sockets with new IP Address structs
This commit is contained in:
parent
be8fcb3e1c
commit
c15a8993ec
@ -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,7 +34,8 @@
|
|||||||
*
|
*
|
||||||
* 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)
|
||||||
* {
|
* {
|
||||||
@ -46,7 +47,7 @@
|
|||||||
* 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);
|
||||||
@ -58,7 +59,6 @@
|
|||||||
* 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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.address4 = Address4(0);
|
||||||
this.address6 = address.toV6();
|
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;
|
|
Loading…
Reference in New Issue
Block a user