#!/usr/bin/perl use strict; use POE qw/ Filter::IRCD Filter::Line Filter::Stream Filter::Stackable Wheel::ReadWrite Wheel::SocketFactory Driver::SysRW /; use Data::Dumper; use Socket; my $server_host = "ryoko"; ####################################################################### # Create a listening session to watch sockets for incoming connections. # Names: listener, socket POE::Session->create( inline_states => { _start => \&listener_start, _stop => \&listener_stop, socket_success => \&socket_success, socket_failure => \&socket_failure, } ); $poe_kernel->run(); exit; sub listener_start { my $heap = $_[HEAP]; print "Server startup, opening sockets for listening\n"; $heap->{listener} = POE::Wheel::SocketFactory->new( BindAddress => '0.0.0.0', BindPort => 'ircd', Reuse => 'yes', SuccessEvent => 'socket_success', FailureEvent => 'socket_failure', ); POE::Session->create( inline_states => { _start => \&peer_start, _stop => \&peer_stop, new_socket => \&peer_new_socket, reclass_socket => \&peer_reclass_socket, } ); } sub listener_stop { my $heap = $_[HEAP]; print "Server shutdown, cleaning up sockets\n"; delete $heap->{listener}; } sub socket_success { my ($kernel, $socket, $address, $port) = @_[KERNEL, ARG0, ARG1, ARG2]; $address = inet_ntoa($address); print "Socket opened!\n"; $kernel->post('peer', 'new_socket', $socket, $address, $port); } sub socket_failure { my $heap = $_[HEAP]; print "Socket failed, deleteing all running sockets\n"; delete $heap->{socket_wheel}; } ########################################################################### # Peer Handler # Name: peer sub peer_start { my ($kernel, $heap) = @_[KERNEL, HEAP]; print "Peer handler started!\n"; $kernel->alias_set( 'peer' ); $heap->{common} = { nicks => {}, } } sub peer_stop { } sub peer_new_socket { my ($heap, $socket, $address, $port) = @_[HEAP, ARG0, ARG1, ARG2]; $heap->{host_address} = $address; $heap->{host_port} = $port; print "New Peer socket opened!\n"; POE::Session->create( inline_states => { _start => \&auth_start, _stop => \&auth_stop, auth_input => \&auth_input, auth_failure => \&auth_failure, irc_pass => \&auth_irc_pass, irc_nick => \&auth_irc_nick, irc_user => \&auth_irc_user, _default => \&auth_default, }, args => [ $socket, $address, $port ], heap => { common => $heap->{common} }, ); } sub peer_reclass_socket { } ############################################################################ # Auth shiznit # sub auth_start { my ($heap, $socket, $address, $port) = @_[HEAP, ARG0, ARG1, ARG2]; print "Auth-phase started on $address:$port\n"; my $filter = POE::Filter::Stackable->new(); $filter->push( POE::Filter::Line->new( InputRegexp => '\015?\012', OutputLiteral => "\015\012" ), POE::Filter::IRCv2->new(), ); $heap->{socket_wheel} = POE::Wheel::ReadWrite->new( Handle => $socket, Driver => POE::Driver::SysRW->new(), Filter => $filter, InputEvent => 'auth_input', ErrorEvent => 'auth_failure', ); } sub auth_stop { } sub auth_input { my ($kernel, $buf) = @_[KERNEL, ARG0]; $kernel->yield( 'irc_' . lc($buf->{'command'}), $buf ); } sub auth_failure { } sub auth_irc_pass { my ($heap, $buf) = @_[HEAP, ARG0]; } sub auth_irc_nick { my ($heap, $buf) = @_[HEAP, ARG0]; my $params = $buf->{params}; my $nicks = $heap->{common}->{nicks}; if (exists $nicks->{lc($params->[0])} ) { $heap->{socket_wheel}->put({ prefix => $server_host, command => '433', params => [ $params->[0], "Nickname is already in use."], }); } else { $heap->{nick} = $params->[0]; $nicks->{lc($params->[0])} = $heap->{socket_wheel}; } } sub auth_irc_user { my ($heap, $buf) = @_[HEAP, ARG0]; if (exists $heap->{nick}) { $heap->{username} = $buf->{params}->[0]; $heap->{realname} = $buf->{params}->[3]; print "User connected $heap->{nick}\n"; $heap->{socket_wheel}->put({ prefix => $server_host, command => '001', params => ["Welcome to POEIRCD $heap->{nick}!"], }); $heap->{socket_wheel}->put({ prefix => $server_host, command => '002', params => ["Your host is $server_host"], }); } } sub auth_default { }