Author: dylan
Date: 2005-07-18 00:34:36 -0400 (Mon, 18 Jul 2005)
New Revision: 869

Modified:
   trunk/
   trunk/perl/client/lib/Haver/Client/POE.pm
Log:
 [EMAIL PROTECTED]:  dylan | 2005-07-18 00:34:14 -0400
 Um, svk is being weird.



Property changes on: trunk
___________________________________________________________________
Name: svk:merge
   - 1f59643a-e6e5-0310-bc24-f7d4c744f460:/haver/havercurs-objc:43089
1f59643a-e6e5-0310-bc24-f7d4c744f460:/haver/local/trunk:11166
1f59643a-e6e5-0310-bc24-f7d4c744f460:/haver/local/trunk-merge-10131:11178
27e50396-46e3-0310-8b22-ae223a1f35ce:/local:212
e9404bb1-7af0-0310-a7ff-e22194cd388b:/haver/local:1268
edfcd8bd-4ce7-0310-a97e-bb1efd40edf3:/local:238
   + 1f59643a-e6e5-0310-bc24-f7d4c744f460:/haver/havercurs-objc:43089
1f59643a-e6e5-0310-bc24-f7d4c744f460:/haver/local/trunk:11166
1f59643a-e6e5-0310-bc24-f7d4c744f460:/haver/local/trunk-merge-10131:11178
27e50396-46e3-0310-8b22-ae223a1f35ce:/local:212
e9404bb1-7af0-0310-a7ff-e22194cd388b:/haver/local:1272
edfcd8bd-4ce7-0310-a97e-bb1efd40edf3:/local:238

Modified: trunk/perl/client/lib/Haver/Client/POE.pm
===================================================================
--- trunk/perl/client/lib/Haver/Client/POE.pm   2005-07-18 04:32:51 UTC (rev 
868)
+++ trunk/perl/client/lib/Haver/Client/POE.pm   2005-07-18 04:34:36 UTC (rev 
869)
@@ -17,16 +17,37 @@
 # along with this module; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-# heap fields:
-# heap => {
-#   name => user name,
-#   reg  => {
-#     event name => { session ID => 1 }
-#   },
-#   wheel => active wheel,
-#   state => see below constants,
-#   # for connect events sent while still shutting down
-#   pending => { Host => host, Port => port, Name => name ] | nonexistent
+# object fields:
+# self => {
+# [persistent data]
+#   options => { key => value },
+#   handlers => {
+#     type => {
+#       event name => {
+#         reverse => {
+#           stringified $subref => index
+#         },
+#         forward => [
+#           $subref,
+#           ...
+#         ]
+#       } # event name =>
+#     } # type =>
+#   }, # handlers =>
+#   connection => {
+#   [connection data]
+#     UID => $uid,
+#     authmethods => [ acceptable auth methods ],
+#     state => STATE_NAME,
+#     want => 'CURRENTLY_WANTED',
+#     pending => [
+#       ['WAITING', 'FOR', 'WANT'],
+#     ],
+#     POE => {
+#       connwheel => POE::Wheel::ConnectionFactory,
+#       sockwheel => POE::Wheel::ReadWrite
+#     },
+#   } # connection =>
 # }
 
 =head1 NAME
@@ -41,7 +62,7 @@
   $conn->register(connected => \&on_connect);
   $conn->connect(      Host => 'example.com',
                                        Port => 7070,
-                                       Name => 'example');
+                                       UID  => 'example');
 
 =head1 DESCRIPTION
 
@@ -56,72 +77,53 @@
 package Haver::Client::POE;
 use strict;
 use warnings;
-use Carp;
-use Data::Dumper;
-use Regexp::Shellish;
 
 use constant {
-    S_IDLE   => 0, # not connected, not connecting
-    S_CONN   => 1, # establishing socket connection
-    S_INIT   => 2, # C: HAVER sent
-    S_LOGIN  => 3, # S: HAVER recieved, C: IDENT sent
-    S_ONLINE => 4, # S: HELLO received
-    S_DYING  => 5, # C: BYE sent, socket still open
+       TRUE => 1,
+       FALSE => 0,
+       STATE_IDLE => 0,        # not connected or connecting   
+       STATE_CONNECT => 1,     # establishing connection
+       STATE_AUTH => 2,        # authenticating
+       STATE_READY => 3,       # ready for user control
+       STATE_DISCON => 4,      # disconnecting
 };
 
