From 48a49c2a2d8b246b75fb9e2114f65a3d51f96239 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 8 Feb 2017 20:04:05 +0100 Subject: [PATCH] Add protocol property to the transport Transport should be protocol aware because it should be possible to switch the protocol if the operation is supported, for example for upgrading HTTP to web sockets or HTTP 1.1 to HTTP/2. --- source/tanya/async/event/iocp.d | 2 +- source/tanya/async/event/selector.d | 59 +++++++++++++++++++--- source/tanya/async/iocp.d | 2 +- source/tanya/async/package.d | 2 +- source/tanya/async/transport.d | 32 +++++++++++- source/tanya/async/watcher.d | 6 +-- source/tanya/container/string.d | 77 +++++++++++++++++++++++++++++ 7 files changed, 165 insertions(+), 15 deletions(-) create mode 100644 source/tanya/container/string.d diff --git a/source/tanya/async/event/iocp.d b/source/tanya/async/event/iocp.d index b6522d9..ff2b4c4 100644 --- a/source/tanya/async/event/iocp.d +++ b/source/tanya/async/event/iocp.d @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** - * Copyright: Eugene Wissner 2016. + * Copyright: Eugene Wissner 2016-2017. * 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) diff --git a/source/tanya/async/event/selector.d b/source/tanya/async/event/selector.d index 5508cac..0b2143f 100644 --- a/source/tanya/async/event/selector.d +++ b/source/tanya/async/event/selector.d @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** - * Copyright: Eugene Wissner 2016. + * Copyright: Eugene Wissner 2016-2017. * 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) @@ -13,6 +13,7 @@ module tanya.async.event.selector; version (Posix): import tanya.async.loop; +import tanya.async.protocol; import tanya.async.transport; import tanya.async.watcher; import tanya.container.buffer; @@ -28,6 +29,8 @@ class SelectorStreamTransport : StreamTransport { private ConnectedSocket socket_; + private Protocol protocol_; + /// Input buffer. package WriteBuffer!ubyte input; @@ -40,22 +43,64 @@ class SelectorStreamTransport : StreamTransport * Params: * loop = Event loop. * socket = Socket. + * protocol = Application protocol. + * + * Precondition: $(D_INLINECODE loop !is null + * && socket !is null + * && protocol !is null) */ - this(SelectorLoop loop, ConnectedSocket socket) @nogc + this(SelectorLoop loop, ConnectedSocket socket, Protocol protocol) @nogc + in + { + assert(loop !is null); + assert(socket !is null); + assert(protocol !is null); + } + body { socket_ = socket; this.loop = loop; + protocol_ = protocol; input = WriteBuffer!ubyte(8192, MmapPool.instance); } /** * Returns: Transport socket. */ - inout(ConnectedSocket) socket() inout pure nothrow @safe @nogc + ConnectedSocket socket() pure nothrow @safe @nogc { return socket_; } + /** + * Returns: Application protocol. + */ + @property Protocol protocol() pure nothrow @safe @nogc + { + return protocol_; + } + + /** + * Switches the protocol. + * + * The protocol is deallocated by the event loop, it should currently be + * allocated with $(D_PSYMBOL MmapPool). + * + * Params: + * protocol = Application protocol. + * + * Precondition: $(D_INLINECODE protocol !is null) + */ + @property void protocol(Protocol protocol) pure nothrow @safe @nogc + in + { + assert(protocol !is null); + } + body + { + protocol_ = protocol; + } + /** * Write some data to the transport. * @@ -224,7 +269,8 @@ abstract class SelectorLoop : Loop } IOWatcher io; - auto transport = MmapPool.instance.make!SelectorStreamTransport(this, client); + auto protocol = connection.protocol; + auto transport = MmapPool.instance.make!SelectorStreamTransport(this, client, protocol); if (connections.length > client.handle) { @@ -236,13 +282,12 @@ abstract class SelectorLoop : Loop } if (io is null) { - io = MmapPool.instance.make!IOWatcher(transport, - connection.protocol); + io = MmapPool.instance.make!IOWatcher(transport, protocol); connections[client.handle] = io; } else { - io(transport, connection.protocol); + io(transport, protocol); } reify(io, EventMask(Event.none), EventMask(Event.read, Event.write)); diff --git a/source/tanya/async/iocp.d b/source/tanya/async/iocp.d index 9730262..0dfcbe8 100644 --- a/source/tanya/async/iocp.d +++ b/source/tanya/async/iocp.d @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** - * Copyright: Eugene Wissner 2016. + * Copyright: Eugene Wissner 2016-2017. * 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) diff --git a/source/tanya/async/package.d b/source/tanya/async/package.d index 0c5a743..e9ed007 100644 --- a/source/tanya/async/package.d +++ b/source/tanya/async/package.d @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** - * Copyright: Eugene Wissner 2016. + * Copyright: Eugene Wissner 2016-2017. * 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) diff --git a/source/tanya/async/transport.d b/source/tanya/async/transport.d index d72d42d..6e4460c 100644 --- a/source/tanya/async/transport.d +++ b/source/tanya/async/transport.d @@ -3,13 +3,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** - * Copyright: Eugene Wissner 2016. + * Copyright: Eugene Wissner 2016-2017. * 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) */ module tanya.async.transport; +import tanya.async.protocol; import tanya.network.socket; /** @@ -45,6 +46,33 @@ interface WriteTransport : Transport */ interface DuplexTransport : ReadTransport, WriteTransport { + /** + * Returns: Application protocol. + * + * Postcondition: $(D_INLINECODE protocol !is null) + */ + @property Protocol protocol() pure nothrow @safe @nogc + out (protocol) + { + assert(protocol !is null); + } + + /** + * Switches the protocol. + * + * The protocol is deallocated by the event loop, it should currently be + * allocated with $(D_PSYMBOL MmapPool). + * + * Params: + * protocol = Application protocol. + * + * Precondition: $(D_INLINECODE protocol !is null) + */ + @property void protocol(Protocol protocol) pure nothrow @safe @nogc + in + { + assert(protocol !is null); + } } /** @@ -52,7 +80,7 @@ interface DuplexTransport : ReadTransport, WriteTransport */ interface SocketTransport : Transport { - @property inout(Socket) socket() inout pure nothrow @safe @nogc; + @property Socket socket() pure nothrow @safe @nogc; } /** diff --git a/source/tanya/async/watcher.d b/source/tanya/async/watcher.d index 44b7a1d..de23aa1 100644 --- a/source/tanya/async/watcher.d +++ b/source/tanya/async/watcher.d @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** - * Copyright: Eugene Wissner 2016. + * Copyright: Eugene Wissner 2016-2017. * 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) @@ -90,7 +90,7 @@ class ConnectionWatcher : Watcher /** * Returns: Socket. */ - @property inout(Socket) socket() inout pure nothrow @nogc + @property Socket socket() pure nothrow @nogc { return socket_; } @@ -222,7 +222,7 @@ class IOWatcher : ConnectionWatcher /** * Returns: Socket. */ - override @property inout(Socket) socket() inout pure nothrow @nogc + override @property Socket socket() pure nothrow @nogc { return transport.socket; } diff --git a/source/tanya/container/string.d b/source/tanya/container/string.d new file mode 100644 index 0000000..05f9e70 --- /dev/null +++ b/source/tanya/container/string.d @@ -0,0 +1,77 @@ +/* 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/. */ + +/** + * Copyright: Eugene Wissner 2016-2017. + * 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) + */ +module tanya.container.string; + +import core.exception; +import core.stdc.string; +import tanya.memory; + +/** + * UTF-8 string. + */ +struct String +{ + private char[] data; + private size_t length_; + + invariant + { + assert(length_ <= data.length); + } + + /// Ditto. + this(const(char)[] str, shared Allocator allocator = defaultAllocator) + nothrow @trusted @nogc + { + this(allocator); + + data = cast(char[]) allocator.allocate(str.length); + if (str.length > 0 && data is null) + { + onOutOfMemoryErrorNoGC(); + } + memcpy(data.ptr, str.ptr, str.length); + } + + /// Ditto. + this(const(wchar)[] str, shared Allocator allocator = defaultAllocator) + nothrow @trusted @nogc + { + this(allocator); + + } + + /// Ditto. + this(const(dchar)[] str, shared Allocator allocator = defaultAllocator) + nothrow @trusted @nogc + { + this(allocator); + + } + + /// Ditto. + this(shared Allocator allocator) pure nothrow @safe @nogc + in + { + assert(allocator !is null); + } + body + { + allocator_ = allocator; + } + + ~this() nothrow @trusted @nogc + { + allocator.deallocate(data); + } + + mixin DefaultAllocator; +}