Author: dylan
Date: 2004-07-24 20:35:49 -0400 (Sat, 24 Jul 2004)
New Revision: 328
Modified:
branches/protocol-v4/main/server/lib/Haver/Server/Object.pm
branches/protocol-v4/main/server/lib/Haver/Server/POE.pm
branches/protocol-v4/main/server/lib/Haver/Server/POE/Commands.pm
branches/protocol-v4/main/server/lib/Haver/Server/POE/Connection.pm
Log:
New protocol implemented. Docs will follow.
Modified: branches/protocol-v4/main/server/lib/Haver/Server/Object.pm
===================================================================
--- branches/protocol-v4/main/server/lib/Haver/Server/Object.pm 2004-07-24
01:11:19 UTC (rev 327)
+++ branches/protocol-v4/main/server/lib/Haver/Server/Object.pm 2004-07-25
00:35:49 UTC (rev 328)
@@ -344,7 +344,13 @@
wantarray ? @v : [EMAIL PROTECTED];
}
+
sub list_vals {
+ carp "->list_vals is deprecated!";
+ shift->contents(@_);
+}
+
+sub contents {
my ($me, $ns) = @_;
my $h = $me->{".$ns"};
Modified: branches/protocol-v4/main/server/lib/Haver/Server/POE/Commands.pm
===================================================================
--- branches/protocol-v4/main/server/lib/Haver/Server/POE/Commands.pm
2004-07-24 01:11:19 UTC (rev 327)
+++ branches/protocol-v4/main/server/lib/Haver/Server/POE/Commands.pm
2004-07-25 00:35:49 UTC (rev 328)
@@ -36,12 +36,14 @@
our @Commands = qw(
IDENT
CANT
- PONG
AUTH
AUTH:PASS
- IN TO
- MSG JOIN PART QUIT
- USERS CHANS INFO MARK
+ MSG PMSG
+ JOIN PART BYE
+ HAVER
+ INFO
+ MARK
+ FOREACH
);
@@ -58,36 +60,53 @@
# $cmds{cmd_REVOKE} = 'cmd_GRANTCMD';
# $cmds{cmd_CLEAR} = 'cmd_GRANTCMD';
- $cmds{unknown_cmd} = 'do_unknown_cmd';
return \%cmds;
}
-sub do_unknown_cmd {
- my ($kernel, $heap, $event, $args) = @_[KERNEL, HEAP, ARG0, ARG1];
+#> [HAVER]
+#> C: HAVER $client
+#> S: HAVER $server
+sub cmd_HAVER {
+ my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
+ my $client = $args->[0];
- $kernel->yield('warn', 'unknown.cmd' => [$event], $heap->{scope}{cid});
+ $heap->{socket}->put(['HAVER',
"Haver::Server::POE/$Haver::Server::POE::VERSION"]);
+ $heap->{client} = $client;
+ $kernel->yield('want', 'IDENT');
}
-#> IDENT($uid, $type)
+#> [IDENT]
+#> C: IDENT $id [$type]
+#> S: ACCEPT $id
+#> | WANT AUTH ...
+#> Errors:
+#> * unknown-type -- %1 is an unknown type of client.
+#> * syntax -- %1 this is an illegal id.
+#> * reserved -- %1 is reserved for something else.
+#> * used -- %1 is already being used.
sub cmd_IDENT {
my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
- my ($uid, $type, $client) = @$args;
+ my ($uid, $type) = @$args;
+ $type ||= 'user';
return if $heap->{login};
if ($type ne 'user') {
- $kernel->yield('die', 'unknown.type', [$type]);
+ $kernel->yield('die', 'unknown-type', [$type]);
return;
}
unless (Haver::Server::Object::User->is_valid_id($uid)) {
- $poe_kernel->yield('die', 'syntax.id.user', [$uid]);
+ $kernel->yield('fail', 'IDENT', 'syntax', [$uid]);
+ $kernel->yield('want', 'IDENT');
} elsif ($type eq 'user' and ($uid =~ /&/ or $uid =~ /@/)) {
- $poe_kernel->yield('die', 'reserved.id.user', [$uid]);
+ $poe_kernel->yield('fail', 'IDENT', 'reserved', [$uid]);
+ $kernel->yield('want', 'IDENT');
} else {
if ($Registry->contains('user', $uid)) {
- $poe_kernel->yield('die', 'exists.user', [$uid]);
+ $poe_kernel->yield('fail', 'IDENT', 'used', [$uid]);
+ $kernel->yield('want', 'IDENT');
} else {
my $user = new Haver::Server::Object::User(
id => $uid,
@@ -95,10 +114,11 @@
sid => $_[SESSION]->ID,
);
$user->set(
- ClientType => $type,
- Client => $client,
+ Type => $type,
+ Client => $heap->{client},
Rank => 0,
Role => 'User',
+ _info => [qw( Rank Role Client IP Login Idle
)],
);
if (-e $user->filename) {
eval { $user->load };
@@ -118,8 +138,9 @@
}
}
-
-#> CANT($want)
+#> [CANT]
+#> C: CANT $want
+#> S: ...
sub cmd_CANT {
my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
my $want = $args->[0];
@@ -132,11 +153,15 @@
}
$heap->{want} = undef;
} else {
- $kernel->yield('die', 'cant.stupid' => [$want, $heap->{want}]);
+ $kernel->yield('die', 'cant.insane' => [$want, $heap->{want}]);
}
}
-#> AUTH($method)
+#> [AUTH]
+#> C: AUTH $method ...
+#> S: WANT AUTH:uc($method) ...
+#> Errors:
+#> * unknown -- auth method %1 is unknown
sub cmd_AUTH {
my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
my $method = $args->[0];
@@ -146,12 +171,17 @@
if ($method eq 'pass') {
$kernel->yield('want', 'AUTH:PASS');
} else {
- $kernel->yield('die', 'auth', [$method]);
+ $kernel->yield('fail', 'AUTH', 'unknown', [$method]);
+ $kernel->yield('want', 'IDENT');
}
}
-#> AUTH:PASS($password)
+#> [AUTH:PASS]
+#> C: AUTH:PASS $password
+#> S: ACCEPT $uid
+#> Errors:
+#> * nomatch -- password did not match,
sub cmd_AUTH_PASS {
my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
my ($pass) = @$args;
@@ -163,33 +193,11 @@
if ($pass eq $user->get('.password')) {
$kernel->yield('accept', $uid, $user);
} else {
- $kernel->yield('die', 'auth.pass', [$uid]);
+ $kernel->yield('fail', 'AUTH:PASS', 'nomatch', []);
+ $kernel->yield('bye', 'monkeys');
}
}
-#> IN($cid, @rest)
-sub cmd_IN {
- my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
- my $cid = shift @$args;
- my $cmd = shift @$args;
-
- $heap->{scope}{cid} = $cid;
- $kernel->call($_[SESSION], "cmd_$cmd", $args);
- delete $heap->{scope}{cid};
-}
-
-#> TO($uid, @rest)
-sub cmd_TO {
- my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
- my $uid = shift @$args;
- my $cmd = shift @$args;
-
- $heap->{scope}{uid} = $uid;
- $kernel->call($_[SESSION], "cmd_$cmd", $args);
- delete $heap->{scope}{uid};
-}
-
-#> MARK($mark, @rest)
sub cmd_MARK {
my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
my $mark = shift @$args;
@@ -200,164 +208,166 @@
delete $heap->{scope}{mark};
}
-#> MSG($type, @args)
+
+#> [MSG]
+#> C: MSG $cid $type @args
+#> S: MSG $cid $uid $type @args
+#> Errors:
+#> * syntax -- the cid %1 is invalid.
+#> * notfound -- the cid %1 was not found.
sub cmd_MSG {
my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
+ my ($cid, $type) = (shift @$args, shift @$args);
+ my $chan = check_cid($cid, 'MSG') or return;
+ my $users = $chan->contents('user');
$heap->{user}->set(_last => time);
- if ($heap->{scope}{cid}) {
- my $chan = check_cid($heap->{scope}{cid}) or return;
- my $users = $chan->list_vals('user');
- $kernel->post('Broadcaster', 'send', $users, [
- 'IN', $heap->{scope}{cid},
- 'OF', $heap->{uid}, 'MSG', @$args]);
- } elsif ($heap->{scope}{uid}) {
- my $user = check_uid($heap->{scope}{uid}) or return;
- $user->put(['OF', $heap->{uid}, 'MSG', @$args]);
- } else {
- #return unless check_perm_access($heap->{user}, 'global msg');
- #my $users = $Registry->list_vals('user');
- #$kernel->post('Broadcaster', 'send', $users, ['OF',
$heap->{uid}, 'MSG', @$args]);
- }
+
+ $kernel->post('Broadcaster', 'send', $users,
+ ['MSG', $chan->id, $heap->{uid}, $type, @$args]);
}
+#> [PMSG]
+#> C: PMSG $uid $type @args
+#> S: PMSG $uid $type @args
+#> Errors:
+#> * syntax -- the uid %1 is invalid.
+#> * notfound -- the uid %1 was not found.
+sub cmd_PMSG {
+ my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
+ my $uid = shift @$args;
+ my $user = check_uid($uid, 'PMSG') or return;
+
+ $heap->{user}->set(_last => time);
-#> JOIN($cid)
+ $user->put(['PMSG', $heap->{uid}, @$args]);
+}
+
+#> [JOIN]
+#> C: JOIN $cid
+#> S: JOIN $cid $uid
+#> Errors:
+#> * notfound -- the cid %1 was not found.
+#> * syntax -- the cid %1 is invalid.
+#> * joined -- tried to join %1 while already in it.
sub cmd_JOIN {
my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
- my ($cid) = @$args;
+ my $cid = shift @$args;
+ my $chan = check_cid($cid, 'JOIN') or return;
my $user = $heap->{user};
-
- return unless check_cid($cid);
- # Don't join if already in the channel.
- unless ($user->contains('channel', $cid)) {
- my $chan = $Registry->fetch('channel', $cid);
- ASSERT: defined $chan and ref $chan;
- $chan->add($user);
- $user->add($chan);
- my $uids = $chan->list_ids('user');
- $kernel->post('Broadcaster', 'send', $uids,
- ['IN', $cid, 'OF', $heap->{uid}, 'JOIN'],
- );
- } else {
- # ERROR: insane.join You can't join a channel twice...
- $kernel->yield('warn', 'insane.join' => [$cid]);
+ if ($chan->contains('user', $heap->{uid})) {
+ $kernel->yield('fail', 'JOIN', joined => [$cid]);
+ return;
}
+
+ $chan->add($user);
+ $user->add($chan);
+ my $users = $chan->contents('user');
+ $kernel->post('Broadcaster', 'send', $users, ['JOIN', $cid, $user->id]);
}
-#> PART($cid)
+#> [PART]
+#> C: PART $cid
+#> S: PART $cid $uid
+#> Errors:
+#> * notfound -- the cid %1 was not found.
+#> * syntax -- the cid %1 is invalid.
+#> * timetravel -- you tried to part %1 before you joined it...
sub cmd_PART {
my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
- my ($cid) = @$args;
+ my $cid = shift @$args;
+ my $chan = check_cid($cid, 'PART') or return;
my $user = $heap->{user};
- my $uid = $heap->{uid};
-
- return unless check_cid($cid);
- if ($user->contains('channel', $cid)) {
- my $chan = $Registry->fetch('channel', $cid);
- my $uids = $chan->list_ids('user');
- $kernel->post('Broadcaster', 'send', $uids, ['IN', $cid, 'OF',
$uid, 'PART']);
- $chan->remove($user);
- $user->remove($chan);
- } else {
- # ERROR: insane.part You can't part a channel you're not in...
- $kernel->yield('warn', 'insane.part' => [$cid]);
+
+ unless ($chan->contains('user', $heap->{uid})) {
+ $kernel->yield('fail', 'PART', timetravel => [$cid]);
+ return;
}
-}
+ my $users = $chan->contents('user');
-#> USERS()
-sub cmd_USERS {
- my ($kernel, $heap) = @_[KERNEL, HEAP];
-
- my $chan = $Registry;
- my @p = ();
- if ($heap->{scope}{cid}) {
- $chan = $Registry->fetch('channel', $heap->{scope}{cid});
- @p = ('IN', $heap->{scope}{cid});
- }
-
- $heap->{socket}->put([EMAIL PROTECTED], 'USERS',
$chan->list_ids('user')]);
+ $kernel->post('Broadcaster', 'send', $users, ['PART', $cid, $user->id]);
+ $chan->remove($user);
+ $user->remove($chan);
}
-sub cmd_CHANS {
- my ($kernel, $heap) = @_[KERNEL, HEAP];
- $heap->{socket}->put(['CHANS', $Registry->list_ids('channel')]);
-}
-
-#> QUIT($why)
-sub cmd_QUIT {
+#> [BYE]
+#> C: BYE [$reason]
+#> S: BYE ACTIVE [$reason]
+sub cmd_BYE {
my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
$kernel->yield('shutdown', 'ACTIVE', @$args);
}
-#> INFO()
+#> [INFO]
+#> C: INFO $type $id
+#> S: INFO $type $id (list of key value pairs)
+#> Errors:
+#> * notfound -- the id %1 of type %2 was not found.
+#> * syntax -- the id %1 of type %2 is invalid.
sub cmd_INFO {
my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
- my ($targ, $chan);
- my @in = ();
- my @mark = ();
+ my ($type, $id) = @$args;
+ my $obj = check_id($type, $id, 'INFO') or return;
+ my @keys = @{ $obj->get('_info') };
+ my @out = ('INFO', $type, $id, map { ($_ => $obj->get($_)) } @keys);
- if ($heap->{scope}{mark}) {
- @mark = ('MARK', $heap->{scope}{mark});
+ $heap->{socket}->put([EMAIL PROTECTED]);
+}
+
+
+#> [FOREACH]
+#> C: FOREACH type cid @subcmd
+#> S: ...
+sub cmd_FOREACH {
+ my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
+ my ($type, $cid, $cmd) = splice(@$args, 0, 3);
+ my $chan = check_cid($cid, 'FOREACH');
+
+ if ($cmd ne 'INFO') {
+ $kernel->yield('fail', 'FOREACH', 'forbidden', $cmd);
+ return;
}
-
- if ($heap->{scope}{cid}) {
- $chan = check_cid($heap->{scope}{cid}) or return;
- @in = ('IN', $chan->id);
- } else {
- $chan = $Registry;
+ foreach my $obj ($chan->contents($type)) {
+ my @args = map {
+ if ($_ eq '%id%') {
+ $obj->id;
+ } else {
+ $_;
+ }
+ } @$args;
+ $kernel->post($_[SESSION], "cmd_$cmd", [EMAIL PROTECTED]);
}
-
- if ($heap->{scope}{uid} eq '*') {
- my @users = $chan->list_vals('user');
- foreach my $user (@users) {
- my @info = map { ($_ => $user->get($_)) }
grep(/^[A-Z]/, $user->list_fields);
- $heap->{user}->put([EMAIL PROTECTED], 'OF', $user->id,
@in, 'INFO', @info]);
- }
- } elsif ($heap->{scope}{uid}) {
- my $user = check_uid($heap->{scope}{uid}) or return;
- my @info = map { ($_ => $user->get($_)) } grep(/^[A-Z]/,
$user->list_fields);
- $heap->{user}->put([EMAIL PROTECTED], 'OF', $user->id, @in,
'INFO', @info]);
- }
}
-sub check_uid {
- my $uid = shift;
- my $in = shift;
+sub check_id {
+ my ($type, $id, $cmd) = @_;
-
- # ERROR: syntax.id Badly formed identifier.
- unless (defined $uid and
Haver::Server::Object::User->is_valid_id($uid)) {
- $poe_kernel->yield('warn', 'syntax.id.user' => [$uid], $in);
+ unless (Haver::Server::Object->is_valid_id($id)) {
+ $poe_kernel->yield('fail', $cmd, 'syntax', [$id]);
return undef;
}
-
- unless ($uid eq '.' or $Registry->contains('user', $uid)) {
- $poe_kernel->yield('warn', 'notfound.user' => [$uid], $in);
+ unless ($Registry->contains($type, $id)) {
+ $poe_kernel->yield('fail', $cmd, 'notfound', [$id]);
return undef;
}
- return $Registry->fetch('user', $uid);
+ return $Registry->fetch($type, $id);
}
sub check_cid {
- my $cid = shift;
-
- unless (defined $cid and
Haver::Server::Object::Channel->is_valid_id($cid)) {
- $poe_kernel->yield('warn', 'syntax.id.channel' => [$cid]);
- return undef;
- }
+ my ($id, $cmd) = @_;
- unless ($Registry->contains('channel', $cid)) {
- $poe_kernel->yield('warn', 'notfound.channel' => [$cid]);
- return undef;
- }
+ check_id('channel', $id, $cmd);
+}
- return $Registry->fetch('channel', $cid);
+sub check_uid {
+ my ($id, $cmd) = @_;
+
+ check_id('user', $id, $cmd);
}
1;
Modified: branches/protocol-v4/main/server/lib/Haver/Server/POE/Connection.pm
===================================================================
--- branches/protocol-v4/main/server/lib/Haver/Server/POE/Connection.pm
2004-07-24 01:11:19 UTC (rev 327)
+++ branches/protocol-v4/main/server/lib/Haver/Server/POE/Connection.pm
2004-07-25 00:35:49 UTC (rev 328)
@@ -60,7 +60,7 @@
want => 'on_want',
cleanup => 'on_cleanup',
'shutdown' => 'on_shutdown',
- 'warn' => 'on_warn',
+ 'fail' => 'on_fail',
'die' => 'on_die',
'accept' => 'on_accept',
auth => 'on_auth',
@@ -99,6 +99,8 @@
);
%$heap = (
+ address => $address,
+ port => $port,
timer => $timer,
socket => $sock,
shutdown => 0,
@@ -108,13 +110,6 @@
user => undef,
uid => undef,
);
-
- $sock->put(['HAVER', 3, 2048]);
- $kernel->yield('want', 'IDENT',
- address => $address,
- port => $port,
- );
-
}
sub _stop {
my ($kernel, $heap, $session) = @_[KERNEL, HEAP, SESSION];
@@ -178,12 +173,11 @@
}
}
- if ($heap->{user} or $want or $cmd eq 'CANT') {
- $heap->{scope} = {
- };
+ if ($heap->{user} or $want or $cmd eq 'CANT' or $cmd eq 'HAVER') {
+ $heap->{scope} = {};
$kernel->yield("cmd_$cmd", $args);
} else {
- $kernel->yield('die', 'SPEEDY');
+ $kernel->yield('die', 'speedy');
}
}
@@ -208,7 +202,9 @@
sub on_unknown_cmd {
my ($kernel, $heap, $event, $args) = @_[KERNEL, HEAP, ARG0, ARG1];
- $kernel->yield('warn', UCMD => [$event], $heap->{scope}{cid});
+
+
+ $heap->{socket}->put(['WARN', 'unknown.command', $event]);
}
sub on_shutdown {
@@ -264,11 +260,10 @@
push(@users, $chan->list_ids('user'));
}
my %users = map { ($_ => $_) } @users;
- my $msg = ['OF', $uid, 'QUIT', @args];
+ my $msg = ['QUIT', $uid, @args];
$kernel->post('Broadcaster', 'send', [ keys %users ],
$msg);
}
if ($user) {
- ($heap->{port}, $heap->{address}) = $user->get('_port',
'_address');
$user->save if $user->has('_reg');
}
} else {
@@ -277,7 +272,7 @@
}
sub on_die {
- my ($kernel, $heap, $err, $data, $in) = @_[KERNEL, HEAP, ARG0 .. $#_];
+ my ($kernel, $heap, $err, $data) = @_[KERNEL, HEAP, ARG0 .. $#_];
if (not defined $data) {
$data = [];
@@ -287,12 +282,11 @@
$data = [$data];
}
- my @p = $in ? (IN => $in) : ();
- eval { $heap->{socket}->put([EMAIL PROTECTED], 'DIE', $err, @$data]) };
+ eval { $heap->{socket}->put(['DIE', $err, @$data]) };
$kernel->yield('shutdown', 'DIE');
}
-sub on_warn {
- my ($kernel, $heap, $err, $data, $in) = @_[KERNEL, HEAP, ARG0 .. $#_];
+sub on_fail {
+ my ($kernel, $heap, $cmd, $err, $data) = @_[KERNEL, HEAP, ARG0 .. $#_];
if (not defined $data) {
$data = [];
@@ -302,9 +296,8 @@
$data = [$data];
}
- my @p = $in ? (IN => $in) : ();
- $kernel->post('Logger', 'warn', "Warning $heap->{uid}: $err");
- eval { $heap->{socket}->put([EMAIL PROTECTED], 'WARN', $err, @$data]) };
+ $kernel->post('Logger', 'fail', "failing $heap->{uid} with $cmd -
$err");
+ eval { $heap->{socket}->put(['FAIL', $cmd, $err, @$data]) };
}
sub on_accept {
@@ -316,7 +309,7 @@
$Registry->add($user);
$heap->{user} = $user;
$heap->{uid} = $uid;
- my $addr = join('.', (split(/\./, $heap->{want_data}{address}))[0,1,2])
. '.*';
+ my $addr = join('.', (split(/\./, $heap->{address}))[0,1,2]) . '.*';
my $login_time = time;
$user->set(
IP => $addr,
@@ -328,9 +321,7 @@
my ($u) = @_;
time - $u->get('_last');
},
- '.IP' => $heap->{want_data}{address},
- _address => delete $heap->{want_data}{address},
- _port => delete $heap->{want_data}{port},
+ '.IP' => $heap->{address},
);
delete $heap->{want_data};
$heap->{login} = 1;
Modified: branches/protocol-v4/main/server/lib/Haver/Server/POE.pm
===================================================================
--- branches/protocol-v4/main/server/lib/Haver/Server/POE.pm 2004-07-24
01:11:19 UTC (rev 327)
+++ branches/protocol-v4/main/server/lib/Haver/Server/POE.pm 2004-07-25
00:35:49 UTC (rev 328)
@@ -38,7 +38,7 @@
use Haver::Util::Reload;
-our $VERSION = 0.06;
+our $VERSION = 0.07;
my %Default = (
logger => {