+use Carp;
+
 use POE qw(Wheel::ReadWrite
           Wheel::SocketFactory);
 
-use Haver::Protocol::Filter;
+use POE::Filter::Haver;
+use Haver::Preprocessor;
+use Haver::Formats::Error;
 
 our $VERSION = 0.06;
 
-our %failures = (
-    'invalid.name' => "The server rejected the name %1%.",
-    'reserved.name' => "The name %1% is reserved for internal use by the 
server.",
-    'exists.user' => "The name %1% is in use.",
-    'unknown.user' => "The user %1% is not online.",
-    'unknown.channel' => "The channel %1% does not exist.",
-    'unknown.namespace' => "The namespace %1% does not exist. This is probably 
an application bug.",
-    'invalid.type' => "The type of a message was invalid. This is almost 
certainly an application error.",
-    'already.joined' => "Tried to join %1% when already in it.",
-    'already.parted' => "Tried to leave %1% when not in it.",
-);
-    
-sub _format {
-    my @args = @_;
-    shift @args; # S: FAIL
-    my $code = $args[0];
-
-    if (!$failures{$code}) {
-        return "Unknown error: " . join(' ', @args);
-    }
-
-    my $msg = $failures{$code};
-    $msg = s{%(\d+)%}{$args[$1] || "MISSING ARGUMENT $1"}eg;
-    return $msg;
-}
-
 sub _call {
        return POE::Kernel->call(POE::Kernel->get_active_session(), @_);
 }
 
-sub _dispatch {
-    _call('__dispatch', @_);
-}
-
 sub _dprint {
        my ($level, @text) = @_;
-       return unless POE::Kernel->get_active_session()->get_heap()->{debug} >= 
$level;
+       return unless 
POE::Kernel->get_active_session()->get_heap()->{object}{debug} >= $level;
        print STDERR @text;
 }
 
 sub _dprintf {
        my ($level, $fmt, @text) = @_;
-       return unless POE::Kernel->get_active_session()->get_heap()->{debug} >= 
$level;
+       return unless 
POE::Kernel->get_active_session()->get_heap()->{object}{debug} >= $level;
        printf STDERR $fmt, @text;
 }
 
+sub _object_states {
+       my ($self, $ehash) = @_;
+       $ehash = {qw{
+               _start                  _start
+               _default                _default
+               }, %$ehash};
+       return $self->SUPER::_object_states($ehash);
+}
+
 ### SETUP
 
 =head2 spawn($alias [, $Z<>resolver])
@@ -136,10 +138,12 @@
 sub spawn {
        my ($pkg, $alias, $resolver) = @_;
 
-       my $heap = {
-        reg => {},
-        state => S_IDLE,
-        alias => $alias,
+       my $self = {
+               options => {
+                       version => "Haver::Client::POE/$VERSION",
+               },
+               handlers => {
+               },
         resolver => $resolver
        };
 
@@ -187,16 +191,22 @@
 }
 
 sub _start {
-    my ($kernel, $alias) = @_[KERNEL,ARG0];
-    $kernel->alias_set($alias);
+       die "STUB";
 }
 
-### SESSION MANAGEMENT
+# Internal: _init_event_type($type)
+# Prepares to register events of type $type
 
-=head2 connect(Host => $Z<>host, Name => $Z<>name, [Port => $Z<>port])
+sub _init_event_type {
+       my $self = shift;
+       $self->{handlers}{shift} = {
+               hhash => {},
+               byname => {},
+       }
+}
 
-Connects to the haver server. The Host option is mandatory, all others are 
optional.
-If it is already connected, it will disconnect, then connect with the new 
parameters.
+# Internal: _init_wants
+# Sets up default handlers for wants
 
 =cut
 
@@ -301,19 +311,41 @@
     # XXX: timeout
 }
 
