Mini Shell
# -*- perl -*-
#
#
# PlRPC - Perl RPC, package for writing simple, RPC like clients and
# servers
#
#
# Copyright (c) 1997,1998 Jochen Wiedmann
#
# You may distribute under the terms of either the GNU General Public
# License or the Artistic License, as specified in the Perl README file.
#
# Author: Jochen Wiedmann
# Email: jochen.wiedmann at freenet.de
#
require 5.004;
use strict;
require Storable;
package RPC::PlServer::Comm;
$RPC::PlServer::Comm::VERSION = '0.1003';
############################################################################
#
# Name: new (Class method)
#
# Purpose: Constructor
#
# Inputs: $class - This class
# $attr - Hash ref of attributes
#
# Result: Server object for success, error message otherwise
#
############################################################################
sub new ($) {
my($class, $attr) = @_;
my $self = {};
bless($self, (ref($class) || $class));
if (my $comp = $attr->{'compression'}) {
if ($comp eq 'off') {
$self->{'compression'} = undef;
} elsif ($comp eq 'gzip') {
require Compress::Zlib;
$self->{'compression'} = 'gzip';
} else {
die "Unknown compression type ($comp), use 'off' or 'gzip'";
}
}
if (my $cipher = $attr->{'cipher'}) {
$self->{'cipher'} = $cipher;
}
if (my $maxmessage = $attr->{'maxmessage'}) {
$self->{'maxmessage'} = $maxmessage;
}
$self;
}
############################################################################
#
# Name: Write
#
# Purpose: Writing to a PlRPC socket; used by both the client (when
# sending a method name and arguments) and the server (for
# sending the result list). Communication occurrs in packets.
# Each packet is preceeded by 4 bytes with the true packet
# size. If encryption happens, then the packet is padded with
# NUL bytes to a multiple of blocksize bytes. However, the
# stored size remains unchanged.
#
# Inputs: $self - Instance of RPC::PlServer or RPC::PlClient
# $socket - The socket to write to
# $args - Reference to array of arguments being sent
#
# Result: Nothing; dies in case of errors.
#
############################################################################
sub Write ($$$) {
my($self, $socket, $msg) = @_;
my $encodedMsg = Storable::nfreeze($msg);
$encodedMsg = Compress::Zlib::compress($encodedMsg)
if ($self->{'compression'});
my($encodedSize) = length($encodedMsg);
if (my $cipher = $self->{'cipher'}) {
my $size = $cipher->blocksize;
if (my $addSize = length($encodedMsg) % $size) {
$encodedMsg .= chr(0) x ($size - $addSize);
}
$msg = '';
for (my $i = 0; $i < length($encodedMsg); $i += $size) {
$msg .= $cipher->encrypt(substr($encodedMsg, $i, $size));
}
$encodedMsg = $msg;
}
local $\;
if (!$socket->print(pack("N", $encodedSize), $encodedMsg) ||
!$socket->flush()) {
die "Error while writing socket: $!";
}
}
############################################################################
#
# Name: Read
#
# Purpose: Reading from a PlRPC socket; used by both the client (when
# receiving a result list) and the server (for receiving the
# method name and arguments). Counterpart of Write, see
# above for specs.
#
# Inputs: $self - Instance of RPC::PlServer or RPC::PlClient
# $socket - The socket to read from
#
# Result: Array ref to result list; dies in case of errors.
#
############################################################################
sub Read($$) {
my($self, $socket) = @_;
my $result;
my($encodedSize, $readSize, $blockSize);
$readSize = 4;
$encodedSize = '';
while ($readSize > 0) {
my $result = $socket->read($encodedSize, $readSize,
length($encodedSize));
if (!$result) {
return undef if defined($result);
die "Error while reading socket: $!";
}
$readSize -= $result;
}
$encodedSize = unpack("N", $encodedSize);
my $max = $self->getMaxMessage();
die "Maximum message size of $max exceeded, use option 'maxmessage' to"
. " increase" if $max && $encodedSize > $max;
$readSize = $encodedSize;
if ($self->{'cipher'}) {
$blockSize = $self->{'cipher'}->blocksize;
if (my $addSize = ($encodedSize % $blockSize)) {
$readSize += ($blockSize - $addSize);
}
}
my $msg = '';
my $rs = $readSize;
while ($rs > 0) {
my $result = $socket->read($msg, $rs, length($msg));
if (!$result) {
die "Unexpected EOF" if defined $result;
die "Error while reading socket: $!";
}
$rs -= $result;
}
if ($self->{'cipher'}) {
my $cipher = $self->{'cipher'};
my $encodedMsg = $msg;
$msg = '';
for (my $i = 0; $i < $readSize; $i += $blockSize) {
$msg .= $cipher->decrypt(substr($encodedMsg, $i, $blockSize));
}
$msg = substr($msg, 0, $encodedSize);
}
$msg = Compress::Zlib::uncompress($msg) if ($self->{'compression'});
Storable::thaw($msg);
}
############################################################################
#
# Name: Init
#
# Purpose: Initialize an object for using RPC::PlServer::Comm methods
#
# Input: $self - Instance
#
# Returns: The instance in case of success, dies in case of trouble.
#
############################################################################
############################################################################
#
# Name: getMaxMessage
#
# Purpose: Returns the maximum size of a message
#
# Inputs: None
#
# Returns: Maximum message size or 65536, if none specified
#
############################################################################
sub getMaxMessage() {
my $self = shift;
return defined($self->{'maxmessage'}) ?
$self->{'maxmessage'} : 65536;
}
1;
Zerion Mini Shell 1.0