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.
This commit is contained in:
Eugen Wissner 2017-02-08 20:04:05 +01:00
parent 43c28b749d
commit 48a49c2a2d
7 changed files with 165 additions and 15 deletions

View File

@ -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)

View File

@ -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));

View File

@ -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)

View File

@ -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)

View File

@ -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;
}
/**

View File

@ -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;
}

View File

@ -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;
}