-sub _input {
-    my ($kernel, $heap, $arg) = @_[KERNEL,HEAP,ARG0];
-    return if (ref $arg ne 'ARRAY' || @$arg == 0);
-    print STDERR "S: ", join "\t", @$arg;
-    print STDERR "\n";
-    _dispatch('raw_in', @$arg);
-    my $cmd = $arg->[0];
-    $kernel->yield("_ev_$cmd", @$arg);
+
+
+=head2 setoptions(option => value [, ...])
+
+Sets one or more options to the given value. The following options are 
available:
+
+=head3 debug => level
+
+Sets debugging to the given level. 0 will disable debugging.
+
+=head3 autorespond => [ ... ]
+
+Enables autoresponding to certain types of messages. Currently only PING? and 
TIME? are supported.
+
+=head3 version => "foobar/0.1"
+
+Sets the string sent in response to S: WANT VERSION
+
+=cut
+
+sub setoptions {
+       die "STUB";
 }
 
-sub _err {
-    _dispatch('disconnected', @_[ARG0..ARG2]);
-    _call('_cleanup');
+### SESSION MANAGEMENT
+
+=head2 connect(Host => $Z<>host, [Port => $Z<>port])
+
+Connects to the haver server. The Host option is mandatory, all others are 
optional.
+If it is already connected, it will disconnect, then connect with the new 
parameters.
+
+=cut
+
+sub connect {
+       die "STUB";
 }
 
 =head2 disconnect(Z<>)
@@ -330,27 +362,9 @@
     $poe_kernel->delay('_force_down', 5);
 }
 
-sub _force_down {
-    my $heap = $_[HEAP];
-    $heap->{state} = S_IDLE;
-    _call('_cleanup');
-}
-
-sub _cleanup {
-    my $heap = $_[HEAP];
-    $poe_kernel->delay('_force_down');
-    if ($heap->{pending}) {
-        my @opts = %{delete $heap->{pending}};
-        $poe_kernel->yield('connect', @opts);
-    }
-    delete $heap->{wheel};
-    delete $heap->{name};
-    $heap->{state} = S_IDLE;
-}
-
 =head2 send_raw(@args)
 
-Sends the arguments specified to the haver server. No checking is performed, 
though escaping will be done.
+Sends the arguments specified to the haver server. No checking is performed, 
though escaping may occur.
 
 =cut
 
@@ -372,12 +386,34 @@
 =cut
 
 sub send {
-    my ($kernel, @args) = @_[KERNEL,ARG0..$#_];
-    _call('send_raw', @args);
+       die "STUB"
 }
 
 ### CLIENT EVENTS
 
+=head2 login(UID => $Z<>uid)
+
+Specifies the UID to use to log in. If authentication is already complete,
+this has no effect.
+
+=cut
+
+sub login {
+       die "STUB";
+}
+
+=head2 authenticate($Z<>method, @Z<>args)
+
+Authenticates to the server. $method must be an object of type
+Haver::Client::POE::Auth capable of handling an authentication
+type listed in the auth_request() message.
+
+=cut
+
+sub authenticate {
+       die "STUB";
+}
+
 =head2 join($Z<>channel)
 
 Attempts to join $channel
@@ -385,8 +421,7 @@
 =cut
 
 sub join {
-    my $channel = $_[ARG0];
-    _call('send', 'JOIN', $channel);
+       die "STUB";
 }
 
 =head2 part($Z<>channel)
@@ -396,205 +431,367 @@
 =cut
 
 sub part {
-    my $channel = $_[ARG0];
-    _call('send', 'PART', $channel);
+       die "STUB";
 }
 
-=head2 in($Z<>channel, $Z<>type, @Z<>args)
+=head2 make($Z<>channel)
 
-Sends a message with specified type and arguments to $channel.
+Ask the server to create a channel $channel.
 
 =cut
 
-sub public {
-    my ($kernel, $heap, $c, $t, @a) = @_[KERNEL,HEAP,ARG0..$#_];
-    _call('send', 'IN', $c, $t, @a);
+sub make {
+       die "STUB";
 }
 
-=head2 to($Z<>uid, $Z<>type, @Z<>args)
+=head2 msg($Z<>channel, $Z<>type, $Z<>text)
 
-Sends a private message with specified type and arguments to $uid.
+Sends a message with specified type and text to $channel.
 
 =cut
 
-sub private {
-    my ($kernel, $heap, $d, $t, @a) = @_[KERNEL,HEAP,ARG0..$#_];
-    _call('send', 'TO', $d, $t, @a);
+sub msg {
+       die "STUB";
 }
 
-=head2 list($Z<>channel [, $Z<>type])
+=head2 pmsg($Z<>uid, $Z<>type, $Z<>text)
 
-Ask the server which entities of $type are in $channel. If $type is not
-given, it defaults to 'user'.
+Sends a private message with specified type and text to $uid.
 
 =cut
 
-sub list {
-    my ($chan, $type) = @_[ARG0, ARG1];
-    $type = defined $type || 'user';
-    _call('send', 'LIST', $chan, $type);
+sub pmsg {
+       die "STUB";
 }
 
-=head2 destroy(Z<>)
+=head2 users($Z<>channel)
 
-Disconnects from the Haver server, and destroys the session.
+Ask the server which users are on $channel.
 
 =cut
 
-sub destroy {
-       my ($kernel, $heap) = @_[KERNEL,HEAP];
-    _dispatch('destroyed');
-    delete $heap->{pending};
-    my $reg = $heap->{reg};
-    foreach my $ehash (values %$reg) {
-        foreach my $id (keys %$ehash) {
-            $poe_kernel->refcount_decrement($id, $ehash->{$id});
-        }
-    }
-    $heap->{reg} = {};
-    _call('disconnect');
-    $kernel->alias_remove($heap->{alias});
+sub users {
+       die "STUB";
 }
 
-## server-response stuff
+=head2 chans(Z<>)
 
-sub _ev_HAVER {
-    my ($kernel, $heap) = @_[KERNEL,HEAP];
-    return if ($heap->{state} != S_INIT); # should never happen, unless the
-                                          # server is non-compliant
-    $kernel->yield('send_raw', 'IDENT', $heap->{name});
-    $heap->{state} = S_LOGIN;
-}
+Ask the server for a list of all channels
 
-sub _ev_HELLO {
-    my $heap = $_[HEAP];
-    $heap->{state} = S_ONLINE;
-    _dispatch('ready');
-}
+=cut
 
-sub _ev_JOIN {
-    my ($heap, $chan, $name) = @_[HEAP,ARG1,ARG2];
-    if ($name eq $heap->{name}) {
-        _dispatch('ijoined', $chan);
-    } else {
-        _dispatch('join', $chan, $name);
-    }
+sub chans {
+       die "STUB";
 }
 
-sub _ev_PART {
-    my ($heap, $chan, $name) = @_[HEAP,ARG1,ARG2];
-    if ($name eq $heap->{name}) {
-        _dispatch('iparted', $chan);
-    } else {
-        _dispatch('part', $chan, $name);
-    }
-}
+=head2 destroy(Z<>)
 
-sub _ev_LIST {
-    my ($heap, $chan, $ns, @things) = @_[HEAP,ARG1..$#_];
-    return unless defined $ns;
-    _dispatch('list', $chan, $ns, @things);
-}
+Disconnects from the Haver server, and destroys the session. This event may 
not complete
+immediately, so you should not attempt to create another session with the same 
alias
+until it finishes.
 
-sub _ev_IN {
-    _dispatch('public', @_[ARG1..$#_]);
-}
+=cut
 
-sub _ev_FROM {
-    _dispatch('private', @_[ARG1..$#_]);
+sub destroy {
+       die "STUB";
 }
 
-sub _ev_PING {
-    _call('send_raw', 'PONG', @_[ARG1..$#_]);
+sub _default {
+       my ( $kernel, $state, $event, $args, $self ) = @_[ KERNEL, STATE, ARG0, 
ARG1, OBJECT ];
+       $args ||= [];   # Prevents uninitialized-value warnings.
+       # DEBUG: "default: $state = $event. Args:\n", Dumper $args;
+       return 0;
 }
 
-sub _ev_BYE {
-    my ($type, $detail) = @_[ARG2,ARG3];
-    _dispatch('bye', $detail);
-    _call('_cleanup');
+=head1 HANDLERS
+
+Handlers are subroutines called to handle some event from the server. Any
+number of handlers may be registered to an event, and they will be called
+in reverse order of registration until one indicates that it has handled the
+event.
+
+The handler prototype is as follows:
+
+  sub handler {
+    my ($handled, $type, $name, $args) = @_;
+       # ...
+       $handled = 1; # To handle the event
+  }
+
+$type is the type of event, $name is the event name, and $args is an array ref
+of arguments for the event.
+
+If $$handled is 0 when the handler returns, the next handler in the chain will
+be called. Any changes to the contents of $args will be passed on.
+
+If no handler in a chain handles the event, an event with the same type and
+a name of '_default' will be generated, with the old event name prepended
+to @args. If no handler in the _default chain handles the event, it will be
+discarded.
+
+=head2 METHODS FOR HANDLER MANIPULATION
+
+=head3 register_handler($Z<>type, $Z<>event, $Z<>handler)
+
+Register a handler $handler for an event of type $type, name $event. If such
+a handler already exists, does nothing.
+
+=cut
+
+sub register_handler {
+       my ($self, $type, $event, $handler) = @_;
+       my $htype = $self->{handlers}{$type}
+               or croak "Unknown event type $type";
+       my $hevent = $htype->{$event};
+       if (!$hevent) {
+               $hevent = $htype->{$event} = {
+                       forward => {},
+                       reverse => {},
+               };
+       }
+       return if (exists $hevent->{reverse}{$handler});
+       my $index = @{$hevent->{forward}};
+       push @{$hevent->{forward}}, $handler;
+       $hevent->{reverse}{$handler} = $index;
 }
 
-sub _ev_FAIL {
-    my $msg = _format(@_[ARG0..$#_]);
-    _dispatch('fail', $msg, @_[ARG0..$#_]);
-    my $code = $_[ARG1];
-    $code =~ tr/./_/;
-    _dispatch("fail_$code", $msg, @_[ARG0..$#_]);
+=head3 unregister_handler($Z<>type, $Z<>event, $Z<>handler)
+
+Unregisters a handler previously registered by passing the same arguments
+to register_handler. If such a handler does not exist, does nothing.
+
+=cut
+
+sub unregister_handler {
+       my ($self, $type, $event, $handler) = @_;
+       my $htype = $self->{handlers}{$type}
+               or croak "Unknown event type $type";
+       my $hevent = $self->{handlers}{$type}{$event} or return;
+       my $index = $hevent->{reverse}{$handler} or return;
+       # Remove the item
+       splice @{$hevent->{forward}}, $index, 1;
+       # and renumber the ones afterward
+       my $len = @{$hevent->{forward}};
+       for (; $index < $len; $index++) {
+               my $handler = $hevent->{forward}[$index];
+               $hevent->{reverse}{$handler} = $index;
+       }
+       # and delete the reverse mapping
+       delete $hevent->{reverse}{$handler};
 }
 
-sub _default {
-       my ( $kernel, $state, $event, $args, $self ) = @_[ KERNEL, STATE, ARG0, 
ARG1, OBJECT ];
-       $args ||= [];   # Prevents uninitialized-value warnings.
-       # DEBUG: "default: $state = $event. Args:\n", Dumper $args;
-       return 0;
+# Internal: _event_dispatch($type, $event, @args)
+# dispatches event $event
+
+sub _event_dispatch {
+       my ($self, $type, $event, @args) = @_;
+       my $etype = $self->{handlers}{$type}
+               or croak "Unknown event type $etype";
+       my $ev = $etype->{$event};
+       if (!$ev) {
+               if ($event eq '_default') {
+                       return; # Nobody seems to be interested.
+               }
+               $self->_event_dispatch($type, '_default', $event, @args);
+       }
+       for my $handler (@{$ev->{forward}}) {
+               my $handled = 0;
+               $handler->(\$handled, $type, $event, [EMAIL PROTECTED]);
+               return if $handled;
+       }
+       if ($event ne '_default') {
+               $self->_event_dispatch($type, '_default', $event, @args);
+       }
 }
 
+
+
+1;
+__END__
+
+=head2 TYPES OF HANDLERS
+
+=head3 want
+
+Handlers of type 'want' are invoked when the server sends a S: WANT message. 
The
+first argument of the S: WANT is the event name, the rest are used as
+arguments for the first handler.
+
+The default action, should all handlers pass the event, is to send a
+C: CANT $event to the server.
+
+=head3 smsg
+
+Handlers of type 'smsg' are invoked whenever a command is received from the 
server.
+The command name is used for the event name, and the arguments are passed for
+the first handler's @args.
+
+Note that adding a handler with $type of smsg, and $event of 'WANT' may
+prevent handlers of $type want from being called.
+
 =head1 EVENTS
 
-docme
+Events are sent to inform multiple handlers of some happening on the server.
+Any number of event callbacks may be registered to an event, and they will all
+be invoked in an undefined order when the event is dispatched.
 
 =cut
 
+# implementation notes:
+# events are implemented with handlers, with type 'event'
+# register and unregister create an anonymous wrapper closure to hide the
+# details. These subs are stored in %{$self->{evwrap}}
+# TODO: expire evwrap entries
+
 =head2 EVENT MANIPULATION FUNCTIONS
 
-=head3 register(@Z<>events)
+=head3 register(event => handler)
 
+Registers to receive a specified event with the specified handler function.
+The special event 'all' may be used to receive all events.
+
 =cut
 
 sub register {
-       my ($kernel, $heap, $session, @events) = 
@_[KERNEL,HEAP,SENDER,ARG0..$#_];
-    my $reg = $heap->{reg};
-    my $id  = $session->ID;
-    foreach my $event (@events) {
-        $event = uc $event;
-        next if exists $reg->{$event}{$id};
-        my $tag = '1' . $reg->{$event} . '\0' . $id . '\0' . rand;
-        $reg->{$event}{$id} = $tag;
-        $kernel->refcount_increment( $id, $tag );
-    }
+       my ($self, @events) = @_;
+       while (@events) {
+               my ($ev, $handler) = splice @events, 0, 2;
+               my $wrap = $self->{evwrap}{$handler} || sub {
+                       my ($handled, $type, $name, $args) = @_[1..3];
+                       if ($type ne 'event') {
+                               die "Impossible: event handler on non-event 
type!";
+                       }
+                       $handler->($name, @$args);
+               };
+               $self->{evwrap}{$handler} = $wrap;
+               $self->register_handler('event', $ev, $wrap);
+       }
 }
 
-=head3 unregister(@Z<>events)
+=head3 unregister(event => handler)
 
+Unregisters the given handler for the specified event.
 
 =cut
 
 sub unregister {
-       my ($kernel, $heap, $session, @events) = 
@_[KERNEL,HEAP,SENDER,ARG0..$#_];
-    my $reg = $heap->{reg};
-    my $id  = $session->ID;
-    foreach my $event (@events) {
-        $event = uc $event;
-        my $tag;
-        next unless $tag = delete $reg->{$event}{$id};
-        $kernel->refcount_decrement( $id, $tag );
-    }
+       my ($self, @events) = @_;
+       while (@events) {
+               my ($ev, $handler) = splice @events, 0, 2;
+               my $wrap = $self->{evwrap}{$handler} or next;
+               $self->unregister_handler('event', $ev, $wrap);
+       }
 }
 
 
-sub __dispatch {
-    my ($kernel, $heap, $evname, @args) = @_[KERNEL,HEAP,ARG0..$#_];
-    $evname = uc $evname;
-    my $reg = $heap->{reg};
-    $reg->{$evname} ||= {};
-    $reg->{ALL}     ||= {};
-    my %targ = (%{$reg->{$evname}}, %{$reg->{ALL}});
-    my @ids  = keys %targ;
+=head2 TYPES OF EVENTS
 
-    unshift @args, [$heap->{alias}];
+Client events have the following prototype:
 
     foreach my $id (@ids) {
         $kernel->post($id, "haver_$evname", @args);
     }
 }
 
-=head2 TYPES OF EVENTS
+The contents of @args vary depending on the event name, and are documented
+below.
 
-docme
+=head4 connected(Z<>)
 
+This event is sent when a connection is established (but before it is logged 
in)
+
+=head4 connect_fail($Z<>enum, $Z<>estr)
+
+The connection could not be established. An error code is in $enum, and the 
human-readable
+version is in $estr
+
+=head4 disconnected($Z<>enum, $Z<>estr)
+
+The connection has been lost. If the server closed the connection, $enum will 
be 0 and $estr will
+be meaningless. If the user closed the connection, and the server failed to 
respond, $enum will be -1.
+Otherwise, $enum will contain an error code, and $estr the human-readable 
version.
+
+=head4 raw_in(@data)
+
+The client has received @data from the Haver server. Mostly useful for 
debugging.
+
+=head4 raw_out(@data)
+
+The client has sent @data to the Haver server. Mostly useful for debugging.
+
+=head4 login_request(Z<>)
+
+The server is asking for a UID, and one was not provided in connect().
+The authentication will not proceed until login() is invoked with the UID.
+
+=head4 auth_request(@Z<>methods)
+
+The server requests authentication using one of the listed methods. The
+authentication will not proceed until authenticate() is invoked with a
+suitable authentication handler.
+
+=head4 login(Z<>)
+
+The client has successfully logged in.
+
+=head4 close($Z<>etyp, $Z<>estr)
+Z<XXX: Describe args>
+
+Server is closing connection, and sent $etyp and $estr
+
+=head4 join(Z<>)
+
+$uid has joined $cid
+
+=head4 joined(Z<>)
+
+The client has joined $cid.
+
+=head4 part(Z<>)
+
+$uid has left $cid.
+
+=head4 parted(Z<>)
+
+The client has left $Z<>cid.
+
+=head4 msg($Z<>type, @Z<>msg)
+
+A public message with type $type and contents @msg was sent on channel $cid by 
user $uid.
+
+=head4 pmsg($Z<>type, @Z<>text)
+
+A private message with type $type and contents @msg was sent to you by user 
$uid.
+
+=head4 users(@Z<>who)
+
+Channel $cid has the users listed in @who in it. Sent in response to message 
users().
+
+=head4 bye($Z<>why)
+
+The server is disconnecting you due to the reason in $why
+
+=head4 chans(@Z<>channels)
+
+The server has the channels listed in @channels. Sent in response to message 
chans()
+
+=head4 warn($Z<>err, $Z<>short, $Z<>long, @Z<>args)
+
+The server has sent a non-fatal error message with code $err and arguments 
@args. $short and $long have the
+short and long human-readable forms, respectively.
+
+=head4 die($Z<>err, $Z<>short, $Z<>long, @Z<>args)
+
+The server has sent a fatal error message with code $err and arguments @args. 
$short and $long have the
+short and long human-readable forms, respectively. The connection will be 
closed shortly.
+
+=head4 quit($Z<>why)
+
+UID $uid has disconnected due to the reason in $why.
+
 =head1 SEE ALSO
 
-L<http://haverdev.org>
+L<http://wiki.chani3.com/wiki/ProjectHaver/>
 
 =head1 AUTHOR
 
@@ -621,5 +818,3 @@
 
 
 =cut
-
-1;


Reply via email to