From cf9bdcb93a4545a0b485cc14db9d2b27a1183929 Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Sat, 10 May 2008 21:10:45 -0600 Subject: [PATCH] Refactor how commands are handled. I may refactor it again. --- channel.ml | 67 +++++++++++++++++++++++++++-------------------------- channel.mli | 5 +++- client.ml | 12 +++++----- client.mli | 2 +- tests.ml | 12 +++++----- 5 files changed, 51 insertions(+), 47 deletions(-) diff --git a/channel.ml b/channel.ml index 28b1f98..461b917 100644 --- a/channel.ml +++ b/channel.ml @@ -50,38 +50,39 @@ let broadcast ?(metoo=false) chan sender command args text = let reply iobuf nick num ?(args=[]) text = write iobuf num (nick :: args) (Some text) -let handle_command cli nuhost cmd = - match (Command.as_tuple cmd) with - | (None, ("NOTICE" as cmd_name), [name], Some text) - | (None, ("PRIVMSG" as cmd_name), [name], Some text) -> - let nick = Irc.nick nuhost in - (try - let chan = String_map.find name !by_name in - if String_map.mem nick !(chan.clients) then - broadcast chan (cli, nuhost) cmd_name [name] (Some text) - else - reply cli nick "404" ~args:[name] "Cannot send to channel" - with Not_found -> - reply cli nick "403" ~args:[name] "No such channel") - | (None, "JOIN", ["0"], None) -> - (* Leave all channels *) - failwith "XXX: JOIN 0" - | (None, "JOIN", [name], None) -> - let nick = Irc.nick nuhost in - let chan = - try - String_map.find name !by_name - with Not_found -> - let c = {name = name; modes = ref ""; clients = ref String_map.empty} in - by_name := String_map.add name c !by_name; - c - in +let handle_action (cli_iobuf, cli_nuhost) chan_name action args text = + let chanopt = try + Some (String_map.find chan_name !by_name) + with Not_found -> + None + in + let nick = Irc.nick cli_nuhost in + match (action, chanopt, args, text) with + | ("NOTICE", Some chan, [], Some text) + | ("PRIVMSG", Some chan, [], Some text) -> if String_map.mem nick !(chan.clients) then - (* Apparently we're expected to drop the command *) - () + broadcast chan (cli_iobuf, cli_nuhost) action [chan_name] (Some text) else - let me = (cli, nuhost) in - chan.clients := String_map.add nick me !(chan.clients); - broadcast ~metoo:true chan me "JOIN" [name] None - | _ -> - () + reply cli_iobuf nick "404" ~args:[chan_name] "Cannot send to channel (join first)" + | ("JOIN", _, _, None) -> + let chan = + match chanopt with + | Some chan -> + chan + | None -> + let c = {name = chan_name; modes = ref ""; clients = ref String_map.empty} in + by_name := String_map.add chan_name c !by_name; + c + in + if String_map.mem nick !(chan.clients) then + (* Apparently we're expected to drop the command *) + () + else + let me = (cli_iobuf, cli_nuhost) in + chan.clients := String_map.add nick me !(chan.clients); + broadcast ~metoo:true chan me "JOIN" [chan.name] None + | (_, None, _, _) -> + reply cli_iobuf nick "403" ~args:[chan_name] "No such channel" + | _ -> + () + diff --git a/channel.mli b/channel.mli index 53a85a3..aebc329 100644 --- a/channel.mli +++ b/channel.mli @@ -2,6 +2,9 @@ type t val modes : string -val handle_command : Iobuf.t -> Irc.nuhost -> Command.t -> unit +(** [handle_action (cli_iobuf, cli_nuhost) chan_name action args text] + handles [action] on [chan_name] with arguments [args] and text + [text], sent by [cli_nuhost] from [cli_iobuf] *) +val handle_action : (Iobuf.t * Irc.nuhost) -> string -> string -> string list -> string option -> unit val is_channel_name : string -> bool diff --git a/client.ml b/client.ml index 4452412..3e88c60 100644 --- a/client.ml +++ b/client.ml @@ -56,8 +56,8 @@ let handle_command cli iobuf cmd = Iobuf.close iobuf message | (None, "JOIN", ["0"], None) -> () - | (None, "JOIN", [channels], None) -> - Channel.handle_command cli.iobuf (nuhost cli) cmd + | (None, "JOIN", [chan_name], None) -> + Channel.handle_action (cli.iobuf, (nuhost cli)) chan_name "JOIN" [] None | (None, "JOIN", [channels; keys], None) -> () | (None, "PART", [channels], message) -> @@ -74,17 +74,17 @@ let handle_command cli iobuf cmd = () | (None, "KICK", [channels; users], comment) -> () - | (None, ("PRIVMSG" as command), [target], Some text) - | (None, ("NOTICE" as command), [target], Some text) -> + | (None, ("PRIVMSG" as action), [target], Some text) + | (None, ("NOTICE" as action), [target], Some text) -> if Channel.is_channel_name target then - Channel.handle_command cli.iobuf (nuhost cli) cmd + Channel.handle_action (cli.iobuf, (nuhost cli)) target action [] (Some text) else begin try let peer = lookup target in write peer (Some (Irc.string_of_nuhost (nuhost cli))) - command [target] (Some text) + action [target] (Some text) with Not_found -> reply cli "401" ~args:[target] "No such nick/channel" end diff --git a/client.mli b/client.mli index 0c7ddc7..bf10d56 100644 --- a/client.mli +++ b/client.mli @@ -3,4 +3,4 @@ type t val write_command : t -> Command.t -> unit val write : t -> string option -> string -> string list -> string option -> unit val handle_connection : Dispatch.t -> Unix.file_descr -> Unix.sockaddr -> unit - + diff --git a/tests.ml b/tests.ml index 8fe89ff..07da2f9 100644 --- a/tests.ml +++ b/tests.ml @@ -414,9 +414,13 @@ let regression_tests = [ Send "ISON bob\r\n"; Recv ":testserver.test 303 alice :bob\r\n"; + Send "PRIVMSG #foo :snot\r\n"; + Recv ":testserver.test 403 alice #foo :No such channel\r\n"; + Send "NOTICE #foo :snot\r\n"; + Recv ":testserver.test 403 alice #foo :No such channel\r\n"; Send "JOIN #foo\r\n"; Recv ":alice!alice@UDS JOIN #foo\r\n"; - Send "PRIVMSG bob :Hi Bob!\r\n"; + Send "PRIVMSG bob :Come to #foo\r\n"; Recv ":bob!bob@UDS JOIN #foo\r\n"; Send "PRIVMSG #foo :hello bob\r\n"; Recv ":bob!bob@UDS NOTICE #foo :hello alice\r\n"; @@ -429,11 +433,7 @@ let regression_tests = [ Send "ISON alice charlie\r\n"; Recv ":testserver.test 303 bob :alice\r\n"; - Recv ":alice!alice@UDS PRIVMSG bob :Hi Bob!\r\n"; - Send "PRIVMSG #foo :snot\r\n"; - Recv ":testserver.test 404 bob #foo :Cannot send to channel\r\n"; - Send "NOTICE #foo :snot\r\n"; - Recv ":testserver.test 404 bob #foo :Cannot send to channel\r\n"; + Recv ":alice!alice@UDS PRIVMSG bob :Come to #foo\r\n"; Send "JOIN #foo\r\n"; Recv ":bob!bob@UDS JOIN #foo\r\n"; Recv ":alice!alice@UDS PRIVMSG #foo :hello bob\r\n";