TOC |
|
The Blocks SpaceKit for Perl is a software development kit that implements the Blocks eXtensible eXchange Protocol (BXXP[1]) in Perl. The SpaceKit provides tools to access existing Blocks servers as well as providing a framework for developing Blocks clients and servers using Perl.
To subscribe to the Blocks discussion list, send e-mail; there is also a developers' site.
TOC |
TOC |
SpaceKit requirements:
Perl version 5.004 or later.
Additional Perl modules required by the SpaceKit include:
Additional Perl modules required by the SpaceKit client and server example applications:
All of the above modules should be available from your nearest CPAN site.
Additional documentation on the Blocks protocol is available at:
TOC |
Example client applications are located in the top-level examples/client directory.
Implements the basic client (mixer) interface. The search, fetch, and store mixer operations are supported.
Returns a list of valid "name" attributes (e.g., "doc.rfc.2629") matching the search criteria. These names are suitable as arguments to the fetch operation.
% perl big.pl -server sqa.invisible.net search "<union><intersect><compare subtree='doc.rfc' operator='contains' caseSensitive='false'><path><element property='email' /></path><value>mrose@</value></compare></intersect></union>" doc.rfc.2629
See SEP[2] for further details on the set-union specification used by the search operation.
Fetch the contents of the specified block to standard output.
% perl big.pl -server sqa.invisible.net fetch doc.rfc.2629 <rfc serial="2" name="doc.rfc.2629"> <rfc.props number="2629" category="info" relativeSize="46132"></rfc.props> <doc.props> <doc.front> <doc.title>Writing I-Ds and RFCs using XML</doc.title> <doc.author surname="Rose" fullname="Marshall T. Rose" initials="M.T."> <organization>Invisible Worlds, Inc.</organization> <address> <postal> <street>660 York Street</street> <city>San Francisco</city> <region>CA</region> <code>94110</code> <country>US</country></postal> <phone>+1 415 695 3975</phone> <email>mrose@not.invisible.net</email> <uri>http://invisible.net/</uri></address></doc.author> <doc.date year="1999" month="June"></doc.date> <doc.area>General</doc.area> <doc.keyword>RFC</doc.keyword> <doc.keyword>Request for Comments</doc.keyword> <doc.keyword>I-D</doc.keyword> <doc.keyword>Internet-Draft</doc.keyword> <doc.keyword>XML</doc.keyword> <doc.keyword>Extensible Markup Language</doc.keyword></doc.front><doc.extras abstract="true" note="false"></doc.extras> <doc.links> </doc.links> </doc.props> <remote.props uri="http://sqa.not.invisible.net/public/rfc/html/rfc2629.html"></remote.props> <remote.props uri="http://sqa.not.invisible.net/public/rfc/txt/rfc2629.txt" language="text"></remote.props> </rfc>
Store the specified block using content from standard input. Four modes of store operation are available: create, delete, update, and write. This implementation of store expects to get its block content from standard input.
Create a new block, returning an error if the block already exists.
% perl big.pl -server sqa.invisible.net store test.yoursubtree test.yoursubtree.2629 create < 2629.xml
Delete the specified block, returning an error if the block does not exist. This operation only requires the block name, so a simplified XML input can be provided (e.g., <rfc name="doc.rfc.2629" />).
% perl big.pl -server sqa.invisible.net store test.yoursubtree test.yoursubtree.2629 delete < 2629.xml
Update the specified block, returning an error if the block does not exist.
% perl big.pl -server sqa.invisible.net store test.yoursubtree test.yoursubtree.2629 update < 2629.xml
Create or update the specified block, as appropriate.
% perl big.pl -server sqa.invisible.net store test.yoursubtree test.yoursubtree.2629 write < 2629.xml
- NOTE:
- It is probably not a good idea to allow non-authenticated store operations against your blocks server, which is what the above examples demonstrate. The following is a more likely example in normal use, using SASL/OTP for authentication.
% perl big.pl -server sqa.invisible.net -mechanism otp -username yourusername -passphrase yourpassphrase store test.yoursubtree test.yoursubtree.2629 write < 2629.xml
Opens a channel with the specified server and passes arbitrary text, which is then either echoed back to the client and verified to match what was sent (NULL/ECHO profile) or is simply ignored by the server (NULL/SINK profile).
% perl bxxpng.pl -server sqa.invisible.net echo initializing buffer... done. ..... 5 round-trips: min/avg/max = 312.743 334.746 360.107 (ms) 3 2 2 (KB/s)
% perl bxxpng.pl -server sqa.invisible.net sink initializing buffer... done. ..... 5 round-trips: min/avg/max = 306.301 329.171 376.339 (ms) 3 2 2 (KB/s)
TOC |
The example server implementation is a simple Blocks server that can be used for testing basic connectivity with Blocks client applications. It does not provide datastore support, so it is not possible to perform any of the more advanced client operations, such as: fetch, store, search, etc.
The sample server does provide support for authentication for testing.
The example server application is located in the top-level examples/server directory.
bxxd.pl requires a configuration file in order to start.
The configuration file defines general server parameters as well as the available profiles and their associated parameters. The formal definition of the BXXD configuration file is available in the BXXD configuration DTD
Global configuration parameters:
- homeDirectory:
- all relative pathnames are relative to this directory
- moduleDirectory:
- all relative module files are relative to this directory
- logFile:
- file to log events
- debugLevel:
- debug events, any of: "all", "trace", "timing", and "info" (seperated by spaces) or just "none"
Per profile configuration parameters:
- acl:
- access control list for the profile
- authDirectory:
- all authentication files are relative to this directory
- mode:
- mode requested if the profile supports multiple modes of operation
A typical configuration file contains the following parameters and profiles:
<?xml version="1.0"?> <!DOCTYPE config PUBLIC "-//Blocks//DTD BXXD CONFIG//EN" "http://xml.resource.org/blocks/software/bxxd/config.dtd"> <config> <bxxd port="10288"> <parameter name="homeDirectory" value="/path/to/bxxd" /> <parameter name="moduleDirectory" value="modules" /> <parameter name="logFile" value="logs/bxxd.log" /> <parameter name="debugLevel" value="none" /> <profile uri="http://xml.resource.org/profiles/sasl/ANONYMOUS" module="sasl-anon"> <parameter name="acl" value='subtree "" privs "fetch"' /> </profile> <profile uri="http://xml.resource.org/profiles/sasl/OTP" module="sasl-otp"> <parameter name="authDirectory" value="auth/" /> </profile> <profile uri="http://xml.resource.org/profiles/NULL/ECHO" module="null"> <parameter name="mode" value="echo" /> </profile> <profile uri="http://xml.resource.org/profiles/NULL/SINK" module="null"> <parameter name="mode" value="sink" /> </profile> </bxxd> </config>
This is a configuration file for the default port 10288.
To run the server under the supervision of inetd, first add the following to /etc/services:
bxxp 10288/tcp # Blocks eXtensible eXchange Protocol
Secondly, add the following to /etc/inetd.conf (Note: this should actually be one line, but was split for readability):
bxxp stream tcp nowait bxxpuser /path/to/bxxd/bin/bxxd.pl /path/to/bxxd/bin/bxxd.pl -config /path/to/bxxd/etc/bxxd-config.xml
Where:
You will need to reload inetd as super-user for the change to take effect.
bxxd.pl can run from the command line in "stand-alone daemon" mode. Once started, it continues to run indefinitely. This mode of running is typically used for testing purposes.
This example starts the server on port 12345 using the configuration file in the current directory named bxxd-config.xml:
bxxd.pl -daemon -port 12345 -config bxxd-config.xml
Without "-port" the server uses the default port, 10288.
Authentication and authorization for the Blocks server is provided via either anonymous[5] or One-Time-Password[4] (OTP) SASL[3] user profiles. The location of this user data is in the configuration file as the "authDirectory" profile parameter. It is a combination of the server "homeDirectory" and the "authDirectory" parameters if authDirectory is a relative path name.
To create an anonymous or OTP user profile, see the SASL Administration utility.
You can create your own modules by defining a new profile and implementing a new server module as well as the client using the new profile.
In the example, we create a module named "reverse" that receives a server request, reverses the order of the octets in the request, and responds back to the client with the reversed results.
To access your new module, first define the new profile and its corresponding module in the configuration file for the port using the new profile:
<profile uri="http://xml.resource.org/profiles/REVERSE" module="reverse"> </profile>
If you are using the server in stand-alone mode, you will need to restart since the configuration file loads at start time
Profile modules provide a fairly simple API consisting of 6 public subroutines: boot, info, init, exch, fin, and version.
Determine if the module is run-time bootable/loadable. Returns 0 if bootable and non-zero for all other conditions.
# # reverse profile boot protocol (run-time bootable?) # sub boot { my $log = shift; # clear global error indicator $! = 0; # always bootable 0; }
Returns a list containing information about the profile, including: whether the profile provides transport security (0 or 1), a list of supported profile identities (URIs), and a list of the public methods (callbacks) for using the module.
# # reverse profile info # sub info { my $log = shift; return [ 0, # profile provides transport security? (0 or 1) [ # supported profile identities (an XML DTD or URI) "http://xml.resource.org/profiles/REVERSE", ], { # public methods of this profile bootV => \&Profile::reverse::boot, initV => \&Profile::reverse::init, exchV => \&Profile::reverse::exch, finV => \&Profile::reverse::fin } ]; }
Initialize the module, returning a token (hash reference) to be used by the exch and fin subroutines.
# # reverse profile initialisation # sub init { my $log = shift; # server's log object (reference) my $serverD = shift; # fully-qualified domain name of server my $clientA = shift; # list of client ip address, hostname, and port my $upcallV = shift; # callback for profile to upcall the server my $uri = shift; # profile URI return { log => $log }; }
Although interactions between the server and the profile are synchronous, it's possible that the profile may need to originate traffic. An upcall is provided for this purpose.
Module data/message exchange subroutine.
# # reverse profile data/message exchange # sub exch { my $token = shift; my $data = shift; $token->{log}->entry("DEBUG", "reverse::exch", data: ($data)") if ($debug > 1); return reverse($data); }
Perform module specific clean up operations and dissolve the token created by the module init routine. Parameters are the init token and a status indicator. The "status" parameter indicates whether the finalization is graceful ("+") or extremely prejudicial ("-").
# # reverse profile finalisation # sub fin { my $token = shift; my $status = shift; 0; }
Return the current module version information as module name, version and release number. E.g., Profile::reverse 1.00r1.
# # library version info # sub version { return __PACKAGE__ . " " . $VERSION . "r" . $RELEASE; }
The SASL administration utility is found under the example server directory as etc/sasl-adm.pl. This utility will allow you to create, delete, list, and update the SASL anonymous and SASL OTP user accounts.
Usage: % etc/sasl-adm.pl [-action create|delete|list|update] [-authdir path/to/authdirectory] [-logfile path/to/logfile] [-mechanism anonymous|otp] [-version] [username] [subtree ...] where -action action to perform, defaults to create -authdir path to authentication database directory, defaults to ./auth, and will be created as needed -logfile path to log file, defaults to logs/sasl-adm.log -mechanism SASL mechanism, defaults to otp -version display application version and exit username user account to access, defaults to anonymous subtree list of subtrees user account will be given full access to, default subtree is empty and allows fetch operations on any subtree
TOC |
[1] | Rose, M.T., "The Blocks eXtensible eXchange Protocol", draft-mrose-blocks-protocol-02 (work in progress), April 2000. |
[2] | Rose, M.T., "The Blocks Simple Exchange Profile", draft-mrose-blocks-exchange-01 (work in progress), April 2000. |
[3] | Myers, J.G., "Simple Authentication and Security Layer (SASL)", RFC 2222, October 1997. |
[4] | Newman, C. and J. G. Myers, "ACAP -- Application Configuration Access Protocol", RFC 2244, November 1997. |
[5] | Newman, C., "Anonymous SASL Mechanism", RFC 2245, November 1997. |
TOC |
Brad Burdick | |
Invisible Worlds, Inc. | |
1179 N. McDowell Blvd | |
Suite A | |
Petaluma, CA 94954-6559 | |
US | |
EMail: | bburdick@invisible.net |
URI: | http://invisible.net/ |
TOC |
<!-- DTD for BXXD server configuration, as of 2000-02-14 Copyright 2000 Invisible Worlds, Inc. This document is a DTD and is in full conformance with all provisions of Section 10 of RFC2026 except that the right to produce derivative works is not granted. Refer to this DTD as: <!ENTITY % CONFIG PUBLIC "-//Blocks//DTD BXXD CONFIG//EN" "http://xml.resource.org/blocks/software/bxxd/config.dtd"> %CONFIG; --> <!-- Contents DTD data types Config file definition --> <!-- DTD data types: entity syntax/reference example ====== ================ ======= a uniform resource identifier URI c.f., [RFC1630] "http://xml.resource.org/profiles/" a TCP port number PORTNO 0..65535 10288 a filename FILE echo.pl --> <!ENTITY % URI "CDATA"> <!ENTITY % PORTNO "CDATA"> <!ENTITY % FILE "CDATA"> <!ELEMENT config (bxxd+)> <!ELEMENT bxxd (parameter*,profile*)> <!ATTLIST bxxd port %PORTNO; "10288"> <!ELEMENT profile (parameter*)> <!ATTLIST profile uri %URI; #REQUIRED module %FILE; #REQUIRED privRequired (true|false) "false" privProvider (true|false) "false"> <!-- A profile listed as requiring privacy is available only if privacy is already enabled. A profile listed as providing privacy is unavailable if privacy is already enabled. --> <!ELEMENT parameter EMPTY> <!ATTLIST parameter name CDATA #REQUIRED value CDATA #REQUIRED> <!-- Global parameters: name meaning ==== ======= homeDirectory all pathnames are relative to this directory moduleDirectory all module files are relative to this directory logFile file to log events debugLevel debug events, any of: "all", "trace", "timing", and "info" (seperated by spaces) or just "none" -->
TOC |
Blocks Public License
Copyright (c) 2000, Invisible Worlds, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INVISIBLE WORLDS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.