diff --git a/src/connection.nim b/src/connection.nim index 46a56d5..96ff08c 100644 --- a/src/connection.nim +++ b/src/connection.nim @@ -1,5 +1,5 @@ import overrides/[asyncnet] -import std/[tables,sequtils, times,os , random, asyncdispatch, strutils, net, random] +import std/[tables,sequtils, times,os , random, asyncdispatch,strformat, strutils, net, random] import globals type @@ -7,30 +7,31 @@ type no, pending, yes Connection* = ref object - creation_time*: uint - action_start_time*: uint - id*: uint32 - trusted*: TrustStatus - address*: string - socket*: AsyncSocket - estabilished*: bool - isfakessl*:bool - port*:uint32 - + creation_time*: uint #creation epochtime + action_start_time*: uint #when recv/send action started (0 = idle) + register_start_time*: uint #when the connection is added to the pool (0 = idle) + id*: uint32 #global incremental id + trusted*: TrustStatus #when fake handshake perfromed + socket*: AsyncSocket #wrapped asyncsocket + estabilished*: bool #connection has started + isfakessl*:bool #broken ssl + port*:uint32 #the port the socket points to + Connections* = object - connections*: Table[uint32, Connection] + connections*: seq[Connection] var allConnections:seq[Connection] - -var lgid: uint32 = 1 +var lgid: uint32 = 1 #last incremental global id proc new_uid: uint32 = result = lgid inc lgid -var et:uint = 0 + +var et:uint = 0 #last epoch time proc isTrusted*(con: Connection): bool = con.trusted == TrustStatus.yes +#send with a simple low cost timeout template send*(con: Connection, data: string): untyped = con.action_start_time = et var result = con.socket.send(data) @@ -39,6 +40,7 @@ template send*(con: Connection, data: string): untyped = ) result +#recv with a simple low cost timeout template recv*(con: Connection, data: SomeInteger): untyped = con.action_start_time = et var result = con.socket.recv(data) @@ -47,47 +49,31 @@ template recv*(con: Connection, data: SomeInteger): untyped = ) result -proc isClosed*(con: Connection): bool = con.socket.isClosed() +template isClosed*(con: Connection): bool = con.socket.isClosed() proc prepairClose(con: Connection) = if con.isfakessl: if con.isTrusted: con.socket.isSsl = true -template close*(con: Connection) = - prepairClose(con) - con.socket.close() - let i = allConnections.find(con) - if i != -1: - allConnections.del(i) - -# proc close*(cons: var Connections, con: Connection) = -# con.socket.close() -# if cons.connections.hasKey(con.id): -# cons.connections.del(con.id) - - -proc takeRandom*(cons: Connections): Connection = - var chosen = rand(cons.connections.len()-1) - for k in cons.connections.keys: - if chosen == 0: - return cons.connections[k] - dec chosen - - raise newException(ValueError, "could not take random conn") +proc close*(con: Connection) = + if not con.isClosed(): + prepairClose(con) + con.socket.close() + let i = allConnections.find(con) + if i != -1: + allConnections.del(i) -proc newConnection*(socket: AsyncSocket = nil, address: string, buffered: bool = globals.socket_buffered): Connection = +proc newConnection*(socket: AsyncSocket = nil, buffered: bool = globals.socket_buffered): Connection = new(result) - # result.recv_buffer = newStringOfCap(globals.connection_buf_cap) - # if id == 0 : result.id = new_uid() - result.id = 0 + result.id = new_uid() result.creation_time = epochTime().uint32 result.trusted = TrustStatus.pending - result.address = address result.action_start_time = 0 + result.register_start_time = 0 if socket == nil: result.socket = newAsyncSocket(buffered = buffered) else: result.socket = socket @@ -96,36 +82,35 @@ proc newConnection*(socket: AsyncSocket = nil, address: string, buffered: bool = result.socket.setSockOpt(OptNoDelay, true) allConnections.add result -# proc attachID*(con : var Connection)= -# if con.id == 0: -# con.id = new_uid() - proc grab*(cons: var Connections):Connection= if cons.connections.len() == 0: return nil - for k in cons.connections.keys: - assert cons.connections.pop(k,result) - return result - -proc register*(cons: var Connections, con: Connection) = - if con.id == 0: - con.id = new_uid() - assert not cons.connections.hasKey con.id - - cons.connections[con.id] = con - - + result = cons.connections[0] + cons.connections.del(0) + result.register_start_time = 0 +proc register*(cons: var Connections, con: Connection) = + con.register_start_time = et + cons.connections.add con proc startController*(){.async.}= while true: et = epochTime().uint await sleepAsync(1000) + allConnections.keepIf( proc(x: Connection):bool = - if x.action_start_time == 0: return true - if et - x.action_start_time > globals.max_idle_time : - prepairClose(x) - x.socket.close() - return false + if x.action_start_time != 0: + if et - x.action_start_time > globals.max_idle_time : + prepairClose(x) + x.socket.close() + if globals.log_conn_destory: echo "[Controller] closed a idle connection" + return false + + if x.register_start_time != 0: + if et - x.register_start_time > globals.max_pool_unused_time : + prepairClose(x) + x.socket.close() + if globals.log_conn_destory: echo "[Controller] closed a unused connection" + return false return true )