first attempt to proper channel cleanup

This commit is contained in:
Dmitriy Ryajov 2019-09-07 17:34:40 -06:00
parent 65ce1a93fc
commit b5dcfa9bc4

View File

@ -16,7 +16,7 @@
## This still needs to be implemented properly - I'm leaving it ## This still needs to be implemented properly - I'm leaving it
## here to not forget that this needs to be fixed ASAP. ## here to not forget that this needs to be fixed ASAP.
import tables, sequtils, strformat, options import tables, sequtils, options, strformat
import chronos import chronos
import coder, types, channel, import coder, types, channel,
../../varint, ../../varint,
@ -56,10 +56,15 @@ proc newStreamInternal*(m: Mplex,
result = newChannel(id, m.connection, initiator, name) result = newChannel(id, m.connection, initiator, name)
m.getChannelList(initiator)[id] = result m.getChannelList(initiator)[id] = result
method handle*(m: Mplex): Future[void] {.async, gcsafe.} = method handle*(m: Mplex) {.async, gcsafe.} =
while not m.connection.closed:
try: try:
let (id, msgType, data) = await m.connection.readMsg() while not m.connection.closed:
let msgRes = await m.connection.readMsg()
if msgRes.isNone:
await sleepAsync(100.millis)
continue
let (id, msgType, data) = msgRes.get()
let initiator = bool(ord(msgType) and 1) let initiator = bool(ord(msgType) and 1)
var channel: Channel var channel: Channel
if MessageType(msgType) != MessageType.New: if MessageType(msgType) != MessageType.New:
@ -72,7 +77,18 @@ method handle*(m: Mplex): Future[void] {.async, gcsafe.} =
of MessageType.New: of MessageType.New:
channel = await m.newStreamInternal(false, id, cast[string](data)) channel = await m.newStreamInternal(false, id, cast[string](data))
if not isNil(m.streamHandler): if not isNil(m.streamHandler):
await m.streamHandler(newConnection(channel)) let handlerFut = m.streamHandler(newConnection(channel))
proc cleanUpChan(udata: pointer) {.gcsafe.} =
if handlerFut.finished:
channel.close().addCallback(
proc(udata: pointer) =
# TODO: is waitFor() OK here?
channel.cleanUp()
.addCallback(proc(udata: pointer) =
echo &"cleaned up channel {$id}")
)
handlerFut.addCallback(cleanUpChan)
continue
of MessageType.MsgIn, MessageType.MsgOut: of MessageType.MsgIn, MessageType.MsgOut:
await channel.pushTo(data) await channel.pushTo(data)
of MessageType.CloseIn, MessageType.CloseOut: of MessageType.CloseIn, MessageType.CloseOut:
@ -80,6 +96,7 @@ method handle*(m: Mplex): Future[void] {.async, gcsafe.} =
m.getChannelList(initiator).del(id) m.getChannelList(initiator).del(id)
of MessageType.ResetIn, MessageType.ResetOut: of MessageType.ResetIn, MessageType.ResetOut:
await channel.resetByRemote() await channel.resetByRemote()
break
else: raise newMplexUnknownMsgError() else: raise newMplexUnknownMsgError()
finally: finally:
await m.connection.close() await m.connection.close()
@ -94,7 +111,7 @@ proc newMplex*(conn: Connection,
method newStream*(m: Mplex, name: string = ""): Future[Connection] {.async, gcsafe.} = method newStream*(m: Mplex, name: string = ""): Future[Connection] {.async, gcsafe.} =
let channel = await m.newStreamInternal() let channel = await m.newStreamInternal()
await m.connection.writeMsg(channel.id, MessageType.New, cast[seq[byte]](toSeq(name.items))) await m.connection.writeMsg(channel.id, MessageType.New, name)
result = newConnection(channel) result = newConnection(channel)
method close*(m: Mplex) {.async, gcsafe.} = method close*(m: Mplex) {.async, gcsafe.} =