| HoneyClient-Util documentation | view source | Contained in the HoneyClient-Util distribution. |
HoneyClient::Util::SOAP - Perl extension to provide a generic interface to all client and server SOAP operations, for any HoneyClient module.
This documentation refers to HoneyClient::Util::SOAP version 0.98.
use HoneyClient::Util::SOAP qw(getServerHandle);
# Create a new SOAP server, using default values.
my $daemon = getServerHandle();
# In the previous example, if this code were listed in package
# "A::B", where the package's global configuration variables
# for "address" and "port" was "localhost" and "8080" respectively
# (as listed in etc/honeyclient.conf), then the corresponding
# SOAP server URL would be:
#
# http://localhost:8080/A/B
# Create a new SOAP server, using specific address/ports.
my $daemon = getServerHandle(address => "localhost",
port => 9090);
# Create a new SOAP server, using the specific "A::B::C" namespace.
my $daemon = getServerHandle(address => "localhost",
port => 9090,
namespace => "A::B::C");
# When you're ready to start listening for connections, call
# the handle() function, like:
$daemon->handle();
# Note: Remember, this handle() call *will* block. If you have
# any other code you want to execute after calling handle(), then
# it is suggested that you call handle() from within a child
# process or thread.
use HoneyClient::Util::SOAP qw(getClientHandle);
# Create a new SOAP client, to talk to the HoneyClient::Manager::VM
# module.
my $stub = getClientHandle(namespace => "HoneyClient::Manager::VM");
# Create a new SOAP client, to talk to the HoneyClient::Agent::Driver
# module
my $stub = getClientHandle(namespace => "HoneyClient::Agent::Driver");
# Create a new SOAP client, to talk to the HoneyClient::Manager::VM
# module on localhost:9090.
my $stub = getClientHandle(namespace => "HoneyClient::Agent::Driver",
address => "localhost",
port => 9090);
# Create a new SOAP client, to talk to the HoneyClient::Manager::VM
# module on localhost:9090, using a custom fault handler.
$faultHandler = sub { die "Something bad happened!"; };
my $stub = getClientHandle(namespace => "HoneyClient::Agent::Driver",
address => "localhost",
port => 9090,
fault_handler => $faultHandler);
# Create a new SOAP client, as a callback to this package.
my $stub = getClientHandle();
This library allows any HoneyClient module to quickly create new SOAP servers or interact with existing ones, by using ports and protocols that are globally defined within a configuration file, rather than using hard coded values within each module.
This library makes extensive use of the SOAP::Lite module.
Returns a new SOAP::Server object, using the caller's package namespace as the dispatch location, if not specified. If neither the $localAddr nor $localPort is specified, then the function will attempt to retrieve the "address" and "port" global configuration variables, set within the caller's namespace.
Inputs: $caller is an optional argument, used to explicitly specify the package namespace to be used as the dispatch point.$localAddr is an optional argument, specifying the IP address for the SOAP server to listen on.$localPort is an optional argument, specifying the TCP port for the SOAP server to listen on.
Output: The corresponding SOAP::Server object if successful, croaks otherwise.
Returns a new SOAP::Lite client object, using the caller's package namespace as the URI, if not specified. If neither the $address nor $port is specified, then the function will attempt to retrieve the "address" and "port" global configuration variables, set within the caller's namespace.
Inputs: $caller is an optional argument, used to explicitly specify the package namespace URI.$address is an optional argument, specifying the IP address for the SOAP server to listen on.$port is an optional argument, specifying the TCP port for the SOAP server to listen on.$faultHandler is an optional argument, specifying the code reference to call if a fault occurs during any subsequent SOAP call using this object.
Output: The corresponding SOAP::Lite object if successful, croaks otherwise.
When talking to any SOAP server, it is highly recommended that you create a SOAP fault handler, when creating a new client to talk to the server. This will ensure that all errors are properly relayed back to the client, including errors that occur during a failure within SOAP communications or from errors that occur as a result of a remote call failure.
Q) So, how do I properly generate SOAP faults in my server code?
A1) For basic errors that include just an error string, here's what you'd
include:
# Assume you want to generate fault message "Unspecified argument." within
# function "foo()".
sub foo {
# ... do other stuff ...
# Check for some error status condition.
if ($condition) {
die SOAP::Fault->faultcode(__PACKAGE__ . "->foo()")
->faultstring("Unspecified argument.");
}
}
A2) For complex errors, where you want to include an error number
along with an error message of an upstream function call, then
here's what you'd include:
# Assume you want to generate fault message "Unspecified argument." within
# function "foo()", but include an upstream error number and string as well.
sub foo {
# ... do other stuff ...
# Check for some error status condition.
if ($condition) {
my $errorNumber = ...get the upstream error number...;
my $errorString = ...get the upstream error string...;
die SOAP::Fault->faultcode(__PACKAGE__ . "->foo()")
->faultstring("Unspecified argument.")
->faultdetail(bless { errNo => $errorNumber,
errStr => $errorString },
'err');
}
}
Q) So, now that I'm generating faults in my SOAP server, how do I handle
them within my SOAP client?
A) A default fault handler is provided by this library; however, this
default handler will NOT know how to properly parse any data within
the faultdetail() segment. If you don't plan on using the
faultdetail() field, then the default code will usually suffice.
Otherwise, continue reading on.
Assume you have faults that look like (A1) and (A2) from the previous
EXAMPLE SERVER-SIDE FAULT CODE. Here's example code on how to emit
proper notification back to the user of the SOAP client:
# Handle any faults, as they occur.
# Inputs: Class, SOAP::SOM
# Outputs: None
sub handleFault {
# Extract arguments.
my ($class, $res) = @_;
# Construct error message.
# Figure out if the error occurred in transport or
# over on the other side.
my $errMsg = $class->transport->status; # Assume transport error.
if (ref $res) {
# Extract base error message.
$errMsg = $res->faultcode . ": " . $res->faultstring . "\n";
# Extract error details.
my $errNo = undef;
my $errStr = undef;
my $errDetail = "";
if (defined($res->faultdetail)) {
$errNo = $res->faultdetail->{"err"}->{"errNo"};
$errStr = $res->faultdetail->{"err"}->{"errStr"};
$errDetail = $res->faultcode . ": (" . $errNo . ") " . $errStr;
}
$errMsg = $errMsg . $errDetail . "\n";
}
die __PACKAGE__ . "->handleFault(): Error occurred during processing.\n" . $errMsg;
}
Q) Okay, so I've created this "handleFault()" function within my SOAP client
code. What's the proper way to use this function within the getClientHandle()
call?
A) Here's the proper way to use your fault handler:
# Assume you want to interact with "HoneyClient::Manager::VM" as a SOAP
# client, using the default address and port.
my $stub = getClientHandle(namespace => "HoneyClient::Manager::VM",
fault_handler => \&handleFault);
Most likely, you will always want to specify getClientHandle(namespace => "Path::To::Module"), when creating a new SOAP client to talk to an external module.
If you just use getClientHandle(), without any module specified, then the function will assume you want a SOAP client to simply talk to yourself (the calling package). While this is useful for external callbacks, it's highly unlikely most people will use this for normal communication.
Paul Kulchenko for developing the SOAP::Lite module.
Thanh Truong, <ttruong@mitre.org>
Darien Kindlund, <kindlund@mitre.org>
Copyright (C) 2007 The MITRE Corporation. All rights reserved.
This program 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, using version 2 of the License.
This program 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 program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
| HoneyClient-Util documentation | view source | Contained in the HoneyClient-Util distribution. |