mirror of https://github.com/nealey/irc-bot
Convert to be a bot!
This commit is contained in:
parent
cf9bdcb93a
commit
488fa6a04c
|
@ -1,13 +1,14 @@
|
||||||
OCAMLPACKS[] =
|
OCAMLPACKS[] =
|
||||||
|
unix
|
||||||
str
|
str
|
||||||
OCAML_CLIBS = ocamlepoll
|
OCAML_CLIBS = ocamlepoll
|
||||||
OCAMLCFLAGS += -g
|
OCAMLCFLAGS += -g
|
||||||
|
|
||||||
.DEFAULT: ircd
|
.DEFAULT: bot
|
||||||
|
|
||||||
StaticCLibrary(ocamlepoll, epoll_wrapper)
|
StaticCLibrary(ocamlepoll, epoll_wrapper)
|
||||||
|
|
||||||
OCamlProgram(ircd, ircd irc command iobuf dispatch client channel)
|
OCamlProgram(bot, bot irc command iobuf dispatch)
|
||||||
|
|
||||||
section
|
section
|
||||||
OCAMLPACKS[] +=
|
OCAMLPACKS[] +=
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
let write iobuf command args text =
|
||||||
|
let cmd = Command.create None command args text in
|
||||||
|
print_endline ("--> " ^ (Command.as_string cmd));
|
||||||
|
Iobuf.write iobuf cmd
|
||||||
|
|
||||||
|
let handle_command iobuf cmd =
|
||||||
|
print_endline ("<-- " ^ (Command.as_string cmd));
|
||||||
|
match Command.as_tuple cmd with
|
||||||
|
| (_, "PING", _, text) ->
|
||||||
|
write iobuf "PONG" [] text
|
||||||
|
| (_, "001", _, _) ->
|
||||||
|
write iobuf "JOIN" ["#bot"] None
|
||||||
|
| (Some who, "JOIN", [], Some chan) ->
|
||||||
|
write iobuf "PRIVMSG" [chan] (Some "hi asl")
|
||||||
|
| _ ->
|
||||||
|
()
|
||||||
|
|
||||||
|
let handle_error iobuf str =
|
||||||
|
print_endline str
|
||||||
|
|
||||||
|
let main () =
|
||||||
|
let host = Unix.gethostbyname "woozle.org" in
|
||||||
|
let dispatcher = Dispatch.create 5 in
|
||||||
|
let conn = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
|
||||||
|
let _ = Unix.connect conn (Unix.ADDR_INET (host.Unix.h_addr_list.(0), 6667)) in
|
||||||
|
let iobuf = Iobuf.create dispatcher conn "woozle" handle_command handle_error in
|
||||||
|
write iobuf "NICK" ["bot"] None;
|
||||||
|
write iobuf "USER" ["bot"; "bot"; "bot"] (Some "Da Bot");
|
||||||
|
Dispatch.run dispatcher
|
||||||
|
|
||||||
|
|
||||||
|
let _ =
|
||||||
|
main ()
|
88
channel.ml
88
channel.ml
|
@ -1,88 +0,0 @@
|
||||||
module String_map =
|
|
||||||
Map.Make (struct
|
|
||||||
type t = string
|
|
||||||
let compare = compare
|
|
||||||
end)
|
|
||||||
|
|
||||||
type client = Iobuf.t * Irc.nuhost
|
|
||||||
|
|
||||||
type t = {name: string;
|
|
||||||
modes: string ref;
|
|
||||||
clients: client String_map.t ref}
|
|
||||||
|
|
||||||
let modes = "aimnqpsrtklb"
|
|
||||||
|
|
||||||
let by_name = ref String_map.empty
|
|
||||||
|
|
||||||
let is_channel_name name =
|
|
||||||
match name.[0] with
|
|
||||||
| '#' | '&' | '!' | '+' ->
|
|
||||||
true
|
|
||||||
| _ ->
|
|
||||||
false
|
|
||||||
|
|
||||||
let has_mode chan mode =
|
|
||||||
String.contains !(chan.modes) mode
|
|
||||||
|
|
||||||
(* 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_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
|
|
||||||
broadcast chan (cli_iobuf, cli_nuhost) action [chan_name] (Some text)
|
|
||||||
else
|
|
||||||
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"
|
|
||||||
| _ ->
|
|
||||||
()
|
|
||||||
|
|
10
channel.mli
10
channel.mli
|
@ -1,10 +0,0 @@
|
||||||
type t
|
|
||||||
|
|
||||||
val modes : string
|
|
||||||
|
|
||||||
(** [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
|
|
||||||
|
|
220
client.ml
220
client.ml
|
@ -1,220 +0,0 @@
|
||||||
open Irc
|
|
||||||
|
|
||||||
(* ==========================================
|
|
||||||
* Client stuff
|
|
||||||
*)
|
|
||||||
type t = {iobuf: Iobuf.t;
|
|
||||||
nick: string ref;
|
|
||||||
away: string option ref;
|
|
||||||
username: string;
|
|
||||||
realname: string}
|
|
||||||
|
|
||||||
exception Error of Command.t
|
|
||||||
|
|
||||||
let modes = "l"
|
|
||||||
|
|
||||||
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 nuhost cli = (!(cli.nick), cli.username, (Iobuf.addr cli.iobuf))
|
|
||||||
|
|
||||||
let kill cli message =
|
|
||||||
Iobuf.close cli.iobuf ("Killed: " ^ message)
|
|
||||||
|
|
||||||
let write_command cli cmd =
|
|
||||||
Iobuf.write cli.iobuf cmd
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
let handle_error cli iobuf message =
|
|
||||||
Hashtbl.remove by_nick !(cli.nick)
|
|
||||||
|
|
||||||
let handle_command cli iobuf cmd =
|
|
||||||
match (Command.as_tuple cmd) with
|
|
||||||
| (None, "OPER", [name; password], None) ->
|
|
||||||
()
|
|
||||||
| (None, "MODE", target :: args, None) ->
|
|
||||||
()
|
|
||||||
| (None, "SERVICE", [nickname; _; distribution; svctype; _], Some info) ->
|
|
||||||
()
|
|
||||||
| (None, "QUIT", [], None) ->
|
|
||||||
write cli (Some !(Irc.name)) "ERROR" [] (Some "So long");
|
|
||||||
Iobuf.close iobuf "No reason provided"
|
|
||||||
| (None, "QUIT", [], Some message) ->
|
|
||||||
write cli (Some !(Irc.name)) "ERROR" [] (Some "So long");
|
|
||||||
Iobuf.close iobuf message
|
|
||||||
| (None, "JOIN", ["0"], None) ->
|
|
||||||
()
|
|
||||||
| (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) ->
|
|
||||||
()
|
|
||||||
| (None, "TOPIC", [channel], None) ->
|
|
||||||
()
|
|
||||||
| (None, "TOPIC", [channel], Some topic) ->
|
|
||||||
()
|
|
||||||
| (None, "NAMES", [channels], None) ->
|
|
||||||
()
|
|
||||||
| (None, "LIST", [channels], None) ->
|
|
||||||
()
|
|
||||||
| (None, "INVITE", [nickname; channel], None) ->
|
|
||||||
()
|
|
||||||
| (None, "KICK", [channels; users], comment) ->
|
|
||||||
()
|
|
||||||
| (None, ("PRIVMSG" as action), [target], Some text)
|
|
||||||
| (None, ("NOTICE" as action), [target], Some text) ->
|
|
||||||
if Channel.is_channel_name target then
|
|
||||||
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)))
|
|
||||||
action [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) ->
|
|
||||||
()
|
|
||||||
| (None, "VERSION", [], None) ->
|
|
||||||
reply cli "351" ~args:[Irc.version; !(Irc.name)] ""
|
|
||||||
| (None, "STATS", [], None) ->
|
|
||||||
()
|
|
||||||
| (None, "TIME", [], None) ->
|
|
||||||
let now = Unix.gmtime (Unix.time ()) in
|
|
||||||
let timestr =
|
|
||||||
Printf.sprintf "%04d-%02d-%02dT%02d:%02d:%02dZ"
|
|
||||||
(now.Unix.tm_year + 1900)
|
|
||||||
now.Unix.tm_mday
|
|
||||||
(match now.Unix.tm_mon with
|
|
||||||
| 0 -> 12
|
|
||||||
| mon -> mon)
|
|
||||||
now.Unix.tm_hour
|
|
||||||
now.Unix.tm_min
|
|
||||||
now.Unix.tm_sec
|
|
||||||
in
|
|
||||||
reply cli "391" ~args:[!(Irc.name)] timestr;
|
|
||||||
| (None, "ADMIN", [], None) ->
|
|
||||||
()
|
|
||||||
| (None, "INFO", [], None) ->
|
|
||||||
reply cli "371" (Printf.sprintf "pgircd v%s" Irc.version);
|
|
||||||
reply cli "371" (Printf.sprintf "Running since %f" Irc.start_time);
|
|
||||||
reply cli "374" "End of INFO list"
|
|
||||||
| (None, "SERVLIST", [], None) ->
|
|
||||||
()
|
|
||||||
| (None, "SQUERY", [servicename], Some text) ->
|
|
||||||
()
|
|
||||||
| (None, "WHO", [], None) ->
|
|
||||||
()
|
|
||||||
| (None, "WHO", [mask], None) ->
|
|
||||||
()
|
|
||||||
| (None, "WHO", [mask; "o"], None) ->
|
|
||||||
()
|
|
||||||
| (None, "WHIOS", [masks], None) ->
|
|
||||||
()
|
|
||||||
| (None, "KILL", [nickname; comment], None) ->
|
|
||||||
()
|
|
||||||
| (None, "PING", [], Some text)
|
|
||||||
| (None, "PING", [text], None) ->
|
|
||||||
write cli (Some !(Irc.name)) "PONG" [!(Irc.name)] (Some text)
|
|
||||||
| (None, "PONG", [payload], None) ->
|
|
||||||
(* We do nothing. *)
|
|
||||||
()
|
|
||||||
| (None, "ERROR", [], Some message) ->
|
|
||||||
write cli (Some !(Irc.name)) "NOTICE" [!(cli.nick)] (Some "Bummer.")
|
|
||||||
| (None, "AWAY", [], None) ->
|
|
||||||
cli.away := None;
|
|
||||||
reply cli "305" "You are no longer marked as being away"
|
|
||||||
| (None, "AWAY", [], Some message) ->
|
|
||||||
cli.away := Some message;
|
|
||||||
reply cli "306" "You have been marked as being away"
|
|
||||||
| (None, "REHASH", [], None) ->
|
|
||||||
()
|
|
||||||
| (None, "WALLOPS", [], Some text) ->
|
|
||||||
()
|
|
||||||
| (None, "ISON", nicks, None) ->
|
|
||||||
let ison = List.filter (Hashtbl.mem by_nick) nicks in
|
|
||||||
reply cli "303" (String.concat " " ison)
|
|
||||||
| (_, name, _, _) ->
|
|
||||||
reply cli "421" ~args:[name] "Unknown or misconstructed command"
|
|
||||||
|
|
||||||
let set_nick cli nick =
|
|
||||||
if Hashtbl.mem by_nick nick then
|
|
||||||
raise (error "433" [nick] "Nickname in use");
|
|
||||||
Hashtbl.remove by_nick !(cli.nick);
|
|
||||||
Hashtbl.replace by_nick nick cli;
|
|
||||||
cli.nick := nick
|
|
||||||
|
|
||||||
let rec handle_command_prereg (nick, username, realname, password) iobuf cmd =
|
|
||||||
(* Handle a command during the login phase *)
|
|
||||||
let acc =
|
|
||||||
match (Command.as_tuple cmd) with
|
|
||||||
| (None, "PASS", [password'], None) ->
|
|
||||||
(nick, username, realname, Some password')
|
|
||||||
| (None, "USER", [username'; _; _], Some realname') ->
|
|
||||||
(nick, Some username', Some (Irc.truncate realname' 40), password)
|
|
||||||
| (None, "NICK", [nick'], None) ->
|
|
||||||
(Some nick', username, realname, password)
|
|
||||||
| _ ->
|
|
||||||
Iobuf.write iobuf (Command.create
|
|
||||||
(Some !(Irc.name))
|
|
||||||
"451" ["*"]
|
|
||||||
(Some "Register first."));
|
|
||||||
(nick, username, realname, password)
|
|
||||||
in
|
|
||||||
let welcome cli =
|
|
||||||
try
|
|
||||||
set_nick cli !(cli.nick);
|
|
||||||
reply cli "001" "Welcome to IRC.";
|
|
||||||
reply cli "002" ("I am " ^ !(Irc.name) ^
|
|
||||||
" Running version " ^ Irc.version);
|
|
||||||
reply cli "003" ("This server was created " ^
|
|
||||||
(string_of_float Irc.start_time));
|
|
||||||
reply cli "004" (!(Irc.name) ^
|
|
||||||
" " ^ Irc.version ^
|
|
||||||
" " ^ modes ^
|
|
||||||
" " ^ Channel.modes);
|
|
||||||
Iobuf.bind iobuf (handle_command cli) (handle_error cli)
|
|
||||||
with Error cmd ->
|
|
||||||
Iobuf.write iobuf cmd
|
|
||||||
in
|
|
||||||
match acc with
|
|
||||||
| (Some nick, Some username, Some realname, None) ->
|
|
||||||
welcome {iobuf = iobuf;
|
|
||||||
nick = ref nick;
|
|
||||||
away = ref None;
|
|
||||||
username = username;
|
|
||||||
realname = realname}
|
|
||||||
| (Some nick, Some username, Some realname, Some password) ->
|
|
||||||
Iobuf.write iobuf (Command.create
|
|
||||||
(Some !(Irc.name))
|
|
||||||
"NOTICE" ["AUTH"]
|
|
||||||
(Some "*** Authentication unimplemented"));
|
|
||||||
welcome {iobuf = iobuf;
|
|
||||||
nick = ref nick;
|
|
||||||
away = ref None;
|
|
||||||
username = username;
|
|
||||||
realname = realname}
|
|
||||||
| _ ->
|
|
||||||
Iobuf.bind iobuf (handle_command_prereg acc) (fun _ _ -> ())
|
|
||||||
|
|
||||||
let handle_connection d fd addr =
|
|
||||||
let handle_command = handle_command_prereg (None, None, None, None) in
|
|
||||||
Iobuf.create d fd addr handle_command (fun _ _ -> ())
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
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
|
|
||||||
|
|
30
command.ml
30
command.ml
|
@ -1,27 +1,33 @@
|
||||||
type t = string option * string * string list * string option
|
type t = {sender: string option;
|
||||||
|
name: string;
|
||||||
|
args: string list;
|
||||||
|
text: string option}
|
||||||
|
|
||||||
let create sender name args text =
|
let create sender name args text =
|
||||||
(sender, name, args, text)
|
{sender = sender;
|
||||||
|
name = name;
|
||||||
|
args = args;
|
||||||
|
text = text}
|
||||||
|
|
||||||
let anon = create None
|
let anon = create None
|
||||||
|
|
||||||
let as_string (sender, name, args, text) =
|
let as_string cmd =
|
||||||
let ret = Buffer.create 120 in
|
let ret = Buffer.create 120 in
|
||||||
(match sender with
|
(match cmd.sender with
|
||||||
| None ->
|
| None ->
|
||||||
()
|
()
|
||||||
| Some s ->
|
| Some s ->
|
||||||
Buffer.add_char ret ':';
|
Buffer.add_char ret ':';
|
||||||
Buffer.add_string ret s;
|
Buffer.add_string ret s;
|
||||||
Buffer.add_char ret ' ');
|
Buffer.add_char ret ' ');
|
||||||
Buffer.add_string ret name;
|
Buffer.add_string ret cmd.name;
|
||||||
(match args with
|
(match cmd.args with
|
||||||
| [] ->
|
| [] ->
|
||||||
()
|
()
|
||||||
| l ->
|
| l ->
|
||||||
Buffer.add_char ret ' ';
|
Buffer.add_char ret ' ';
|
||||||
Buffer.add_string ret (String.concat " " l));
|
Buffer.add_string ret (String.concat " " l));
|
||||||
(match text with
|
(match cmd.text with
|
||||||
| None ->
|
| None ->
|
||||||
()
|
()
|
||||||
| Some txt ->
|
| Some txt ->
|
||||||
|
@ -64,9 +70,9 @@ let rec from_string line =
|
||||||
loop None [] line
|
loop None [] line
|
||||||
|
|
||||||
|
|
||||||
let as_tuple cmd = cmd
|
let as_tuple cmd = (cmd.sender, cmd.name, cmd.args, cmd.text)
|
||||||
|
|
||||||
let sender (sender, name, args, text) = sender
|
let sender cmd = cmd.sender
|
||||||
let name (sender, name, args, text) = name
|
let name cmd = cmd.name
|
||||||
let args (sender, name, args, text) = args
|
let args cmd = cmd.args
|
||||||
let text (sender, name, args, text) = text
|
let text cmd = cmd.text
|
||||||
|
|
53
inspect.c
53
inspect.c
|
@ -1,53 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <caml/mlvalues.h>
|
|
||||||
|
|
||||||
void
|
|
||||||
margin (int n)
|
|
||||||
{
|
|
||||||
while (n-- > 0)
|
|
||||||
printf(".");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
print_block(value v,int m)
|
|
||||||
{
|
|
||||||
int size, i;
|
|
||||||
margin(m);
|
|
||||||
if (Is_long(v))
|
|
||||||
{ printf("immediate value (%d)\n", Long_val(v)); return; };
|
|
||||||
printf ("memory block: size=%d - ", size=Wosize_val(v));
|
|
||||||
switch (Tag_val(v))
|
|
||||||
{
|
|
||||||
case Closure_tag :
|
|
||||||
printf("closure with %d free variables\n", size-1);
|
|
||||||
margin(m+4); printf("code pointer: %p\n",Code_val(v)) ;
|
|
||||||
for (i=1;i<size;i++) print_block(Field(v,i), m+4);
|
|
||||||
break;
|
|
||||||
case String_tag :
|
|
||||||
printf("string: %s (%s)\n", String_val(v),(char *) v);
|
|
||||||
break;
|
|
||||||
case Double_tag:
|
|
||||||
printf("float: %g\n", Double_val(v));
|
|
||||||
break;
|
|
||||||
case Double_array_tag :
|
|
||||||
printf ("float array: ");
|
|
||||||
for (i=0;i<size/Double_wosize;i++) printf(" %g", Double_field(v,i));
|
|
||||||
printf("\n");
|
|
||||||
break;
|
|
||||||
case Abstract_tag : printf("abstract type\n"); break;
|
|
||||||
default:
|
|
||||||
if (Tag_val(v)>=No_scan_tag) { printf("unknown tag"); break; };
|
|
||||||
printf("structured block (tag=%d):\n",Tag_val(v));
|
|
||||||
for (i=0;i<size;i++) print_block(Field(v,i),m+4);
|
|
||||||
}
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
value
|
|
||||||
inspect_block (value v)
|
|
||||||
{
|
|
||||||
print_block(v,4);
|
|
||||||
fflush(stdout);
|
|
||||||
return v;
|
|
||||||
}
|
|
16
iobuf.ml
16
iobuf.ml
|
@ -7,7 +7,7 @@ type t = {d: Dispatch.t;
|
||||||
unsent: string ref;
|
unsent: string ref;
|
||||||
ibuf: string;
|
ibuf: string;
|
||||||
ibuf_len: int ref;
|
ibuf_len: int ref;
|
||||||
addr: Unix.sockaddr;
|
name: string;
|
||||||
handle_command: command_handler ref;
|
handle_command: command_handler ref;
|
||||||
handle_error: error_handler ref;
|
handle_error: error_handler ref;
|
||||||
alive: bool ref}
|
alive: bool ref}
|
||||||
|
@ -19,12 +19,7 @@ let ibuf_max = 4096
|
||||||
let max_outq = 50
|
let max_outq = 50
|
||||||
let obuf_max = 4096
|
let obuf_max = 4096
|
||||||
|
|
||||||
let addr iobuf =
|
let name iobuf = iobuf.name
|
||||||
match iobuf.addr with
|
|
||||||
| Unix.ADDR_UNIX s ->
|
|
||||||
"UDS"
|
|
||||||
| Unix.ADDR_INET (addr, port) ->
|
|
||||||
Unix.string_of_inet_addr addr
|
|
||||||
|
|
||||||
let crlf = Str.regexp "\r?\n"
|
let crlf = Str.regexp "\r?\n"
|
||||||
|
|
||||||
|
@ -111,15 +106,16 @@ let bind iobuf handle_command handle_error =
|
||||||
iobuf.handle_command := handle_command;
|
iobuf.handle_command := handle_command;
|
||||||
iobuf.handle_error := handle_error
|
iobuf.handle_error := handle_error
|
||||||
|
|
||||||
let create d fd addr handle_command handle_error =
|
let create d fd name handle_command handle_error =
|
||||||
let iobuf = {d = d;
|
let iobuf = {d = d;
|
||||||
fd = fd;
|
fd = fd;
|
||||||
outq = Queue.create ();
|
outq = Queue.create ();
|
||||||
unsent = ref "";
|
unsent = ref "";
|
||||||
ibuf = String.create ibuf_max;
|
ibuf = String.create ibuf_max;
|
||||||
ibuf_len = ref 0;
|
ibuf_len = ref 0;
|
||||||
addr = addr;
|
name = name;
|
||||||
handle_command = ref handle_command;
|
handle_command = ref handle_command;
|
||||||
handle_error = ref handle_error;
|
handle_error = ref handle_error;
|
||||||
alive = ref true} in
|
alive = ref true} in
|
||||||
Dispatch.add d fd (handle_events iobuf) [Dispatch.Input]
|
Dispatch.add d fd (handle_events iobuf) [Dispatch.Input];
|
||||||
|
iobuf
|
||||||
|
|
|
@ -3,9 +3,9 @@ type t
|
||||||
type command_handler = t -> Command.t -> unit
|
type command_handler = t -> Command.t -> unit
|
||||||
type error_handler = t -> string -> unit
|
type error_handler = t -> string -> unit
|
||||||
|
|
||||||
val create : Dispatch.t -> Unix.file_descr -> Unix.sockaddr -> command_handler -> error_handler -> unit
|
val create : Dispatch.t -> Unix.file_descr -> string -> command_handler -> error_handler -> t
|
||||||
val close: t -> string -> unit
|
val close: t -> string -> unit
|
||||||
|
|
||||||
val addr : t -> string
|
val name : t -> string
|
||||||
val write : t -> Command.t -> unit
|
val write : t -> Command.t -> unit
|
||||||
val bind : t -> command_handler -> error_handler -> unit
|
val bind : t -> command_handler -> error_handler -> unit
|
||||||
|
|
1
irc.mli
1
irc.mli
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
(** (Nickname, username, hostname) tuple *)
|
(** (Nickname, username, hostname) tuple *)
|
||||||
type nuhost = (string * string * string)
|
type nuhost = (string * string * string)
|
||||||
|
|
||||||
|
|
40
ircd.ml
40
ircd.ml
|
@ -1,40 +0,0 @@
|
||||||
let dbg msg a =
|
|
||||||
prerr_endline msg;
|
|
||||||
a
|
|
||||||
|
|
||||||
(** Establish a server on the given address.
|
|
||||||
|
|
||||||
[connection_handler] will be called with the file descriptor of
|
|
||||||
any new connections.
|
|
||||||
*)
|
|
||||||
let establish_server d connection_handler addr =
|
|
||||||
let rec handle_event fd events =
|
|
||||||
match events with
|
|
||||||
| [] ->
|
|
||||||
()
|
|
||||||
| Dispatch.Input :: tl ->
|
|
||||||
let cli_fd, cli_addr = Unix.accept fd in
|
|
||||||
connection_handler cli_fd cli_addr;
|
|
||||||
handle_event fd tl
|
|
||||||
| Dispatch.Hangup :: tl ->
|
|
||||||
Dispatch.delete d fd;
|
|
||||||
handle_event fd tl
|
|
||||||
| _ :: tl ->
|
|
||||||
handle_event fd tl
|
|
||||||
in
|
|
||||||
let srv = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
|
|
||||||
Unix.bind srv addr;
|
|
||||||
Unix.listen srv 50;
|
|
||||||
Unix.setsockopt srv Unix.SO_REUSEADDR true;
|
|
||||||
Dispatch.add d fd handle_event [Dispatch.Input]
|
|
||||||
|
|
||||||
let main () =
|
|
||||||
let d = Dispatch.create 50 in
|
|
||||||
establish_server
|
|
||||||
ues
|
|
||||||
(Client.handle_connection d)
|
|
||||||
(Unix.ADDR_INET (Unix.inet_addr_any, 6667));
|
|
||||||
Dispatch.run d
|
|
||||||
|
|
||||||
let _ =
|
|
||||||
main ()
|
|
Loading…
Reference in New Issue