Properly closing client connections, reworked client connection creation

Now the test script has two subsequent connections in it, for great justice.
This commit is contained in:
Neale Pickett 2008-03-06 21:30:49 -07:00
parent 36ef378852
commit c89eeb3160
7 changed files with 61 additions and 49 deletions

View File

@ -177,9 +177,9 @@ let chat script proc =
Unixqueue.run ues; Unixqueue.run ues;
with with
| Chat_match (got, expected) -> | Chat_match (got, expected) ->
raise (Failure ("Not matched: got " ^ raise (Failure ("Not matched: got \"" ^
(String.escaped got) ^ (String.escaped got) ^
", expected " ^ "\"\n expected " ^
(string_of_chat_event expected))) (string_of_chat_event expected)))
| Chat_timeout evt -> | Chat_timeout evt ->
raise (Failure ("Timeout waiting for " ^ raise (Failure ("Timeout waiting for " ^

View File

@ -21,14 +21,8 @@ let by_nick = Hashtbl.create 25
let error num args text = let error num args text =
Error (Command.create (Some !(Irc.name)) num args (Some text)) Error (Command.create (Some !(Irc.name)) num args (Some text))
let close cli ues g fd = let close cli =
Hashtbl.remove by_nick !(cli.nick); Iobuf.close cli.iobuf
Unix.close fd;
Unixqueue.remove_resource ues g (Unixqueue.Wait_in fd);
try
Unixqueue.remove_resource ues g (Unixqueue.Wait_out fd);
with Not_found ->
()
let write cli cmd = let write cli cmd =
Iobuf.write cli.iobuf cmd Iobuf.write cli.iobuf cmd
@ -40,6 +34,9 @@ let reply cli num ?(args=[]) text =
([!(cli.nick)] @ args) ([!(cli.nick)] @ args)
(Some text)) (Some text))
let handle_close cli () =
Hashtbl.remove by_nick !(cli.nick)
let handle_command cli iobuf cmd = let handle_command cli iobuf cmd =
match (Command.as_tuple cmd) with match (Command.as_tuple cmd) with
| (None, "OPER", [name; password], None) -> | (None, "OPER", [name; password], None) ->
@ -174,7 +171,7 @@ let rec handle_command_prereg (nick', username', realname', password') iobuf cmd
" " ^ Irc.version ^ " " ^ Irc.version ^
" " ^ modes ^ " " ^ modes ^
" " ^ Channel.modes); " " ^ Channel.modes);
Iobuf.rebind iobuf (handle_command cli) Iobuf.rebind iobuf (handle_command cli) (handle_close cli)
with Error cmd -> with Error cmd ->
Iobuf.write iobuf cmd Iobuf.write iobuf cmd
in in
@ -194,7 +191,10 @@ let rec handle_command_prereg (nick', username', realname', password') iobuf cmd
username = username; username = username;
realname = realname} realname = realname}
| _ -> | _ ->
Iobuf.rebind iobuf (handle_command_prereg acc) Iobuf.rebind iobuf (handle_command_prereg acc) ignore
let handle_connection ues grp fd =
let command_handler = handle_command_prereg (None, None, None, None) in
let close_handler = ignore in
Iobuf.bind ues grp fd command_handler close_handler
let create_command_handler () =
handle_command_prereg (None, None, None, None)

View File

@ -1,5 +1,5 @@
type t type t
val write : t -> Command.t -> unit val write : t -> Command.t -> unit
val create_command_handler : unit -> Iobuf.t -> Command.t -> unit val handle_connection : Unixqueue.event_system -> Unixqueue.group -> Unix.file_descr -> unit

View File

