Difference between revisions of "Server.pl"

From Organic Design wiki
(Remove logging now that peer.swf getting message (needed terminating \x00))
(Remove \x00's if any exist (not in HTTP1.1 RFC, but SWF sends them))
Line 76: Line 76:
 
$::activePeers{$stream}{buffer} .= $input;
 
$::activePeers{$stream}{buffer} .= $input;
 
if ( $::activePeers{$stream}{buffer} =~ s/^(.*\r?\n\r?\n)//s )
 
if ( $::activePeers{$stream}{buffer} =~ s/^(.*\r?\n\r?\n)//s )
{ recvMessage $handle, $_ for split /\r?\n\r?\n/, $1 }
+
{ recvMessage $handle, $_ for split /\r?\n\r?\n\x00?/, $1 }
 
}
 
}
 
else {
 
else {

Revision as of 20:25, 26 March 2006

use IO::Socket; use IO::Select; use MIME::Base64;

  1. Declare network subroutines

sub recvMessage; sub sendMessage;

sub serverStart {

%::activePeers = {};

# Initialise server listening on a port # - we need some graceful trapping here $::server = 0; do { $::server = new IO::Socket::INET Listen => 1, LocalPort => $::port, Proto => 'tcp'; unless ( $::server ) { logAdd "Failed to bind to Port$::port, waiting 10 seconds..."; sleep(10); } } until ( $::server ); $::server->autoflush();

$::select = new IO::Select $::server; $0 = "$::daemon: $::peer (http$::port)"; logAdd "Listening on port $::port";

# HTML interface environment $::template = readFile 'peer.html'; $::template =~ s//$::title ($::daemon)/g; $::template =~ s//$::peer/g; $::deny = readFile "$::peer.401";

# Views my $views = ; $views .= "*$_\n" for ( 'Update', 'Filter', 'Events', 'Edit' ); $::template =~ s// wikiParse($views) /e;

# Navigation my $nav = "*Gir Home\n*User:$peer\n"; $nav .= "*$_\n" for ( "env/cmd|Environment Info", "peerlog/cmd|Peer Log", "syslog/cmd|Syslog", "restart/cmd|Restart $::peer", "stop/cmd|Stop $::peer", "reboot/cmd|Restart this server", "fileSync/cmd|Manual fileSync", "wikiSync/cmd|Manual wikiSync", "swfCompile/cmd|Manual swfCompile", "wikiBackup/cmd|Backup wiki now", "peerBackup/cmd|Backup peer now", "Yi|Hexagrams" ); $::template =~ s// wikiParse($nav) /e;

# Main server loop while(1) { for my $handle ( $::select->can_read(1) ) { my $stream = fileno $handle; if ($handle == $::server) { # Handle is the server, set up a new peer # - but it can't be identified until its msg processed my $newhandle = $::server->accept; $stream = fileno $newhandle; $::select->add($newhandle); $::activePeers{$stream}{buffer} = ; $::activePeers{$stream}{handle} = $newhandle; logAdd "New connection: Stream$stream", 'main/new'; } elsif (sysread $handle, my $input, 10000) { # Handle is an existing stream with data to read # NOTE: we should disconnect after certain size limit) # - Process (and remove) all complete messages from this peer's buffer $::activePeers{$stream}{buffer} .= $input; if ( $::activePeers{$stream}{buffer} =~ s/^(.*\r?\n\r?\n)//s ) { recvMessage $handle, $_ for split /\r?\n\r?\n\x00?/, $1 } } else { # Handle is an existing stream with no more data to read $::select->remove($handle); delete $::activePeers{$stream}; $handle->close(); logAdd "Stream$stream disconnected."; } } } }

  1. Send an HTTP message to a handle

sub sendMessage { my ($handle, $msg) = @_; # If no handle found, try establishing a new stream unless ( defined $handle ) {

# !!!!!!!!!!!!! must change !!!!!!!!!!!!!!!! $peer =~ /([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+$)/; # get rid of "peer-" bit $handle = IO::Socket::INET->new( PeerAddr => $1, Proto => 'tcp' );

return logAdd " Couldn't establish connection to $peer!", 'send' unless defined $handle; # Connected to new peer, add to local activePeers my $stream = fileno $handle; $::activePeers{$stream}{buffer} = ; $::activePeers{$stream}{handle} = $handle; $::activePeers{$stream}{peer} = $peer; $::select->add($handle); logAdd " Stream$stream is connection to $peer", 'send'; } print $handle $msg; }

  1. Process an incoming HTTP message

sub recvMessage { my ( $handle, $msg ) = @_; if ( $msg eq 'Hello?' ) { return sendMessage $handle, "Hi there peer.swf, this is peerd :-)\x00" } my $article = $::deny; my $http = '200 OK'; my $date = strftime "%a, %d %b %Y %H:%M:%S %Z", localtime; my ( $title, $ct ) = $msg =~ /GET\s+\/+(.+?)(\/(.+))?\s+HTTP/ ? ( $1, $3 ) : ( $peer, ); # If request authenticates service it, else return 401 if ( $ct eq 'cmd' ? ( $msg =~ /Authorization: Basic (\w+)/ and decode_base64($1) eq "$::peer:$::pwd1" ) : 1 ) {

# Process request if ( $ct eq 'cmd' ) { logAdd "Executing $title command.";

$article = '

'.command($title).'

';

$ct = ; } elsif ( $ct eq 'swf' ) { my $width = 640; my $height = 480; my $file = "/$::peer.swf/application/x-shockwave-flash"; $article = "<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0\" width=\"$width\" height=\"$height\" id=\"$file\" align=\"\" type=\"application/x-shockwave-flash\" data=\"$file\"> <param name=\"movie\" value=\"$file\"> <param name=\"quality\" value=\"high\"> <param name=\"bgcolor\" value=\"cccccc\"> <embed src=\"$file\" quality=\"high\" bgcolor=\"cccccc\" width=\"$width\" height=\"$height\" align=\"\" name=\"$file\" type=\"application/x-shockwave-flash\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\" /> </object>"; $ct = ; } else { logAdd "$title($ct) requested"; $article = readFile $title; }

# Render article unless ( $ct ) { $ct = 'text/html'; my $tmp = $::template; $tmp =~ s//$title/g; $tmp =~ s// wikiParse $article /e; $article = $tmp; } } else { $http = "401 Authorization Required\r\nWWW-Authenticate: Basic realm=\"private\"" }

# Send response back to requestor my $cl = 2 + length $article; sendMessage $handle, "HTTP/1.1 $http\r\nDate: $date\r\nServer: $::daemon\r\nContent-Length: $cl\r\nContent-Type: $ct;charset=utf-8\r\nContent-Disposition: inline;filename=$::peer.swf\r\n\r\n$article\r\n"; }