HoneyClient::Util::SOAP - Perl extension to provide a generic interface


HoneyClient-Util documentation  | view source Contained in the HoneyClient-Util distribution.

Index


NAME

Top

HoneyClient::Util::SOAP - Perl extension to provide a generic interface to all client and server SOAP operations, for any HoneyClient module.

VERSION

Top

This documentation refers to HoneyClient::Util::SOAP version 0.98.

SYNOPSIS

Top

CREATING A SOAP SERVER

  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.

CREATING A SOAP CLIENT

  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();

DESCRIPTION

Top

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.

EXPORTS

Top

getServerHandle(namespace => $caller, address => $localAddr, port => $localPort)

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.

getClientHandle(namespace => $caller, address => $address, port => $port, fault_handler => $faultHandler)

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.

HANDLING FAULTS

Top

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.

EXAMPLE SERVER-SIDE FAULT CODE

  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');
      }
  }

EXAMPLE CLIENT-SIDE FAULT CODE

  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);

BUGS & ASSUMPTIONS

Top

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.

SEE ALSO

Top

http://www.honeyclient.org/trac

SOAP::Lite, SOAP::Transport::HTTP

http://www.soaplite.com

REPORTING BUGS

Top

http://www.honeyclient.org/trac/newticket

ACKNOWLEDGEMENTS

Top

Paul Kulchenko for developing the SOAP::Lite module.

AUTHORS

Top

Thanh Truong, <ttruong@mitre.org>

Darien Kindlund, <kindlund@mitre.org>

COPYRIGHT & LICENSE

Top


HoneyClient-Util documentation  | view source Contained in the HoneyClient-Util distribution.