diff --git a/channel.ml b/channel.ml index 3a1d0bb..8b79f5f 100644 --- a/channel.ml +++ b/channel.ml @@ -8,11 +8,11 @@ type client = Iobuf.t * Irc.nuhost type t = {name: string; modes: string ref; - clients: client String_map.t} + clients: client String_map.t ref} let modes = "aimnqpsrtklb" -let channels = String_map.empty +let by_name = ref String_map.empty let is_channel_name name = match name.[0] with @@ -24,7 +24,54 @@ let is_channel_name name = let has_mode chan mode = String.contains !(chan.modes) mode -let handle_command iobuf (nick, username, hostname) cmd = +(* Channels handle: + + NICK, MODE, JOIN, PART, QUIT, TOPIC, NAMES, LIST, INVITE, KICK, PRIVMSG, NOTICE +*) + +let write iobuf command args text = + Iobuf.write iobuf (Command.create (Some !(Irc.name)) command args text) + +let broadcast ?(metoo=false) chan sender command args text = + let sender_iobuf, sender_nuhost = sender in + let cmd = + Command.create + (Some (Irc.string_of_nuhost sender_nuhost)) + command + args + text + in + let bwrite _ (iobuf, nuhost) = + if (metoo || (nuhost <> sender_nuhost)) then + Iobuf.write iobuf cmd + in + String_map.iter bwrite !(chan.clients) + + +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, "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 + if String_map.mem nick !(chan.clients) then + (* Apparently we're expected to drop the command *) + () + else + let me = (cli, nuhost) in + chan.clients := String_map.add nick me !(chan.clients); + broadcast ~metoo:true chan me "JOIN" [name] None | _ -> () diff --git a/channel.mli b/channel.mli index 73a33e6..53a85a3 100644 --- a/channel.mli +++ b/channel.mli @@ -1,10 +1,5 @@ type t -(* Channels handle: - - MODE, JOIN, PART, TOPIC, NAMES, LIST, INVITE, KICK, PRIVMSG, NOTICE -*) - val modes : string val handle_command : Iobuf.t -> Irc.nuhost -> Command.t -> unit diff --git a/client.ml b/client.ml index 08a9e97..89676c3 100644 --- a/client.ml +++ b/client.ml @@ -36,7 +36,7 @@ let write cli sender name args text = write_command cli (Command.create sender name args text) let reply cli num ?(args=[]) text = - write cli (Some !(Irc.name)) num ([!(cli.nick)] @ args) (Some text) + write cli (Some !(Irc.name)) num (!(cli.nick) :: args) (Some text) let handle_error cli iobuf message = Hashtbl.remove by_nick !(cli.nick) @@ -58,7 +58,8 @@ let handle_command cli iobuf cmd = | (None, "JOIN", ["0"], None) -> () | (None, "JOIN", [channels], None) -> - () + let nuhost = (!(cli.nick), cli.username, (Iobuf.addr cli.iobuf)) in + Channel.handle_command cli.iobuf nuhost cmd | (None, "JOIN", [channels; keys], None) -> () | (None, "PART", [channels], message) -> diff --git a/irc.ml b/irc.ml index fe2b4dd..26bf66d 100644 --- a/irc.ml +++ b/irc.ml @@ -40,3 +40,8 @@ let truncate s len = s else Str.string_before s (min slen len) + +let string_of_nuhost (nick, user, host) = nick ^ "!" ^ user ^ "@" ^ host +let nick (nick, user, host) = nick +let user (nick, user, host) = user +let host (nick, user, host) = host diff --git a/irc.mli b/irc.mli index a1627ae..d34cf6c 100644 --- a/irc.mli +++ b/irc.mli @@ -1,3 +1,4 @@ + (** (Nickname, username, hostname) tuple *) type nuhost = (string * string * string) @@ -8,3 +9,8 @@ val start_time : float val uppercase : string -> string val lowercase : string -> string val truncate : string -> int -> string + +val string_of_nuhost : nuhost -> string +val nick : nuhost -> string +val user : nuhost -> string +val host : nuhost -> string diff --git a/ircd.ml b/ircd.ml index 500923a..3ff931d 100644 --- a/ircd.ml +++ b/ircd.ml @@ -26,7 +26,7 @@ let establish_server d connection_handler addr = Unix.bind srv addr; Unix.listen srv 50; Unix.setsockopt srv Unix.SO_REUSEADDR true; - Dispatch.add d fd handle_event [Dispatch.Input]; + Dispatch.add d fd handle_event [Dispatch.Input] let main () = let d = Dispatch.create 50 in diff --git a/tests.ml b/tests.ml index d2bf6b8..d51c8e5 100644 --- a/tests.ml +++ b/tests.ml @@ -414,7 +414,10 @@ let regression_tests = [ Send "ISON bob\r\n"; Recv ":testserver.test 303 alice :bob\r\n"; + Send "JOIN #foo\r\n"; + Recv ":alice!alice@UDS JOIN #foo\r\n"; Send "PRIVMSG bob :Hi Bob!\r\n"; + Recv ":bob!bob@UDS JOIN #foo\r\n"; Send "QUIT :foo\r\n"; Recv ":testserver.test ERROR :So long\r\n"; ] @@ -425,6 +428,8 @@ let regression_tests = Send "ISON alice\r\n"; Recv ":testserver.test 303 bob :alice\r\n"; Recv ":alice!alice@UDS PRIVMSG bob :Hi Bob!\r\n"; + Send "JOIN #foo\r\n"; + Recv ":bob!bob@UDS JOIN #foo\r\n"; Send "QUIT :foo\r\n"; Recv ":testserver.test ERROR :So long\r\n"; ]