Author: dylan
Date: 2004-10-25 16:52:37 -0400 (Mon, 25 Oct 2004)
New Revision: 404
Added:
branches/haver-server-cleanup/lib/Haver/Server/Commands.pm
branches/haver-server-cleanup/lib/Haver/Server/Commands/Connection.pm
branches/haver-server-cleanup/lib/Haver/Server/Plugin.pm
branches/haver-server-cleanup/lib/Haver/Server/Plugin/
branches/haver-server-cleanup/lib/Haver/Server/Plugin/Loader.pm
Log:
Haver::Server::Plugin is a generic module
for loading state handlers into an active session,
sort of like a POE::Wheel.
Haver::Server::Commands is a subclass of this,
which provides some Command specific stuff.
Haver::Server::Commands::Connection are the commands and
needed when a client first connects.
Haver::Server::Plugin::Loader is a container
that loads and unloads plugins.
Added: branches/haver-server-cleanup/lib/Haver/Server/Commands/Connection.pm
===================================================================
--- branches/haver-server-cleanup/lib/Haver/Server/Commands/Connection.pm
2004-10-25 20:49:58 UTC (rev 403)
+++ branches/haver-server-cleanup/lib/Haver/Server/Commands/Connection.pm
2004-10-25 20:52:37 UTC (rev 404)
@@ -0,0 +1,217 @@
+# vim: set ft=perl ts=4 sw=4:
+# Commands::Basic - description
+#
+# Copyright (C) 2004 Dylan William Hardison.
+#
+# This module is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This module is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this module; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+package Haver::Server::Commands::Connection;
+use strict;
+use warnings;
+
+use Haver::Formats qw( :duration );
+use Digest::SHA1 qw( sha1_base64 );
+use Haver::Server::Registry qw( $Registry );
+
+use base 'Haver::Server::Commands';
+
+our $VERSION = '0.01';
+
+sub setup {
+ my $me = shift;
+
+ $me->SUPER::setup();
+
+ foreach my $state (qw(want accept auth reject unknown_cmd init
timeout)) {
+ $me->provide($state, "on_$state");
+ }
+
+}
+
+sub commands {
+ qw(
+ HAVER IDENT CANT AUTH AUTH:PASS
+ );
+}
+
+sub cmd_HAVER {
+ my ($me, $kernel, $heap, $args) = @_[OBJECT, KERNEL, HEAP, ARG0];
+ my $client = $args->[0];
+
+ if (exists $me->{version}) {
+ $kernel->yield('oops', 'repeat', ['HAVER']);
+ return;
+ }
+
+ eval {
+ $heap->{client}->put(['HAVER',
+ "Haver::Server/$Haver::Server::VERSION",
+ ]);
+ };
+ $me->{version} = $client;
+ $kernel->yield('want', 'IDENT');
+}
+
+sub cmd_IDENT {
+ my ($me, $kernel, $heap, $args) = @_[OBJECT, KERNEL, HEAP, ARG0];
+ my ($id, $ns) = @$args;
+
+ $ns ||= 'user';
+
+ # This may only be called once.
+ if ($me->{did}{IDENT}++) {
+ $kernel->yield('oops', "repeat", ['IDENT']);
+ return;
+ }
+
+ # We don't support other types of clients right now.
+ if ($ns ne 'user') {
+ $kernel->yield('fail', 'IDENT', 'unsupported.ns', [$ns]);
+ $kernel->yield('want', 'IDENT');
+ return;
+ }
+
+ # Make sure it's a valid id.
+ if (not Haver::Server::Object->is_valid_id($id)) {
+ $kernel->yield('fail', 'IDENT', 'syntax.id', [$id]);
+ $kernel->yield('want', 'IDENT');
+ return;
+ }
+
+ # users arn't allowed to have names that begin with
+ # & or @ in them.
+ if ($ns eq 'user' and ($id =~ /^&/ or $id =~ /@/)) {
+ $kernel->yield('fail', 'IDENT', 'reserved.id', [$id]);
+ $kernel->yield('want', 'IDENT');
+ return;
+ }
+
+ if ($Registry->contains('user', $id)) {
+ $kernel->yield('fail', 'IDENT', 'used.id', [$id]);
+ $kernel->yield('want', 'IDENT');
+ return;
+ }
+
+ my $user = new Haver::Server::Object::User (
+ id => $id,
+ wheel => $heap->{client},
+ sid => $_[SESSION]->ID,
+ );
+ $user->set (
+ Client => $heap->{version},
+ Rank => 0,
+ Role => 'User',
+ _info => [qw( Rank Role Client IP Login Idle )],
+ );
+
+ $kernel->yield('accept', $id, $user);
+}
+
+sub cmd_AUTH {
+ my ($me, $kernel, $heap, $args) = @_[OBJECT, KERNEL, HEAP, ARG0];
+ my $method = $args->[0];
+
+ if ($me->{did}{AUTH}++) {
+ $kernel->yield('oops', 'repeat', ['AUTH']);
+ return;
+ }
+
+ if ($method eq 'pass') {
+ $kernel->yield('want', 'AUTH:PASS');
+ } else {
+ $kernel->yield('fail', 'AUTH', 'unknown.method', [$method]);
+ $kernel->yield('want', 'IDENT');
+ }
+
+}
+
+sub cmd_AUTH_PASS {
+ my ($me, $kernel, $heap, $args) = @_[OBJECT, KERNEL, HEAP, ARG0];
+ my ($pass) = @$args;
+ my $user = delete $heap->{user};
+ my $id = delete $heap->{uid};
+
+ if ($heap->{did}{'AUTH:PASS'}++) {
+ $kernel->yield('oops', 'repeat', ['AUTH:PASS']);
+ return;
+ }
+
+ if ($pass eq $user->get('.password')) {
+ $kernel->yield('accept');
+ } else {
+ $kernel->yield('fail', 'AUTH:PASS', 'nomatch.passhash', []);
+ $kernel->yield('bye', 'monkeys');
+ }
+}
+
+#-------------------------------- Events
--------------------------------------#
+
+sub on_init {
+ my ($me, $kernel, $heap) = @_[OBJECT, KERNEL, HEAP];
+
+ $me->{timeout} = $kernel->alarm_set('timeout', time + (60 * 3));
+}
+
+sub on_timeout {
+ my ($kernel, $heap) = @_[KERNEL, HEAP];
+
+ delete $heap->{client};
+ $kernel->yield('shutdown');
+}
+
+sub on_want {
+ my ($kernel, $heap, $want) = @_[KERNEL, HEAP, ARG0];
+
+ delete $me->{did}{$want};
+ $heap->{client}->put(['WANT', $want]);
+}
+
+sub since {
+ my ($then, $now) = @_;
+
+ $now ||= time;
+ format_duration($now - $then);
+}
+
+sub on_accept {
+ my ($me, $kernel, $heap, $uid, $user) = @_[OBJECT, KERNEL, HEAP, ARG0,
ARG1];
+
+ $kernel->alarm_remove(delete $me->{timeout});
+
+ $Registry->add($user);
+ my $addr = join('.', (split(/\./, $heap->{address}))[0,1,2]) .
'.*';
+ my $login_time = time;
+
+ $user->set(
+ IP => $addr,
+ Login => sub {
+ since($login_time);
+ },
+ _lastmsg => time,
+ Idle => sub {
+ my ($u) = @_;
+ since($u->get('_lastmsg'));
+ },
+ '.IP' => $heap->{address},
+ );
+
+ $kernel->call($_[SESSION], 'ready', $uid, $user);
+ $heap->{client}->put(['ACCEPT', $uid]);
+}
+
+
+
+
+
+1;
Added: branches/haver-server-cleanup/lib/Haver/Server/Commands.pm
===================================================================
--- branches/haver-server-cleanup/lib/Haver/Server/Commands.pm 2004-10-25
20:49:58 UTC (rev 403)
+++ branches/haver-server-cleanup/lib/Haver/Server/Commands.pm 2004-10-25
20:52:37 UTC (rev 404)
@@ -0,0 +1,38 @@
+# vim: set ft=perl ts=4 sw=4:
+# Commands - description
+#
+# Copyright (C) 2004 Dylan William Hardison.
+#
+# This module is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This module is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this module; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+package Haver::Server::Commands;
+use strict;
+use warnings;
+
+our $VERSION = '0.01';
+
+sub setup {
+ my $me = shift;
+
+ foreach my $cmd ($me->commands) {
+ my $method = $cmd;
+ $method =~ s/:/_/g;
+ $me->provide("cmd_$cmd", "cmd_$method");
+ }
+}
+
+
+
+1;
+
Added: branches/haver-server-cleanup/lib/Haver/Server/Plugin/Loader.pm
===================================================================
--- branches/haver-server-cleanup/lib/Haver/Server/Plugin/Loader.pm
2004-10-25 20:49:58 UTC (rev 403)
+++ branches/haver-server-cleanup/lib/Haver/Server/Plugin/Loader.pm
2004-10-25 20:52:37 UTC (rev 404)
@@ -0,0 +1,51 @@
+# vim: set ft=perl ts=4 sw=4:
+# Plugin::Loader - description
+#
+# Copyright (C) 2004 Dylan William Hardison.
+#
+# This module is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This module is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this module; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+package Haver::Server::Plugin::Loader;
+use strict;
+use warnings;
+use Carp;
+use base 'Haver::Base';
+
+our $VERSION = '0.01';
+
+sub initialize {
+ my $me = shift;
+
+ $me->{plugins} = {};
+}
+
+
+sub load {
+ my ($me, $class) = @_;
+
+ croak "$class is not a Haver::Plugin!" unless
$class->isa('Haver::Plugin');
+
+ $me->{plugins}{$class} = $class->new(load => 1);
+}
+
+sub unload {
+ my ($me, $class) = @_;
+
+ croak "$class is not a Haver::Plugin!" unless
$class->isa('Haver::Plugin');
+ croak "I never loaded a $class!" unless exists $me->{plugins}{$class};
+
+ delete $me->{plugins}{$class};
+}
+
+1;
Added: branches/haver-server-cleanup/lib/Haver/Server/Plugin.pm
===================================================================
--- branches/haver-server-cleanup/lib/Haver/Server/Plugin.pm 2004-10-25
20:49:58 UTC (rev 403)
+++ branches/haver-server-cleanup/lib/Haver/Server/Plugin.pm 2004-10-25
20:52:37 UTC (rev 404)
@@ -0,0 +1,117 @@
+# vim: set ft=perl ts=4 sw=4:
+# Haver::Server::Commands - description
+#
+# Copyright (C) 2004 Dylan William Hardison.
+#
+# This module is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This module is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this module; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+package Haver::Server::Plugin;
+use strict;
+use warnings;
+use base 'Haver::Base';
+
+our $VERSION = '0.01';
+my $Kernel = $POE::Kernel::poe_kernel;
+
+sub initialize {
+ my ($me) = @_;
+
+ $me->{provides} = [];
+ $me->{states} = {};
+
+ $me->setup();
+
+ if ($me->{load}) {
+ $me->load();
+ }
+}
+
+
+sub provide {
+ my ($me, $state, $method) = @_;
+
+ foreach my $state (@states) {
+ push @{ $me->{provides} }, [ $state, $method ];
+ }
+
+ return $me;
+}
+
+sub load {
+ my ($me) = @_;
+
+ # $p = ['state', 'method']
+ # OR $p = ['state']
+ foreach my $p ($me->provided) {
+ $me->register(@$p);
+ }
+}
+
+sub unload {
+ my ($me) = @_;
+
+ foreach my $state ($me->registered) {
+ $me->unregister($state);
+ }
+}
+
+
+sub register {
+ my ($me, $state, $method) = @_;
+
+ if (exists $me->{states}{$state}) {
+ croak "Can't register $state, already registered!";
+ }
+
+ $me->{states}{$state} = 1;
+ $Kernel->state(
+ $state,
+ not($me->{package}) ? $me : ref($me),
+ $method,
+ );
+}
+
+sub unregister {
+ my ($this, $state) = @_;
+
+ if (not exists $me->{states}{$state}) {
+ croak "Can't unregister $state, it is not registered!";
+ }
+
+ delete $me->{states}{$state};
+ $Kernel->state($state);
+}
+
+sub registered {
+ my ($me) = @_;
+
+ return keys %{ $me->{states} };
+}
+
+# Returns: List of arrays.
+# Example:
+# (['state'], ['state', 'method']);
+sub provided {
+ my ($me) = @_;
+
+ return @{ $me->{provides} };
+}
+
+sub finalize {
+ my ($me) = @_;
+
+ $me->unload();
+}
+
+1;