@ -8,7 +8,8 @@ type t = {ues: Unixqueue.event_system;
unsent: string ref; unsent: string ref;
ibuf: string; ibuf: string;
ibuf_len: int ref; ibuf_len: int ref;
handle_command: (t -> Command.t -> unit) ref} command_handler: (t -> Command.t -> unit) ref;
close_handler: (unit -> unit) ref}
let ibuf_max = 4096 let ibuf_max = 4096
let max_outq = 50 let max_outq = 50
@ -16,25 +17,6 @@ let obuf_max = 4096
let by_file_descr = Hashtbl.create 25 let by_file_descr = Hashtbl.create 25
let bind ues grp fd handle_command =
let (outq, unsent, ibuf, ibuf_len) =
(Queue.create (), ref "", String.create ibuf_max, ref 0)
in
let iobuf = {ues = ues;
grp = grp;
fd = fd;
outq = outq;
unsent = unsent;
ibuf = ibuf;
ibuf_len = ibuf_len;
handle_command = ref handle_command}
in
Hashtbl.replace by_file_descr fd iobuf;
Unixqueue.add_resource ues grp (Unixqueue.Wait_in fd, -.1.0)
let rebind t handle_command =
t.handle_command := handle_command
let write iobuf cmd = let write iobuf cmd =
let was_empty = Queue.is_empty iobuf.outq in let was_empty = Queue.is_empty iobuf.outq in
Queue.add cmd iobuf.outq; Queue.add cmd iobuf.outq;
@ -43,6 +25,7 @@ let write iobuf cmd =
iobuf.ues iobuf.grp (Unixqueue.Wait_out iobuf.fd, -.1.0) iobuf.ues iobuf.grp (Unixqueue.Wait_out iobuf.fd, -.1.0)
let close iobuf = let close iobuf =
!(iobuf.close_handler) ();
Hashtbl.remove by_file_descr iobuf.fd; Hashtbl.remove by_file_descr iobuf.fd;
Unix.close iobuf.fd; Unix.close iobuf.fd;
Unixqueue.remove_resource iobuf.ues iobuf.grp (Unixqueue.Wait_in iobuf.fd); Unixqueue.remove_resource iobuf.ues iobuf.grp (Unixqueue.Wait_in iobuf.fd);
@ -51,6 +34,13 @@ let close iobuf =
with Not_found -> with Not_found ->
() ()
let handle_close fd =
try
let iobuf = Hashtbl.find by_file_descr fd in
close iobuf
with Not_found ->
()
let crlf = Str.regexp "\r?\n" let crlf = Str.regexp "\r?\n"
let handle_input iobuf = let handle_input iobuf =
@ -65,7 +55,7 @@ let handle_input iobuf =
String.blit leftover 0 iobuf.ibuf 0 !(iobuf.ibuf_len) String.blit leftover 0 iobuf.ibuf 0 !(iobuf.ibuf_len)
| line :: tl -> | line :: tl ->
let parsed = Command.from_string line in let parsed = Command.from_string line in
!(iobuf.handle_command) iobuf parsed; !(iobuf.command_handler) iobuf parsed;
loop tl loop tl
in in
loop lines loop lines
@ -113,5 +103,24 @@ let handle_event ues esys e =
| Unixqueue.Extra exn -> | Unixqueue.Extra exn ->
print_endline "extra" print_endline "extra"
let add_event_handler ues g = let bind ues grp fd command_handler close_handler =
Unixqueue.add_handler ues g handle_event let (outq, unsent, ibuf, ibuf_len) =
(Queue.create (), ref "", String.create ibuf_max, ref 0)
in
let iobuf = {ues = ues;
grp = grp;
fd = fd;
outq = outq;
unsent = unsent;
ibuf = ibuf;
ibuf_len = ibuf_len;
command_handler = ref command_handler;
close_handler = ref close_handler}
in
Hashtbl.replace by_file_descr fd iobuf;
Unixqueue.add_resource ues grp (Unixqueue.Wait_in fd, -.1.0);
Unixqueue.add_close_action ues grp (fd, handle_close)
let rebind t command_handler close_handler =
t.command_handler := command_handler;
t.close_handler := close_handler

View File

@ -1,8 +1,7 @@
type t type t
val write : t -> Command.t -> unit val write : t -> Command.t -> unit
val bind : Unixqueue.event_system -> Unixqueue.group -> Unix.file_descr -> (t -> Command.t -> unit) -> unit val bind : Unixqueue.event_system -> Unixqueue.group -> Unix.file_descr -> (t -> Command.t -> unit) -> (unit -> unit) -> unit
val rebind: t -> (t -> Command.t -> unit) -> unit val rebind: t -> (t -> Command.t -> unit) -> (unit -> unit) -> unit
val close: t -> unit val close: t -> unit
val add_event_handler : Unixqueue.event_system -> Unixqueue.group -> unit val handle_event : Unixqueue.event_system -> Unixqueue.event Equeue.t -> Unixqueue.event -> unit

View File

@ -27,13 +27,10 @@ let establish_server ues connection_handler addr =
let main () = let main () =
let ues = Unixqueue.create_unix_event_system () in let ues = Unixqueue.create_unix_event_system () in
let g = Unixqueue.new_group ues in let g = Unixqueue.new_group ues in
let handle_connection fd = Unixqueue.add_handler ues g Iobuf.handle_event;
Iobuf.bind ues g fd (Client.create_command_handler ())
in
Iobuf.add_event_handler ues g;
establish_server establish_server
ues ues
handle_connection Client.handle_connection
(Unix.ADDR_INET (Unix.inet_addr_any, 7777)); (Unix.ADDR_INET (Unix.inet_addr_any, 7777));
ues#run () ues#run ()

View File

@ -6,8 +6,8 @@ open Irc
let do_chat script () = let do_chat script () =
let ircd_instance ues fd = let ircd_instance ues fd =
let g = Unixqueue.new_group ues in let g = Unixqueue.new_group ues in
Iobuf.add_event_handler ues g; Unixqueue.add_handler ues g Iobuf.handle_event;
Iobuf.bind ues g fd (Client.create_command_handler ()) Client.handle_connection ues g fd
in in
chat script ircd_instance chat script ircd_instance
@ -70,6 +70,13 @@ let regression_tests =
Send "ISON otherguy thirdguy\r\n"; Send "ISON otherguy thirdguy\r\n";
Recv ":testserver.test 303 nick :\r\n"; Recv ":testserver.test 303 nick :\r\n";
])); ]));
"Second connection" >::
(do_chat ((do_login "otherguy") @
[
Send "ISON nick otherguy\r\n";
Recv ":testserver.test 303 otherguy :otherguy\r\n";
]));
] ]
let _ = let _ =