diff --git a/channel.ml b/channel.ml index 870bb51..0caf517 100644 --- a/channel.ml +++ b/channel.ml @@ -9,3 +9,11 @@ let lookup name = let create name = {name = name} + +let is_channel_name name = + match name.[0] with + | '#' | '&' | '!' | '+' -> + true + | _ -> + false + diff --git a/channel.mli b/channel.mli index 4691d8b..bd7a277 100644 --- a/channel.mli +++ b/channel.mli @@ -2,5 +2,7 @@ type t val modes : string -val create : string -> t val lookup : string -> t +val create : string -> t +val is_channel_name : string -> bool + diff --git a/client.ml b/client.ml index 447a9c3..44ab1d0 100644 --- a/client.ml +++ b/client.ml @@ -18,9 +18,15 @@ let dbg msg a = prerr_endline msg; a let by_nick = Hashtbl.create 25 +let lookup nick = + Hashtbl.find by_nick nick + let error num args text = Error (Command.create (Some !(Irc.name)) num args (Some text)) +let uhost cli = + (!(cli.nick) ^ "!" ^ cli.username ^ "@" ^ (Iobuf.addr cli.iobuf)) + let close cli = Iobuf.close cli.iobuf @@ -67,10 +73,22 @@ let handle_command cli iobuf cmd = () | (None, "KICK", [channels; users], comment) -> () - | (None, "PRIVMSG", [target], Some text) -> - () - | (None, "NOTICE", [target], Some text) -> - () + | (None, ("PRIVMSG" as command), [target], Some text) + | (None, ("NOTICE" as command), [target], Some text) -> + if Channel.is_channel_name target then + reply cli "403" ~args:[target] "No such channel" + else + begin + try + let peer = lookup target in + write peer (Command.create + (Some (uhost cli)) + command + [target] + (Some text)) + with Not_found -> + reply cli "401" ~args:[target] "No such nick/channel" + end | (None, "MOTD", [], None) -> reply cli "422" "MOTD File is missing" | (None, "LUSERS", [], None) -> diff --git a/iobuf.ml b/iobuf.ml index 1250b09..3d89b2f 100644 --- a/iobuf.ml +++ b/iobuf.ml @@ -8,6 +8,7 @@ type t = {ues: Unixqueue.event_system; unsent: string ref; ibuf: string; ibuf_len: int ref; + addr: string; command_handler: (t -> Command.t -> unit) ref; close_handler: (unit -> unit) ref} @@ -17,6 +18,8 @@ let obuf_max = 4096 let by_file_descr = Hashtbl.create 25 +let addr iobuf = iobuf.addr + let write iobuf cmd = let was_empty = Queue.is_empty iobuf.outq in Queue.add cmd iobuf.outq; @@ -107,6 +110,13 @@ let bind ues grp fd command_handler close_handler = let (outq, unsent, ibuf, ibuf_len) = (Queue.create (), ref "", String.create ibuf_max, ref 0) in + let addr = + match Unix.getpeername fd with + | Unix.ADDR_UNIX s -> + "UDS" + | Unix.ADDR_INET (addr, port) -> + Unix.string_of_inet_addr addr + in let iobuf = {ues = ues; grp = grp; fd = fd; @@ -114,6 +124,7 @@ let bind ues grp fd command_handler close_handler = unsent = unsent; ibuf = ibuf; ibuf_len = ibuf_len; + addr = addr; command_handler = ref command_handler; close_handler = ref close_handler} in diff --git a/iobuf.mli b/iobuf.mli index dcbc684..c869dda 100644 --- a/iobuf.mli +++ b/iobuf.mli @@ -1,5 +1,7 @@ type t +val addr : t -> string + val write : t -> Command.t -> 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 -> unit) -> unit diff --git a/tests.ml b/tests.ml index d8bf474..aac629c 100644 --- a/tests.ml +++ b/tests.ml @@ -69,6 +69,12 @@ let regression_tests = Recv ":testserver.test 303 nick :nick\r\n"; Send "ISON otherguy thirdguy\r\n"; Recv ":testserver.test 303 nick :\r\n"; + Send "PRIVMSG nick :hello\r\n"; + Recv ":nick!nick@UDS PRIVMSG nick :hello\r\n"; + Send "NOTICE nick :hello\r\n"; + Recv ":nick!nick@UDS NOTICE nick :hello\r\n"; + Send "PRIVMSG otherguy :hello\r\n"; + Recv ":testserver.test 401 nick otherguy :No such nick/channel\r\n"; ])); "Second connection" >::