diff --git a/lib/modules/Protocols.pmod/Ident.pmod b/lib/modules/Protocols.pmod/Ident.pmod index 556f1b72f8a11a7c6f5fd507e2ca1dc855e3dd37..3b21ca3580617d881d4fb3d40ba0131a532f161a 100644 --- a/lib/modules/Protocols.pmod/Ident.pmod +++ b/lib/modules/Protocols.pmod/Ident.pmod @@ -1,8 +1,144 @@ // An implementation of the IDENT protocol, specified in RFC 931. // -// $Id: Ident.pmod,v 1.4 1998/05/27 05:47:41 neotron Exp $ +// $Id: Ident.pmod,v 1.5 1998/05/28 00:13:41 grubba Exp $ +#define IDENT_DEBUG + +class lookup_async +{ + object con; + + function(array(string), mixed ...:void) callback; + array cb_args; + + string query; + string read_buf = ""; + + void do_callback(array(string) reply) + { +#ifdef IDENT_DEBUG + werror("Protocols.Ident: calling callback\n"); +#endif /* IDENT_DEBUG */ + + mixed err; + if (callback) { + err = catch { + callback(reply, @cb_args); + }; + callback = 0; + cb_args = 0; + } + if (con) { + con->close(); + destruct(con); + } + query = ""; + read_buf = ""; + con = 0; + if (err) { + throw(err); + } + } + + void write_cb() + { +#ifdef IDENT_DEBUG + werror("Protocols.Ident: sending query\n"); +#endif /* IDENT_DEBUG */ + + int i = con->write(query); + if (i >= 0) { + query = query[i..]; + if (sizeof(query)) { + return; + } + con->set_write_callback(0); + } else { + do_callback(({ "ERROR", "FAILED TO SEND REQUEST" })); + } + } + + void read_cb(mixed ignored, string data) + { +#ifdef IDENT_DEBUG + werror("Protocols.Ident: reading data\n"); +#endif /* IDENT_DEBUG */ + + read_buf += data; + int i = search(read_buf, "\r\n"); + if (i != -1) { + string reply = read_buf[..i-1]; + read_buf = read_buf[i+1..]; + + array(string) response = reply/":"; + if (sizeof(response) < 2) { + do_callback(({ "ERROR", "BAD REPLY" })); + } else { + do_callback(response[1..]); + } + } else if (sizeof(read_buf) > 1024) { + do_callback(({ "ERROR", "REPLY TOO LARGE" })); + } + } + + void close_cb() + { +#ifdef IDENT_DEBUG + werror("Protocols.Ident: Connection closed\n"); +#endif /* IDENT_DEBUG */ + + do_callback(({ "ERROR", "CONNECTION CLOSED" })); + } + + void timeout() + { +#ifdef IDENT_DEBUG + werror("Protocols.Ident: Timeout\n"); +#endif /* IDENT_DEBUG */ + + do_callback(({ "ERROR", "TIMEOUT" })); + } + + void create(object fd, function(array(string), mixed ...:void) cb, + mixed ... args) + { + string|array(string) raddr = fd->query_address(); + string|array(string) laddr = fd->query_address(1); + + if(!raddr || !laddr) { + // Does this ever happen? + error("Protocols.Ident - cannot lookup address"); + } + + laddr = laddr / " "; + raddr = raddr / " "; + + query = raddr[1]+","+laddr[1]+"\r\n"; + + con = Stdio.File(); + if (!con->open_socket(0, laddr[0])) { + destruct(con); + error("Protocols.Ident: open_socket() failed."); + } + mixed err; + if (err = catch(con->connect(raddr[0], 113))) { + destruct(con); + throw(err); + } + +#ifdef IDENT_DEBUG + werror(sprintf("Protocols.Ident: Connection OK, query:%O\n", query)); +#endif /* IDENT_DEBUG */ + + callback = cb; + cb_args = args; + con->set_nonblocking(read_cb, write_cb, close_cb); + + call_out(timeout, 60); + } +} + int|array (string) lookup(object fd) { mixed raddr; // Remote Address.