106 lines
3.0 KiB
Factor
106 lines
3.0 KiB
Factor
! Copyright (C) 2009 Doug Coleman.
|
|
! See http://factorcode.org/license.txt for BSD license.
|
|
USING: accessors assocs calendar continuations destructors io
|
|
io.encodings.binary io.servers.connection io.sockets
|
|
io.streams.duplex fry kernel locals math math.ranges multiline
|
|
namespaces prettyprint random sequences sets splitting threads
|
|
tools.continuations ;
|
|
IN: managed-server
|
|
|
|
TUPLE: managed-server < threaded-server clients ;
|
|
|
|
TUPLE: managed-client
|
|
input-stream output-stream local-address remote-address
|
|
username object quit? logged-in? ;
|
|
|
|
HOOK: handle-login threaded-server ( -- username )
|
|
HOOK: handle-managed-client* managed-server ( -- )
|
|
HOOK: handle-already-logged-in managed-server ( -- )
|
|
HOOK: handle-client-join managed-server ( -- )
|
|
HOOK: handle-client-disconnect managed-server ( -- )
|
|
|
|
ERROR: already-logged-in username ;
|
|
|
|
M: managed-server handle-already-logged-in already-logged-in ;
|
|
M: managed-server handle-client-join ;
|
|
M: managed-server handle-client-disconnect ;
|
|
|
|
: server ( -- managed-client ) managed-server get ;
|
|
: client ( -- managed-client ) managed-client get ;
|
|
: clients ( -- assoc ) server clients>> ;
|
|
: client-streams ( -- assoc ) clients values ;
|
|
: username ( -- string ) client username>> ;
|
|
: everyone-else ( -- assoc )
|
|
clients [ drop username = not ] assoc-filter ;
|
|
: everyone-else-streams ( -- assoc ) everyone-else values ;
|
|
|
|
ERROR: no-such-client username ;
|
|
|
|
<PRIVATE
|
|
|
|
: (send-client) ( managed-client seq -- )
|
|
[ output-stream>> ] dip '[ _ print flush ] with-output-stream* ;
|
|
|
|
PRIVATE>
|
|
|
|
: send-client ( seq username -- )
|
|
clients ?at [ no-such-client ] [ (send-client) ] if ;
|
|
|
|
: send-everyone ( seq -- )
|
|
[ client-streams ] dip '[ _ (send-client) ] each ;
|
|
|
|
: send-everyone-else ( seq -- )
|
|
[ everyone-else-streams ] dip '[ _ (send-client) ] each ;
|
|
|
|
<PRIVATE
|
|
|
|
: <managed-client> ( username -- managed-client )
|
|
managed-client new
|
|
swap >>username
|
|
input-stream get >>input-stream
|
|
output-stream get >>output-stream
|
|
local-address get >>local-address
|
|
remote-address get >>remote-address ;
|
|
|
|
: maybe-login-client ( -- )
|
|
username clients key? [
|
|
handle-already-logged-in
|
|
] [
|
|
t client (>>logged-in?)
|
|
client username clients set-at
|
|
] if ;
|
|
|
|
: when-logged-in ( quot -- )
|
|
client logged-in?>> [ call ] [ drop ] if ; inline
|
|
|
|
: delete-managed-client ( -- )
|
|
[ username server clients>> delete-at ] when-logged-in ;
|
|
|
|
: handle-managed-client ( -- )
|
|
handle-login <managed-client> managed-client set
|
|
maybe-login-client [
|
|
handle-client-join
|
|
[ handle-managed-client* client quit?>> not ] loop
|
|
] when-logged-in ;
|
|
|
|
: cleanup-client ( -- )
|
|
[
|
|
delete-managed-client
|
|
handle-client-disconnect
|
|
] when-logged-in ;
|
|
|
|
PRIVATE>
|
|
|
|
M: managed-server handle-client*
|
|
managed-server set
|
|
[ handle-managed-client ]
|
|
[ cleanup-client ]
|
|
[ ] cleanup ;
|
|
|
|
: new-managed-server ( port name encoding class -- server )
|
|
new-threaded-server
|
|
swap >>name
|
|
swap >>insecure
|
|
f >>timeout
|
|
H{ } clone >>clients ; inline
|