+++ /dev/null
-#!/bin/bash
-
-OPT_ACTION=""
-OPT_PERL_CONFIG=""
-OPT_C_CONFIG=""
-OPT_PID_DIR=""
-
-# ---------------------------------------------------------------------------
-# Make sure we're running as the correct user
-# ---------------------------------------------------------------------------
-[ $(whoami) != 'opensrf' ] && echo 'Must run as user "opensrf"' && exit;
-
-
-# NOTE: Eventually, there will be one OpenSRF config file format
-# When this happens, we will only need a single OPT_CONFIG variable
-
-function usage {
- echo "";
- echo "usage: $0 -d <pid_dir> -p <perl_config> -c <c_config> -a <action>";
- echo "";
- echo "Actions include:"
- echo -e "\tstart_router"
- echo -e "\tstop_router"
- echo -e "\trestart_router"
- echo -e "\tstart_perl"
- echo -e "\tstop_perl"
- echo -e "\trestart_perl"
- echo -e "\tstart_c"
- echo -e "\tstop_c"
- echo -e "\trestart_c"
- echo -e "\tstart_osrf"
- echo -e "\tstop_osrf"
- echo -e "\trestart_osrf"
- echo -e "\tstop_all"
- echo -e "\tstart_all"
- echo -e "\trestart_all"
- echo "";
- echo "Example:";
- echo " $0 -p bootstrap.conf -c opensrf_core.xml -a restart_all";
- echo "";
- exit;
-}
-
-
-# ---------------------------------------------------------------------------
-# Load the command line options and set the global vars
-# ---------------------------------------------------------------------------
-while getopts "p:c:a:d:h" flag; do
- case $flag in
- "a") OPT_ACTION="$OPTARG";;
- "c") OPT_C_CONFIG="$OPTARG";;
- "p") OPT_PERL_CONFIG="$OPTARG";;
- "d") OPT_PID_DIR="$OPTARG";;
- "h"|*) usage;;
- esac;
-done
-
-
-[ -z "$OPT_PID_DIR" ] && OPT_PID_DIR=/tmp;
-[ -z "$OPT_ACTION" ] && usage;
-
-PID_ROUTER="$OPT_PID_DIR/router.pid";
-PID_OSRF_PERL="$OPT_PID_DIR/osrf_perl.pid";
-PID_OSRF_C="$OPT_PID_DIR/osrf_c.pid";
-
-
-# ---------------------------------------------------------------------------
-# Utility code for checking the PID files
-# ---------------------------------------------------------------------------
-function do_action {
-
- action="$1";
- pidfile="$2";
- item="$3";
-
- if [ $action == "start" ]; then
-
- if [ -e $pidfile ]; then
- pid=$(cat $pidfile);
- echo "$item already started : $pid";
- return 0;
- fi;
- echo "Starting $item";
- fi;
-
- if [ $action == "stop" ]; then
-
- if [ ! -e $pidfile ]; then
- echo "$item not running";
- return 0;
- fi;
-
- pid=$(cat $pidfile);
- echo "Stopping $item : $pid";
- kill -s INT $pid 2> /dev/null;
- sleep 1;
- kill -9 $pid 2> /dev/null;
- rm -f $pidfile;
-
- fi;
-
- return 0;
-}
-
-
-# ---------------------------------------------------------------------------
-# Start / Stop functions
-# ---------------------------------------------------------------------------
-
-
-function start_router {
- do_action "start" $PID_ROUTER "OpenSRF Router";
- opensrf_router $OPT_C_CONFIG router
- pid=$(ps ax | grep "OpenSRF Router" | grep -v grep | awk '{print $1}')
- echo $pid > $PID_ROUTER;
- return 0;
-}
-
-function stop_router {
- do_action "stop" $PID_ROUTER "OpenSRF Router";
- return 0;
-}
-
-function start_perl {
- do_action "start" $PID_OSRF_PERL "OpenSRF Perl";
- perl -MOpenSRF::System="$OPT_PERL_CONFIG" -e 'OpenSRF::System->bootstrap()' &
- pid=$!;
- echo $pid > $PID_OSRF_PERL;
- sleep 5;
- return 0;
-}
-
-function stop_perl {
- do_action "stop" $PID_OSRF_PERL "OpenSRF Perl";
- sleep 1;
- return 0;
-}
-
-function start_c {
- host=$(perl -MNet::Domain=hostfqdn -e 'print hostfqdn()')
- do_action "start" $PID_OSRF_C "OpenSRF C (host=$host)";
- opensrf-c $host $OPT_C_CONFIG opensrf;
- pid=$(ps ax | grep "OpenSRF System-C" | grep -v grep | awk '{print $1}')
- echo $pid > "$PID_OSRF_C";
- return 0;
-}
-
-function stop_c {
- do_action "stop" $PID_OSRF_C "OpenSRF C";
- killall -9 opensrf-c # hack for now to force kill all C services
- sleep 1;
- return 0;
-}
-
-
-
-# ---------------------------------------------------------------------------
-# Do the requested action
-# ---------------------------------------------------------------------------
-case $OPT_ACTION in
- "start_router") start_router;;
- "stop_router") stop_router;;
- "restart_router") stop_router; start_router;;
- "start_perl") start_perl;;
- "stop_perl") stop_perl;;
- "restart_perl") stop_perl; start_perl;;
- "start_c") start_c;;
- "stop_c") stop_c;;
- "restart_c") stop_c; start_c;;
- "start_osrf") start_perl; start_c;;
- "stop_osrf") stop_perl; stop_c;;
- "restart_osrf") stop_perl; stop_c; start_perl; start_c;;
- "stop_all") stop_c; stop_perl; stop_router;;
- "start_all") start_router; start_perl; start_c;;
- "restart_all") stop_c; stop_perl; stop_router; start_router; start_perl; start_c;;
- *) usage;;
-esac;
-
-
-
+++ /dev/null
-OpenSRF Application development API
------------------------------------
-
-OpenSRF offers a very simple Application development API to users of the
-framework. All that is required is to create a Perl module that subclasses
-the OpenSRF::Application package and register it's methods with the
-Method Dispatcher framework.
-
-Each method executes in the OpenSRF::Application namespace as an instance of
-the custom Application. There are some instance methods on this object which
-can be used by the method to alter the behavior or response that the method
-sends to the client:
-
- $self->api_name # returns the name of the method as called by the client
-
- $self->method # returns the actual perl name of the sub implementing the
- # method
-
- my $meth = $self->method_lookup( 'api_name' )
- # constructs a new instance object implementing another
- # method in the same Application package as a subrequest
-
- my ($subresult) = $meth->run( @params )
- # runs the subrequest method and returns the array of
- # results
-
-
-The method is also handed an OpenSRF::AppRequest object that has been
-constructed for the client request that generated the call to the method.
-This OpenSRF::AppRequest object is used to communicate back to the client,
-passing status messages or streaming response packets.
-
-All that is required to register an Application with OpenSRF is to place a
-setting in the configuration file that names the module that implements the
-new Application, and to add the new Application's symbolic name to the list of
-servers that should be started by OpenSRF.
-
- Example Application
- -------------------
-
- # Perl module and package implementing an math server.
- package MyMathServer;
- use OpenSRF::Application;
- use base 'OpenSRF::Application';
-
- sub do_math {
- my $self = shift; # instance of MyMathServer
-
- my $client = shift; # instance of OpenSRF::AppRequest connected
- # to the client
-
- my $left_side = shift;
- my $op = shift;
- my $right_side = shift;
-
- return eval "$left_side $op $right_side";
- }
-
- __PACKAGE__->register_method(
- api_name => 'useless.do_math',
- argc => 3,
- method => 'do_math'
- );
-
- 1;
-
-
-
- # Another Perl module and package implementing a square-root server on top
- # of the previous math server
- package MySquareRootServer;
- use OpenSRF::Application;
- use base 'OpenSRF::Application';
- use MyMathServer;
-
- sub sqrt_math {
- my $self = shift; # instance of MySquareRootServer
-
- my $client = shift; # instance of OpenSRF::AppRequest connected
- # to the client
-
- my $math_method = $self->method_lookup('useless.do_math');
- my ($result) = $math_method->run( @_ );
-
- return sqrt( $result );
- }
-
- __PACKAGE__->register_method(
- api_name => 'simple.sqrt',
- argc => 3,
- method => 'sqrt_math'
- );
-
- 1;
-
+++ /dev/null
-<html>
-
- <head>
-
- <title> OILS Messaging </title>
-
- </head>
-
- <body>
-
-
- <h1> Abstract </h1>
-
- <p>
-
- The OpenSRF messaging system works on two different primary layers: the transport layer and the
- application layer. The transport layer manages virtual connections between client and server,
- while the application layer manages user/application level messages.
-
- All messages must declare which protocol version they are requesting. The current protocol level
- is 1.
-
- <h1> Transport Layer </h1>
-
- <p>
- There are currently three types of messages in the transport layer: <b>CONNECT, STATUS, </b> and
- <b>DISCONNECT</b>.
-
- <p>
- <b>STATUS</b> messages provide general information to the transport layer and are used in different
- ways throughout the system. They are sent primarily by the server in response to client requests.
- Each message comes with
- a status and statusCode. The actual status part of the STATUS message is just a helpful message
- (mostly for debugging). The
- statusCode is an integer representing the exact status this message represents. The status codes
- are modeled after HTTP status codes. Currently used codes consist of the following:
-
- <b> <pre style="border: solid thin blue; margin: 2% 10% 2% 10%; padding-left: 50px">
- 100 STATUS_CONTINUE
- 200 STATUS_OK
- 205 STATUS_COMPLETE
- 307 STATUS_REDIRECTED
- 400 STATUS_BADREQUEST
- 404 STATUS_NOTFOUND
- 408 STATUS_TIMEOUT
- 417 STATUS_EXPFAILED
- </pre> </b>
-
- <p>
- This list is likely to change at least a little.
-
-
- <p>
- The <b>CONNECT</b> message initiates the virtual connection for a client and expects a <b>STATUS</b>
- in return. If the connection is successful, the statusCode for the <b>STATUS</b> message shall be
- <b>STATUS_OK</b>.
-
- <p>
- If at any point the client sends a non-connect message to the server when the client is not connected or the
- connection has timed out, the <b>STATUS</b> that is returned shall have statusCode <b>STATUS_EXPFAILED</b>.
-
- <p>
- The <b>DISCONNECT</b> message is sent by the client to the server to end the virtual session. The server
- shall not respond to any disconnect messages.
-
-
- <h1> Message Layer </h1>
-
- <p>
- There are currently two types of message layer messages: <b>REQUEST</b> and <b>RESULT</b>. <b>REQUEST</b>
- messages represent application layer requests made by a client and <b>RESULT</b> messages are the servers
- response to such <b>REQUEST</b>'s.
-
- <p>
- By design, all <b>CONNECT</b> and <b>REQUEST</b> messages sent by a client will be acknowledged by one or
- more responses from the server. This is much like the SYN-ACK philosophy of TCP, however different in many
- ways. The only guarantees made by the server are 1. you will know that we received your request and 2. you
- will know the final outcome of your request. It is the responsibility of the actual application to send
- the requested application data (e.g. RESULT messages, intermediate STATUS messages).
-
-
- <p>
- The server responses are matched to client requests by a <b>threadTrace</b>. A threadTrace is simply a
- number and all application layer messages and STATUS messages are required to have one. (Note that the
- threadTrace contained within a STATUS message sent in response to a CONNECT will be ignored). Currently,
- there is no restriction on the number other than it shall be unique within a given virtual connection.
- When the server receives a <b>REQUEST</b> message, it extracts the <b>threadTrace</b> from the message
- and all responses to that request will contain the same <b>threadTrace</b>.
-
- <p>
- As mentioned above, every <b>CONNECT</b> message will be acknowledged by a single
- <b>STATUS</b> message. <b>REQUEST</b>'s are a little more complex, however. A <b>REQUEST</b>
- will receive one or more <b>RESULT</b>'s if the <b>REQUEST</b> warrants such a response. A <b>REQUEST</b>
- may even receive one or more intermediate <b>STATUS</b>'s (e.g. <b>STATUS_CONTINUE</b>). (Consult the
- documentation on the application request the client is requesting for more information on the number and
- type of responses to that request). All <b>REQUEST</b>'s, however, regardless of other response types,
- shall receieve as the last response a <b>STATUS</b> message with statusCode <b>STATUS_COMPLETE</b>. This
- allows the client to wait for REQUEST "completeness" as opposed to waiting on or calculating individual
- responses.
-
-
- <h1> Client Pseudocode </h1>
-
- <pre style="border: solid thin blue; margin: 0% 10% 0% 10%; padding-left: 50px">
-
-send CONNECT
-
-msg = recv()
-
-if ( msg.statusCode == STATUS_OK )
-
- OK. continue
-
-while ( more requests ) {
-
- /* you may send multiple requests before processing any responses. For the sake
- of this example, we will only walk through a single client request */
-
- send REQUEST with threadTrace X
-
- while ( response = recv ) {
-
- if ( response.threadTrace != X )
-
- continue/ignore
-
- if ( response.type == STATUS )
-
- if ( response.statusCode == STATUS_TIMEOUT or
- response.statusCode == STATUS_REDIRECTED or
- response.statusCode == STATUS_EXPFAILED)
-
- resend the the request with threadTrace X because it was not honored.
-
- if ( response.statusCode == STATUS_COMPLETE )
-
- the request is now complete, nothing more to be done with this request
- break out of loop
-
- if ( response.typ == RESULT )
-
- pass result to the application layer for processing
-
- } // receiving
-
-} // sending
-
-
- </pre>
-
- <br>
- <h1> Server Pseudocode </h1>
-
- <pre style="border: solid thin blue; margin: 0% 10% 0% 10%; padding-left: 50px">
-
-while( message = recv() ) {
-
- if( message.type != CONNECT )
-
- return a STATUS with statusCode STATUS_EXPFAILED
- start loop over
-
- if ( message.type == CONNECT )
-
- return STATUS with statusCode STATUS_OK and continue
-
- while ( msg = recv() and virtual session is active ) {
-
-
- if ( msg.type == REQUEST )
-
- Record the threadTrace. Pass the REQUEST to the application layer for processing.
- When the application layer has completed processing, respond to the client
- with a STATUS message with statusCode STATUS_COMPLETE and threadTrace matching
- the threadTrace of the REQUEST. Once the final STATUS_COMPLETE message is sent,
- the session is over. Return to outer server loop.
-
- /* Note: during REQUEST processing by the application layer, the application may
- opt to send RESULT and/or STATUS messages to the client. The server side
- transport mechanism is not concerned with these messages. The server only
- needs to be notified when the REQUEST has been sucessfully completed. */
-
- if( message.type == DISCONNECT )
-
- Virtual session has ended. Return to outer loop.
-
-
- } // Sessin loop
-
-} // Main server loop
-
-
-
- </pre>
-
-
- <br>
- <h1> XML Examples</h1>
- <br>
-
-
- <h2> Protocol Element </h2>
-
- <pre style="border: solid thin blue; margin: 0% 10% 0% 10%; padding-left: 50px">
-
-<oils:domainObjectAttr value="1" name="protocol"/>
-
- </pre>
-
- <h2> threadTrace Element </h2>
-
- <pre style="border: solid thin blue; margin: 0% 10% 0% 10%; padding-left: 50px">
-
-<oils:domainObjectAttr value="1" name="threadTrace"/>
-
- </pre>
-
- <h2> CONNECT Message </h2>
-
- <pre style="border: solid thin blue; margin: 0% 10% 0% 10%; padding-left: 50px">
-
-<oils:domainObject name="oilsMessage">
- <oils:domainObjectAttr value="CONNECT" name="type"/>
- <oils:domainObjectAttr value="1" name="threadTrace"/>
- <oils:domainObjectAttr value="1" name="protocol"/>
-</oils:domainObject>
-
- </pre>
-
-
- <h2> DISCONNECT Message </h2>
-
- <pre style="border: solid thin blue; margin: 0% 10% 0% 10%; padding-left: 50px">
-
-<oils:domainObject name="oilsMessage">
- <oils:domainObjectAttr value="DISCONNECT" name="type"/>
- <oils:domainObjectAttr value="0" name="threadTrace"/>
- <oils:domainObjectAttr value="1" name="protocol"/>
-</oils:domainObject>
-
- </pre>
-
- <h2> STATUS Message </h2>
-
- <pre style="border: solid thin blue; margin: 0% 10% 0% 10%; padding-left: 50px">
-
-<oils:domainObject name="oilsMessage">
- <oils:domainObjectAttr value="STATUS" name="type"/>
- <oils:domainObjectAttr value="0" name="threadTrace"/>
- <oils:domainObjectAttr value="1" name="protocol"/>
- <oils:domainObject name="oilsConnectStatus">
- <oils:domainObjectAttr value="Connection Successful" name="status"/>
- <oils:domainObjectAttr value="200" name="statusCode"/>
- </oils:domainObject>
-</oils:domainObject>
-
- </pre>
-
- <h2> REQUEST Message </h2>
-
- <pre style="border: solid thin blue; margin: 0% 10% 0% 10%; padding-left: 50px">
-
-<oils:domainObject name="oilsMessage">
- <oils:domainObjectAttr value="REQUEST" name="type"/>
- <oils:domainObjectAttr value="4" name="threadTrace"/>
- <oils:domainObjectAttr value="1" name="protocol"/>
- <oils:domainObject name="oilsMethod">
- <oils:domainObjectAttr value="mult" name="method"/>
- <oils:params>[1, 2]</oils:params>
- </oils:domainObject>
-</oils:domainObject>
-
- </pre>
-
- <h2> RESULT Message </h2>
-
- <pre style="border: solid thin blue; margin: 0% 10% 0% 10%; padding-left: 50px">
-
-<oils:domainObject name="oilsMessage">
- <oils:domainObjectAttr value="RESULT" name="type"/>
- <oils:domainObjectAttr value="4" name="threadTrace"/>
- <oils:domainObjectAttr value="1" name="protocol"/>
- <oils:domainObject name="oilsResult">
- <oils:domainObjectAttr value="OK" name="status"/>
- <oils:domainObjectAttr value="200" name="statusCode"/>
- <oils:domainObject name="oilsScalar">2</oils:domainObject>
- </oils:domainObject>
-</oils:domainObject>
-
- </pre>
-
-
- </body>
-
-</html>
-
-
+++ /dev/null
-<html>
- <head>
- <title>OpenSRF Persistence Application API-Namespace</title>
- <style><!--
-
- * { font-family: sans-serif;
- font-size: 13pt;
- }
-
- .sectionhead { border: solid black 1px;
- background-color: #333333;
- font-weight: bold;
- color: white;
- text-align: center;
- padding: 5px;
- margin: 5px;
- }
-
- .section { border: solid black 1px;
- background-color: lightgray;
- color: black;
- padding: 5px;
- margin: 5px;
- margin-bottom: 15px;
- }
-
- .listheader { font-weight: bold;
- margin-top: 15px
- }
-
- .value { font-style: italic;
- margin-top: 5px;
- margin-left: 20px;
- }
-
- .description { margin-top: 0px;
- margin-left: 30px;
- }
-
- //-->
- </style>
-
- </head>
- <body>
- <center>
- <h2>OpenSRF Persistence Application API-Namespace</h2>
- <hr width="90%">
- </center>
-
- <div style="margin: 30px;">
- The Persistence Application provides other OpenSRF Applications with a standard API for
- sharing and caching data. These data are stored in Slots, and there are three basic
- interfaces for interacting with Slots: QUEUEs, STACKs and OBJECTs.
- </div>
-
- <ul>
- <li> <h3>General Persistence Slot methods</h3>
-
- Methods used to create, set up and destroy slots.
- <br><br>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.slot.create( slot_name )</div>
-
- Creates a Persistence Slot.
-
- <div class="listheader">Parameters:</div>
- <div class="value">slot_name (optional)</div>
- <div class="description">
- The name of the Persistence Slot to create. If a name is not specified
- then the Slot is given a generic, unique name. Automatically named Slots
- are destroyed as soon as they are empty.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">The name of the Slot that was created.</div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.slot.create_expirable( slot_name, expire_interval )</div>
-
- Creates a Persistence Slot that is automatically destroyed after the specified interval.
-
- <div class="listheader">Parameters:</div>
- <div class="value">slot_name</div>
- <div class="description">The name of the Persistence Slot to create.</div>
- <div class="value">expire_interval</div>
- <div class="description">
- An interval describing how long to wait after an access has
- occured on the Slot before automatically destroying it. The interval
- can be specified using a fairly complex, human readable format, or as
- a number of seconds. For example:
- <ul>
- <li> 1 day, 2 hours and 35 minutes </li>
- <li> +2h </li>
- <li> 1 week </li>
- <li> 300 </li>
- </ul>
-
- A setting of 0 (zero) disables automatic expiration for a Slot.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">The name of the Slot that was created.</div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.slot.set_expire( slot_name, expire_interval )</div>
-
- Sets or disables the expiration interval on an existing Persistence Slot.
-
- <div class="listheader">Parameters:</div>
- <div class="value">slot_name</div>
- <div class="description">The name of the Persistence Slot to update.</div>
- <div class="value">expire_interval</div>
- <div class="description">
- An interval describing how long to wait after an access has
- occured on the Slot before automatically destroying it. The interval
- can be specified using a fairly complex, human readable format, or as
- a number of seconds. For example:
- <ul>
- <li> 1 day, 2 hours and 35 minutes </li>
- <li> +2h </li>
- <li> 1 week </li>
- <li> 300 </li>
- </ul>
-
- A setting of 0 (zero) disables automatic expiration for a Slot.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">The number of seconds the requested interval represents.</div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.slot.destroy( slot_name )</div>
-
- Destroys a Persistence Slot.
-
- <div class="listheader">Parameters:</div>
- <div class="value">slot_name</div>
- <div class="description">The name of the Persistence Slot to destroy.</div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">The name of the Slot that was destroyed.</div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <br>
- </li>
-
- <li> <h3>QUEUE API-Namespace Slot methods</h3>
-
- Uses the Slot in FIFO mode, pushing values onto one end an pulling them off the other.
- The QUEUE API-Namespace is useful for creating an ordered message passing access point.
-
- <br><br>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.queue.push( slot_name, object )</div>
-
- Adds an object to a Slot in FIFO order.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">The name of the Persistence Slot to use for storing the object.</div>
-
- <div class="value">object</div>
- <div class="description">The object that should be pushed onto the front of the QUEUE.</div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">The name of the Slot that was used.</div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.queue.pop( slot_name )</div>
-
- Removes and returns the next value in a QUEUE type Slot.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">
- The name of the Persistence Slot from which an object should be retrieved.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">
- The next object on the QUEUE Slot, or an empty
- (NULL) result if the Slot is empty.
- </div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.queue.peek( slot_name )</div>
-
- Returns the next value in a QUEUE type Slot <u>without</u> removing it.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">
- The name of the Persistence Slot from which an object should be retrieved.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">
- The next object on the QUEUE Slot, or an empty
- (NULL) result if the Slot is empty.
- </div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.queue.peek.all( slot_name )</div>
-
- Returns all values in a QUEUE type Slot <u>without</u> removing them.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">
- The name of the Persistence Slot from which the objects should be retrieved.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">
- A stream of all objects on the QUEUE Slot, or an empty
- (NULL) result if the Slot is empty.
- </div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.queue.peek.all.atomic( slot_name )</div>
-
- Returns all values in a QUEUE type Slot <u>without</u> removing them.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">
- The name of the Persistence Slot from which the objects should be retrieved.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">
- A single array of all objects on the QUEUE Slot, or an empty
- array if the Slot is empty.
- </div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.queue.length( slot_name )</div>
-
- Returns the number of objects in the QUEUE type Slot.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">
- The name of the Persistence Slot in question.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">The number of objects in the Persistence Slot.</div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.queue.size( slot_name )</div>
-
- Returns the number bytes taken up by the JSON encoded version of
- the objects in the QUEUE type Slot.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">
- The name of the Persistence Slot in question.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">
- The space, in bytes, used by the JSON encoded
- objects in the Persistence Slot.
- </div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <br>
- </li>
-
- <li> <h3>STACK style Slot methods</h3>
-
- Uses the Slot in FILO mode, pushing and pulling objects at the same end of a list.
- The STACK API-Namespace is useful for creating a global Application context stack.
-
- <br><br>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.stack.push( slot_name, object )</div>
-
- Adds an object to a Slot in FILO order.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">The name of the Persistence Slot to use for storing the object.</div>
-
- <div class="value">object</div>
- <div class="description">The object that should be pushed onto the front of the STACK.</div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">The name of the Slot that was used.</div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.stack.pop( slot_name )</div>
-
- Removes and returns the next value in a STACK type Slot.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">
- The name of the Persistence Slot from which an object should be retrieved.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">
- The next object on the STACK Slot, or an empty
- (NULL) result if the Slot is empty.
- </div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.stack.peek( slot_name )</div>
-
- Returns the next value in a STACK type Slot <u>without</u> removing it.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">
- The name of the Persistence Slot from which an object should be retrieved.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">
- The next object on the STACK Slot, or an empty
- (NULL) result if the Slot is empty.
- </div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.stack.peek.all( slot_name )</div>
-
- Returns all values in a STACK type Slot <u>without</u> removing them.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">
- The name of the Persistence Slot from which the objects should be retrieved.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">
- A stream of all objects on the STACK Slot, or an empty
- (NULL) result if the Slot is empty.
- </div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.stack.peek.all.atomic( slot_name )</div>
-
- Returns all values in a STACK type Slot <u>without</u> removing them.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">
- The name of the Persistence Slot from which the objects should be retrieved.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">
- A single array of all objects on the STACK Slot, or an empty
- array if the Slot is empty.
- </div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.stack.depth( slot_name )</div>
-
- Returns the number of objects in the STACK type Slot.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">
- The name of the Persistence Slot in question.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">The number of objects in the Persistence Slot.</div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.stack.size( slot_name )</div>
-
- Returns the number bytes taken up by the JSON encoded version of
- the objects in the STACK type Slot.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">
- The name of the Persistence Slot in question.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">
- The space, in bytes, used by the JSON encoded
- objects in the Persistence Slot.
- </div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <br>
- </li>
-
- <li> <h3>OBJECT style Slot methods</h3>
-
- Uses the Slot in Single Object mode, storing a single object in the Slot.
-
- <br><br>
-
- The OBJECT API-Namespace is useful for globally caching unique objects.
-
- <br><br>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.object.set( slot_name, object )</div>
-
- Sets the value of a Slot. If the Slot has been used in STACK or QUEUE
- mode and <b>opensrf.persist.object.set</b> is called then all objects currently
- in the Slot will be lost.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">The name of the Persistence Slot to use for storing the object.</div>
-
- <div class="value">object</div>
- <div class="description">The object that should be set as the one object in the Slot.</div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">The name of the Slot that was used.</div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.object.get( slot_name )</div>
-
- Removes and returns the value in an OBJECT type Slot.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">
- The name of the Persistence Slot from which the object should be retrieved.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">
- The object in the OBJECT Slot, or an empty
- (NULL) result if the Slot is empty.
- </div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.object.peek( slot_name )</div>
-
- Returns the value in an OBJECT type Slot <u>without</u> removing it.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">
- The name of the Persistence Slot from which the object should be retrieved.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">
- The object on the OBJECT Slot, or an empty
- (NULL) result if the Slot is empty.
- </div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- <div class="section">
- <div class="sectionhead">opensrf.persist.object.size( slot_name )</div>
-
- Returns the number bytes taken up by the JSON encoded version of
- the object in the OBJECT type Slot.
-
- <div class="listheader">Parameters:</div>
-
- <div class="value">slot_name</div>
- <div class="description">
- The name of the Persistence Slot in question.
- </div>
-
-
- <div class="listheader">Returns:</div>
-
- <div class="value">Success</div>
- <div class="description">
- The space, in bytes, used by the JSON encoded
- object in the Persistence Slot.
- </div>
-
- <div class="value">Failure</div>
- <div class="description">An empty (NULL) result.</div>
- </div>
-
- </li>
- </ul>
- </body>
-</html>
+++ /dev/null
-Roadmap for OpenSRF === The high points as of Febuary 2005
-----------------------------------------------------------
-
-We will attempt to keep this file up to date as requirements for
-Open-ILS change over time, as they are certain to...
-
-==========
-
-# Version 0.1 (January 2005) -- Evolving CVS version ... stay tuned
-
- * Session failure recovery
- * Initial specification for Application API
- * Basic Application support
- * Sub-requests within one Application
-
-# Version 0.2 (Febuary/March 2005) -- First full release as a package
-
- * Centralized Application configuration management
- * Automatic cross-server API discovery
- * Transparent remote server sub-requests
- * Object Persistence Application implementing Stacks, Queues
- and Object Stores based on SQLite
-
-# Version 0.3 (March/April 2005) -- Version for use in the Alpha
- release of Open-ILS
-
- * Partial implementation of a BROADCAST mode for addressing all
- Servers of a particular Class on one Router
- * Distributed version of the Object Persistence Application
-
-# Version 0.5 (July/August 2005)
-
- * Full implementation of a BROADCAST mode for addressing all
- Servers of any number of Classes on any number of Routers
- * Client side use of transparent API discovery; the client
- libraries will automatically discover and use the correct
- Server for any valid method request
-
-# Version 0.7 (October/November 2005)
-
- * Basic inter-server session migration support in addition
- to session failure recovery due to server failure
-
-# Version 0.9 (Some time in 2006)
-
- * Built in distributed transaction support.
-
-# Version 1.0 (in the future)
-
- * Who knows?
-
+++ /dev/null
-#!/usr/bin/perl -w
-use OpenSRF::System qw(/pines/conf/bootstrap.conf);
-use Getopt::Long
-
-$| = 1;
-
-my $cvs_base = 'http://open-ils.org/cgi-bin/viewcvs.cgi/ILS/Open-ILS/src/perlmods/';
-my $nest = 0;
-my $service;
-my $filter;
-my $sort_ignore;
-
-GetOptions( 'cvs_base=s' => \$cvs_base,
- 'nest' => \$nest,
- 'service=s' => \$service,
- 'ignore=s' => \$sort_ignore,
- 'filter=s' => \$filter,
-);
-
-unless( $service ) {
- print "usage: $0 -s <service name> [-c <cvs repo base URL> -f <regex filter for method names> -n]\n";
- exit;
-}
-
-OpenSRF::System->bootstrap_client();
-my $session = OpenSRF::AppSession->create( $service );
-
-my $req;
-if ($filter) {
- $req = $session->request('opensrf.system.method', $filter);
-} else {
- $req = $session->request('opensrf.system.method.all');
-}
-
-my $count = 1;
-my %m;
-while( my $meth = $req->recv(60) ) {
- $meth = $meth->content;
-
- $api_name = $meth->{api_name};
-
- $m{$api_name}{api_name} = $meth->{api_name};
-
- $m{$api_name}{package} = $meth->{package};
- $m{$api_name}{method} = $meth->{method};
-
- $m{$api_name}{api_level} = int $meth->{api_level};
- $m{$api_name}{server_class} = $meth->{server_class} || '**ALL**';
- $m{$api_name}{stream} = int($meth->{stream} || 0);
- $m{$api_name}{cachable} = int($meth->{cachable} || 0);
-
- $m{$api_name}{note} = $meth->{note} || 'what I do';
- ($m{$api_name}{cvs} = $m{$api_name}{package}) =~ s/::/\//go;
-
- $m{$api_name}{stream} = $m{$api_name}{stream}?'Yes':'No';
- $m{$api_name}{cachable} = $m{$api_name}{cachable}?'Yes':'No';
-
- print STDERR "." unless ($count % 10);
-
- $count++;
-}
-
-warn "\nThere are ".scalar(keys %m)." methods published by $service\n";
-
-my @m_list;
-if (!$sort_ignore) {
- @m_list = sort keys %m;
-} else {
- @m_list =
- map { ($$_[0]) }
- sort {
- $$a[1] cmp $$b[1]
- ||
- length($$b[0]) <=> length($$a[0])
- } map {
- [$_ =>
- do {
- (my $x = $_) =~ s/^$sort_ignore//go;
- $x;
- } ]
- } keys %m;
-}
-
-for my $meth ( @m_list ) {
-
- my $pad = 0;
- my $header = '=====';
- if ($nest) {
- no warnings;
- (my $x = $meth) =~ s/\./$pad++;$1/eg;
- }
- $pad = ' 'x$pad;
-
- print <<" METHOD";
-$pad$header $meth $header
-
-$m{$meth}{note}
-
- * [[osrf-devel:terms#opensrf_api-level|API Level]]: $m{$meth}{api_level}
- * [[osrf-devel:terms#opensrf_server_class|Server Class]]: $m{$meth}{server_class}
- * Implementation Method: [[$cvs_base/$m{$meth}{cvs}.pm|$m{$meth}{package}\::$m{$meth}{method}]]
- * Streaming [[osrf-devel:terms#opensrf_method|Method]]: $m{$meth}{stream}
- * Cachable [[osrf-devel:terms#opensrf_method|Method]]: $m{$meth}{cachable}
-
- * **Parameters:**
- * //param1//\\\\ what it is...
- * **Returns:**
- * //Success//\\\\ successful format
- * //Failure//\\\\ failure format (exception, etc)
-
-
- METHOD
-}
-
+++ /dev/null
-# ----------------------------------------------------------
-# bootstrap config file
-# ----------------------------------------------------------
-[bootstrap]
-
-# location of the opensrf.xml config file
-settings_config = /path/to/opensrf.xml
-
-# log files directory
-log_dir = /path/to/log
-
-## Log file is either a file name or syslog:<facility>
-#logfile = osrfysys.log
-logfile = syslog:local0
-
-# defines the syslog facility for the activity log
-#actlog = activity.log
-actlog = syslog:local1
-
-# log level
-debug = ERROR
-#debug = INFO
-#debug = DEBUG
-#debug = INTERNAL
-
-# the jabber login of the router (changing this will likely cause problems)
-router_name = router
-
-# all jabber domains we want our app to connect to
-list:domains = router1.domain.com, router2.domain.com
-
-# jabber login
-username = jabber_username
-
-# jabber password
-passwd = jabber_password
-
-# if port is non-numeric (e.g. /tmp/mysock.sock) then we will attempt to
-# connect to the specified string as a unix socket file
-# This works with Chop Chop jabber only (opensrf custom jabber server)
-port = 5222
-
-# --------------------------------------
-
+++ /dev/null
-<xsl:stylesheet
- version='1.0'
- xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
- xmlns:opensrf="http://opensrf.org/xmlns/opensrf"
- xmlns:cdbi="http://opensrf.org/xmlns/opensrf/cdbi"
- xmlns:database="http://opensrf.org/xmlns/opensrf/database"
- xmlns:perl="http://opensrf.org/xmlns/opensrf/perl"
- xmlns:javascript="http://opensrf.org/xmlns/opensrf/javascript"
- xmlns:c="http://opensrf.org/xmlns/opensrf/c">
- <xsl:output method="text" />
- <xsl:strip-space elements="*"/>
-
- <xsl:template match="/">
- <xsl:apply-templates select="opensrf:fieldmapper/opensrf:classes"/>
-1;
- </xsl:template>
-
-
- <!-- sub-templates -->
- <xsl:template match="opensrf:classes">
- <xsl:for-each select="opensrf:class">
- <xsl:sort select="@id"/>
- <xsl:apply-templates select="."/>
- </xsl:for-each>
- <xsl:apply-templates select="opensrf:class/opensrf:links/opensrf:link[@type='has_a']"/>
- <xsl:apply-templates select="opensrf:class/opensrf:links/opensrf:link[@type='has_many']"/>
- </xsl:template>
-
-
-
- <xsl:template match="opensrf:class">
- #-------------------------------------------------------------------------------
- # <xsl:value-of select="$driver"/> Class definition for "<xsl:value-of select="@id"/>" (<xsl:value-of select="cdbi:class"/>)
- #-------------------------------------------------------------------------------
- package <xsl:value-of select="@cdbi:class"/>;
- use base '<xsl:value-of select="cdbi:superclass"/>';
-
- __PACKAGE__->table("<xsl:value-of select="database:table[@rdbms=$driver]/database:name"/>");
- <xsl:if test="database:table[@rdbms=$driver]/database:sequence">
- __PACKCAGE__->sequence("<xsl:value-of select="database:table[@rdbms=$driver]/database:sequence"/>");
- </xsl:if>
-
- __PACKAGE__->columns(Primary => <xsl:apply-templates select="opensrf:fields/opensrf:field[@database:primary='true']"/>);
- <xsl:if test="opensrf:fields/opensrf:field[@database:required='true' and not(@database:primary='true')]">
- __PACKAGE__->columns(
- Essential => <xsl:apply-templates
- select="opensrf:fields/opensrf:field[@database:required='true' and not(@database:primary='true')]"/>
- );
- </xsl:if>
- <xsl:if test="opensrf:fields/opensrf:field[not(@database:required='true') and not(@database:primary='true')]">
- __PACKAGE__->columns(
- Others => <xsl:apply-templates
- select="opensrf:fields/opensrf:field[not(@database:required='true') and not(@database:primary='true')]"/>
- );
- </xsl:if>
- </xsl:template>
-
-
-
- <xsl:template match="database:table">
- </xsl:template>
-
-
-
- <xsl:template match="opensrf:field">
- '<xsl:value-of select='@name'/>',
- </xsl:template>
-
-
-
- <xsl:template match="opensrf:link">
- <xsl:variable name='source' select='@source'/>
- <xsl:value-of select="../../@cdbi:class"/>-><xsl:value-of select="@type"/>(
- <xsl:value-of select="@field"/> => '<xsl:value-of select="//*[@id=$source]/@cdbi:class"/>'
- );
-
- </xsl:template>
-</xsl:stylesheet>
-
+++ /dev/null
-<xsl:stylesheet
- version='1.0'
- xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
- xmlns:opensrf="http://opensrf.org/xmlns/opensrf"
- xmlns:cdbi="http://opensrf.org/xmlns/opensrf/cdbi"
- xmlns:database="http://opensrf.org/xmlns/opensrf/database"
- xmlns:perl="http://opensrf.org/xmlns/opensrf/perl"
- xmlns:javascript="http://opensrf.org/xmlns/opensrf/javascript"
- xmlns:c="http://opensrf.org/xmlns/opensrf/c">
- <xsl:output method="text" />
- <xsl:strip-space elements="xsl:*"/>
- <xsl:variable name="last_field_pos"/>
-
- <xsl:template match="/">
-// support functions
-
-var IE = false;
-var unit_test = false;
-
-function instanceOf(object, constructorFunction) {
- if(!IE) {
- while (object != null) {
- if (object == constructorFunction.prototype)
- return true;
- object = object.__proto__;
- }
- } else {
- while(object != null) {
- if( object instanceof constructorFunction )
- return true;
- object = object.__proto__;
- }
- }
- return false;
-}
-
-// Top level superclass
-function Fieldmapper(array) {
- this.array = [];
- if(array) {
- if (array.constructor == Array) {
- this.array = array;
- } else if ( instanceOf( array, String ) || instanceOf( array, Number ) ) {
-
- var obj = null;
- if (this.cacheable) {
- try {
- obj = this.baseClass.obj_cache[this.classname][array];
- } catch (E) {};
- }
-
- if (!obj) {
- obj = user_request(
- 'open-ils.proxy',
- 'open-ils.proxy.proxy',
- [
- mw.G.auth_ses[0],
- 'open-ils.storage',
- 'open-ils.storage.direct.' + this.db_type + '.retrieve',
- array
- ]
- )[0];
-
- if (this.cacheable) {
- if (this.baseClass.obj_cache[this.classname] == null)
- this.baseClass.obj_cache[this.classname] = {};
-
- this.baseClass.obj_cache[this.classname][obj.id()] = obj;
- }
- }
- this.array = obj.array;
-
- } else {
- throw new FieldmapperException( "Attempt to build fieldmapper object with something wierd");
- }
- }
-}
-Fieldmapper.prototype.baseClass = Fieldmapper;
-Fieldmapper.prototype.obj_cache = {};
-
-Fieldmapper.prototype.search function (type,field,value) {
-
- var list = user_request(
- 'open-ils.proxy',
- 'open-ils.proxy.proxy',
- [
- mw.G.auth_ses[0],
- 'open-ils.storage',
- 'open-ils.storage.direct.' + type.db_type + '.search.' + field,
- array
- ]
- )[0];
- if (type.cacheable) {
- if (type.baseClass.obj_cache[type.classname] == null)
- type.baseClass.obj_cache[type.classname] = {};
- for (var i in list) {
- type.baseClass.obj_cache[type.classname][list[i].id()] = list[i];
- }
- }
- return list;
-}
-
-Fieldmapper.prototype.clone = function() {
- var obj = new this.constructor();
-
- for( var i in this.array ) {
- var thing = this.array[i];
- if(thing == null) continue;
-
- if( thing._isfieldmapper ) {
- obj.array[i] = thing.clone();
- } else {
-
- if(instanceOf(thing, Array)) {
- obj.array[i] = new Array();
-
- for( var j in thing ) {
-
- if( thing[j]._isfieldmapper )
- obj.array[i][j] = thing[j].clone();
- else
- obj.array[i][j] = thing[j];
- }
- } else {
- obj.array[i] = thing;
- }
- }
- }
- return obj;
-}
-
-function FieldmapperException(message) {
- this.message = message;
-}
-
-FieldmapperException.toString = function() {
- return "FieldmapperException: " + this.message + "\n";
-
-}
-
-
- <xsl:apply-templates select="opensrf:fieldmapper/opensrf:classes"/>
- </xsl:template>
-
-
-
-
-
-<!-- sub-templates -->
- <xsl:template match="opensrf:fieldmapper/opensrf:classes">
- <xsl:for-each select="opensrf:class">
- <xsl:sort select="@id"/>
- <xsl:apply-templates select="."/>
- </xsl:for-each>
- </xsl:template>
-
-
-
-
- <xsl:template match="opensrf:class">
- <xsl:apply-templates select="@javascript:class"/>
- <xsl:apply-templates select="opensrf:fields"/>
- <xsl:apply-templates select="opensrf:links/opensrf:link[@type='has_many']"/>
- </xsl:template>
-
-
-
-
- <xsl:template match="opensrf:fields">
- <xsl:apply-templates select="opensrf:field"/>
- </xsl:template>
-
-
-
-
-
- <xsl:template match="@javascript:class">
-
-// Class definition for "<xsl:value-of select="."/>"
-
-function <xsl:value-of select="."/> (array) {
-
- if (!instanceOf(this, <xsl:value-of select="."/>))
- return new <xsl:value-of select="."/>(array);
-
- this.baseClass.call(this,array);
- this.classname = "<xsl:value-of select="."/>";
- this._isfieldmapper = true;
- this.uber = <xsl:value-of select="."/>.baseClass.prototype;
-}
-
-<xsl:value-of select="."/>.prototype = new <xsl:value-of select="../javascript:superclass"/>();
-<xsl:value-of select="."/>.prototype.constructor = <xsl:value-of select="."/>;
-<xsl:value-of select="."/>.baseClass = <xsl:value-of select="../javascript:superclass"/>;
-<xsl:value-of select="."/>.prototype.cachable = true;
-<xsl:value-of select="."/>.prototype.fields = [];
-<xsl:value-of select="."/>.last_real_field = 2;
-
-<!-- XXX This needs to come from somewhere else!!!! -->
-<xsl:value-of select="."/>.prototype.db_type = "<xsl:value-of select="../database:table[@rdbms='Pg']/database:name"/>";
-
-<xsl:value-of select="."/>.prototype.isnew = function(new_value) {
- if(arguments.length == 1) { this.array[0] = new_value; }
- return this.array[0];
-}
-
-<xsl:value-of select="."/>.prototype.ischanged = function(new_value) {
- if(arguments.length == 1) { this.array[1] = new_value; }
- return this.array[1];
-}
-
-<xsl:value-of select="."/>.prototype.isdeleted = function(new_value) {
- if(arguments.length == 1) { this.array[2] = new_value; }
- return this.array[2];
-}
-
- </xsl:template>
-
-
-
-
-
- <!-- scalar valued fields and "has_a" relationships -->
- <xsl:template match="opensrf:field">
-
- <xsl:variable name="num"><xsl:number/></xsl:variable>
- <xsl:variable name="field_pos" select="$num + 2"/>
- <xsl:variable name="last_field_pos" select="$field_pos + 1"/>
- <xsl:variable name="field_name" select="@name"/>
-
-// Accessor/mutator for <xsl:value-of select="../../@javascript:class"/>.<xsl:value-of select="$field_name"/>:
-<xsl:value-of select="../../@javascript:class"/>.last_real_field++;
-<xsl:value-of select="../../@javascript:class"/>.prototype.fields.push("<xsl:value-of select="$field_name"/>");
-<xsl:value-of select="../../@javascript:class"/>.prototype.<xsl:value-of select="$field_name"/> = function (new_value) {
- if(arguments.length == 1) { this.array[<xsl:value-of select="$field_pos"/>] = new_value; }
-
- <xsl:if test="../../opensrf:links/opensrf:link[@field=$field_name and @type='has_a']">
- <!-- We have a fkey on this field. Go fetch the referenced object. -->
- <xsl:variable
- name="source"
- select="../../opensrf:links/opensrf:link[@field=$field_name and @type='has_a']/@source"/>
-
- var val = this.array[<xsl:value-of select="$field_pos"/>];
-
- if (!instanceOf(this.array[<xsl:value-of select="$field_pos"/>], <xsl:value-of select="$source"/>)) {
- if (this.array[<xsl:value-of select="$field_pos"/>] != null) {
- this.array[<xsl:value-of select="$field_pos"/>] = new <xsl:value-of select="$source"/>(val);
- }
- }
- </xsl:if>
- return this.array[<xsl:value-of select="$field_pos"/>];
-}
- </xsl:template>
-
-
-
-
-
- <!-- "has_many" relationships -->
- <xsl:template match="opensrf:links/opensrf:link[@type='has_many']">
- <xsl:variable name="num"><xsl:number/></xsl:variable>
- <xsl:variable name="source"><xsl:value-of select="@source"/></xsl:variable>
- <xsl:variable name="classname"><xsl:value-of select="../../@javascript:class"/></xsl:variable>
- <xsl:variable name="id"><xsl:value-of select="../../@id"/></xsl:variable>
- <xsl:variable name="fkey" select="//*[@id=$source]/opensrf:links/opensrf:link[@type='has_a' and @source=$id]/@field"/>
- <xsl:variable name="pkey" select="../../opensrf:fields/opensrf:field[@database:primary='true']/@name"/>
-
-// accessor for <xsl:value-of select="$classname"/>:
-<xsl:value-of select="$classname"/>.prototype.<xsl:value-of select="@field"/> = function () {
-
- var _pos = <xsl:value-of select="$classname"/>.last_real_field + <xsl:value-of select="$num"/>;
-
- if (!instanceOf(this.array[_pos], Array)) {
- this.array[_pos] = [];
-
- if (this.array[_pos].length == 0) {
- /* get the real thing.
- * search where <xsl:value-of select="$source"/>.<xsl:value-of select="$fkey"/>()
- * equals this.<xsl:value-of select="../../opensrf:fields/opensrf:field[@database:primary='true']/@name"/>();
- */
- this.array[_pos] = this.uber.search(
- <xsl:value-of select="$source"/>,
- "<xsl:value-of select="$fkey"/>",
- this.<xsl:value-of select="$pkey"/>()
- );
- }
-
- return this.array[_pos];
-}
-
- </xsl:template>
-
-
-
-
-</xsl:stylesheet>
-
+++ /dev/null
-<xsl:stylesheet
- version='1.0'
- xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
- xmlns:opensrf="http://opensrf.org/xmlns/opensrf"
- xmlns:cdbi="http://opensrf.org/xmlns/opensrf/cdbi"
- xmlns:database="http://opensrf.org/xmlns/opensrf/database"
- xmlns:perl="http://opensrf.org/xmlns/opensrf/perl"
- xmlns:javascript="http://opensrf.org/xmlns/opensrf/javascript"
- xmlns:c="http://opensrf.org/xmlns/opensrf/c">
- <xsl:output method="text" />
- <xsl:strip-space elements="xsl:*"/>
- <xsl:variable name="last_field_pos"/>
-
- <xsl:template match="/">
-package Fieldmapper;
-use JSON;
-use Data::Dumper;
-use base 'OpenSRF::Application';
-
-use OpenSRF::Utils::Logger;
-my $log = 'OpenSRF::Utils::Logger';
-
-sub new {
- my $self = shift;
- my $value = shift;
- if (defined $value) {
- if (!ref($value) or ref($value) ne 'ARRAY') {
- # go fetch the object by id...
- }
- } else {
- $value = [];
- }
- return bless $value => $self->class_name;
-}
-
-sub decast {
- my $self = shift;
- return [ @$self ];
-}
-
-sub DESTROY {}
-
-sub class_name {
- my $class_name = shift;
- return ref($class_name) || $class_name;
-}
-
-sub isnew { return $_[0][0]; }
-sub ischanged { return $_[0][1]; }
-sub isdeleted { return $_[0][2]; }
-
-
- <xsl:apply-templates select="opensrf:fieldmapper/opensrf:classes"/>
-
-1;
- </xsl:template>
-
-
-
-
-
-<!-- sub-templates -->
- <xsl:template match="opensrf:fieldmapper/opensrf:classes">
- <xsl:for-each select="opensrf:class">
- <xsl:sort select="@id"/>
- <xsl:apply-templates select="."/>
- <xsl:apply-templates select="opensrf:links/opensrf:link[@type='has_many']"/>
- </xsl:for-each>
- </xsl:template>
-
-
-
-
- <xsl:template match="opensrf:class">
- <xsl:apply-templates select="@perl:class"/>
- <xsl:apply-templates select="opensrf:fields"/>
- </xsl:template>
-
-
-
-
- <xsl:template match="opensrf:fields">
- <xsl:apply-templates select="opensrf:field"/>
- </xsl:template>
-
-
-
-
-
- <xsl:template match="@perl:class">
-
-#-------------------------------------------------------------------------------
-# Class definition for "<xsl:value-of select="."/>"
-#-------------------------------------------------------------------------------
-
-package <xsl:value-of select="."/>;
-use base "<xsl:value-of select="../perl:superclass"/>";
-
-{ my @real;
- sub real_fields {
- push @real, @_ if (@_);
- return @real;
- }
-}
-
-{ my $last_real;
- sub last_real_field : lvalue {
- $last_real;
- }
-}
-
- <xsl:if test="../@cdbi:class">
-sub cdbi {
- return "<xsl:value-of select="../@cdbi:class"/>";
-}
- </xsl:if>
-
-sub json_hint {
- return "<xsl:value-of select="../@id"/>";
-}
-
-
-sub is_virtual {
- <xsl:choose>
- <xsl:when test="../@virutal">
- return 1;
- </xsl:when>
- <xsl:otherwise>
- return 0;
- </xsl:otherwise>
- </xsl:choose>
-}
-
- </xsl:template>
-
-
-
-
-
- <!-- scalar valued fields and "has_a" relationships -->
- <xsl:template match="opensrf:field">
-
- <xsl:variable name="num"><xsl:number/></xsl:variable>
- <xsl:variable name="field_pos" select="$num + 2"/>
- <xsl:variable name="last_field_pos" select="$field_pos + 1"/>
- <xsl:variable name="field_name" select="@name"/>
- <xsl:variable name="classname" select="../../@perl:class"/>
-
-# Accessor/mutator for <xsl:value-of select="$classname"/>::<xsl:value-of select="$field_name"/>:
-__PACKAGE__->last_real_field()++;
-__PACKAGE__->real_fields("<xsl:value-of select="$field_name"/>");
-sub <xsl:value-of select="$field_name"/> {
- my $self = shift;
- my $new_val = shift;
- $self->[<xsl:value-of select="$field_pos"/>] = $new_val if (defined $new_val);
-
- <xsl:if test="../../opensrf:links/opensrf:link[@field=$field_name and @type='has_a']">
- <!-- We have a fkey on this field. Go fetch the referenced object. -->
- <xsl:variable
- name="source"
- select="../../opensrf:links/opensrf:link[@field=$field_name and @type='has_a']/@source"/>
- <xsl:variable
- name="sourceclass"
- select="//*[@id=$source]/@perl:class"/>
-
- my $val = $self->[<xsl:value-of select="$field_pos"/>];
-
- if (defined $self->[<xsl:value-of select="$field_pos"/>]) {
- if (!UNIVERSAL::isa($self->[<xsl:value-of select="$field_pos"/>], <xsl:value-of select="$sourceclass"/>)) {
- $self->[<xsl:value-of select="$field_pos"/>] = <xsl:value-of select="$sourceclass"/>->new($val);
- }
- }
- </xsl:if>
-
- return $self->[<xsl:value-of select="$field_pos"/>];
-}
-
-
-sub clear_<xsl:value-of select="$field_name"/> {
- my $self = shift;
- $self->[<xsl:value-of select="$field_pos"/>] = undef;
- return 1;
-}
-
- </xsl:template>
-
-
-
-
-
-
- <!-- "has_many" relationships -->
- <xsl:template match="opensrf:links/opensrf:link[@type='has_many']">
- <xsl:variable name="num"><xsl:number/></xsl:variable>
- <xsl:variable name="source"><xsl:value-of select="@source"/></xsl:variable>
- <xsl:variable name="sourceclass"><xsl:value-of select="//*[@id=$source]/@perl:class"/></xsl:variable>
- <xsl:variable name="classname"><xsl:value-of select="../../@perl:class"/></xsl:variable>
- <xsl:variable name="id"><xsl:value-of select="../../@id"/></xsl:variable>
- <xsl:variable name="fkey" select="//*[@id=$source]/opensrf:links/opensrf:link[@type='has_a' and @source=$id]/@field"/>
- <xsl:variable name="pkey" select="../../opensrf:fields/opensrf:field[@database:primary='true']/@name"/>
-
-# accessor for <xsl:value-of select="$classname"/>::<xsl:value-of select="@field"/>:
-sub <xsl:value-of select="@field"/> {
- my $self = shift;
-
- my $_pos = <xsl:value-of select="$classname"/>->last_real_field + <xsl:value-of select="$num"/>;
-
- if (!ref($self->[$_pos]) ne 'ARRAY') {
- $self->[$_pos] = [];
-
- if (@{$self->[$_pos]} == 0) {
- # get the real thing.
- # search where <xsl:value-of select="$sourceclass"/>-><xsl:value-of select="$fkey"/> == $self-><xsl:value-of select="$pkey"/>;
- }
-
- return $self->[$_pos];
-}
-
- </xsl:template>
-
-
-
-
-</xsl:stylesheet>
-
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<fieldmapper
- xmlns="http://opensrf.org/xmlns/opensrf"
- xmlns:cdbi="http://opensrf.org/xmlns/opensrf/cdbi"
- xmlns:database="http://opensrf.org/xmlns/opensrf/database"
- xmlns:perl="http://opensrf.org/xmlns/opensrf/perl"
- xmlns:javascript="http://opensrf.org/xmlns/opensrf/javascript"
- xmlns:c="http://opensrf.org/xmlns/opensrf/c">
-
- <classes>
- <!-- template class definition -->
- <!--
- <class
- id=""
- perl:class=""
- cdbi:class=""
- javascript:class="">
-
- <database:table rdbms="Pg">
- <database:name></database:name>
- <database:sequence></database:sequence>
- </database:table>
- <database:table rdbms="MySQL">
- <database:name></database:name>
- </database:table>
-
- <javascript:superclass>Fieldmapper</javascript:superclass>
- <perl:superclass>Fieldmapper</perl:superclass>
- <cdbi:superclass>OpenILS::Storage::CDBI</cdbi:superclass>
-
- <fields>
- <field name="" datatype="" database:primary="" database:required="" default="" database:default=""/>
- </fields>
-
- <links>
- <link field="" source="" javascript:list="" type=""/>
- </links>
-
- </class>
- -->
-
- <class
- id="asvr"
- virtual="0"
- perl:class="Fieldmapper::action::survey_response"
- cdbi:class="action::survey_response"
- javascript:class="asvr"
- c:class="asvr">
- <database:table rdbms="Pg">
- <database:name>action.survey_response</database:name>
- <database:sequence>action.survey_response_id_seq</database:sequence>
- </database:table>
- <database:table rdbms="MySQL">
- <database:name>action_survey_response</database:name>
- </database:table>
-
- <javascript:superclass>Fieldmapper</javascript:superclass>
- <perl:superclass>Fieldmapper</perl:superclass>
- <cdbi:superclass>OpenILS::Storage::CDBI</cdbi:superclass>
-
- <fields>
- <field
- name="id"
- datatype="int"
- database:primary="true" />
-
- <field
- name="survey"
- datatype="int"
- database:required="true" />
-
- <field
- name="question"
- datatype="int"
- database:required="true" />
-
- <field
- name="answer"
- datatype="int"
- database:required="true" />
-
- <field
- name="usr"
- datatype="int"
- database:required="true" />
-
- <field
- name="response_group_id"
- datatype="int"
- database:required="true" />
-
- <field
- name="answser_date"
- datatype="timestamp"
- database:required="true" />
-
- <field
- name="effective_date"
- datatype="timestamp"
- database:required="true" />
-
- </fields>
-
- <links>
- <link field="survey" source="asv" type="has_a"/>
- <link field="question" source="asvq" type="has_a"/>
- <link field="answer" source="asva" type="has_a"/>
- <!-- <link field="usr" source="au" type="has_a"/> -->
- </links>
-
- </class>
-
- <class
- id="asvq"
- perl:class="Fieldmapper::action::survey_question"
- cdbi:class="action::survey_question"
- javascript:class="asvq"
- c:class="asvq">
- <database:table rdbms="Pg">
- <database:name>action.survey_question</database:name>
- <database:sequence>action.survey_question_id_seq</database:sequence>
- </database:table>
- <database:table rdbms="MySQL">
- <database:name>action_survey_question</database:name>
- </database:table>
-
- <javascript:superclass>Fieldmapper</javascript:superclass>
- <perl:superclass>Fieldmapper</perl:superclass>
- <cdbi:superclass>OpenILS::Storage::CDBI</cdbi:superclass>
-
- <fields>
- <field
- name="id"
- datatype="int"
- database:primary="true" />
-
- <field
- name="survey"
- datatype="int"
- database:required="true" />
-
- <field
- name="question"
- datatype="text"
- database:required="true" />
-
- </fields>
-
- <links>
- <link field="survey" source="asv" type="has_a"/>
- <link field="answers" source="asva" type="has_many"/>
- </links>
- </class>
-
- <class
- id="asva"
- perl:class="Fieldmapper::action::survey_answer"
- cdbi:class="action::survey_answer"
- javascript:class="asva"
- c:class="asva">
- <database:table rdbms="Pg">
- <database:name>action.survey_answer</database:name>
- <database:sequence>action.survey_answer_id_seq</database:sequence>
- </database:table>
- <database:table rdbms="MySQL">
- <database:name>action_survey_answer</database:name>
- </database:table>
-
- <javascript:superclass>Fieldmapper</javascript:superclass>
- <perl:superclass>Fieldmapper</perl:superclass>
- <cdbi:superclass>OpenILS::Storage::CDBI</cdbi:superclass>
-
- <fields>
- <field
- name="id"
- datatype="int"
- database:primary="true" />
-
- <field
- name="question"
- datatype="int"
- database:required="true" />
-
- <field
- name="answer"
- datatype="text"
- database:required="true" />
-
- </fields>
-
- <links>
- <link field="question" source="asvq" type="has_a"/>
- <link field="responses" source="asvr" type="has_many"/>
- </links>
- </class>
-
- <class
- id="aou"
- perl:class="Fieldmapper::actor::org_unit"
- cdbi:class="actor::org_unit"
- javascript:class="aou"
- c:class="aou">
- <database:table rdbms="Pg">
- <database:name>actor.org_unit</database:name>
- <database:sequence>actor.org_unit_id_seq</database:sequence>
- </database:table>
- <database:table rdbms="MySQL">
- <database:name>actor_org_unit</database:name>
- </database:table>
-
- <javascript:superclass>Fieldmapper</javascript:superclass>
- <perl:superclass>Fieldmapper</perl:superclass>
- <cdbi:superclass>OpenILS::Storage::CDBI</cdbi:superclass>
-
- <fields>
- <field
- name="id"
- datatype="int"
- database:primary="true" />
- </fields>
- </class>
-
- <!-- Survey class definition -->
- <class
- id="asv"
- perl:class="Fieldmapper::action::survey"
- cdbi:class="action::survey"
- javascript:class="asv"
- c:class="asv">
- <database:table rdbms="Pg">
- <database:name>action.survey</database:name>
- <database:sequence>action.survey_id_seq</database:sequence>
- </database:table>
- <database:table rdbms="MySQL">
- <database:name>action_survey</database:name>
- </database:table>
-
- <javascript:superclass>Fieldmapper</javascript:superclass>
- <perl:superclass>Fieldmapper</perl:superclass>
- <cdbi:superclass>OpenILS::Storage::CDBI</cdbi:superclass>
-
- <methods interface='authenticated' service='open-ils.proxy'>
- <create method='open-ils.storage.direct.action.survey.create'/>
- <retrieve method='open-ils.storage.direct.action.survey.retrieve'/>
- <search method='open-ils.storage.direct.action.survey.search'/>
- <update method='open-ils.storage.direct.action.survey.update'/>
- <delete method='open-ils.storage.direct.action.survey.delete'/>
- </methods>
-
- <methods interface='trusted' service='open-ils.storage'>
- <create method='open-ils.storage.direct.action.survey.create'/>
- <retrieve method='open-ils.storage.direct.action.survey.retrieve'/>
- <search method='open-ils.storage.direct.action.survey.search'/>
- <update method='open-ils.storage.direct.action.survey.update'/>
- <delete method='open-ils.storage.direct.action.survey.delete'/>
- </methods>
-
- <fields>
- <field
- name="id"
- datatype="int"
- database:primary="true" />
-
- <field
- name="name"
- datatype="text"
- database:required="true" />
-
- <field
- name="description"
- datatype="text"
- database:required="true" />
-
- <field
- name="owner"
- datatype="int"
- database:required="true" />
-
- <field
- name="start_date"
- datatype="timestamp"
- database:required="true"
- database:default="now()" />
-
- <field
- name="end_date"
- datatype="timestamp"
- database:required="true"
- database:default="now() + '1 month'" />
-
- <field
- name="usr_summary"
- datatype="bool"
- database:required="true"
- default="t" />
-
- <field
- name="opac"
- datatype="bool"
- database:required="true"
- default="f" />
-
- <field
- name="poll"
- datatype="bool"
- database:required="true"
- default="f" />
-
- <field
- name="required"
- datatype="bool"
- database:required="true"
- default="f" />
-
- </fields>
-
- <links>
- <link field="questions" source="asvq" type="has_many"/>
- <link field="responses" source="asvr" type="has_many"/>
- <link field="owner" source="aou" type="has_a"/>
- </links>
-
- </class>
-
- </classes>
-</fieldmapper>
-
+++ /dev/null
-#!/usr/bin/perl
-use strict; use warnings;
-use OpenSRF::System;
-use Time::HiRes qw/time/;
-use OpenSRF::Utils::Logger;
-my $log = "OpenSRF::Utils::Logger";
-
-# Test script which runs queries agains the opensrf.math service and reports on
-# the average round trip time of the requests.
-
-# how many batches of 4 requests do we send
-my $count = $ARGV[0];
-print "usage: $0 <num_requests>\n" and exit unless $count;
-
-# * connect to the Jabber network
-OpenSRF::System->bootstrap_client( config_file => "/openils/conf/bootstrap.conf" );
-$log->set_service('math_bench');
-
-# * create a new application session for the opensrf.math service
-my $session = OpenSRF::AppSession->create( "opensrf.math" );
-
-my @times; # "delta" times for each round trip
-
-# we're gonna call methods "add", "sub", "mult", and "div" with
-# params 1, 2. The hash below maps the method name to the
-# expected response value
-my %vals = ( add => 3, sub => -1, mult => 2, div => 0.5 );
-
-# print the counter grid
-for my $x (1..100) {
- if( $x % 10 ) { print ".";}
- else{ print $x/10; };
-}
-print "\n";
-
-my $c = 0;
-
-for my $scale ( 1..$count ) {
- for my $mname ( keys %vals ) { # cycle through add, sub, mult, and div
-
- my $starttime = time();
-
- # * Fires the request and gathers the response object, which in this case
- # is just a string
- my $resp = $session->request( $mname, 1, 2 )->gather(1);
- push @times, time() - $starttime;
-
-
- if( "$resp" eq $vals{$mname} ) {
- # we got the response we expected
- print "+";
-
- } elsif($resp) {
- # we got some other response
- print "\n* BAD Data: $resp\n";
-
- } else {
- # we got no data
- print "Received nothing\n";
- }
-
- $c++;
-
- }
-
- print " [$c] \n" unless $scale % 25;
-}
-
-my $total = 0;
-
-$total += $_ for (@times);
-
-$total /= scalar(@times);
-
-print "\n\n\tAverage Round Trip Time: $total Seconds\n";
-
-
+++ /dev/null
-all: clean client
- @echo
-
-client:
- @echo We need the OpenSRF javascript code...
- mkdir math/content/OpenSRF/
- cp ../../src/javascript/*.js math/content/OpenSRF/
- @echo We need a log directory...
- mkdir math/content/log
- touch math/content/log/preserve.directory.when.zipping
- @echo We also need a math/content/conf/client_config.xml pointing to a running OpenSRF Math application.
- @echo Then we package this into a Mozilla XPI file...
- zip -q -r math.xpi install.js math/
- @echo After installing the XPI, use the chrome URL:
- @echo chrome://math/content/
-
-clean:
- @echo Removing the OpenSRF javascript code, the log directory, and math.xpi...
- rm -rf math/content/OpenSRF/ math/content/log math.xpi
+++ /dev/null
-// ripped from Evergreen installation file
-
-/* We'll want to make this more flexible later */
-
-install();
-
-// ----------------------------------------------------------------------------
-// Performs the install
-// ----------------------------------------------------------------------------
-function install() {
-
- // ----------------------------------------------------------------------------
- var _authors = "PINES";
- var _package = "math";
- var _packg_l = "math";
- var _version = "0.0.1";
- // ----------------------------------------------------------------------------
-
- var err; // track the error
-
- err = initInstall( _package, "/"+_authors+"/"+_package, _version );
- if( err != 0 ) { return warn( "initInstall: " + err );}
-
- // ----------------------------------------------------------------------------
- // Discovers the path to the install directory
- // ----------------------------------------------------------------------------
- install_dir = getFolder("Chrome", _packg_l );
- logComment( "Installing to: " + install_dir );
-
- // ----------------------------------------------------------------------------
- // Directory where the 'content' is stored
- // ----------------------------------------------------------------------------
- content_dir = getFolder( install_dir, "content" );
- if( err != 0 ) { return warn("getFolder:content_dir: " + err);}
-
- // ----------------------------------------------------------------------------
- // Directory where the skins are stored
- // ----------------------------------------------------------------------------
- skin_dir = getFolder( install_dir, "skin" );
- if( err != 0 ) { return warn("getFolder:skin: " + err);}
-
- // ----------------------------------------------------------------------------
- // Directory where the local data is stored
- // ----------------------------------------------------------------------------
- locale_dir = getFolder( install_dir, "locale" );
- if( err != 0 ) { return warn("getFolder:locale: " + err);}
-
- // ----------------------------------------------------------------------------
- // Sets the install directory for Evergreen
- // ----------------------------------------------------------------------------
- err = setPackageFolder(install_dir);
- if( err != 0 ) { return warn("setPackageFolder: " + err);}
-
- // ----------------------------------------------------------------------------
- // Searches the .xpi file for the directory name stored in _packg_l and
- // copies that directory from the .xpi into Mozilla's chrome directory.
- // In this case, we are copying over the entire evergreen folder
- // ----------------------------------------------------------------------------
- err = addDirectory( _packg_l )
- if( err != 0 ) { return warn("addDirectory: " + err);}
-
-
- // ----------------------------------------------------------------------------
- // Register the content directory
- // The final argument is where Mozilla should expect to find the contents.rdf
- // file *after* installation for the CONTENT portion of the package
- // ----------------------------------------------------------------------------
- err = registerChrome( Install.CONTENT, content_dir );
- if( err != 0 ) { return warn("registerChrome:content " + err );}
-
- // ----------------------------------------------------------------------------
- // Register the skin directory
- // ----------------------------------------------------------------------------
- err = registerChrome( Install.SKIN, skin_dir );
- if( err != 0 ) { return warn("registerChrome:skin " + err );}
-
- // ----------------------------------------------------------------------------
- // Register the locale directory
- // ----------------------------------------------------------------------------
- //err = registerChrome( Install.LOCALE, locale_dir );
- //if( err != 0 ) { return warn("registerChrome:locale " + err );}
-
- err = registerChrome( Install.LOCALE, getFolder(locale_dir, "en-US") );
- if( err != 0 ) { return warn("registerChrome:locale " + err );}
-
- // ----------------------------------------------------------------------------
- // Do it.
- // ----------------------------------------------------------------------------
- performInstall();
-
-}
-
-function warn( message ) {
- alert( message );
- logComment( message );
- return;
-}
-
+++ /dev/null
-<?xml version="1.0" ?>
-
-<oils_config>
-
- <!-- General system settings -->
-
- <system>
- <hostname>myhostname</hostname>
-
- <!-- log_level
- Levels run between 0 and 3. O is no logging. 3 is full debug output -->
- <log_level>0</log_level>
-
- <!-- stdout_log
- When set to 0, no stdout logging is done, when set to 1, all logging
- goes to both stdout as well as their destined log file, if set to
- 2, the messages only go to stdout. -->
- <stdout_log>0</stdout_log>
- </system>
-
-
- <!-- Log files -->
-
- <logs>
- <debug>debug.log</debug>
- <transport>transport.log</transport>
- <error>error.log</error>
- </logs>
-
- <!-- Remote services -->
-
- <remote_service>
- <math>router@localhost/math</math>
- <mathdb>router@localhost/mathdb</mathdb>
- <storage>router@localhost/storage</storage>
- </remote_service>
-
- <!-- Transport -->
-
- <transport>
- <transport_impl>jabber_connection</transport_impl>
-
- <!-- connect_timeout doubles as both the low level transport timeout
- as well as the app connection timeout -->
- <connect_timeout>15</connect_timeout>
- <username>math_user</username>
- <password>math_user_password</password>
- <primary>localhost</primary>
- <port>5222</port>
- <ssl>0</ssl>
- </transport>
-
-</oils_config>
+++ /dev/null
-<?xml version="1.0"?>
-
-<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
-
- <RDF:Seq about="urn:mozilla:package:root">
- <RDF:li resource="urn:mozilla:package:math"/>
- </RDF:Seq>
-
- <RDF:Description about="urn:mozilla:package:math"
- chrome:displayName="Math"
- chrome:author="PINES"
- chrome:name="math"
- chrome:extension="true"/>
-
-</RDF:RDF>
-
+++ /dev/null
-<?xml version="1.0"?>
-<!-- Test Application: Math -->
-
-<!-- Stylesheets -->
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://math/skin/math.css" type="text/css"?>
-
-<!-- Localization -->
-<!DOCTYPE window SYSTEM "chrome://math/locale/math.dtd">
-
-<window id="math_win" title="&math.title;" orient="vertical" style="overflow: auto"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
- <!-- Overlays for this XUL file -->
- <?xul-overlay href="chrome://math/content/math_overlay.xul"?>
-
- <!-- OpenSRF -->
- <script>var myPackageDir = "math";</script>
- <script src="OpenSRF/JSON.js" />
- <script src="OpenSRF/md5.js" />
- <script src="OpenSRF/opensrf_utils.js" />
- <script src="OpenSRF/opensrf_config.js" />
- <script src="OpenSRF/opensrf_dom_element.js" />
- <script src="OpenSRF/opensrf_domain_object.js" />
- <script src="OpenSRF/opensrf_transport.js" />
- <script src="OpenSRF/opensrf_jabber_transport.js" />
- <script src="OpenSRF/opensrf_msg_stack.js" />
- <script src="OpenSRF/opensrf_app_session.js" />
-
- <!-- The logic for this app -->
- <script src="math_app.js" />
-
- <!-- Layout to be filled in by overlays and javascript -->
- <vbox id="main_vbox" class="test_class">
- </vbox>
-
-</window>
-
+++ /dev/null
-// connect and stup
-
-var ses;
-
-function execute( opp ) {
-
- var a = document.getElementById("num1");
- var b = document.getElementById("num2");
- do_stuff( opp, a.value, b.value );
-
-}
-
-function do_stuff( opp, a, b ) {
-
-
-
- try {
-
- if( ses == null || ! AppSession.transport_handle.connected() ) {
-
- /* deprecated */
- ses = new AppSession( "user_name", "12345", "math" );
- if( ! ses.connect() ) { alert( "Connect timed out!" ); }
- }
-
- var meth = new oilsMethod(opp, [ a, b ] );
-
- var req = new AppRequest( ses, meth );
- req.make_request();
- var resp = req.recv( 5000 );
- if( ! resp ) {
- alert( "NO response from server!!!" );
- quit(); return;
- }
-
- var scalar = resp.getContent();
- var value = scalar.getValue();
-
- var lab = document.getElementById( "answer" );
- lab.value = "Answer: " + value;
- req.finish();
-
- } catch( E ) { alert( E.message ); }
-
-}
-
-
-function quit() { ses.disconnect(); window.close(); }
-
-
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://math/skin/math.css" type="text/css"?>
-<!DOCTYPE overlay SYSTEM "chrome://math/locale/math.dtd">
-<overlay id="math_overlay"
- xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
-<vbox id="main_vbox" flex="1">
- <label value="&math.title;" />
- <textbox id="num1" />
- <textbox id="num2" />
- <grid flex="1" class="test_class">
- <columns>
- <column />
- <column />
- </columns>
- <rows>
- <row>
- <button label="&math.add;" oncommand="execute('add');"/>
- <button label="&math.sub;" oncommand="execute('sub');"/>
- </row>
- <row>
- <button label="&math.mul;" oncommand="execute('mult');"/>
- <button label="&math.div;" oncommand="execute('div');"/>
- </row>
- </rows>
- </grid>
- <label id="answer" value="" />
- <button label="&math.quit;" oncommand="quit();"/>
-</vbox>
-
-</overlay>
+++ /dev/null
-<?xml version="1.0"?>
-<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
- <RDF:Seq about="urn:mozilla:locale:root">
- <RDF:li resource="urn:mozilla:locale:en-US"/>
- </RDF:Seq>
-
- <RDF:Description about="urn:mozilla:locale:en-US"
- chrome:displayName="Math"
- chrome:author="PINES"
- chrome:name="en-US">
- <chrome:packages>
- <RDF:Seq about="urn:mozilla:locale:en-US:packages">
- <RDF:li resource="urn:mozilla:locale:en-US:math"/>
- </RDF:Seq>
- </chrome:packages>
- </RDF:Description>
-</RDF:RDF>
-
+++ /dev/null
-<!ENTITY math.title "Math App">
-<!ENTITY math.add "Add">
-<!ENTITY math.sub "Subtract">
-<!ENTITY math.mul "Multiply">
-<!ENTITY math.div "Divide">
-<!ENTITY math.quit "Quit">
-
+++ /dev/null
-<?xml version="1.0"?>
-
-<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
-
- <RDF:Seq about="urn:mozilla:skin:root">
- <RDF:li resource="urn:mozilla:skin:math/1.0"/>
- </RDF:Seq>
-
- <RDF:Description about="urn:mozilla:skin:math/1.0"
- chrome:displayName="Math"
- chrome:author="PINES"
- chrome:name="math/1.0">
-
- <chrome:packages>
- <RDF:Seq about="urn:mozilla:skin:math/1.0:packages">
- <RDF:li resource="urn:mozilla:skin:math/1.0:math"/>
- </RDF:Seq>
- </chrome:packages>
- </RDF:Description>
-
-</RDF:RDF>
-
+++ /dev/null
-@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-@namespace html url("http://www.w3.org/TR/REC-html40");
-
-.test_class { border: solid thin blue; }
+++ /dev/null
-#!/usr/bin/perl
-use lib '/openils/lib/perl5/';
-use OpenSRF::System;
-use OpenILS::Application::AppUtils;
-use OpenILS::Event;
-use OpenSRF::EX qw/:try/;
-use JSON;
-use Data::Dumper;
-use OpenILS::Utils::Fieldmapper;
-use Digest::MD5 qw/md5_hex/;
-use OpenSRF::Utils qw/:daemon/;
-use OpenSRF::MultiSession;
-use OpenSRF::AppSession;
-use Time::HiRes qw/time/;
-use JSON;
-
-my $config = shift;
-
-unless (-e $config) {
- die "Gimme a config file!!!";
-}
-OpenSRF::System->bootstrap_client( config_file => $config );
-
-if (!@ARGV) {
- @ARGV = ('open-ils.storage','opensrf.system.echo');
-}
-
-my $app = shift;
-
-my $count = 100;
-
-my $overhead = time;
-
-my $mses = OpenSRF::MultiSession->new( app => $app, cap => 10, api_level => 1 );
-
-$mses->success_handler(
- sub {
- my $ses = shift;
- my $req = shift;
- print $req->{params}->[0] . "\t: " . JSON->perl2JSON($req->{response}->[0]->content)."\n";
- }
-);
-
-$mses->failure_handler(
- sub {
- my $ses = shift;
- my $req = shift;
- warn "record $req->{params}->[0] failed: ".JSON->perl2JSON($req->{response});
- }
-);
-
-
-$mses->connect;
-
-my $start = time;
-$overhead = $start - $overhead;
-
-for (1 .. $count) {
- $mses->request( @ARGV,$_ );
-}
-$mses->session_wait(1);
-$mses->disconnect;
-
-my $end = time;
-
-my @c = $mses->completed;
-my @f = $mses->failed;
-
-my $x = 0;
-$x += $_->{duration} for (@c);
-
-print "\n". '-'x40 . "\n";
-print "Startup Overhead: ".sprintf('%0.3f',$overhead)."s\n";
-print "Completed Commands: ".@c."\n";
-print "Failed Commands: ".@f."\n";
-print "Serial Run Time: ".sprintf('%0.3f',$x)."s\n";
-print "Serial Avg Time: ".sprintf('%0.3f',$x/$count)."s\n";
-print "Total Run Time: ".sprintf('%0.3f',$end-$start)."s\n";
-print "Total Avg Time: ".sprintf('%0.3f',($end-$start)/$count)."s\n";
-
+++ /dev/null
-<?xml version='1.0'?>
-
-<opensrf version='0.0.1'>
-
- <!--
-
- There is one <host> entry for each server on the network. Settings for the
- 'default' host are used for every setting that isn't overridden within a given
- host's config.
-
- To specify which applications a host is serving, list those applications
- within that host's config section. If the defaults are acceptible, then
- that's all that needs to be added/changed.
-
- Any valid XML may be added to the <default> block and server components will have
- acces to it.
-
- -->
-
- <default>
-
- <dirs>
-
- <!-- opensrf log files go in this directory -->
- <log>/path/to/log</log>
-
- <!-- opensrf unix domaind socket files go here -->
- <sock>/path/to/sock</sock>
-
- <!-- opensrf pids go here -->
- <pid>/path/to/pid</pid>
-
- <!-- global config directory -->
- <conf>/path/to/conf</conf>
-
- </dirs>
-
- <!-- prefork, simple. prefork is suggested -->
- <server_type>prefork</server_type>
-
- <!-- Default doesn't host any apps -->
- <activeapps/>
-
- <cache>
- <global>
- <servers>
- <!-- memcached server ip:port -->
- <server>127.0.0.1:10101</server>
- </servers>
- <!-- maximun time that anything may stay in the cache -->
- <max_cache_time>86400</max_cache_time>
- </global>
- </cache>
-
- <!-- These are the defaults for every served app. Each server should
- duplicate the node layout for any nodes that need changing.
- Any settings that are overridden in the server specific section
- will be used as the config values for that server. Any settings that are
- not overridden will fall back on the defaults
- Note that overriding 'stateless' will break things -->
-
- <apps>
-
- <opensrf.persist>
-
- <!-- How many seconds to wait between server
- requests before timing out a stateful server session. -->
- <keepalive>1</keepalive>
-
- <!-- if 1, then we support stateless sessions (no connect required), if
- 0 then we don't -->
- <stateless>1</stateless>
-
- <!-- Tells the servers which language this implementation is coded in
- In this case non "perl" servers will not be able to load the module -->
- <language>perl</language>
-
- <!-- Module the implements this application -->
- <implementation>OpenSRF::Application::Persist</implementation>
-
- <!-- max stateful requests before a session automatically disconnects a client -->
- <max_requests>97</max_requests>
-
- <!-- settings for the backend application drones. These are probably sane defaults -->
-
- <unix_config>
- <!-- unix socket file -->
- <unix_sock>opensrf.persist_unix.sock</unix_sock>
-
- <!-- pid file -->
- <unix_pid>opensrf.persist_unix.pid</unix_pid>
-
- <!-- max requests per process backend before a child is recycled -->
- <max_requests>1000</max_requests>
-
- <!-- log file for this application -->
- <unix_log>opensrf.persist_unix.log</unix_log>
-
- <!-- Number of children to pre-fork -->
- <min_children>5</min_children>
-
- <!-- maximun number of children to fork -->
- <max_children>25</max_children>
-
- <!-- minimun number of spare forked children -->
- <min_spare_children>2</min_spare_children>
-
- <!-- max number of spare forked children -->
- <max_spare_children>5</max_spare_children>
-
- </unix_config>
-
- <!-- Any additional setting for a particular application go in the app_settings node -->
- <app_settings>
-
- <!-- sqlite database file -->
- <dbfile>/path/to/dbfile/persist.db</dbfile>
- </app_settings>
-
- </opensrf.persist>
-
- <opensrf.math>
- <keepalive>3</keepalive>
- <stateless>1</stateless>
- <language>perl</language>
- <implementation>OpenSRF::Application::Demo::Math</implementation>
- <max_requests>97</max_requests>
- <unix_config>
- <unix_sock>opensrf.math_unix.sock</unix_sock>
- <unix_pid>opensrf.math_unix.pid</unix_pid>
- <max_requests>1000</max_requests>
- <unix_log>opensrf.math_unix.log</unix_log>
- <min_children>5</min_children>
- <max_children>15</max_children>
- <min_spare_children>2</min_spare_children>
- <max_spare_children>5</max_spare_children>
- </unix_config>
- </opensrf.math>
-
- <opensrf.dbmath>
- <keepalive>3</keepalive>
- <stateless>1</stateless>
- <language>perl</language>
- <implementation>OpenSRF::Application::Demo::MathDB</implementation>
- <max_requests>99</max_requests>
- <unix_config>
- <max_requests>1000</max_requests>
- <unix_log>opensrf.dbmath_unix.log</unix_log>
- <unix_sock>opensrf.dbmath_unix.sock</unix_sock>
- <unix_pid>opensrf.dbmath_unix.pid</unix_pid>
- <min_children>5</min_children>
- <max_children>15</max_children>
- <min_spare_children>2</min_spare_children> <max_spare_children>5</max_spare_children>
- </unix_config>
- </opensrf.dbmath>
-
- <opensrf.settings>
- <keepalive>1</keepalive>
- <stateless>0</stateless>
- <language>perl</language>
- <implementation>OpenSRF::Application::Settings</implementation>
- <max_requests>17</max_requests>
- <unix_config>
- <unix_sock>opensrf.settings_unix.sock</unix_sock>
- <unix_pid>opoensrf.settings_unix.pid</unix_pid>
- <max_requests>1000</max_requests>
- <unix_log>opensrf.settings_unix.log</unix_log>
- <min_children>5</min_children>
- <max_children>15</max_children>
- <min_spare_children>3</min_spare_children>
- <max_spare_children>5</max_spare_children>
- </unix_config>
- </opensrf.settings>
-
- </apps>
-
- </default>
-
- <hosts>
-
- <myhost.mydomain.org>
- <!-- ^-=-
- must match the fully qualified domain name of the host
- on Linux, this is usually the output of "hostname -f"
- -->
-
-
- <!-- List all of the apps this server will be running -->
- <activeapps>
- <appname>opensrf.persist</appname>
- <appname>opensrf.settings</appname>
- <appname>opensrf.math</appname>
- <appname>opensrf.dbmath</appname>
- </activeapps>
-
- <apps> <!-- Example of an app-specific setting override -->
- <opensrf.persist>
- <app_settings>
- <dbfile>/different/path/to/dbfile/persist.db</dbfile>
- </app_settings>
- </opensrf.persist>
- </apps>
-
- </myhost.mydomain.org>
-
- </hosts>
-
-</opensrf>
+++ /dev/null
-<?xml version='1.0'?>
-
-<config>
-
- <opensrf> <!-- bootstrap config for the C apps -->
-
- <!-- the routers's name on the network -->
- <!-- do not change this -->
- <router_name>router</router_name>
-
- <routers>
- <!--
- list of router domains we should register with.
- We must at least have our default jabber domain in here
- -->
- <router>localhost</router>
- </routers>
-
- <domains>
- <!-- Our jabber domain, currenlty only one domain is supported -->
- <domain>localhost</domain>
- </domains>
-
- <username>client</username>
- <passwd>mypass</passwd>
- <port>5222</port>
-
- <!-- log to a local file -->
- <logfile>/openils/var/log/osrfsys.log</logfile>
-
- <!--
- Log to syslog. You can use this same layout for
- defining the logging of all services in this file
- -->
-
- <!--
- <logfile>syslog</logfile>
- <syslog>local2</syslog>
- <actlog>local1</actlog>
- -->
-
- <!-- 0 None, 1 Error, 2 Warning, 3 Info, 4 debug, 5 Internal (Nasty) -->
- <loglevel>3</loglevel>
- </opensrf>
-
-
- <!-- Update this if you use ChopChop -->
- <chopchop> <!-- Our jabber server -->
- <domain>localhost</domain>
- <port>5222</port>
-
- <!-- used when multiple servers need to communicate -->
- <s2sport>5269</s2sport>
- <secret>secret</secret>
-
- <listen_address>10.0.0.3</listen_address>
- <loglevel>3</loglevel>
- <logfile>/openils/var/log/osrfsys.log</logfile>
- </chopchop>
-
-
- <!-- The section between <gateway>...</gateway> is a standard OpenSRF C stack config file -->
- <gateway>
-
- <!-- we consider ourselves to be the "originating" client for requests,
- which means we define the log XID string for log traces -->
- <client>true</client>
-
- <!-- the routers's name on the network -->
- <router_name>router</router_name>
-
- <!-- jabber domains to connect to (domain1, domain2, ...) -->
- <domains>
- <domain>localhost</domain>
- </domains>
-
- <!-- These are the services that the gateway will serve.
- Any other requests will receive an HTTP_NOT_FOUND (404)
- DO NOT put any services here that you don't want the internet to have access to
- -->
- <services>
- <service>opensrf.math</service>
- <service>open-ils.cat</service>
- <service>open-ils.search</service>
- <service>open-ils.circ</service>
- <service>open-ils.actor</service>
- <service>open-ils.auth</service>
- </services>
-
-
- <!-- jabber login info -->
- <username>mylogin</username>
- <passwd>mypassword</passwd>
- <port>5222</port>
-
- <logfile>/openils/var/log/gateway.log</logfile>
- <loglevel>3</loglevel>
-
- </gateway>
-
-
- <!-- ======================================================================================== -->
-
- <router>
-
- <!-- do not change -->
- <component>0</component>
-
- <trusted_domains>
- <!-- Trusted servers are allowed to register apps with the router -->
- <server>localhost</server>
- <!-- Trusted clients are allowed to send packets through the router -->
- <client>localhost</client>
- </trusted_domains>
-
- <transport>
- <!-- jabber server are we connecting to -->
- <server>localhost</server>
- <port>5222</port>
-
- <!-- if this is changed, all "router_name" settings
- will need to be updated to match this setting -->
- <username>router</username>
-
- <password>mypassword</password>
-
- <!-- router's jabber resource -->
- <!-- do not change this -->
- <resource>router</resource>
-
- <connect_timeout>10</connect_timeout>
- <max_reconnect_attempts>5</max_reconnect_attempts>
- </transport>
-
- <logfile>/openils/var/log/router.log</logfile>
- <loglevel>3</loglevel>
-
- </router>
-
- <!-- ======================================================================================== -->
-
-</config>
-
-
-
-
+++ /dev/null
-#!/usr/bin/perl
-# ----------------------------------------------------------------------
-# Utility script for registring users on a jabber server.
-# ----------------------------------------------------------------------
-use Net::Jabber;
-use strict;
-
-if (@ARGV < 4) {
- print "\nperl $0 <server> <port> <username> <password> \n\n";
- exit(0);
-}
-
-my $server = $ARGV[0];
-my $port = $ARGV[1];
-my $username = $ARGV[2];
-my $password = $ARGV[3];
-my $resource = "test_${server}_$$";
-
-my $connection = Net::Jabber::Client->new;
-
-my $status = $connection->Connect(hostname=>$server, port=>$port);
-
-my @stat = $connection->RegisterSend(
- $server,
- username => $username,
- password => $password );
-
-
-print "Register results : @stat\n";
-
-
-if (!defined($status)) {
- print "ERROR: Jabber server is down or connection was not allowed.\n";
- print " ($!)\n";
- exit(0);
-}
-
-my @result = $connection->AuthSend(
- username=>$username, password=>$password, resource=>$resource);
-
-if ($result[0] ne "ok") {
- print "ERROR: Authorization failed: $result[0] - $result[1]\n";
- exit(0);
-}
-
-print "Logged in OK to $server:$port\nRegistration succeeded for $username\@$server!\n";
-
-$connection->Disconnect();
-
-
+++ /dev/null
-<!-- This file follows the standard C stack bootstrap config file layout -->
-<srfsh>
- <router_name>router</router_name>
- <domains>
- <domain>127.0.0.1</domain>
- </domains>
- <username>myusername</username>
- <passwd>mypassword</passwd>
- <port>5222</port>
- <logfile>/path/to/log/srfsh.log</logfile>
- <loglevel>4</loglevel>
-</srfsh>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<!--
-
-Copyright (C) 2007 Laurentian University
-Dan Scott <dscott@laurentian.ca>
-
-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; either version 2
-of the License, or (at your option) any later version.
-
-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
-
--->
-
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
-
-<!-- define types -->
-<xs:simpleType name="loglevelType">
- <xs:restriction base="xs:positiveInteger">
- <xs:maxInclusive value="4"/>
- </xs:restriction>
-</xs:simpleType>
-
-<xs:simpleType name="portType">
- <xs:restriction base="xs:positiveInteger">
- <xs:maxInclusive value="65535"/>
- </xs:restriction>
-</xs:simpleType>
-
-
-<!-- define simple elements -->
-<xs:element name="router_name" type="xs:string"/>
-<xs:element name="domain" type="xs:string"/>
-<xs:element name="username" type="xs:string"/>
-<xs:element name="passwd" type="xs:string"/>
-<xs:element name="port" type="portType"/>
-<xs:element name="logfile" type="xs:string"/>
-<xs:element name="loglevel" type="loglevelType"/>
-
-<!-- group type -->
-<xs:group name="srfshElements">
- <xs:all>
- <xs:element ref="router_name"/>
- <xs:element ref="domains"/>
- <xs:element ref="username"/>
- <xs:element ref="passwd"/>
- <xs:element ref="port"/>
- <xs:element ref="logfile"/>
- <xs:element ref="loglevel"/>
- </xs:all>
-</xs:group>
-
-<!-- complex elements -->
-<xs:element name="domains">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="domain" minOccurs="1" maxOccurs="unbounded"/>
- </xs:sequence>
- </xs:complexType>
-</xs:element>
-
-<xs:element name="srfsh">
- <xs:complexType>
- <xs:group ref="srfshElements"/>
- </xs:complexType>
-</xs:element>
-
-</xs:schema>
+++ /dev/null
-# TOP level 'src' makefile for OpenSRF
-
-
-export TMPDIR = $(TMP)/opensrf
-export OPENSRF = opensrf
-export BINDIR = $(PREFIX)/bin
-export LIBDIR = $(PREFIX)/lib
-export PERLDIR = $(LIBDIR)/perl5
-export INCLUDEDIR = $(PREFIX)/include
-
-export LDLIBS +=
-export LDFLAGS += -Wl,-rpath=$(LIBDIR) -L $(TMPDIR) -L . -L /opt/lib
-export CFLAGS += -pipe -g -Wall -O2 -fPIC -I$(LIBXML2_HEADERS) -I$(APACHE2_HEADERS) \
- -I$(LIBXML2_HEADERS)/libxml -I$(TMP) \
- -I$(APR_HEADERS) -I$(TMPDIR)
-
-LIBOPENSRF = libopensrf.so
-
-OPENSRF_TARGETS = libtransport/transport_session.o \
- libtransport/transport_client.o \
- libtransport/transport_message.o \
- libstack/osrf_app_session.o \
- libstack/osrf_stack.o \
- libstack/osrfConfig.o \
- libstack/osrf_settings.o \
- libstack/osrf_message.o \
- libstack/osrf_prefork.o \
- libstack/osrf_system.o \
- libstack/osrf_application.o \
- libstack/osrf_cache.o \
- libstack/xml_utils.o \
- libstack/osrf_transgroup.o \
- libstack/osrf_list.o \
- libstack/osrf_hash.o \
- utils/socket_bundle.o \
- utils/string_array.o \
- utils/utils.o \
- utils/log.o \
- utils/md5.o \
- utils/sha.o
-
-OPENSRF_HEADERS = libtransport/transport_session.h \
- libtransport/transport_client.h \
- libtransport/transport_message.h \
- libstack/osrf_app_session.h \
- libstack/osrf_stack.h \
- libstack/osrfConfig.h \
- libstack/osrf_settings.h \
- libstack/osrf_message.h \
- libstack/osrf_prefork.h \
- libstack/osrf_system.h \
- libstack/osrf_application.h \
- libstack/osrf_cache.h \
- libstack/xml_utils.h \
- libstack/osrf_transgroup.h \
- libstack/osrf_list.h \
- libstack/osrf_hash.h \
- utils/socket_bundle.h \
- utils/string_array.h \
- utils/utils.h \
- utils/log.h \
- utils/md5.h \
- utils/sha.h
-
-all: prep \
- libopensrf.so \
- libstack/opensrf \
- router \
- srfsh \
- jserver \
- gateway
-
-install: install-prep \
- opensrf-install \
- gateway-install \
- router-install \
- srfsh-install \
- jserver-install \
- perl-install \
- objson-install
-
-prep:
- mkdir -p $(TMPDIR)
-
-libopensrf.so: objson/libobjson.so
- @echo utils
- make -C utils
- @echo transport
- make -C libtransport
- @echo stack
- make -C libstack
- @echo $@
- $(CC) -shared -W1 $(LDFLAGS) -lxml2 -lmemcache -lobjson $(OPENSRF_TARGETS) -o $(TMPDIR)/$(LIBOPENSRF)
- @echo apps
- make -C c-apps
-
-
-opensrf-install: objson-install
- @echo $@
- cp $(TMPDIR)/$(LIBOPENSRF) $(LIBDIR)/$(LIBOPENSRF)
- cp $(OPENSRF_HEADERS) $(INCLUDEDIR)/opensrf/
- cp libstack/opensrf $(BINDIR)/opensrf-c
- make -C c-apps install
-
-
-objson/libobjson.so: prep
- @echo $@
- make -C objson
-
-# --------------------------------------------------------------------------------
-# BINARIES
-# --------------------------------------------------------------------------------
-libstack/opensrf.o: libstack/opensrf.c libopensrf.so
-libstack/opensrf: libstack/opensrf.o
- @echo $@
- $(CC) $(CFLAGS) $(LDFLAGS) -lxml2 -lopensrf -lobjson libstack/opensrf.o -o $@
-
-
-router: libopensrf.so
- @echo $@
- make -C router
-
-srfsh: libopensrf.so
- @echo $@
- make -C srfsh
-
-gateway: libopensrf.so
- @echo $@
- make -C gateway
-
-jserver: libopensrf.so
- @echo $@
- make -C jserver
-
-
-# --------------------------------------------------------------------------------
-# INSTALL
-# --------------------------------------------------------------------------------
-install-prep:
- @echo $@
- mkdir -p $(LIBDIR)
- mkdir -p $(BINDIR)
- mkdir -p $(PERLDIR)
- mkdir -p $(INCLUDEDIR)
- mkdir -p $(INCLUDEDIR)/$(OPENSRF)
- mkdir -p $(ETCDIR)
- mkdir -p $(TEMPLATEDIR)
-
-objson-install: install-prep
- @echo $@
- make -C objson install
-
-libopensrf-install: install-prep
- @echo $@
- cp $(TMPDIR)/$(LIBOPENSRF) $(LIBDIR)
-
-gateway-install: install-prep opensrf-install
- @echo $@
- make -C gateway install
-
-router-install: install-prep opensrf-install
- @echo $@
- make -C router install
-
-srfsh-install: install-prep opensrf-install
- @echo $@
- make -C srfsh install
-
-jserver-install: install-prep
- @echo $@
- make -C jserver install
-
-perl-install: install-prep
- @echo $@
- cp -r perlmods/* $(PERLDIR)/
- cp ../examples/bootstrap.conf.example $(ETCDIR)
- cp ../bin/osrf_ctl.sh $(BINDIR)
- cp ../examples/opensrf.xml.example $(ETCDIR)
- cp ../examples/opensrf_core.xml.example $(ETCDIR)
- cp ../examples/srfsh.xml.example $(ETCDIR)
-
-
-# --------------------------------------------------------------------------------
-# CLEAN
-# --------------------------------------------------------------------------------
-clean:
- @echo $@
- make -C libtransport clean
- make -C libstack clean
- make -C router clean
- make -C gateway clean
- make -C jserver clean
- make -C utils clean
- make -C objson clean
- make -C srfsh clean
- make -C c-apps clean
- echo "Removing directory [$(TMPDIR)]"
- /bin/rm -rf $(TMPDIR) *.o
-
-
+++ /dev/null
-LDLIBS += -lobjson -lopensrf
-CFLAGS += -DOSRF_LOG_PARAMS
-
-all: osrf_math.so osrf_dbmath.so osrf_version.so
-
-osrf_math.o: osrf_math.c
-osrf_dbmath.o: osrf_dbmath.c
-osrf_version.o: osrf_version.c
-
-osrf_math.so: osrf_math.o
- $(CC) -shared -W1 $(LDLIBS) $(LDFLAGS) osrf_math.o -o $(TMPDIR)/osrf_math.so
-
-osrf_dbmath.so: osrf_dbmath.o
- $(CC) -shared -W1 $(LDLIBS) $(LDFLAGS) osrf_dbmath.o -o $(TMPDIR)/osrf_dbmath.so
-
-osrf_version.so: osrf_version.o
- $(CC) -shared -W1 $(LDLIBS) $(LDFLAGS) osrf_version.o -o $(TMPDIR)/osrf_version.so
-
-install:
- cp $(TMPDIR)/osrf_math.so $(LIBDIR)/
- cp $(TMPDIR)/osrf_dbmath.so $(LIBDIR)/
- cp $(TMPDIR)/osrf_version.so $(LIBDIR)/
-
-clean:
- rm -f *.o *.so
+++ /dev/null
-#include "opensrf/osrf_app_session.h"
-#include "opensrf/osrf_application.h"
-#include "objson/object.h"
-#include "opensrf/log.h"
-
-#define MODULENAME "opensrf.dbmath"
-
-int osrfAppInitialize();
-int osrfAppChildInit();
-int osrfMathRun( osrfMethodContext* );
-
-
-int osrfAppInitialize() {
-
- osrfAppRegisterMethod(
- MODULENAME,
- "add",
- "osrfMathRun",
- "Addss two numbers", 2, 0 );
-
- osrfAppRegisterMethod(
- MODULENAME,
- "sub",
- "osrfMathRun",
- "Subtracts two numbers", 2, 0 );
-
- osrfAppRegisterMethod(
- MODULENAME,
- "mult",
- "osrfMathRun",
- "Multiplies two numbers", 2, 0 );
-
- osrfAppRegisterMethod(
- MODULENAME,
- "div",
- "osrfMathRun",
- "Divides two numbers", 2, 0 );
-
- return 0;
-}
-
-int osrfAppChildInit() {
- return 0;
-}
-
-int osrfMathRun( osrfMethodContext* ctx ) {
-
- OSRF_METHOD_VERIFY_CONTEXT(ctx);
-
- jsonObject* x = jsonObjectGetIndex(ctx->params, 0);
- jsonObject* y = jsonObjectGetIndex(ctx->params, 1);
-
- if( x && y ) {
-
- char* a = jsonObjectToSimpleString(x);
- char* b = jsonObjectToSimpleString(y);
-
- if( a && b ) {
-
- double i = strtod(a, NULL);
- double j = strtod(b, NULL);
- double r = 0;
-
- if(!strcmp(ctx->method->name, "add")) r = i + j;
- if(!strcmp(ctx->method->name, "sub")) r = i - j;
- if(!strcmp(ctx->method->name, "mult")) r = i * j;
- if(!strcmp(ctx->method->name, "div")) r = i / j;
-
- jsonObject* resp = jsonNewNumberObject(r);
- osrfAppRespondComplete( ctx, resp );
- jsonObjectFree(resp);
-
- free(a); free(b);
- return 0;
- }
- }
-
- return -1;
-}
-
-
-
+++ /dev/null
-#include "opensrf/osrf_app_session.h"
-#include "opensrf/osrf_application.h"
-#include "objson/object.h"
-#include "opensrf/log.h"
-
-#define MODULENAME "opensrf.math"
-
-int osrfAppInitialize();
-int osrfAppChildInit();
-void osrfAppChildExit();
-int osrfMathRun( osrfMethodContext* );
-
-
-int osrfAppInitialize() {
-
- osrfAppRegisterMethod(
- MODULENAME, /* which application has this method */
- "add", /* the name of the method */
- "osrfMathRun", /* the symbol that runs the method */
- "Adds two numbers", /* description of the method */
- 2, /* the minimum number of params required to run the method */
- 0 ); /* method options, 0 for not special options */
-
- osrfAppRegisterMethod(
- MODULENAME,
- "sub",
- "osrfMathRun",
- "Subtracts two numbers", 2, 0 );
-
- osrfAppRegisterMethod(
- MODULENAME,
- "mult",
- "osrfMathRun",
- "Multiplies two numbers", 2, 0 );
-
- osrfAppRegisterMethod(
- MODULENAME,
- "div",
- "osrfMathRun",
- "Divides two numbers", 2, 0 );
-
- return 0;
-}
-
-/* called when this process is just coming into existence */
-int osrfAppChildInit() {
- return 0;
-}
-
-/* called when this process is about to exit */
-void osrfAppChildExit() {
- osrfLogDebug(OSRF_LOG_MARK, "Child is exiting...");
-}
-
-
-int osrfMathRun( osrfMethodContext* ctx ) {
-
- OSRF_METHOD_VERIFY_CONTEXT(ctx); /* see osrf_application.h */
-
- /* collect the request params */
- jsonObject* x = jsonObjectGetIndex(ctx->params, 0);
- jsonObject* y = jsonObjectGetIndex(ctx->params, 1);
-
- if( x && y ) {
-
- /* pull out the params as strings since they may be either
- strings or numbers depending on the client */
- char* a = jsonObjectToSimpleString(x);
- char* b = jsonObjectToSimpleString(y);
-
- if( a && b ) {
-
- osrfLogActivity( OSRF_LOG_MARK, "Running opensrf.math %s [ %s : %s ]",
- ctx->method->name, a, b );
-
- /* construct a new params object to send to dbmath */
- jsonObject* newParams = jsonParseStringFmt( "[ %s, %s ]", a, b );
- free(a); free(b);
-
- /* connect to db math */
- osrfAppSession* ses = osrfAppSessionClientInit("opensrf.dbmath");
-
- /* forcing an explicit connect allows us to talk to one worker backend
- * regardless of "stateful" config settings for the server
- * This buys us nothing here since we're only sending one request...
- * */
- /*osrfAppSessionConnect(ses);*/
-
- /* dbmath uses the same method names that math does */
- int req_id = osrfAppSessionMakeRequest( ses, newParams, ctx->method->name, 1, NULL );
- osrfMessage* omsg = osrfAppSessionRequestRecv( ses, req_id, 60 );
-
- if(omsg) {
- /* return dbmath's response to the user */
- osrfAppRespondComplete( ctx, osrfMessageGetResult(omsg) );
- osrfMessageFree(omsg);
- osrfAppSessionFree(ses);
- return 0;
- }
-
- osrfAppSessionFree(ses);
- }
- }
-
- return -1;
-}
-
-
-
+++ /dev/null
-#include "opensrf/osrf_app_session.h"
-#include "opensrf/osrf_application.h"
-#include "objson/object.h"
-#include "opensrf/utils.h"
-#include "opensrf/log.h"
-
-#define OSRF_VERSION_CACHE_TIME 300
-
-int osrfAppInitialize();
-int osrfAppChildInit();
-int osrfVersion( osrfMethodContext* );
-
-
-int osrfAppInitialize() {
-
- osrfAppRegisterMethod(
- "opensrf.version",
- "opensrf.version.verify",
- "osrfVersion",
- "The data for a service/method/params combination will be retrieved "
- "from the necessary server and the MD5 sum of the total values received "
- "will be returned. PARAMS( serviceName, methodName, [param1, ...] )",
- 2, 0 );
-
- return 0;
-}
-
-int osrfAppChildInit() {
- return 0;
-}
-
-int osrfVersion( osrfMethodContext* ctx ) {
-
- OSRF_METHOD_VERIFY_CONTEXT(ctx);
-
- /* First, see if the data is in the cache */
- char* json = jsonObjectToJSON(ctx->params);
- char* paramsmd5 = md5sum(json);
- char* cachedmd5 = osrfCacheGetString(paramsmd5);
- free(json);
-
- if( cachedmd5 ) {
- osrfLogDebug(OSRF_LOG_MARK, "Found %s object in cache, returning....", cachedmd5 );
- jsonObject* resp = jsonNewObject(cachedmd5);
- osrfAppRespondComplete( ctx, resp );
- jsonObjectFree(resp);
- free(paramsmd5);
- free(cachedmd5);
- return 0;
- }
-
- jsonObject* serv = jsonObjectGetIndex(ctx->params, 0);
- jsonObject* meth = jsonObjectGetIndex(ctx->params, 1);
- char* service = jsonObjectGetString(serv);
- char* methd = jsonObjectGetString(meth);
-
- if( service && methd ) {
- /* shove the additional params into an array */
- jsonObject* tmpArray = jsonNewObject(NULL);
- int i;
- for( i = 2; i != ctx->params->size; i++ )
- jsonObjectPush( tmpArray, jsonObjectClone(jsonObjectGetIndex(ctx->params, i)));
-
- osrfAppSession* ses = osrfAppSessionClientInit(service);
- int reqid = osrfAppSessionMakeRequest( ses, tmpArray, methd, 1, NULL );
- osrfMessage* omsg = osrfAppSessionRequestRecv( ses, reqid, 60 );
- jsonObjectFree(tmpArray);
-
- if( omsg ) {
-
- jsonObject* result = osrfMessageGetResult( omsg );
- char* resultjson = jsonObjectToJSON(result);
- char* resultmd5 = md5sum(resultjson);
- free(resultjson);
- osrfMessageFree(omsg);
-
- if( resultmd5 ) {
- jsonObject* resp = jsonNewObject(resultmd5);
- osrfAppRespondComplete( ctx, resp );
- jsonObjectFree(resp);
- osrfAppSessionFree(ses);
- osrfLogDebug(OSRF_LOG_MARK, "Found version string %s, caching and returning...", resultmd5 );
- osrfCachePutString( paramsmd5, resultmd5, OSRF_VERSION_CACHE_TIME );
- free(resultmd5);
- free(paramsmd5);
- return 0;
- }
- }
- osrfAppSessionFree(ses);
- }
-
- free(paramsmd5);
-
- return -1;
-}
-
-
-
+++ /dev/null
-<?xml-stylesheet type="text/xsl" href="#"?>
-<xsl:stylesheet
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- xmlns:res="http://opensrf.org/-/namespaces/gateway/v1"
- version="1.0"
- >
- <xsl:template match="xsl:stylesheet">
- <html>
- <head>
- <style type="text/css">
-body { background-color:#F0F0F0; font: 9pt Verdana, Arial, "Arial Unicode MS", Helvetica, sans-serif;}
-input.button { font:8pt Verdana, Arail, "Arial Unicode MS", Helvetica, sans-serif;}
-input.text {}
-div.DDB { position:absolute; top:20pt; left:15pt; visibility:visible; }
-div.DLC { position:absolute; top:20pt; left:15pt; visibility:hidden; }
-div.numFound { position:absolute; top:0px; left:0pt; font-weight:bold;}
-
-table { background-color:lightgray; font-size:10pt; margin:10pt 0pt 15pt 0pt; width:90%; border-collapse: collapse; spacing:0; padding:0;}
-td { background-color:#f0f0f0; border: solid lightgray 1px; }
-td.fulltag { background-color:#f0f0f0;}
-td.fullind { background-color:#f0f0f0; width:20pt;}
-td.fullfield{ background-color:#f0f0f0; width:100%;}
-
-table.signature { background-color:lightgray; font-size:10pt; margin:0; width:100%; border:none; padding:0;}
-table.params { background-color:lightgray; font-size:10pt; margin:3px 0px 3px 0px; width:100%; border: solid black 1px; padding:0;}
-td.params { background-color:lightgray; font-size:10pt; border: solid black 1px;}
-
-h1 { text-decoration: underline; }
-
-td.header { font-weight:bold; color:black; font-size:14pt; border-bottom: solid gray 2px}
-td.label { vertical-align:top; padding-left:10pt; width:120pt; font-weight:normal; color:darkblue;}
-td.value { vertical-align:top; text-align:left; font-weight: bold;}
-span.subcode { color:darkblue;} </style>
-
- </head>
- <body>
- <a name="top"/>
-
-<!--#if expr='$QUERY_STRING = /limit=([^&]+)/' -->
- <!--#set var="limit" value="$1" -->
-<!--#else -->
- <!--#set var="limit" value="25" -->
-<!--#endif -->
-
-<!--#if expr='$QUERY_STRING = /offset=([^&]+)/' -->
- <!--#set var="offset" value="$1" -->
-<!--#else -->
- <!--#set var="offset" value="0" -->
-<!--#endif -->
-
-<!--#if expr='$QUERY_STRING = /service=([^&]+)/' -->
- <!--#set var="service" value="$1" -->
-<!--#else -->
- <!--#set var="service" value="" -->
-<!--#endif -->
-
-<!--#if expr='$QUERY_STRING = /method=([^&]+)/' -->
- <!--#set var="method" value="$1" -->
-<!--#endif -->
-
-<!--#if expr="$QUERY_STRING = /all=on/" -->
- <!--#set var="all" value="on" -->
- <!--#set var="method" value="opensrf.sysemt.method.all" -->
-<!--#else -->
- <!--#set var="all" value="off" -->
- <!--#set var="method" value="opensrf.sysemt.method" -->
-<!--#endif -->
-
-<!--#if expr='$QUERY_STRING = /param=%22(.+?)%22/' -->
- <!--#set var="param" value="$1" -->
-<!--#else -->
- <!--#set var="param" value="" -->
-<!--#endif -->
-
- <xsl:if test="not(res:response)">
- <br/><br/><br/><br/><br/><br/>
- <br/><br/><br/><br/><br/><br/>
- </xsl:if>
-
- <form
- method="GET"
- action='<!--#echo var="DOCUMENT_URI" -->'
- onsubmit='
- this.param.value = "\"" + this.param.value + "\"";
- if (this.all.checked) this.method.value = "opensrf.system.method.all";
- '>
- <xsl:if test="not(res:response)">
- <xsl:attribute name="style">
- <xsl:value-of select="'text-align:center;'"/>
- </xsl:attribute>
- </xsl:if>
- Application:
- <input name="service" type="text" value='<!--#echo var="service" -->'/> 
- API Method Name Regex:
- <input name="param" type="text" value='<!--#echo var="param" -->'>
- <xsl:if test="'<!--#echo var="all" -->' = 'on'">
- <xsl:attribute name="disabled">
- <xsl:value-of select="'true'"/>
- </xsl:attribute>
- </xsl:if>
- </input> 
- All Methods (Use with care!)
- <input
- name="all"
- type="checkbox"
- value="on"
- onclick='
- if (this.checked) this.form.param.disabled = true;
- else this.form.param.disabled = false;
- '>
- <xsl:if test="'<!--#echo var="all" -->' = 'on'">
- <xsl:attribute name="checked">
- <xsl:value-of select="'checked'"/>
- </xsl:attribute>
- </xsl:if>
-
- </input> 
- <input type="hidden" name="offset" value="<!--#echo var="offset" -->"/>
- <button name="limit" value="<!--#echo var="limit" -->">Find 'em</button>
- </form>
-
- <xsl:if test="res:response">
- <hr/>
-
- <xsl:apply-templates select="res:response"/>
-
- <hr/>
-
- <form
- method="GET"
- action='<!--#echo var="DOCUMENT_URI" -->'
- onsubmit='
- this.param.value = "\"" + this.param.value + "\"";
- if (this.all.checked) this.method.value = "opensrf.system.method.all";
- '>
- <xsl:if test="not(res:response)">
- <xsl:attribute name="style">
- <xsl:value-of select="'text-align:center;'"/>
- </xsl:attribute>
- </xsl:if>
- Application:
- <input name="service" type="text" value='<!--#echo var="service" -->'/> 
- API Method Name Regex:
- <input name="param" type="text" value='<!--#echo var="param" -->'>
- <xsl:if test="'<!--#echo var="all" -->' = 'on'">
- <xsl:attribute name="disabled">
- <xsl:value-of select="'true'"/>
- </xsl:attribute>
- </xsl:if>
- </input> 
- All Methods (Use with care!)
- <input
- name="all"
- type="checkbox"
- value="on"
- onclick='
- if (this.checked) this.form.param.disabled = true;
- else this.form.param.disabled = false;
- '>
- <xsl:if test="'<!--#echo var="all" -->' = 'on'">
- <xsl:attribute name="checked">
- <xsl:value-of select="'checked'"/>
- </xsl:attribute>
- </xsl:if>
-
- </input> 
- <input type="hidden" name="offset" value="<!--#echo var="offset" -->"/>
- <button name="limit" value="<!--#echo var="limit" -->">Find 'em</button>
- </form>
-
- </xsl:if>
- </body>
- </html>
- </xsl:template>
-
- <xsl:template name="apiNameLink">
- API Level: <xsl:value-of select="../res:element[@key='api_level']/res:number"/> / Method:
- <a>
- <xsl:attribute name="href">#<xsl:value-of select="../res:element[@key='api_level']/res:number"/>/<xsl:value-of select="res:string"/></xsl:attribute>
- <xsl:value-of select="res:string"/>
- </a>
- <br/>
- </xsl:template>
-
- <xsl:template match="res:response">
- <xsl:choose>
- <xsl:when test="count(//res:element[@key='api_name']) > 1 or <!--#echo var="offset" --> > 0">
- <h1>Matching Methods</h1>
-
- <xsl:if test="<!--#echo var="offset" --> > 0">
- <span>
- <a>
- <xsl:attribute name="href">docgen.xsl?service=<!--#echo var="service" -->&all=<!--#echo var="all" -->&param="<!--#echo var="param" -->"&limit=<!--#echo var="limit" -->&offset=<xsl:value-of select='<!--#echo var="offset" --> - <!--#echo var="limit" -->'/></xsl:attribute>
- Previous Page</a>
- //
- </span>
- </xsl:if>
-
-
- <span>
- <xsl:value-of select='<!--#echo var="offset" --> + 1'/>
- -
- <xsl:value-of select='<!--#echo var="offset" --> + count(//res:element[@key="api_name"])'/>
- </span>
-
- <xsl:if test="count(//res:element[@key='api_name']) = <!--#echo var="limit" -->">
- <span>
- //
- <a>
- <xsl:attribute name="href">docgen.xsl?service=<!--#echo var="service" -->&all=<!--#echo var="all" -->&param="<!--#echo var="param" -->"&limit=<!--#echo var="limit" -->&offset=<xsl:value-of select='<!--#echo var="offset" --> + <!--#echo var="limit" -->'/></xsl:attribute>
- Next Page</a>
- </span>
- </xsl:if>
-
- <br/>
- <br/>
-
- <xsl:for-each select="//res:element[@key='api_name']">
- <xsl:sort select="concat(../res:element[@key='api_level']/res:number/text(), res:string/text())"/>
- <xsl:call-template name="apiNameLink"/>
- </xsl:for-each>
-
- <h1>Method Definitions</h1>
- </xsl:when>
- <xsl:when test="count(//res:element[@key='api_name']) = 0">
- <h1><i>No Matching Methods Found</i></h1>
- </xsl:when>
- </xsl:choose>
-
- <xsl:for-each select="res:payload/res:object">
- <xsl:sort select="concat(../res:element[@key='api_level']/res:number/text(), res:string/text())"/>
- <xsl:call-template name="methodDefinition"/>
- </xsl:for-each>
- </xsl:template>
-
-
- <xsl:template name="methodDefinition">
- <xsl:if test="res:element[@key='remote']/res:number/text()='0'">
-
- <xsl:if test="count(//res:element[@key='api_name']) > 1">
- <a>
- <xsl:attribute name="name"><xsl:value-of select="res:element[@key='api_level']/res:number"/>/<xsl:value-of select="res:element[@key='api_name']/res:string"/></xsl:attribute>
- </a>
- <a href="#top">Top</a>
- </xsl:if>
-
- <table>
- <tr>
- <td colspan="3" class="header"><xsl:value-of select="res:element[@key='api_name']/res:string"/></td>
- </tr>
- <tr>
- <td class="label">API Level:</td>
- <td colspan="2" class="value"><xsl:value-of select="res:element[@key='api_level']/res:number"/></td>
- </tr>
- <tr>
- <td class="label">Package:</td>
- <td colspan="2" class="value"><xsl:value-of select="res:element[@key='package']/res:string"/></td>
- </tr>
- <tr>
- <td class="label">Packaged Method:</td>
- <td colspan="2" class="value"><xsl:value-of select="res:element[@key='method']/res:string"/></td>
- </tr>
- <tr>
- <td class="label">Required argument count:</td>
- <td colspan="2" class="value"><xsl:value-of select="res:element[@key='argc']/res:number"/></td>
- </tr>
- <xsl:if test="normalize-space(res:element[@key='signature']/res:object/res:element[@key='desc']/res:string/text()) != normalize-space(res:element[@key='notes']/res:string/text())">
- <tr>
- <td class="label">
- <xsl:attribute name='rowspan'>
- <xsl:value-of select='
- count(res:element[@key="signature"]/res:object/res:element[@key="params"]/res:array/res:object) +
- count(res:element[@key="signature"]/res:object/res:element[@key="params"]/res:array[res:object]) +
- 5
- '/>
- </xsl:attribute>
- Signature:
- </td>
- </tr>
- <xsl:for-each select="res:element[@key='signature']/res:object">
- <xsl:call-template name="methodSignature"/>
- </xsl:for-each>
- </xsl:if>
- <tr>
- <td class="label">Streaming method:</td>
- <td colspan="2" class="value">
- <xsl:if test="res:element[@key='stream']/res:number/text()='1'">Yes</xsl:if>
- <xsl:if test="res:element[@key='stream']/res:number/text()='0'">No</xsl:if>
- </td>
- </tr>
- <xsl:if test="res:element[@key='notes']">
- <tr>
- <td class="label">Notes:</td>
- <td colspan="2" class="value"><pre style="font-weight:normal;font-size:10px;"><xsl:value-of select="res:element[@key='notes']/res:string"/></pre></td>
- </tr>
- </xsl:if>
- </table>
- </xsl:if>
- </xsl:template>
-
-
- <xsl:template name="paramInfoLine">
- <tr>
- <td class="label params">
- <xsl:if test="@key='name'">Name:</xsl:if>
- <xsl:if test="@key='desc'">Description:</xsl:if>
- <xsl:if test="@key='type'">Data type:</xsl:if>
- <xsl:if test="@key='class'">Object class:</xsl:if>
- </td>
- <td class="value params"><xsl:value-of select="res:string"/></td>
- </tr>
- </xsl:template>
-
-
- <xsl:template name="paramInfo">
- <tr>
- <td>
- <table class="params">
- <tr>
- <td class="label params">Position:</td>
- <td class="value params"><xsl:value-of select="position()"/></td>
- </tr>
- <xsl:for-each select="res:element">
- <xsl:call-template name="paramInfoLine"/>
- </xsl:for-each>
- </table>
- </td>
- </tr>
- </xsl:template>
-
-
- <xsl:template name="methodSignature">
- <xsl:if test="res:element[@key='desc']">
- <tr>
- <td class="label">Description:</td>
- <td class="value"><xsl:value-of select="res:element[@key='desc']/res:string"/></td>
- </tr>
- </xsl:if>
- <xsl:if test="res:element[@key='params']/res:array/res:object">
- <tr>
- <td class="label">
- <xsl:attribute name='rowspan'>
- <xsl:value-of select='count(res:element[@key="params"]/res:array/res:object) + 1'/>
- </xsl:attribute>
- Parameters:</td>
- </tr>
- </xsl:if>
- <xsl:for-each select="res:element[@key='params']/res:array/res:object">
- <xsl:sort select="position()"/>
- <xsl:call-template name="paramInfo"/>
- </xsl:for-each>
- <xsl:if test="res:element[@key='return']">
- <tr>
- <td class="label">Returns:</td>
- <td class="value"><xsl:value-of select="res:element[@key='return']/res:object/res:element[@key='desc']/res:string"/></td>
- </tr>
- <tr>
- <td class="label">Return type:</td>
- <td class="value"><xsl:value-of select="res:element[@key='return']/res:object/res:element[@key='type']/res:string"/></td>
- </tr>
- <tr>
- <td class="label">Return type class:</td>
- <td class="value"><xsl:value-of select="res:element[@key='return']/res:object/res:element[@key='class']/res:string"/></td>
- </tr>
- </xsl:if>
- </xsl:template>
-
-
- <!--#if expr="$QUERY_STRING = /service=[^&]+/" -->
- <!--#if expr="$QUERY_STRING = /param=%22[^&]+%22/" -->
- <!-- virtual="/gateway?format=xml&${QUERY_STRING}"-->
- <!-- virtual="/restgateway?${QUERY_STRING}"-->
- <!--#include virtual='/gateway?format=xml&service=$service&method=opensrf.system.method¶m="$param"¶m=$limit¶m=$offset'-->
- <!--#endif -->
- <!--#if expr="$QUERY_STRING = /all=on/" -->
- <!-- virtual="/gateway?format=xml&${QUERY_STRING}"-->
- <!-- virtual="/restgateway?${QUERY_STRING}"-->
- <!--#include virtual='/gateway?format=xml&service=$service&method=opensrf.system.method.all¶m=$limit¶m=$offset' -->
- <!--#endif -->
- <!--#endif -->
-
-
-</xsl:stylesheet>
-
+++ /dev/null
-#CFLAGS += -DASSUME_STATELESS -DOSRF_GATEWAY_NASTY_DEBUG
-CFLAGS += -DASSUME_STATELESS
-LDLIBS += -lobjson -lopensrf
-
-all: osrf_json_gateway.so copy
-
-install:
- $(APXS2) -i -a -n osrf_json_gateway osrf_json_gateway.so
- cp apachetools.h $(INCLUDEDIR)/opensrf/
-
-copy:
- cp apachetools.h $(TMPDIR)
-
-apachetools.o: apachetools.h apachetools.c
- $(CC) -c $(CFLAGS) apachetools.c -o $@
-
-osrf_json_gateway.o: osrf_json_gateway.c
- $(CC) -c $(CFLAGS) osrf_json_gateway.c -o $@
-
-osrf_json_gateway.so: copy apachetools.o osrf_json_gateway.o
- $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -shared -W1 apachetools.o osrf_json_gateway.o -o osrf_json_gateway.so
-
-
-clean:
- /bin/rm -f *.o *.so
+++ /dev/null
-#include "apachetools.h"
-
-string_array* apacheParseParms(request_rec* r) {
-
- if( r == NULL ) return NULL;
-
- char* arg = r->args; /* url query string */
- apr_pool_t *p = r->pool; /* memory pool */
- string_array* sarray = init_string_array(12); /* method parameters */
-
- growing_buffer* buffer = NULL; /* POST data */
- growing_buffer* tmp_buf = NULL; /* temp buffer */
-
- char* key = NULL; /* query item name */
- char* val = NULL; /* query item value */
-
- /* gather the post args and append them to the url query string */
- if( !strcmp(r->method,"POST") ) {
-
- ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK);
-
- osrfLogDebug(OSRF_LOG_MARK, "gateway reading post data..");
-
- if(ap_should_client_block(r)) {
-
- char body[1025];
- memset(body,0,1025);
- buffer = buffer_init(1025);
-
-
- osrfLogDebug(OSRF_LOG_MARK, "gateway client has post data, reading...");
-
- long bread;
- while( (bread = ap_get_client_block(r, body, 1024)) ) {
-
- if(bread < 0) {
- osrfLogInfo(OSRF_LOG_MARK,
- "ap_get_client_block(): returned error, exiting POST reader");
- break;
- }
-
- buffer_add( buffer, body );
- memset(body,0,1025);
-
- osrfLogDebug(OSRF_LOG_MARK,
- "gateway read %d bytes: %d bytes of data so far", bread, buffer->n_used);
-
- if(buffer->n_used == 0) break;
-
- if(buffer->n_used > APACHE_TOOLS_MAX_POST_SIZE) {
- osrfLogError(OSRF_LOG_MARK, "gateway received POST larger "
- "than %d bytes. dropping reqeust", APACHE_TOOLS_MAX_POST_SIZE);
- buffer_free(buffer);
- return NULL;
- }
- }
-
- osrfLogDebug(OSRF_LOG_MARK, "gateway done reading post data");
-
- if(arg && arg[0]) {
-
- tmp_buf = buffer_init(1024);
- buffer_add(tmp_buf,arg);
- buffer_add(tmp_buf,buffer->buf);
- arg = (char*) apr_pstrdup(p, tmp_buf->buf);
- buffer_free(tmp_buf);
-
- } else if(buffer->n_used > 0){
- arg = (char*) apr_pstrdup(p, buffer->buf);
-
- } else {
- arg = NULL;
- }
-
- buffer_free(buffer);
- }
- }
-
-
- osrfLogDebug(OSRF_LOG_MARK, "gateway done mangling post data");
-
- if( !arg || !arg[0] ) { /* we received no request */
- return NULL;
- }
-
-
- osrfLogDebug(OSRF_LOG_MARK, "parsing URL params from post/get request data: %s", arg);
- int sanity = 0;
- while( arg && (val = ap_getword(p, (const char**) &arg, '&'))) {
-
- key = ap_getword(r->pool, (const char**) &val, '=');
- if(!key || !key[0])
- break;
-
- ap_unescape_url((char*)key);
- ap_unescape_url((char*)val);
-
- osrfLogDebug(OSRF_LOG_MARK, "parsed URL params %s=%s", key, val);
-
- string_array_add(sarray, key);
- string_array_add(sarray, val);
-
- if( sanity++ > 1000 ) {
- osrfLogError(OSRF_LOG_MARK,
- "Parsing URL params failed sanity check: 1000 iterations");
- string_array_destroy(sarray);
- return NULL;
- }
-
- }
-
- if(sarray)
- osrfLogDebug(OSRF_LOG_MARK,
- "Apache tools parsed %d params key/values", sarray->size / 2 );
-
- return sarray;
-}
-
-
-
-string_array* apacheGetParamKeys(string_array* params) {
- if(params == NULL) return NULL;
- string_array* sarray = init_string_array(12);
- int i;
- osrfLogDebug(OSRF_LOG_MARK, "Fetching URL param keys");
- for( i = 0; i < params->size; i++ )
- string_array_add(sarray, string_array_get_string(params, i++));
- return sarray;
-}
-
-string_array* apacheGetParamValues(string_array* params, char* key) {
-
- if(params == NULL || key == NULL) return NULL;
- string_array* sarray = init_string_array(12);
-
- osrfLogDebug(OSRF_LOG_MARK, "Fetching URL values for key %s", key);
- int i;
- for( i = 0; i < params->size; i++ ) {
- char* nkey = string_array_get_string(params, i++);
- if(key && !strcmp(nkey, key))
- string_array_add(sarray, string_array_get_string(params, i));
- }
- return sarray;
-}
-
-
-char* apacheGetFirstParamValue(string_array* params, char* key) {
- if(params == NULL || key == NULL) return NULL;
-
- int i;
- osrfLogDebug(OSRF_LOG_MARK, "Fetching first URL value for key %s", key);
- for( i = 0; i < params->size; i++ ) {
- char* nkey = string_array_get_string(params, i++);
- if(key && !strcmp(nkey, key))
- return strdup(string_array_get_string(params, i));
- }
-
- return NULL;
-}
-
-
-int apacheDebug( char* msg, ... ) {
- VA_LIST_TO_STRING(msg);
- fprintf(stderr, "%s\n", VA_BUF);
- fflush(stderr);
- return 0;
-}
-
-
-int apacheError( char* msg, ... ) {
- VA_LIST_TO_STRING(msg);
- fprintf(stderr, "%s\n", VA_BUF);
- fflush(stderr);
- return HTTP_INTERNAL_SERVER_ERROR;
-}
-
-
-/* taken more or less directly from O'Reillly - Writing Apache Modules in Perl and C */
-/* needs updating...
-
-apr_table_t* apacheParseCookies(request_rec *r) {
-
- const char *data = apr_table_get(r->headers_in, "Cookie");
- osrfLogDebug(OSRF_LOG_MARK, "Loaded cookies: %s", data);
-
- apr_table_t* cookies;
- const char *pair;
- if(!data) return NULL;
-
- cookies = apr_make_table(r->pool, 4);
- while(*data && (pair = ap_getword(r->pool, &data, ';'))) {
- const char *name, *value;
- if(*data == ' ') ++data;
- name = ap_getword(r->pool, &pair, '=');
- while(*pair && (value = ap_getword(r->pool, &pair, '&'))) {
- ap_unescape_url((char *)value);
- apr_table_add(cookies, name, value);
- }
- }
-
- return cookies;
-}
-
-*/
-
-
+++ /dev/null
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_protocol.h"
-//#include "apr_compat.h"
-#include "apr_strings.h"
-#include "apr_reslist.h"
-#include "http_log.h"
-
-
-#include "opensrf/string_array.h"
-#include "opensrf/utils.h"
-#include "opensrf/log.h"
-
-#ifndef APACHE_TOOLS_H
-#define APACHE_TOOLS_H
-
-#define APACHE_TOOLS_MAX_POST_SIZE 10485760 /* 10 MB */
-
-
-/* parses apache URL params (GET and POST).
- Returns a string_array of the form [ key, val, key, val, ...]
- Returns NULL if there are no params */
-string_array* apacheParseParms(request_rec* r);
-
-/* provide the params string array, and this will generate a
- string of array of param keys
- the returned string_array most be freed by the caller
- */
-string_array* apacheGetParamKeys(string_array* params);
-
-/* provide the params string array and a key name, and
- this will provide the value found for that key
- the returned string_array most be freed by the caller
- */
-string_array* apacheGetParamValues(string_array* params, char* key);
-
-/* returns the first value found for the given param.
- char* must be freed by the caller */
-char* apacheGetFirstParamValue(string_array* params, char* key);
-
-/* Writes msg to stderr, flushes stderr, and returns 0 */
-int apacheDebug( char* msg, ... );
-
-/* Writes to stderr, flushe stderr, and returns HTTP_INTERNAL_SERVER_ERROR;
- */
-int apacheError( char* msg, ... );
-
-/*
- * Creates an apache table* of cookie name / value pairs
- */
-/*
-apr_table_t* apacheParseCookies(request_rec *r);
-*/
-
-
-#endif
+++ /dev/null
-#!/usr/bin/perl
-use strict;
-use lib '../perlmods/';
-
-my $map = {};
-eval "
- use lib '../../../Open-ILS/src/perlmods/';
- use OpenILS::Utils::Fieldmapper;
-";
-$map = $Fieldmapper::fieldmap unless ($@);
-
-
-if(!$ARGV[1]) {
- print "usage: $0 <header_file> <source_file>\n";
- exit;
-}
-
-warn "Generating fieldmapper-c code...\n";
-
-
-print $ARGV[0] . "\n";
-print $ARGV[1] . "\n";
-
-open(HEADER, ">$ARGV[0]");
-open(SOURCE, ">$ARGV[1]");
-
-warn "Generating fieldmapper-c code...\n";
-
-print HEADER <<C;
-#ifndef _TOXML_H_
-#define _TOXML_H_
-
-char* json_string_to_xml(char*);
-
-#endif
-C
-
-print SOURCE <<C;
-
-#include <string.h>
-
-/* and the JSON parser, so we can read the response we're XMLizing */
-#include <string.h>
-#include <stdio.h>
-#include "objson/object.h"
-#include "objson/json_parser.h"
-#include "opensrf/utils.h"
-
-char* json_string_to_xml(char*);
-void _rest_xml_output(growing_buffer*, object*, char*, int, int);
-char * _lookup_fm_field(char*,int);
-char* _escape_xml (char*);
-
-char* json_string_to_xml(char* content) {
- object * obj;
- growing_buffer * res_xml;
- char * output;
- int i;
-
- obj = json_parse_string( content );
- res_xml = buffer_init(1024);
-
- if (!obj)
- return NULL;
-
- buffer_add(res_xml, "<response>");
-
- if(obj->is_array) {
- for( i = 0; i!= obj->size; i++ ) {
- _rest_xml_output(res_xml, obj->get_index(obj,i), NULL, 0,0);
- }
- } else {
- _rest_xml_output(res_xml, obj, NULL, 0,0);
- }
-
- buffer_add(res_xml, "</response>");
-
- output = buffer_data(res_xml);
- buffer_free(res_xml);
- free_object(obj);
-
- return output;
-}
-
-char* _escape_xml (char* text) {
- char* out;
- growing_buffer* b = buffer_init(256);
- int len = strlen(text);
- int i;
- for (i = 0; i < len; i++) {
- if (text[i] == '&')
- buffer_add(b,"&");
- else if (text[i] == '<')
- buffer_add(b,"<");
- else if (text[i] == '>')
- buffer_add(b,">");
- else
- buffer_add_char(b,text[i]);
- }
- out = buffer_data(b);
- buffer_free(b);
- return out;
-}
-
-void _rest_xml_output(growing_buffer* buf, object* obj, char * fm_class, int fm_index, int notag) {
- char * tag;
- int i;
-
- if(!obj) return;
-
- if (obj->classname)
- notag = 1;
-
- if(fm_class) {
- tag = _lookup_fm_field(fm_class,fm_index);
- } else {
- tag = strdup("datum");
- }
-
-
- /* add class hints if we have a class name */
- if(obj->classname) {
- if(obj->is_null) {
- buffer_fadd(buf,"<%s><Object class_hint=\\\"%s\\\"/></%s>", tag, obj->classname, tag);
- return;
- } else {
- buffer_fadd(buf,"<%s><Object class_hint=\\\"%s\\\">", tag, obj->classname);
- }
- }
-
-
- /* now add the data */
- if(obj->is_null) {
- if (!notag)
- buffer_fadd(buf, "<%s/>",tag);
- } else if(obj->is_bool && obj->bool_value) {
- if (notag)
- buffer_add(buf, "true");
- else
- buffer_fadd(buf, "<%s>true</%s>",tag,tag);
-
- } else if(obj->is_bool && ! obj->bool_value) {
- if (notag)
- buffer_add(buf, "false");
- else
- buffer_fadd(buf, "<%s>false</%s>",tag,tag);
-
- } else if (obj->is_string) {
- if (notag) {
- char * t = _escape_xml(obj->string_data);
- buffer_add(buf,t);
- free(t);
- } else {
- char * t = _escape_xml(obj->string_data);
- buffer_fadd(buf,"<%s>%s</%s>",tag,t,tag);
- free(t);
- }
-
- } else if(obj->is_number) {
-
- if (notag)
- buffer_fadd(buf,"%ld",obj->num_value);
- else
- buffer_fadd(buf,"<%s>%ld</%s>",tag,obj->num_value,tag);
-
-
- } else if(obj->is_double) {
- if (notag)
- buffer_fadd(buf,"%f",tag,obj->double_value,tag);
- else
- buffer_fadd(buf,"<%s>%f</%s>",tag,obj->double_value,tag);
-
-
- } else if (obj->is_array) {
- if (!notag) {
- if(!fm_class)
- buffer_add(buf,"<array>");
- else
- buffer_fadd(buf,"<%s>",tag);
- }
-
- for( i = 0; i!= obj->size; i++ ) {
- _rest_xml_output(buf, obj->get_index(obj,i), obj->classname, i,0);
- }
-
- if (!notag) {
- if(!fm_class)
- buffer_add(buf,"</array>");
- else
- buffer_fadd(buf,"</%s>",tag);
- }
-
- } else if (obj->is_hash) {
-
- if (!notag) {
- if(!fm_class)
- buffer_add(buf,"<hash>");
- else
- buffer_fadd(buf,"<%s>",tag);
- }
-
- object_iterator* itr = new_iterator(obj);
- object_node* tmp;
- while( (tmp = itr->next(itr)) ) {
- if (notag) {
- buffer_fadd(buf,"<%s>",tmp->key);
- } else {
- buffer_add(buf,"<pair>");
- buffer_fadd(buf,"<key>%s</key><value>",tmp->key);
- }
-
- _rest_xml_output(buf, tmp->item, NULL,0,notag);
-
- if (notag) {
- buffer_fadd(buf,"</%s>",tmp->key);
- } else {
- buffer_add(buf,"</value></pair>");
- }
- }
- free_iterator(itr);
-
- if (!notag) {
- if(!fm_class)
- buffer_add(buf,"</hash>");
- else
- buffer_fadd(buf,"</%s>",tag);
- }
-
- }
-
- if (obj->classname)
- buffer_fadd(buf,"</Object></%s>",tag);
-
- free(tag);
-}
-
-char * _lookup_fm_field(char * class, int pos) {
-
-C
-
-print SOURCE " if (class == NULL) return NULL;";
-
-for my $object (keys %$map) {
-
- my $short_name = $map->{$object}->{hint};
-
- print SOURCE <<" C";
-
- else if (!strcmp(class, "$short_name")) {
- switch (pos) {
- C
-
- for my $field (keys %{$map->{$object}->{fields}}) {
- my $position = $map->{$object}->{fields}->{$field}->{position};
-
- print SOURCE <<" C";
- case $position:
- return strdup("$field");
- break;
- C
- }
- print SOURCE " }\n";
- print SOURCE " }\n";
-}
-print SOURCE ' return strdup("datum");'."\n";
-print SOURCE "}\n";
-
-close HEADER;
-close SOURCE;
-
-warn "done\n";
-
+++ /dev/null
-#include "apachetools.h"
-#include "opensrf/osrf_app_session.h"
-#include "opensrf/osrf_system.h"
-#include "opensrf/osrfConfig.h"
-#include "objson/object.h"
-#include "objson/json2xml.h"
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <unistd.h>
-
-
-#define MODULE_NAME "osrf_json_gateway_module"
-#define GATEWAY_CONFIG "OSRFGatewayConfig"
-#define CONFIG_CONTEXT "gateway"
-
-#define GATEWAY_DEFAULT_CONFIG "/openils/conf/opensrf_core.xml"
-
-
-/* our config structure */
-typedef struct {
- char* configfile; /* our bootstrap config file */
-} osrf_json_gateway_config;
-
-module AP_MODULE_DECLARE_DATA osrf_json_gateway_module;
-
-char* osrf_json_gateway_config_file = NULL;
-int bootstrapped = 0;
-int numserved = 0;
-osrfStringArray* allowedServices = NULL;
-
-static const char* osrf_json_gateway_set_config(cmd_parms *parms, void *config, const char *arg) {
- osrf_json_gateway_config *cfg;
- cfg = ap_get_module_config(parms->server->module_config, &osrf_json_gateway_module);
- cfg->configfile = (char*) arg;
- osrf_json_gateway_config_file = (char*) arg;
- return NULL;
-}
-
-/* tell apache about our commands */
-static const command_rec osrf_json_gateway_cmds[] = {
- AP_INIT_TAKE1( GATEWAY_CONFIG, osrf_json_gateway_set_config,
- NULL, RSRC_CONF, "osrf json gateway config file"),
- {NULL}
-};
-
-/* build the config object */
-static void* osrf_json_gateway_create_config( apr_pool_t* p, server_rec* s) {
- osrf_json_gateway_config* cfg = (osrf_json_gateway_config*)
- apr_palloc(p, sizeof(osrf_json_gateway_config));
- cfg->configfile = GATEWAY_DEFAULT_CONFIG;
- return (void*) cfg;
-}
-
-
-static void osrf_json_gateway_child_init(apr_pool_t *p, server_rec *s) {
-
- char* cfg = osrf_json_gateway_config_file;
- char buf[32];
- memset(buf, 0x0, 32);
- int t = time(NULL);
- snprintf(buf, 32, "%d", t);
-
- if( ! osrfSystemBootstrapClientResc( cfg, CONFIG_CONTEXT, buf ) ) {
- ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
- "Unable to Bootstrap OpenSRF Client with config %s..", cfg);
- return;
- }
-
- bootstrapped = 1;
- allowedServices = osrfNewStringArray(8);
- osrfLogInfo(OSRF_LOG_MARK, "Bootstrapping gateway child for requests");
- osrfConfigGetValueList( NULL, allowedServices, "/services/service" );
-
- int i;
- for( i = 0; i < allowedServices->size; i++ ) {
- ap_log_error( APLOG_MARK, APLOG_DEBUG, 0, s,
- "allowed service: %s\n", osrfStringArrayGetString(allowedServices, i));
- }
-}
-
-static int osrf_json_gateway_method_handler (request_rec *r) {
-
- /* make sure we're needed first thing*/
- if (strcmp(r->handler, MODULE_NAME )) return DECLINED;
-
- osrfLogDebug(OSRF_LOG_MARK, "osrf gateway: entered request handler");
-
- /* verify we are connected */
- if( !bootstrapped || !osrf_system_get_transport_client()) {
- ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r, "Cannot process request "
- "because the OpenSRF JSON gateway has not been bootstrapped...");
- usleep( 100000 ); /* 100 milliseconds */
- exit(1);
- }
-
- osrfLogSetAppname("osrf_json_gw");
-
- char* service = NULL; /* service to connect to */
- char* method = NULL; /* method to perform */
- char* format = NULL; /* method to perform */
- char* a_l = NULL; /* request api level */
- int isXML = 0;
- int api_level = 1;
-
- r->allowed |= (AP_METHOD_BIT << M_GET);
- r->allowed |= (AP_METHOD_BIT << M_POST);
-
- osrfLogDebug(OSRF_LOG_MARK, "osrf gateway: parsing URL params");
- string_array* mparams = NULL;
- string_array* params = apacheParseParms(r); /* free me */
- service = apacheGetFirstParamValue( params, "service" );
- method = apacheGetFirstParamValue( params, "method" );
- format = apacheGetFirstParamValue( params, "format" );
- a_l = apacheGetFirstParamValue( params, "api_level" );
- mparams = apacheGetParamValues( params, "param" ); /* free me */
-
- /* set the user defined timeout value */
- int timeout = 60;
- char* tout = apacheGetFirstParamValue( params, "timeout" ); /* request timeout in seconds */
- if( tout ) {
- timeout = atoi(tout);
- osrfLogDebug(OSRF_LOG_MARK, "Client supplied timeout of %d", timeout);
- }
-
-
- if (a_l)
- api_level = atoi(a_l);
-
- if (format && !strcasecmp(format, "xml" )) {
- isXML = 1;
- ap_set_content_type(r, "application/xml");
- } else {
- ap_set_content_type(r, "text/plain");
- }
-
- int ret = OK;
-
- if(!(service && method) ||
- !osrfStringArrayContains(allowedServices, service)) {
-
- osrfLogError(OSRF_LOG_MARK,
- "Service [%s] not found or not allowed", service);
- ret = HTTP_NOT_FOUND;
-
- } else {
-
- /* This will log all heaers to the apache error log
- const apr_array_header_t* arr = apr_table_elts(r->headers_in);
- const void* ptr;
-
- while( (ptr = apr_array_pop(arr)) ) {
- apr_table_entry_t* e = (apr_table_entry_t*) ptr;
- fprintf(stderr, "Table entry: %s : %s\n", e->key, e->val );
- }
- fflush(stderr);
- */
-
- osrfAppSession* session = osrf_app_client_session_init(service);
-
- double starttime = get_timestamp_millis();
- int req_id = osrf_app_session_make_req( session, NULL, method, api_level, mparams );
-
-
- if( req_id == -1 ) {
- osrfLogError(OSRF_LOG_MARK, "I am unable to communcate with opensrf..going away...");
- /* we don't want to spawn an intense re-forking storm
- * if there is no jabber server.. so give it some time before we die */
- usleep( 100000 ); /* 100 milliseconds */
- exit(1);
- }
-
-
- /* ----------------------------------------------------------------- */
- /* log all requests to the activity log */
- const char* authtoken = apr_table_get(r->headers_in, "X-OILS-Authtoken");
- if(!authtoken) authtoken = "";
- growing_buffer* act = buffer_init(128);
- buffer_fadd(act, "[%s] [%s] %s %s", r->connection->remote_ip, authtoken, service, method );
- char* str; int i = 0;
- while( (str = osrfStringArrayGetString(mparams, i++)) ) {
- if( i == 1 ) {
- OSRF_BUFFER_ADD(act, " ");
- OSRF_BUFFER_ADD(act, str);
- } else {
- OSRF_BUFFER_ADD(act, ", ");
- OSRF_BUFFER_ADD(act, str);
- }
- }
-
- osrfLogActivity( OSRF_LOG_MARK, act->buf );
- buffer_free(act);
- /* ----------------------------------------------------------------- */
-
-
- osrf_message* omsg = NULL;
-
- int statuscode = 200;
-
- /* kick off the object */
- if (isXML)
- ap_rputs("<response xmlns=\"http://opensrf.org/-/namespaces/gateway/v1\"><payload>", r);
- else
- ap_rputs("{\"payload\":[", r);
-
- int morethan1 = 0;
- char* statusname = NULL;
- char* statustext = NULL;
- char* output = NULL;
-
- while((omsg = osrfAppSessionRequestRecv( session, req_id, timeout ))) {
-
- statuscode = omsg->status_code;
- jsonObject* res;
-
- if( ( res = osrfMessageGetResult(omsg)) ) {
-
- if (isXML) {
- output = jsonObjectToXML( res );
- } else {
- output = jsonObjectToJSON( res );
- if( morethan1 ) ap_rputs(",", r); /* comma between JSON array items */
- }
- ap_rputs(output, r);
- free(output);
- morethan1 = 1;
-
- } else {
-
- if( statuscode > 299 ) { /* the request returned a low level error */
- statusname = omsg->status_name ? strdup(omsg->status_name) : strdup("Unknown Error");
- statustext = omsg->status_text ? strdup(omsg->status_text) : strdup("No Error Message");
- osrfLogError( OSRF_LOG_MARK, "Gateway received error: %s", statustext );
- }
- }
-
- osrf_message_free(omsg);
- if(statusname) break;
- }
-
- double duration = get_timestamp_millis() - starttime;
- osrfLogDebug(OSRF_LOG_MARK, "gateway request took %f seconds", duration);
-
-
- if (isXML)
- ap_rputs("</payload>", r);
- else
- ap_rputs("]",r); /* finish off the payload array */
-
- if(statusname) {
-
- /* add a debug field if the request died */
- ap_log_rerror( APLOG_MARK, APLOG_INFO, 0, r,
- "OpenSRF JSON Request returned error: %s -> %s", statusname, statustext );
- int l = strlen(statusname) + strlen(statustext) + 32;
- char buf[l];
- bzero(buf,l);
-
- if (isXML)
- snprintf( buf, l, "<debug>\"%s : %s\"</debug>", statusname, statustext );
-
- else {
- char bb[l];
- bzero(bb, l);
- snprintf(bb, l, "%s : %s", statusname, statustext);
- jsonObject* tmp = jsonNewObject(bb);
- char* j = jsonObjectToJSON(tmp);
- snprintf( buf, l, ",\"debug\": %s", j);
- free(j);
- jsonObjectFree(tmp);
- }
-
- ap_rputs(buf, r);
-
- free(statusname);
- free(statustext);
- }
-
- /* insert the status code */
- char buf[32];
- bzero(buf,32);
-
- if (isXML)
- snprintf(buf, 32, "<status>%d</status>", statuscode );
- else
- snprintf(buf, 32, ",\"status\":%d", statuscode );
-
- ap_rputs( buf, r );
-
- if (isXML)
- ap_rputs("</response>", r);
- else
- ap_rputs( "}", r ); /* finish off the object */
-
- osrf_app_session_destroy(session);
- }
-
- osrfLogInfo(OSRF_LOG_MARK, "Completed processing service=%s, method=%s", service, method);
- string_array_destroy(params);
- string_array_destroy(mparams);
-
- osrfLogDebug(OSRF_LOG_MARK, "Gateway served %d requests", ++numserved);
- osrfLogClearXid();
-
- return ret;
-}
-
-
-
-static void osrf_json_gateway_register_hooks (apr_pool_t *p) {
- ap_hook_handler(osrf_json_gateway_method_handler, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_child_init(osrf_json_gateway_child_init,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-
-module AP_MODULE_DECLARE_DATA osrf_json_gateway_module = {
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- osrf_json_gateway_create_config,
- NULL,
- osrf_json_gateway_cmds,
- osrf_json_gateway_register_hooks,
-};
-
-
-
-
+++ /dev/null
-#JAVA_LIBS = .:lib:ext/json-jdk1.5-2007-05-01.jar:ext/wstx-asl-3.2.1.jar:ext/stax-api-1.0.1.jar:ext/xercesImpl-1.4.4-2.jar
-JAVA_LIBDIR = .lib
-JAVAC=javac -J-Xmx256m
-JAVA=java -Xmx256m
-JAVA_LIBS = .:$(JAVA_LIBDIR):ext/json-jdk1.5-2007-05-01.jar:ext/wstx-lgpl-3.2.1.jar:ext/stax-api-1.0.1.jar:ext/java_memcached-release_1.5.1.jar
-JAVA_SRC = \
- org/opensrf/net/xmpp/*.java \
- org/opensrf/util/*.java \
- org/opensrf/*.java \
- org/opensrf/test/*.java
-
-all:
- mkdir -p $(JAVA_LIBDIR)
- $(JAVAC) -d $(JAVA_LIBDIR) -cp $(JAVA_LIBS) $(JAVA_SRC) 2>&1
-
-# only prints the first 30 lines of errors
-slim:
- mkdir -p $(JAVA_LIBDIR)
- $(JAVAC) -d $(JAVA_LIBDIR) -cp $(JAVA_LIBS) $(JAVA_SRC) 2>&1 | head -n 30
- @echo -e "\nTruncating at 30 lines"
-
-check:
- mkdir -p $(JAVA_LIBDIR)
- $(JAVAC) -Xlint:unchecked -d $(JAVA_LIBDIR) -cp $(JAVA_LIBS) $(JAVA_SRC) 2>&1 | head -n 30
- @echo -e "\nTruncating at 30 lines"
-
-run:
- @$(JAVA) -cp $(JAVA_LIBS) $(JAVA_EXE) $(JAVA_ARGS)
-
-deps:
- mkdir -p ext
- wget 'http://woodstox.codehaus.org/stax-api-1.0.1.jar' -O ext/stax-api-1.0.1.jar
- wget 'http://woodstox.codehaus.org/3.2.1/wstx-lgpl-3.2.1.jar' -O ext/wstx-lgpl-3.2.1.jar
- wget 'http://img.whalin.com/memcached/jdk5/standard/java_memcached-release_1.5.1.jar' -O ext/java_memcached-release_1.5.1.jar
- mkdir -p .tmp && cd .tmp && wget 'http://www.json.org/java/json.zip' && unzip json.zip
- $(JAVAC) -d $(JAVA_LIBDIR) .tmp/org/json/*.java
-
-docs:
- find . -name *.java > files;
- javadoc -classpath $(JAVA_LIBS) -d doc @files;
- rm files;
-
-clean:
- rm -r $(JAVA_LIBDIR)
-
-
-
+++ /dev/null
-package org.opensrf;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.ArrayList;
-import java.util.Random;
-import java.util.Arrays;
-
-import org.opensrf.util.*;
-import org.opensrf.net.xmpp.*;
-
-
-/**
- * Models an OpenSRF client session.
- */
-public class ClientSession extends Session {
-
- /** The remote service to communicate with */
- private String service;
- /** OpenSRF domain */
- private String domain;
- /** Router name */
- private String router;
-
- /**
- * original remote node. The current remote node will change based
- * on server responses. This is used to reset the remote node to
- * its original state.
- */
- private String origRemoteNode;
- /** The next request id */
- private int nextId;
- /** The requests this session has sent */
- private Map<Integer, Request> requests;
-
- /**
- * Creates a new client session. Initializes the
- * @param service The remove service.
- */
- public ClientSession(String service) throws ConfigException {
- this.service = service;
-
- /** generate the remote node string */
- domain = (String) Config.global().getFirst("/domains/domain");
- router = Config.global().getString("/router_name");
- setRemoteNode(router + "@" + domain + "/" + service);
- origRemoteNode = getRemoteNode();
-
-
- /** create a random thread */
- long time = new Date().getTime();
- Random rand = new Random(time);
- setThread(rand.nextInt()+""+rand.nextInt()+""+time);
-
- nextId = 0;
- requests = new HashMap<Integer, Request>();
- cacheSession();
- }
-
- /**
- * Creates a new request to send to our remote service.
- * @param method The method API name
- * @param params The list of method parameters
- * @return The request object.
- */
- public Request request(String method, List<Object> params) throws SessionException {
- return request(new Request(this, nextId++, method, params));
- }
-
- /**
- * Creates a new request to send to our remote service.
- * @param method The method API name
- * @param params The list of method parameters
- * @return The request object.
- */
- public Request request(String method, Object[] params) throws SessionException {
- return request(new Request(this, nextId++, method, Arrays.asList(params)));
- }
-
-
- /**
- * Creates a new request to send to our remote service.
- * @param method The method API name
- * @return The request object.
- */
- public Request request(String method) throws SessionException {
- return request(new Request(this, nextId++, method));
- }
-
-
- private Request request(Request req) throws SessionException {
- if(getConnectState() != ConnectState.CONNECTED)
- resetRemoteId();
- requests.put(new Integer(req.getId()), req);
- req.send();
- return req;
- }
-
-
- /**
- * Resets the remoteNode to its original state.
- */
- public void resetRemoteId() {
- setRemoteNode(origRemoteNode);
- }
-
-
- /**
- * Pushes a response onto the result queue of the appropriate request.
- * @param msg The received RESULT Message
- */
- public void pushResponse(Message msg) {
-
- Request req = findRequest(msg.getId());
- if(req == null) {
- /** LOG that we've received a result to a non-existant request */
- return;
- }
- OSRFObject payload = (OSRFObject) msg.get("payload");
-
- /** build a result and push it onto the request's result queue */
- req.pushResponse(
- new Result(
- payload.getString("status"),
- payload.getInt("statusCode"),
- payload.get("content")
- )
- );
- }
-
- public Request findRequest(int reqId) {
- return requests.get(new Integer(reqId));
- }
-
- /**
- * Removes a request for this session's request set
- */
- public void cleanupRequest(int reqId) {
- requests.remove(new Integer(reqId));
- }
-
- public void setRequestComplete(int reqId) {
- Request req = findRequest(reqId);
- if(req == null) return;
- req.setComplete();
- }
-}
-
+++ /dev/null
-package org.opensrf;
-import org.opensrf.util.*;
-
-
-public class Message implements OSRFSerializable {
-
- /** Message types */
- public static final String REQUEST = "REQUEST";
- public static final String STATUS = "STATUS";
- public static final String RESULT = "RESULT";
- public static final String CONNECT = "CONNECT";
- public static final String DISCONNECT = "DISCONNECT";
-
- /** Message ID. This number is used to relate requests to responses */
- private int id;
- /** type of message. */
- private String type;
- /** message payload */
- private Object payload;
-
- /** Create a registry for the osrfMessage object */
- private static OSRFRegistry registry =
- OSRFRegistry.registerObject(
- "osrfMessage",
- OSRFRegistry.WireProtocol.HASH,
- new String[] {"threadTrace", "type", "payload"});
-
- /**
- * @param id This message's ID
- * @param type The type of message
- */
- public Message(int id, String type) {
- setId(id);
- setString(type);
- }
-
- /**
- * @param id This message's ID
- * @param type The type of message
- * @param payload The message payload
- */
- public Message(int id, String type, Object payload) {
- this(id, type);
- setPayload(payload);
- }
-
-
- public int getId() {
- return id;
- }
- public String getType() {
- return type;
- }
- public Object getPayload() {
- return payload;
- }
- public void setId(int id) {
- this.id = id;
- }
- public void setString(String type) {
- this.type = type;
- }
- public void setPayload(Object p) {
- payload = p;
- }
-
- /**
- * Implements the generic get() API required by OSRFSerializable
- */
- public Object get(String field) {
- if("threadTrace".equals(field))
- return getId();
- if("type".equals(field))
- return getType().toString();
- if("payload".equals(field))
- return getPayload();
- return null;
- }
-
- /**
- * @return The osrfMessage registry.
- */
- public OSRFRegistry getRegistry() {
- return registry;
- }
-}
-
-
+++ /dev/null
-package org.opensrf;
-import java.util.List;
-import java.util.ArrayList;
-import org.opensrf.util.*;
-
-
-public class Method extends OSRFObject {
-
- /** The method API name */
- private String name;
- /** The ordered list of method params */
- private List<Object> params;
-
- /** Create a registry for the osrfMethod object */
- private static OSRFRegistry registry =
- OSRFRegistry.registerObject(
- "osrfMethod",
- OSRFRegistry.WireProtocol.HASH,
- new String[] {"method", "params"});
-
- /**
- * @param name The method API name
- */
- public Method(String name) {
- this.name = name;
- this.params = new ArrayList<Object>(8);
- }
-
- /**
- * @param name The method API name
- * @param params The ordered list of params
- */
- public Method(String name, List<Object> params) {
- this.name = name;
- this.params = params;
- }
-
- /**
- * @return The method API name
- */
- public String getName() {
- return name;
- }
- /**
- * @return The ordered list of params
- */
- public List<Object> getParams() {
- return params;
- }
-
- /**
- * Pushes a new param object onto the set of params
- * @param p The new param to add to the method.
- */
- public void addParam(Object p) {
- this.params.add(p);
- }
-
- /**
- * Implements the generic get() API required by OSRFSerializable
- */
- public Object get(String field) {
- if("method".equals(field))
- return getName();
- if("params".equals(field))
- return getParams();
- return null;
- }
-
- /**
- * @return The osrfMethod registry.
- */
- public OSRFRegistry getRegistry() {
- return registry;
- }
-
-}
-
+++ /dev/null
-package org.opensrf;
-
-/**
- * Thrown when the server responds with a method exception.
- */
-public class MethodException extends Exception {
- public MethodException(String info) {
- super(info);
- }
-}
-
+++ /dev/null
-package org.opensrf;
-import java.util.Queue;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.List;
-import java.util.Date;
-import org.opensrf.net.xmpp.XMPPException;
-
-public class Request {
-
- /** This request's controlling session */
- private ClientSession session;
- /** The method */
- private Method method;
- /** The ID of this request */
- private int id;
- /** Queue of Results */
- private Queue<Result> resultQueue;
- /** If true, the receive timeout for this request should be reset */
- private boolean resetTimeout;
-
- /** If true, the server has indicated that this request is complete. */
- private boolean complete;
-
- /**
- * @param ses The controlling session for this request.
- * @param id This request's ID.
- * @param method The requested method.
- */
- public Request(ClientSession ses, int id, Method method) {
- this.session = ses;
- this.id = id;
- this.method = method;
- resultQueue = new ConcurrentLinkedQueue<Result>();
- complete = false;
- resetTimeout = false;
- }
-
- /**
- * @param ses The controlling session for this request.
- * @param id This request's ID.
- * @param methodName The requested method's API name.
- */
- public Request(ClientSession ses, int id, String methodName) {
- this(ses, id, new Method(methodName));
- }
-
- /**
- * @param ses The controlling session for this request.
- * @param id This request's ID.
- * @param methodName The requested method's API name.
- * @param params The list of request params
- */
- public Request(ClientSession ses, int id, String methodName, List<Object> params) {
- this(ses, id, new Method(methodName, params));
- }
-
- /**
- * Sends the request to the server.
- */
- public void send() throws SessionException {
- session.send(new Message(id, Message.REQUEST, method));
- }
-
- /**
- * Receives the next result for this request. This method
- * will wait up to the specified number of milliseconds for
- * a response.
- * @param millis Number of milliseconds to wait for a result. If
- * negative, this method will wait indefinitely.
- * @return The result or null if none arrives in time
- */
- public Result recv(long millis) throws SessionException, MethodException {
-
- Result result = null;
-
- if(millis < 0 && !complete) {
- /** wait potentially forever for a result to arrive */
- session.waitForMessage(millis);
- if((result = resultQueue.poll()) != null)
- return result;
-
- } else {
-
- while(millis >= 0 && !complete) {
-
- /** wait up to millis milliseconds for a result. waitForMessage()
- * will return if a response to any request arrives, so we keep track
- * of how long we've been waiting in total for a response to
- * this request
- */
- long start = new Date().getTime();
- session.waitForMessage(millis);
- millis -= new Date().getTime() - start;
- if((result = resultQueue.poll()) != null)
- return result;
- }
- }
-
- return null;
- }
-
- /**
- * Pushes a result onto the result queue
- * @param result The result to push
- */
- public void pushResponse(Result result) {
- resultQueue.offer(result);
- }
-
- /**
- * @return This request's ID
- */
- public int getId() {
- return id;
- }
-
- /**
- * Removes this request from the controlling session's request set
- */
- public void cleanup() {
- session.cleanupRequest(id);
- }
-
- /** Sets this request as complete */
- public void setComplete() {
- complete = true;
- }
-}
+++ /dev/null
-package org.opensrf;
-import org.opensrf.util.*;
-
-
-/**
- * Models a single result from a method request.
- */
-public class Result implements OSRFSerializable {
-
- /** Method result content */
- private Object content;
- /** Name of the status */
- private String status;
- /** Status code number */
- private int statusCode;
-
-
- /** Register this object */
- private static OSRFRegistry registry =
- OSRFRegistry.registerObject(
- "osrfResult",
- OSRFRegistry.WireProtocol.HASH,
- new String[] {"status", "statusCode", "content"});
-
-
- /**
- * @param status The status message for this result
- * @param statusCode The status code
- * @param content The content of the result
- */
- public Result(String status, int statusCode, Object content) {
- this.status = status;
- this.statusCode = statusCode;
- this.content = content;
- }
-
- /**
- * Get status.
- * @return status as String.
- */
- public String getStatus() {
- return status;
- }
-
- /**
- * Set status.
- * @param status the value to set.
- */
- public void setStatus(String status) {
- this.status = status;
- }
-
- /**
- * Get statusCode.
- * @return statusCode as int.
- */
- public int getStatusCode() {
- return statusCode;
- }
-
- /**
- * Set statusCode.
- * @param statusCode the value to set.
- */
- public void setStatusCode(int statusCode) {
- this.statusCode = statusCode;
- }
-
- /**
- * Get content.
- * @return content as Object.
- */
- public Object getContent() {
- return content;
- }
-
- /**
- * Set content.
- * @param content the value to set.
- */
- public void setContent(Object content) {
- this.content = content;
- }
-
- /**
- * Implements the generic get() API required by OSRFSerializable
- */
- public Object get(String field) {
- if("status".equals(field))
- return getStatus();
- if("statusCode".equals(field))
- return getStatusCode();
- if("content".equals(field))
- return getContent();
- return null;
- }
-
- /**
- * @return The osrfMethod registry.
- */
- public OSRFRegistry getRegistry() {
- return registry;
- }
-
-}
-
+++ /dev/null
-package org.opensrf;
-
-/**
- * Models an OpenSRF server session.
- */
-public class ServerSession extends Session {
-}
-
+++ /dev/null
-package org.opensrf;
-import org.opensrf.util.JSONWriter;
-import org.opensrf.net.xmpp.*;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Arrays;
-
-public abstract class Session {
-
- /** Represents the different connection states for a session */
- public enum ConnectState {
- DISCONNECTED,
- CONNECTING,
- CONNECTED
- };
-
- /** local cache of existing sessions */
- private static Map<String, Session>
- sessionCache = new HashMap<String, Session>();
-
- /** the current connection state */
- private ConnectState connectState;
-
- /** The address of the remote party we are communicating with */
- private String remoteNode;
-
- /**
- * The thread is used to link messages to a given session.
- * In other words, each session has a unique thread, and all messages
- * in that session will carry this thread around as an indicator.
- */
- private String thread;
-
- public Session() {
- connectState = ConnectState.DISCONNECTED;
- }
-
- /**
- * Sends a Message to our remoteNode.
- */
- public void send(Message omsg) throws SessionException {
-
- /** construct the XMPP message */
- XMPPMessage xmsg = new XMPPMessage();
- xmsg.setTo(remoteNode);
- xmsg.setThread(thread);
- xmsg.setBody(new JSONWriter(Arrays.asList(new Message[] {omsg})).write());
- XMPPSession ses = XMPPSession.getGlobalSession();
-
- try {
- XMPPSession.getGlobalSession().send(xmsg);
- } catch(XMPPException e) {
- connectState = ConnectState.DISCONNECTED;
- throw new SessionException("Error sending message to " + remoteNode, e);
- }
- }
-
- /**
- * Waits for a message to arrive over the network and passes
- * all received messages to the stack for processing
- * @param millis The number of milliseconds to wait for a message to arrive
- */
- public static void waitForMessage(long millis) throws SessionException, MethodException {
- try {
- Stack.processXMPPMessage(
- XMPPSession.getGlobalSession().recv(millis));
- } catch(XMPPException e) {
- throw new SessionException("Error waiting for message", e);
- }
- }
-
- /**
- * Removes this session from the session cache.
- */
- public void cleanup() {
- sessionCache.remove(thread);
- }
-
- /**
- * Searches for the cached session with the given thread.
- * @param thread The session thread.
- * @return The found session or null.
- */
- public static Session findCachedSession(String thread) {
- return sessionCache.get(thread);
- }
-
- /**
- * Puts this session into session cache.
- */
- protected void cacheSession() {
- sessionCache.put(thread, this);
- }
-
- /**
- * Sets the remote address
- * @param nodeName The name of the remote node.
- */
- public void setRemoteNode(String nodeName) {
- remoteNode = nodeName;
- }
- /**
- * @return The remote node
- */
- public String getRemoteNode() {
- return remoteNode;
- }
-
-
- /**
- * Get thread.
- * @return thread as String.
- */
- public String getThread() {
- return thread;
- }
-
- /**
- * Set thread.
- * @param thread the value to set.
- */
- public void setThread(String thread) {
- this.thread = thread;
- }
-
- /**
- * Get connectState.
- * @return connectState as ConnectState.
- */
- public ConnectState getConnectState() {
- return connectState;
- }
-
- /**
- * Set connectState.
- * @param connectState the value to set.
- */
- public void setConnectState(ConnectState connectState) {
- this.connectState = connectState;
- }
-}
+++ /dev/null
-package org.opensrf;
-/**
- * Used by sessions to indicate communication errors
- */
-public class SessionException extends Exception {
- public SessionException(String info) {
- super(info);
- }
- public SessionException(String info, Throwable cause) {
- super(info, cause);
- }
-}
-
+++ /dev/null
-package org.opensrf;
-import org.opensrf.net.xmpp.XMPPMessage;
-import org.opensrf.util.*;
-import java.util.Date;
-import java.util.List;
-import java.util.Iterator;
-
-
-public class Stack {
-
- public static void processXMPPMessage(XMPPMessage msg) throws MethodException {
-
- if(msg == null) return;
-
- //System.out.println(msg.getBody());
-
- /** fetch this session from the cache */
- Session ses = Session.findCachedSession(msg.getThread());
-
- if(ses == null) {
- /** inbound client request, create a new server session */
- return;
- }
-
- /** parse the JSON message body, which should result in a list of OpenSRF messages */
- List msgList;
-
- try {
- msgList = new JSONReader(msg.getBody()).readArray();
- } catch(JSONException e) {
- /** XXX LOG error */
- e.printStackTrace();
- return;
- }
-
- Iterator itr = msgList.iterator();
-
- OSRFObject obj = null;
- long start = new Date().getTime();
-
- /** cycle through the messages and push them up the stack */
- while(itr.hasNext()) {
-
- /** Construct a Message object from the parsed generic OSRFObject */
- obj = (OSRFObject) itr.next();
-
- processOSRFMessage(
- ses,
- new Message(
- obj.getInt("threadTrace"),
- obj.getString("type"),
- obj.get("payload")
- )
- );
- }
-
- /** LOG the duration */
- }
-
- private static void processOSRFMessage(Session ses, Message msg) throws MethodException {
- if( ses instanceof ClientSession )
- processResponse((ClientSession) ses, msg);
- else
- processRequest((ServerSession) ses, msg);
- }
-
- /**
- * Process a server response
- */
- private static void processResponse(ClientSession session, Message msg) throws MethodException {
- String type = msg.getType();
-
- if(msg.RESULT.equals(type)) {
- session.pushResponse(msg);
- return;
- }
-
- if(msg.STATUS.equals(type)) {
-
- OSRFObject obj = (OSRFObject) msg.getPayload();
- Status stat = new Status(obj.getString("status"), obj.getInt("statusCode"));
- int statusCode = stat.getStatusCode();
- String status = stat.getStatus();
-
- switch(statusCode) {
- case Status.COMPLETE:
- session.setRequestComplete(msg.getId());
- break;
- case Status.NOTFOUND:
- session.setRequestComplete(msg.getId());
- throw new MethodException(status);
- }
- }
- }
-
- /**
- * Process a client request
- */
- private static void processRequest(ServerSession session, Message msg) {
- }
-}
+++ /dev/null
-package org.opensrf;
-import org.opensrf.util.*;
-
-public class Status {
-
- public static final int CONTINUE = 100;
- public static final int OK = 200;
- public static final int ACCEPTED = 202;
- public static final int COMPLETE = 205;
- public static final int REDIRECTED = 307;
- public static final int EST = 400;
- public static final int STATUS_UNAUTHORIZED = 401;
- public static final int FORBIDDEN = 403;
- public static final int NOTFOUND = 404;
- public static final int NOTALLOWED = 405;
- public static final int TIMEOUT = 408;
- public static final int EXPFAILED = 417;
- public static final int INTERNALSERVERERROR = 500;
- public static final int NOTIMPLEMENTED = 501;
- public static final int VERSIONNOTSUPPORTED = 505;
-
- private OSRFRegistry registry = OSRFRegistry.registerObject(
- "osrfConnectStatus",
- OSRFRegistry.WireProtocol.HASH,
- new String[] {"status", "statusCode"});
-
- /** The name of the status */
- String status;
- /** The status code */
- int statusCode;
-
- public Status(String status, int statusCode) {
- this.status = status;
- this.statusCode = statusCode;
- }
-
- public int getStatusCode() {
- return statusCode;
- }
- public String getStatus() {
- return status;
- }
-
- /**
- * Implements the generic get() API required by OSRFSerializable
- */
- public Object get(String field) {
- if("status".equals(field))
- return getStatus();
- if("statusCode".equals(field))
- return new Integer(getStatusCode());
- return null;
- }
-
- /**
- * @return The osrfMessage registry.
- */
- public OSRFRegistry getRegistry() {
- return registry;
- }
-}
-
-
+++ /dev/null
-package org.opensrf;
-
-import org.opensrf.util.*;
-import org.opensrf.net.xmpp.*;
-
-
-public class Sys {
-
- /**
- * Connects to the OpenSRF network so that client sessions may communicate.
- * @param configFile The OpenSRF config file
- * @param configContext Where in the XML document the config chunk lives. This
- * allows an OpenSRF client config chunk to live in XML files where other config
- * information lives.
- */
- public static void bootstrapClient(String configFile, String configContext)
- throws ConfigException, SessionException {
-
- /** create the config parser */
- Config config = new Config(configContext);
- config.parse(configFile);
- Config.setConfig(config); /* set this as the global config */
-
- /** Collect the network connection info from the config */
- String username = config.getString("/username");
- String passwd = config.getString("/passwd");
- String host = (String) config.getFirst("/domains/domain");
- int port = config.getInt("/port");
-
- try {
- /** Connect to the Jabber network */
- XMPPSession xses = new XMPPSession(host, port);
- xses.connect(username, passwd, "test-java"); /* XXX */
- XMPPSession.setGlobalSession(xses);
- } catch(XMPPException e) {
- throw new SessionException("Unable to bootstrap client", e);
- }
- }
-
- /**
- * Shuts down the connection to the opensrf network
- */
- public static void shutdown() {
- XMPPSession.getGlobalSession().disconnect();
- }
-}
-
+++ /dev/null
-package org.opensrf.net.xmpp;
-
-/**
- * Used for XMPP stream/authentication errors
- */
-public class XMPPException extends Exception {
- public XMPPException(String info) {
- super(info);
- }
-}
+++ /dev/null
-package org.opensrf.net.xmpp;
-
-import java.io.*;
-
-/**
- * Models a single XMPP message.
- */
-public class XMPPMessage {
-
- /** Message body */
- private String body;
- /** Message recipient */
- private String to;
- /** Message sender */
- private String from;
- /** Message thread */
- private String thread;
- /** Message xid */
- private String xid;
-
- public XMPPMessage() {
- }
-
- public String getBody() {
- return body;
- }
- public String getTo() {
- return to;
- }
- public String getFrom() {
- return from;
- }
- public String getThread() {
- return thread;
- }
- public String getXid() {
- return xid;
- }
- public void setBody(String body) {
- this.body = body;
- }
- public void setTo(String to) {
- this.to = to;
- }
- public void setFrom(String from) {
- this.from = from;
- }
- public void setThread(String thread) {
- this.thread = thread;
- }
- public void setXid(String xid) {
- this.xid = xid;
- }
-
-
- /**
- * Generates the XML representation of this message.
- */
- public String toXML() {
- StringBuffer sb = new StringBuffer("<message to='");
- escapeXML(to, sb);
- sb.append("' osrf_xid='");
- escapeXML(xid, sb);
- sb.append("'><thread>");
- escapeXML(thread, sb);
- sb.append("</thread><body>");
- escapeXML(body, sb);
- sb.append("</body></message>");
- return sb.toString();
- }
-
-
- /**
- * Escapes non-valid XML characters.
- * @param s The string to escape.
- * @param sb The StringBuffer to append new data to.
- */
- private void escapeXML(String s, StringBuffer sb) {
- if( s == null ) return;
- char c;
- int l = s.length();
- for( int i = 0; i < l; i++ ) {
- c = s.charAt(i);
- switch(c) {
- case '<':
- sb.append("<");
- break;
- case '>':
- sb.append(">");
- break;
- case '&':
- sb.append("&");
- break;
- default:
- sb.append(c);
- }
- }
- }
-}
-
-
+++ /dev/null
-package org.opensrf.net.xmpp;
-
-import javax.xml.stream.*;
-import javax.xml.stream.events.* ;
-import javax.xml.namespace.QName;
-import java.util.Queue;
-import java.io.InputStream;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.Date;
-
-
-/**
- * Slim XMPP Stream reader. This reader only understands enough XMPP
- * to handle logins and recv messages. It's implemented as a StAX parser.
- * @author Bill Erickson, Georgia Public Library Systems
- */
-public class XMPPReader implements Runnable {
-
- /** Queue of received messages. */
- private Queue<XMPPMessage> msgQueue;
- /** Incoming XMPP XML stream */
- private InputStream inStream;
- /** Current message body */
- private StringBuffer msgBody;
- /** Current message thread */
- private StringBuffer msgThread;
- /** Current message status */
- private StringBuffer msgStatus;
- /** Current message error type */
- private StringBuffer msgErrType;
- /** Current message sender */
- private String msgFrom;
- /** Current message recipient */
- private String msgTo;
- /** Current message error code */
- private int msgErrCode;
-
- /** Where this reader currently is in the document */
- private XMLState xmlState;
-
- /** The current connect state to the XMPP server */
- private XMPPStreamState streamState;
-
-
- /** Used to represent out connection state to the XMPP server */
- public static enum XMPPStreamState {
- DISCONNECTED, /* not connected to the server */
- CONNECT_SENT, /* we've sent the initial connect message */
- CONNECT_RECV, /* we've received a response to our connect message */
- AUTH_SENT, /* we've sent an authentication request */
- CONNECTED /* authentication is complete */
- };
-
-
- /** Used to represents where we are in the XML document stream. */
- public static enum XMLState {
- IN_NOTHING,
- IN_BODY,
- IN_THREAD,
- IN_STATUS
- };
-
-
- /**
- * Creates a new reader. Initializes the message queue.
- * Sets the stream state to disconnected, and the xml
- * state to in_nothing.
- * @param inStream the inbound XML stream
- */
- public XMPPReader(InputStream inStream) {
- msgQueue = new ConcurrentLinkedQueue<XMPPMessage>();
- this.inStream = inStream;
- resetBuffers();
- xmlState = XMLState.IN_NOTHING;
- streamState = XMPPStreamState.DISCONNECTED;
- }
-
- /**
- * Change the connect state and notify that a core
- * event has occurred.
- */
- protected void setXMPPStreamState(XMPPStreamState state) {
- streamState = state;
- notifyCoreEvent();
- }
-
- /**
- * @return The current stream state of the reader
- */
- public XMPPStreamState getXMPPStreamState() {
- return streamState;
- }
-
-
- /**
- * @return The next message in the queue, or null
- */
- public XMPPMessage popMessageQueue() {
- return (XMPPMessage) msgQueue.poll();
- }
-
-
- /**
- * Initializes the message buffers
- */
- private void resetBuffers() {
- msgBody = new StringBuffer();
- msgThread = new StringBuffer();
- msgStatus = new StringBuffer();
- msgErrType = new StringBuffer();
- msgFrom = "";
- msgTo = "";
- }
-
-
- /**
- * Notifies the waiting thread that a core event has occurred.
- * Each reader should have exactly one dependent session thread.
- */
- private synchronized void notifyCoreEvent() {
- notify();
- }
-
-
- /**
- * Waits up to timeout milliseconds for a core event to occur.
- * Also, having a message already waiting in the queue
- * constitutes a core event.
- * @param timeout The number of milliseconds to wait. If
- * timeout is negative, waits potentially forever.
- * @return The number of milliseconds in wait
- */
- public synchronized long waitCoreEvent(long timeout) {
-
- if(msgQueue.peek() != null || timeout == 0) return 0;
-
- long start = new Date().getTime();
- try{
- if(timeout < 0) wait();
- else wait(timeout);
- } catch(InterruptedException ie) {}
-
- return new Date().getTime() - start;
- }
-
-
-
- /** Kickoff the thread */
- public void run() {
- read();
- }
-
-
- /**
- * Parses XML data from the provided XMPP stream.
- */
- public void read() {
-
- try {
-
- XMLInputFactory factory = XMLInputFactory.newInstance();
-
- /** disable as many unused features as possible to speed up the parsing */
- factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.FALSE);
- factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
- factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE);
- factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.FALSE);
- factory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
-
- /** create the stream reader */
- XMLStreamReader reader = factory.createXMLStreamReader(inStream);
- int eventType;
-
- while(reader.hasNext()) {
- /** cycle through the XML events */
-
- eventType = reader.next();
-
- switch(eventType) {
-
- case XMLEvent.START_ELEMENT:
- handleStartElement(reader);
- break;
-
- case XMLEvent.CHARACTERS:
- switch(xmlState) {
- case IN_BODY:
- msgBody.append(reader.getText());
- break;
- case IN_THREAD:
- msgThread.append(reader.getText());
- break;
- case IN_STATUS:
- msgStatus.append(reader.getText());
- break;
- }
- break;
-
- case XMLEvent.END_ELEMENT:
- xmlState = XMLState.IN_NOTHING;
- if("message".equals(reader.getName().toString())) {
-
- /** build a message and add it to the message queue */
- XMPPMessage msg = new XMPPMessage();
- msg.setFrom(msgFrom);
- msg.setTo(msgTo);
- msg.setBody(msgBody.toString());
- msg.setThread(msgThread.toString());
-
- msgQueue.offer(msg);
- resetBuffers();
- notifyCoreEvent();
- }
- break;
- }
- }
-
- } catch(javax.xml.stream.XMLStreamException se) {
- /* XXX log an error */
- xmlState = XMLState.IN_NOTHING;
- streamState = XMPPStreamState.DISCONNECTED;
- notifyCoreEvent();
- }
- }
-
-
- /**
- * Handles the start_element event.
- */
- private void handleStartElement(XMLStreamReader reader) {
-
- String name = reader.getName().toString();
-
- if("message".equals(name)) {
- xmlState = XMLState.IN_BODY;
-
- /** add a special case for the opensrf "router_from" attribute */
- String rf = reader.getAttributeValue(null, "router_from");
- if( rf != null )
- msgFrom = rf;
- else
- msgFrom = reader.getAttributeValue(null, "from");
- msgTo = reader.getAttributeValue(null, "to");
- return;
- }
-
- if("body".equals(name)) {
- xmlState = XMLState.IN_BODY;
- return;
- }
-
- if("thread".equals(name)) {
- xmlState = XMLState.IN_THREAD;
- return;
- }
-
- if("stream:stream".equals(name)) {
- setXMPPStreamState(XMPPStreamState.CONNECT_RECV);
- return;
- }
-
- if("iq".equals(name)) {
- if("result".equals(reader.getAttributeValue(null, "type")))
- setXMPPStreamState(XMPPStreamState.CONNECTED);
- return;
- }
-
- if("status".equals(name)) {
- xmlState = XMLState.IN_STATUS;
- return;
- }
-
- if("stream:error".equals(name)) {
- setXMPPStreamState(XMPPStreamState.DISCONNECTED);
- return;
- }
-
- if("error".equals(name)) {
- msgErrType.append(reader.getAttributeValue(null, "type"));
- msgErrCode = Integer.parseInt(reader.getAttributeValue(null, "code"));
- setXMPPStreamState(XMPPStreamState.DISCONNECTED);
- return;
- }
- }
-}
-
-
-
-
+++ /dev/null
-package org.opensrf.net.xmpp;
-
-import java.io.*;
-import java.net.Socket;
-
-
-/**
- * Represents a single XMPP session. Sessions are responsible for writing to
- * the stream and for managing a stream reader.
- */
-public class XMPPSession {
-
- /** Initial jabber message */
- public static final String JABBER_CONNECT =
- "<stream:stream to='%s' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>";
-
- /** Basic auth message */
- public static final String JABBER_BASIC_AUTH =
- "<iq id='123' type='set'><query xmlns='jabber:iq:auth'>" +
- "<username>%s</username><password>%s</password><resource>%s</resource></query></iq>";
-
- public static final String JABBER_DISCONNECT = "</stream:stream>";
-
- /** jabber domain */
- private String host;
- /** jabber port */
- private int port;
- /** jabber username */
- private String username;
- /** jabber password */
- private String password;
- /** jabber resource */
- private String resource;
-
- /** XMPP stream reader */
- XMPPReader reader;
- /** Fprint-capable socket writer */
- PrintWriter writer;
- /** Raw socket output stream */
- OutputStream outStream;
- /** The raw socket */
- Socket socket;
-
- /** The process-wide session. All communication occurs
- * accross this single connection */
- private static XMPPSession globalSession;
-
-
- /**
- * Creates a new session.
- * @param host The jabber domain
- * @param port The jabber port
- */
- public XMPPSession( String host, int port ) {
- this.host = host;
- this.port = port;
- }
-
- /**
- * Returns the global, process-wide session
- */
- public static XMPPSession getGlobalSession() {
- return globalSession;
- }
-
- /**
- * Sets the global, process-wide section
- */
- public static void setGlobalSession(XMPPSession ses) {
- globalSession = ses;
- }
-
-
- /** true if this session is connected to the server */
- public boolean connected() {
- return (
- reader != null &&
- reader.getXMPPStreamState() ==
- XMPPReader.XMPPStreamState.CONNECTED);
- }
-
-
- /**
- * Connects to the network.
- * @param username The jabber username
- * @param password The jabber password
- * @param resource The Jabber resource
- */
- public void connect(String username, String password, String resource) throws XMPPException {
-
- this.username = username;
- this.password = password;
- this.resource = resource;
-
- try {
- /* open the socket and associated streams */
- socket = new Socket(host, port);
-
- /** the session maintains control over the output stream */
- outStream = socket.getOutputStream();
- writer = new PrintWriter(outStream, true);
-
- /** pass the input stream to the reader */
- reader = new XMPPReader(socket.getInputStream());
-
- } catch(IOException ioe) {
- throw new
- XMPPException("unable to communicate with host " + host + " on port " + port);
- }
-
- /* build the reader thread */
- Thread thread = new Thread(reader);
- thread.setDaemon(true);
- thread.start();
-
- /* send the initial jabber message */
- sendConnect();
- reader.waitCoreEvent(10000);
- if( reader.getXMPPStreamState() != XMPPReader.XMPPStreamState.CONNECT_RECV )
- throw new XMPPException("unable to connect to jabber server");
-
- /* send the basic auth message */
- sendBasicAuth(); /* XXX add support for other auth mechanisms */
- reader.waitCoreEvent(10000);
- if(!connected())
- throw new XMPPException("Authentication failed");
- }
-
- /** Sends the initial jabber message */
- private void sendConnect() {
- writer.printf(JABBER_CONNECT, host);
- reader.setXMPPStreamState(XMPPReader.XMPPStreamState.CONNECT_SENT);
- }
-
- /** Send the basic auth message */
- private void sendBasicAuth() {
- writer.printf(JABBER_BASIC_AUTH, username, password, resource);
- reader.setXMPPStreamState(XMPPReader.XMPPStreamState.AUTH_SENT);
- }
-
-
- /**
- * Sends an XMPPMessage.
- * @param msg The message to send.
- */
- public synchronized void send(XMPPMessage msg) throws XMPPException {
- checkConnected();
- try {
- String xml = msg.toXML();
- outStream.write(xml.getBytes());
- } catch (Exception e) {
- throw new XMPPException(e.toString());
- }
- }
-
-
- /**
- * @throws XMPPException if we are no longer connected.
- */
- private void checkConnected() throws XMPPException {
- if(!connected())
- throw new XMPPException("Disconnected stream");
- }
-
-
- /**
- * Receives messages from the network.
- * @param timeout Maximum number of milliseconds to wait for a message to arrive.
- * If timeout is negative, this method will wait indefinitely.
- * If timeout is 0, this method will not block at all, but will return a
- * message if there is already a message available.
- */
- public XMPPMessage recv(long timeout) throws XMPPException {
-
- XMPPMessage msg;
-
- if(timeout < 0) {
-
- while(true) { /* wait indefinitely for a message to arrive */
- reader.waitCoreEvent(timeout);
- msg = reader.popMessageQueue();
- if( msg != null ) return msg;
- checkConnected();
- }
-
- } else {
-
- while(timeout >= 0) { /* wait at most 'timeout' milleseconds for a message to arrive */
- timeout -= reader.waitCoreEvent(timeout);
- msg = reader.popMessageQueue();
- if( msg != null ) return msg;
- checkConnected();
- }
- }
-
- return null;
- }
-
-
- /**
- * Disconnects from the jabber server and closes the socket
- */
- public void disconnect() {
- try {
- outStream.write(JABBER_DISCONNECT.getBytes());
- socket.close();
- } catch(Exception e) {}
- }
-}
-
+++ /dev/null
-package org.opensrf.test;
-import org.opensrf.*;
-import org.opensrf.util.*;
-import java.util.Date;
-import java.util.List;
-import java.util.ArrayList;
-import java.io.PrintStream;
-
-
-public class MathBench {
-
- public static void main(String args[]) throws Exception {
-
- PrintStream out = System.out;
-
- if(args.length < 2) {
- out.println("usage: java org.opensrf.test.MathBench <osrfConfig> <numIterations>");
- return;
- }
-
- /** connect to the opensrf network */
- Sys.bootstrapClient(args[0], "/config/opensrf");
-
- /** how many iterations */
- int count = Integer.parseInt(args[1]);
-
- /** create the client session */
- ClientSession session = new ClientSession("opensrf.math");
-
- /** params are 1,2 */
- List<Object> params = new ArrayList<Object>();
- params.add(new Integer(1));
- params.add(new Integer(2));
-
- Request request;
- Result result;
- long start;
- double total = 0;
-
- for(int i = 0; i < count; i++) {
-
- start = new Date().getTime();
-
- /** create (and send) the request */
- request = session.request("add", params);
-
- /** wait up to 3 seconds for a response */
- result = request.recv(3000);
-
- /** collect the round-trip time */
- total += new Date().getTime() - start;
-
- if(result.getStatusCode() == Status.OK) {
- out.print("+");
- } else {
- out.println("\nrequest failed");
- out.println("status = " + result.getStatus());
- out.println("status code = " + result.getStatusCode());
- }
-
- /** remove this request from the session's request set */
- request.cleanup();
-
- if((i+1) % 100 == 0) /** print 100 responses per line */
- out.println(" [" + (i+1) + "]");
- }
-
- out.println("\nAverage request time is " + (total/count) + " ms");
-
- /** remove this session from the global session cache */
- session.cleanup();
-
- /** disconnect from the opensrf network */
- Sys.shutdown();
- }
-}
-
-
-
+++ /dev/null
-package org.opensrf.test;
-import org.opensrf.*;
-import org.opensrf.util.*;
-import java.util.List;
-import java.util.ArrayList;
-
-public class TestCache {
- public static void main(String args[]) throws Exception {
-
- /**
- * args is a list of string like so: server:port server2:port server3:port ...
- */
-
- Cache.initCache(args);
- Cache cache = new Cache();
-
- cache.set("key1", "HI, MA!");
- cache.set("key2", "HI, MA! 2");
- cache.set("key3", "HI, MA! 3");
-
- System.out.println("got key1 = " + (String) cache.get("key1"));
- System.out.println("got key2 = " + (String) cache.get("key2"));
- System.out.println("got key3 = " + (String) cache.get("key3"));
- }
-}
-
-
+++ /dev/null
-package org.opensrf.test;
-import org.opensrf.*;
-import org.opensrf.util.*;
-import java.util.Map;
-import java.util.Date;
-import java.util.List;
-import java.util.ArrayList;
-import java.io.PrintStream;
-
-
-public class TestClient {
-
- public static void main(String args[]) throws Exception {
-
- PrintStream out = System.out;
- if(args.length < 3) {
- out.println( "usage: org.opensrf.test.TestClient "+
- "<osrfConfigFile> <service> <method> [<JSONparam1>, <JSONparam2>]");
- return;
- }
-
- Sys.bootstrapClient(args[0], "/config/opensrf");
- String service = args[1];
- String method = args[2];
-
- /** build the client session and send the request */
- ClientSession session = new ClientSession(service);
- List<Object> params = new ArrayList<Object>();
- JSONReader reader;
-
- for(int i = 3; i < args.length; i++) /* add the params */
- params.add(new JSONReader(args[i]).read());
-
-
- Result result;
-
- long start = new Date().getTime();
- Request request = session.request(method, params);
-
- while( (result = request.recv(60000)) != null ) {
- /** loop over the results and print the JSON version of the content */
-
- if(result.getStatusCode() != 200) { /* make sure the request succeeded */
- out.println("status = " + result.getStatus());
- out.println("status code = " + result.getStatusCode());
- continue;
- }
-
- out.println("result JSON: " + new JSONWriter(result.getContent()).write());
- }
- out.println("Request round trip took: " + (new Date().getTime() - start) + " ms.");
- }
-}
-
-
-
+++ /dev/null
-package org.opensrf.test;
-import org.opensrf.*;
-import org.opensrf.util.*;
-
-public class TestConfig {
- public static void main(String args[]) throws Exception {
- Config config = new Config("");
- config.parse(args[0]);
- Config.setConfig(config);
- System.out.println(config);
- System.out.println("");
-
- for(int i = 1; i < args.length; i++)
- System.out.println("Found config value: " + args[i] + ": " + Config.global().get(args[i]));
- }
-}
+++ /dev/null
-package org.opensrf.test;
-
-import org.opensrf.*;
-import org.opensrf.util.*;
-import java.util.*;
-
-public class TestJSON {
-
- public static void main(String args[]) throws Exception {
-
- Map<String,Object> map = new HashMap<String,Object>();
- map.put("key1", "value1");
- map.put("key2", "value2");
- map.put("key3", "value3");
- map.put("key4", "athe\u0301s");
- map.put("key5", null);
-
- List<Object> list = new ArrayList<Object>(16);
- list.add(new Integer(1));
- list.add(new Boolean(true));
- list.add("WATER");
- list.add(null);
- map.put("key6", list);
-
- System.out.println(new JSONWriter(map).write() + "\n");
-
- String[] fields = {"isnew", "name", "shortname", "ill_address"};
- OSRFRegistry.registerObject("aou", OSRFRegistry.WireProtocol.ARRAY, fields);
-
- OSRFObject obj = new OSRFObject(OSRFRegistry.getRegistry("aou"));
- obj.put("name", "athens clarke county");
- obj.put("ill_address", new Integer(1));
- obj.put("shortname", "ARL-ATH");
-
- map.put("key7", obj);
- list.add(obj);
- System.out.println(new JSONWriter(map).write() + "\n");
-
-
- Message m = new Message(1, Message.REQUEST);
- Method method = new Method("opensrf.settings.host_config.get");
- method.addParam("app07.dev.gapines.org");
- m.setPayload(method);
-
- String s = new JSONWriter(m).write();
- System.out.println(s + "\n");
-
- Object o = new JSONReader(s).read();
- System.out.println("Read+Wrote: " + new JSONWriter(o).write());
- }
-}
+++ /dev/null
-package org.opensrf.test;
-import org.opensrf.*;
-import org.opensrf.util.*;
-
-public class TestSettings {
- public static void main(String args[]) throws Exception {
- Sys.bootstrapClient(args[0], "/config/opensrf");
- SettingsClient client = SettingsClient.instance();
- String lang = client.getString("/apps/opensrf.settings/language");
- String impl = client.getString("/apps/opensrf.settings/implementation");
- System.out.println("opensrf.settings language = " + lang);
- System.out.println("opensrf.settings implementation = " + impl);
- }
-}
+++ /dev/null
-package org.opensrf.test;
-
-import org.opensrf.net.xmpp.XMPPReader;
-import org.opensrf.net.xmpp.XMPPMessage;
-import org.opensrf.net.xmpp.XMPPSession;
-
-public class TestXMPP {
-
- /**
- * Connects to the jabber server and waits for inbound messages.
- * If a recipient is provided, a small message is sent to the recipient.
- */
- public static void main(String args[]) throws Exception {
-
- String host;
- int port;
- String username;
- String password;
- String resource;
- String recipient;
-
- try {
- host = args[0];
- port = Integer.parseInt(args[1]);
- username = args[2];
- password = args[3];
- resource = args[4];
-
- } catch(ArrayIndexOutOfBoundsException e) {
- System.err.println("usage: org.opensrf.test.TestXMPP <host> <port> <username> <password> <resource> [<recipient>]");
- return;
- }
-
- XMPPSession session = new XMPPSession(host, port);
- session.connect(username, password, resource);
-
- XMPPMessage msg;
-
- if( args.length == 6 ) {
-
- /** they specified a recipient */
-
- recipient = args[5];
- msg = new XMPPMessage();
- msg.setTo(recipient);
- msg.setThread("test-thread");
- msg.setBody("Hello, from java-xmpp");
- System.out.println("Sending message to " + recipient);
- session.send(msg);
- }
-
- while(true) {
- System.out.println("waiting for message...");
- msg = session.recv(-1); /* wait forever for a message to arrive */
- System.out.println("got message: " + msg.toXML());
- }
- }
-}
-
-
-
-
-
+++ /dev/null
-package org.opensrf.util;
-import com.danga.MemCached.*;
-import java.util.List;
-
-/**
- * Memcache client
- */
-public class Cache extends MemCachedClient {
-
- public Cache() {
- super();
- setCompressThreshold(4096); /* ?? */
- }
-
- /**
- * Initializes the cache client
- * @param serverList Array of server:port strings specifying the
- * set of memcache servers this client will talk to
- */
- public static void initCache(String[] serverList) {
- SockIOPool pool = SockIOPool.getInstance();
- pool.setServers(serverList);
- pool.initialize();
- com.danga.MemCached.Logger logger =
- com.danga.MemCached.Logger.getLogger(MemCachedClient.class.getName());
- logger.setLevel(logger.LEVEL_ERROR);
- }
-
- /**
- * Initializes the cache client
- * @param serverList List of server:port strings specifying the
- * set of memcache servers this client will talk to
- */
- public static void initCache(List<String> serverList) {
- initCache(serverList.toArray(new String[]{}));
- }
-}
-
+++ /dev/null
-package org.opensrf.util;
-
-import org.json.*;
-import java.util.Map;
-import java.util.List;
-
-
-/**
- * Config reader and accesor module. This module reads an XML config file,
- * then loads the file into an internal config, whose values may be accessed
- * by xpath-style lookup paths.
- */
-public class Config {
-
- /** The globl config instance */
- private static Config config;
- /** The object form of the parsed config */
- private Map configObject;
- /**
- * The log parsing context. This is used as a prefix to the
- * config item search path. This allows config XML chunks to
- * be inserted into arbitrary XML files.
- */
- private String context;
-
- public static Config global() {
- return config;
- }
-
-
- /**
- * @param context The config context
- */
- public Config(String context) {
- this.context = context;
- }
-
- /**
- * Sets the global config object.
- * @param c The config object to use.
- */
- public static void setGlobalConfig(Config c) {
- config = c;
- }
-
- /**
- * Parses an XML config file.
- * @param filename The path to the file to parse.
- */
- public void parse(String filename) throws ConfigException {
- try {
- String xml = Utils.fileToString(filename);
- JSONObject jobj = XML.toJSONObject(xml);
- configObject = (Map) new JSONReader(jobj.toString()).readObject();
- } catch(Exception e) {
- throw new ConfigException("Error parsing config", e);
- }
- }
-
- public static void setConfig(Config conf) {
- config = conf;
- }
-
- public void setConfigObject(Map config) {
- this.configObject = config;
- }
-
- protected Map getConfigObject() {
- return this.configObject;
- }
-
-
- /**
- * Returns the configuration value found at the requested path.
- * @param path The search path
- * @return The config value, or null if no value exists at the given path.
- * @throws ConfigException thrown if nothing is found at the path
- */
- public String getString(String path) throws ConfigException {
- try {
- return (String) get(path);
- } catch(Exception e) {
- throw new
- ConfigException("No config string found at " + path);
- }
- }
-
- /**
- * Gets the int value at the given path
- * @param path The search path
- */
- public int getInt(String path) throws ConfigException {
- try {
- return Integer.parseInt(getString(path));
- } catch(Exception e) {
- throw new
- ConfigException("No config int found at " + path);
- }
- }
-
- /**
- * Returns the configuration object found at the requested path.
- * @param path The search path
- * @return The config value
- * @throws ConfigException thrown if nothing is found at the path
- */
- public Object get(String path) throws ConfigException {
- try {
- Object obj = Utils.findPath(configObject, context + path);
- if(obj == null)
- throw new ConfigException("");
- return obj;
- } catch(Exception e) {
- e.printStackTrace();
- throw new ConfigException("No config object found at " + path);
- }
- }
-
- /**
- * Returns the first item in the list found at the given path. If
- * no list is found, ConfigException is thrown.
- * @param path The search path
- */
- public Object getFirst(String path) throws ConfigException {
- Object obj = get(path);
- if(obj instanceof List)
- return ((List) obj).get(0);
- return obj;
- }
-
-
- /**
- * Returns the config as a JSON string
- */
- public String toString() {
- return new JSONWriter(configObject).write();
- }
-}
-
+++ /dev/null
-package org.opensrf.util;
-
-/**
- * Thrown by the Config module when a user requests a configuration
- * item that does not exist
- */
-public class ConfigException extends Exception {
- public ConfigException(String info) {
- super(info);
- }
- public ConfigException(String info, Throwable t) {
- super(info, t);
- }
-}
+++ /dev/null
-package org.opensrf.util;
-/**
- * Used to indicate JSON parsing errors
- */
-public class JSONException extends Exception {
- public JSONException(String s) {
- super(s);
- }
-}
+++ /dev/null
-package org.opensrf.util;
-
-import java.io.*;
-import java.util.*;
-
-import org.json.JSONTokener;
-import org.json.JSONObject;
-import org.json.JSONArray;
-
-
-/**
- * JSON utilities.
- */
-public class JSONReader {
-
- /** Special OpenSRF serializable object netClass key */
- public static final String JSON_CLASS_KEY = "__c";
-
- /** Special OpenSRF serializable object payload key */
- public static final String JSON_PAYLOAD_KEY = "__p";
-
- /** The JSON string to parser */
- private String json;
-
- /**
- * @param json The JSON to parse
- */
- public JSONReader(String json) {
- this.json = json;
- }
-
- /**
- * Parses JSON and creates an object.
- * @return The resulting object which may be a List,
- * Map, Number, String, Boolean, or null
- */
- public Object read() throws JSONException {
- JSONTokener tk = new JSONTokener(json);
- try {
- return readSubObject(tk.nextValue());
- } catch(org.json.JSONException e) {
- throw new JSONException(e.toString());
- }
- }
-
- /**
- * Assumes that a JSON array will be read. Returns
- * the resulting array as a list.
- */
- public List<?> readArray() throws JSONException {
- Object o = read();
- try {
- return (List<?>) o;
- } catch(Exception e) {
- throw new JSONException("readArray(): JSON cast exception");
- }
- }
-
- /**
- * Assumes that a JSON object will be read. Returns
- * the resulting object as a map.
- */
- public Map<?,?> readObject() throws JSONException {
- Object o = read();
- try {
- return (Map<?,?>) o;
- } catch(Exception e) {
- throw new JSONException("readObject(): JSON cast exception");
- }
- }
-
-
- /**
- * Recurse through the object and turn items into maps, lists, etc.
- */
- private Object readSubObject(Object obj) throws JSONException {
-
- if( obj == null ||
- obj instanceof String ||
- obj instanceof Number ||
- obj instanceof Boolean)
- return obj;
-
- try {
-
- if( obj instanceof JSONObject ) {
-
- /* read objects */
- String key;
- JSONObject jobj = (JSONObject) obj;
- Map<String, Object> map = new HashMap<String, Object>();
-
- for( Iterator e = jobj.keys(); e.hasNext(); ) {
- key = (String) e.next();
-
- /* we encoutered the special class key */
- if( JSON_CLASS_KEY.equals(key) )
- return buildRegisteredObject(
- (String) jobj.get(key), jobj.get(JSON_PAYLOAD_KEY));
-
- /* we encountered the data key */
- if( JSON_PAYLOAD_KEY.equals(key) )
- return buildRegisteredObject(
- (String) jobj.get(JSON_CLASS_KEY), jobj.get(key));
-
- map.put(key, readSubObject(jobj.get(key)));
- }
- return map;
- }
-
- if ( obj instanceof JSONArray ) {
-
- JSONArray jarr = (JSONArray) obj;
- int length = jarr.length();
- List<Object> list = new ArrayList<Object>(length);
-
- for( int i = 0; i < length; i++ )
- list.add(readSubObject(jarr.get(i)));
- return list;
-
- }
-
- } catch(org.json.JSONException e) {
-
- throw new JSONException(e.toString());
- }
-
- return null;
- }
-
-
-
- /**
- * Builds an OSRFObject map registered OSRFHash object based on the JSON object data.
- * @param netClass The network class hint for this object.
- * @param paylaod The actual object on the wire.
- */
- private OSRFObject buildRegisteredObject(
- String netClass, Object payload) throws JSONException {
-
- OSRFRegistry registry = OSRFRegistry.getRegistry(netClass);
- OSRFObject obj = new OSRFObject(registry);
-
- try {
- if( payload instanceof JSONArray ) {
- JSONArray jarr = (JSONArray) payload;
-
- /* for each array item, instert the item into the hash. the hash
- * key is found by extracting the fields array from the registered
- * object at the current array index */
- String fields[] = registry.getFields();
- for( int i = 0; i < jarr.length(); i++ ) {
- obj.put(fields[i], readSubObject(jarr.get(i)));
- }
-
- } else if( payload instanceof JSONObject ) {
-
- /* since this is a hash, simply copy the data over */
- JSONObject jobj = (JSONObject) payload;
- String key;
- for( Iterator e = jobj.keys(); e.hasNext(); ) {
- key = (String) e.next();
- obj.put(key, readSubObject(jobj.get(key)));
- }
- }
-
- } catch(org.json.JSONException e) {
- throw new JSONException(e.toString());
- }
-
- return obj;
- }
-}
-
-
-
+++ /dev/null
-package org.opensrf.util;
-
-import java.io.*;
-import java.util.*;
-
-
-/**
- * JSONWriter
- */
-public class JSONWriter {
-
- /** The object to serialize to JSON */
- private Object obj;
-
- /**
- * @param obj The object to encode
- */
- public JSONWriter(Object obj) {
- this.obj = obj;
- }
-
-
- /**
- * Encodes a java object to JSON.
- */
- public String write() {
- StringBuffer sb = new StringBuffer();
- write(sb);
- return sb.toString();
- }
-
-
-
- /**
- * Encodes a java object to JSON.
- * Maps (HashMaps, etc.) are encoded as JSON objects.
- * Iterable's (Lists, etc.) are encoded as JSON arrays
- */
- public void write(StringBuffer sb) {
- write(obj, sb);
- }
-
- /**
- * Encodes the object as JSON into the provided buffer
- */
- public void write(Object obj, StringBuffer sb) {
-
- /** JSON null */
- if(obj == null) {
- sb.append("null");
- return;
- }
-
- /** JSON string */
- if(obj instanceof String) {
- sb.append('"');
- Utils.escape((String) obj, sb);
- sb.append('"');
- return;
- }
-
- /** JSON number */
- if(obj instanceof Number) {
- sb.append(obj.toString());
- return;
- }
-
- /** JSON array */
- if(obj instanceof Iterable) {
- encodeJSONArray((Iterable) obj, sb);
- return;
- }
-
- /** OpenSRF serializable objects */
- if(obj instanceof OSRFSerializable) {
- encodeOSRFSerializable((OSRFSerializable) obj, sb);
- return;
- }
-
- /** JSON object */
- if(obj instanceof Map) {
- encodeJSONObject((Map) obj, sb);
- return;
- }
-
- /** JSON boolean */
- if(obj instanceof Boolean) {
- sb.append((((Boolean) obj).booleanValue() ? "true" : "false"));
- return;
- }
- }
-
-
- /**
- * Encodes a List as a JSON array
- */
- private void encodeJSONArray(Iterable iterable, StringBuffer sb) {
- Iterator itr = iterable.iterator();
- sb.append("[");
- boolean some = false;
-
- while(itr.hasNext()) {
- some = true;
- write(itr.next(), sb);
- sb.append(',');
- }
-
- /* remove the trailing comma if the array has any items*/
- if(some)
- sb.deleteCharAt(sb.length()-1);
- sb.append("]");
- }
-
-
- /**
- * Encodes a Map as a JSON object
- */
- private void encodeJSONObject(Map map, StringBuffer sb) {
- Iterator itr = map.keySet().iterator();
- sb.append("{");
- Object key = null;
-
- while(itr.hasNext()) {
- key = itr.next();
- write(key, sb);
- sb.append(':');
- write(map.get(key), sb);
- sb.append(',');
- }
-
- /* remove the trailing comma if the object has any items*/
- if(key != null)
- sb.deleteCharAt(sb.length()-1);
- sb.append("}");
- }
-
-
- /**
- * Encodes a network-serializable OpenSRF object
- */
- private void encodeOSRFSerializable(OSRFSerializable obj, StringBuffer sb) {
-
- OSRFRegistry reg = obj.getRegistry();
- String[] fields = reg.getFields();
- Map<String, Object> map = new HashMap<String, Object>();
- map.put(JSONReader.JSON_CLASS_KEY, reg.getNetClass());
-
- if( reg.getWireProtocol() == OSRFRegistry.WireProtocol.ARRAY ) {
-
- /** encode arrays as lists */
- List<Object> list = new ArrayList<Object>(fields.length);
- for(String s : fields)
- list.add(obj.get(s));
- map.put(JSONReader.JSON_PAYLOAD_KEY, list);
-
- } else {
-
- /** encode hashes as maps */
- Map<String, Object> subMap = new HashMap<String, Object>();
- for(String s : fields)
- subMap.put(s, obj.get(s));
- map.put(JSONReader.JSON_PAYLOAD_KEY, subMap);
-
- }
-
- /** now serialize the encoded object */
- write(map, sb);
- }
-}
-
-
-
+++ /dev/null
-package org.opensrf.util;
-
-import java.util.Map;
-import java.util.HashMap;
-
-
-/**
- * Generic OpenSRF network-serializable object. This allows
- * access to object fields.
- */
-public class OSRFObject extends HashMap<String, Object> implements OSRFSerializable {
-
- /** This objects registry */
- private OSRFRegistry registry;
-
- public OSRFObject() {
- }
-
- /**
- * Creates a new object with the provided registry
- */
- public OSRFObject(OSRFRegistry reg) {
- this();
- registry = reg;
- }
-
- /**
- * @return This object's registry
- */
- public OSRFRegistry getRegistry() {
- return registry;
- }
-
- /**
- * Implement get() to fulfill our contract with OSRFSerializable
- */
- public Object get(String field) {
- return super.get(field);
- }
-
- /** Returns the string value found at the given field */
- public String getString(String field) {
- return (String) get(field);
- }
-
- /** Returns the int value found at the given field */
- public int getInt(String field) {
- Object o = get(field);
- if(o instanceof String)
- return Integer.parseInt((String) o);
- return ((Integer) get(field)).intValue();
- }
-}
+++ /dev/null
-package org.opensrf.util;
-
-import java.util.Map;
-import java.util.HashMap;
-
-
-/**
- * Manages the registration of OpenSRF network-serializable objects.
- * A serializable object has a class "hint" (called netClass within) which
- * describes the type of object. Each object also has a set of field names
- * for accessing/mutating object properties. Finally, objects have a
- * serialization wire protocol. Currently supported protocols are HASH
- * and ARRAY.
- */
-public class OSRFRegistry {
-
-
- /**
- * Global collection of registered net objects.
- * Maps netClass names to registries.
- */
- private static HashMap<String, OSRFRegistry>
- registry = new HashMap<String, OSRFRegistry>();
-
-
- /** Serialization types for registered objects */
- public enum WireProtocol {
- ARRAY, HASH
- };
-
-
- /** Array of field names for this registered object */
- String fields[];
- /** The wire protocol for this object */
- WireProtocol wireProtocol;
- /** The network class for this object */
- String netClass;
-
- /**
- * Returns the array of field names
- */
- public String[] getFields() {
- return this.fields;
- }
-
-
- /**
- * Registers a new object.
- * @param netClass The net class for this object
- * @param wireProtocol The object's wire protocol
- * @param fields An array of field names. For objects whose
- * wire protocol is ARRAY, the positions of the field names
- * will be used as the array indices for the fields at serialization time
- */
- public static OSRFRegistry registerObject(String netClass, WireProtocol wireProtocol, String fields[]) {
- OSRFRegistry r = new OSRFRegistry(netClass, wireProtocol, fields);
- registry.put(netClass, r);
- return r;
- }
-
- /**
- * Returns the registry for the given netclass
- * @param netClass The network class to lookup
- */
- public static OSRFRegistry getRegistry(String netClass) {
- if( netClass == null ) return null;
- return (OSRFRegistry) registry.get(netClass);
- }
-
-
- /**
- * @param field The name of the field to lookup
- * @return the index into the fields array of the given field name.
- */
- public int getFieldIndex(String field) {
- for( int i = 0; i < fields.length; i++ )
- if( fields[i].equals(field) )
- return i;
- return -1;
- }
-
- /** Returns the wire protocol of this object */
- public WireProtocol getWireProtocol() {
- return this.wireProtocol;
- }
-
- /** Returns the netClass ("hint") of this object */
- public String getNetClass() {
- return this.netClass;
- }
-
- /**
- * Creates a new registry object.
- * @param netClass The network class/hint
- * @param wireProtocol The wire protocol
- * @param fields The array of field names. For array-based objects,
- * the fields array must be sorted in accordance with the sorting
- * of the objects in the array.
- */
- public OSRFRegistry(String netClass, WireProtocol wireProtocol, String fields[]) {
- this.netClass = netClass;
- this.wireProtocol = wireProtocol;
- this.fields = fields;
- }
-}
-
-
+++ /dev/null
-package org.opensrf.util;
-
-/**
- * All network-serializable OpenSRF object must implement this interface.
- */
-public interface OSRFSerializable {
-
- /**
- * Returns the object registry object for the implementing class.
- */
- public abstract OSRFRegistry getRegistry();
-
- /**
- * Returns the object found at the given field
- */
- public abstract Object get(String field);
-}
-
-
+++ /dev/null
-package org.opensrf.util;
-import org.opensrf.*;
-import java.util.Map;
-
-/**
- * Connects to the OpenSRF Settings server to fetch the settings config.
- * Provides a Config interface for fetching settings via path
- */
-public class SettingsClient extends Config {
-
- /** Singleton SettingsClient instance */
- private static SettingsClient client = new SettingsClient();
-
- public SettingsClient() {
- super("");
- }
-
- /**
- * @return The global settings client instance
- */
- public static SettingsClient instance() throws ConfigException {
- if(client.getConfigObject() == null)
- client.fetchConfig();
- return client;
- }
-
- /**
- * Fetches the settings object from the settings server
- */
- private void fetchConfig() throws ConfigException {
-
- ClientSession ses = new ClientSession("opensrf.settings");
- try {
-
- Request req = ses.request(
- "opensrf.settings.host_config.get",
- new String[]{(String)Config.global().getFirst("/domains/domain")});
-
- Result res = req.recv(12000);
- if(res == null) {
- /** throw exception */
- }
- setConfigObject((Map) res.getContent());
-
- } catch(Exception e) {
- throw new ConfigException("Error fetching settings config", e);
-
- } finally {
- ses.cleanup();
- }
- }
-}
-
+++ /dev/null
-package org.opensrf.util;
-
-import java.io.*;
-import java.util.*;
-
-/**
- * Collection of general, static utility methods
- */
-public class Utils {
-
- /**
- * Returns the string representation of a given file.
- * @param filename The file to turn into a string
- */
- public static String fileToString(String filename)
- throws FileNotFoundException, IOException {
-
- StringBuffer sb = new StringBuffer();
- BufferedReader in = new BufferedReader(new FileReader(filename));
- String str;
- while ((str = in.readLine()) != null)
- sb.append(str);
- in.close();
- return sb.toString();
- }
-
-
- /**
- * Escapes a string.
- */
- public static String escape(String string) {
- StringBuffer sb = new StringBuffer();
- escape(string, sb);
- return sb.toString();
- }
-
- /**
- * Escapes a string. Turns bare newlines into \n, etc.
- * Escapes \n, \r, \t, ", \f
- * Encodes non-ascii characters as UTF-8: \u0000
- * @param string The string to escape
- * @param sb The string buffer to write the escaped string into
- */
- public static void escape(String string, StringBuffer sb) {
- int len = string.length();
- String utf;
- char c;
- for( int i = 0; i < len; i++ ) {
- c = string.charAt(i);
- switch (c) {
- case '\\':
- sb.append("\\\\");
- break;
- case '"':
- sb.append("\\\"");
- break;
- case '\b':
- sb.append("\\b");
- break;
- case '\t':
- sb.append("\\t");
- break;
- case '\n':
- sb.append("\\n");
- break;
- case '\f':
- sb.append("\\f");
- break;
- case '\r':
- sb.append("\\r");
- break;
- default:
- if (c < 32 || c > 126 ) {
- /* escape all non-ascii or control characters as UTF-8 */
- utf = "000" + Integer.toHexString(c);
- sb.append("\\u" + utf.substring(utf.length() - 4));
- } else {
- sb.append(c);
- }
- }
- }
- }
-
-
- /**
- * Descends into the map along the given XPATH-style path
- * and returns the object found there.
- * @param path The XPATH-style path to search. Path
- * components are separated by '/' characters.
- * Example: /opensrf/loglevel
- * @return The found object.
- */
-
- public static Object findPath(Map map, String path) {
- String keys[] = path.split("/", -1);
- int i = 0;
- if(path.charAt(0) == '/') i++;
- for(; i < keys.length - 1; i++ )
- map = (Map) map.get(keys[i]);
-
- return map.get(keys[i]);
- }
-}
-
-
-
+++ /dev/null
-// in case we run on an implimentation that doesn't have "undefined";
-var undefined;
-
-function Cast (obj, class_constructor) {
- try {
- if (eval(class_constructor + '["_isfieldmapper"]')) {
- obj = eval("new " + class_constructor + "(obj)");
- }
- } catch( E ) {
- alert( E + "\n");
- } finally {
- return obj;
- }
-}
-
-function JSON2js (json) {
-
- json = String(json).replace( /\/\*--\s*S\w*?\s*?\s+\w+\s*--\*\//g, 'Cast(');
- json = String(json).replace( /\/\*--\s*E\w*?\s*?\s+(\w+)\s*--\*\//g, ', "$1")');
-
- var obj;
- if (json != '') {
- try {
- eval( 'obj = ' + json );
- } catch(E) {
- debug("Error building JSON object with string " + E + "\nString:\n" + json );
- return null;
- }
- }
- return obj;
-}
-
-
-function object2Array(obj) {
- if( obj == null ) return null;
-
- var arr = new Array();
- for( var i = 0; i < obj.length; i++ ) {
- arr[i] = obj[i];
- }
- return arr;
-}
-
-
-function js2JSON(arg) {
- return _js2JSON(arg);
-}
-
-function _js2JSON(arg) {
- var i, o, u, v;
-
- switch (typeof arg) {
- case 'object':
-
- if(arg) {
-
- if (arg._isfieldmapper) { /* magi-c-ast for fieldmapper objects */
-
- if( arg.a.constructor != Array ) {
- var arr = new Array();
- for( var i = 0; i < arg.a.length; i++ ) {
- if( arg.a[i] == null ) {
- arr[i] = null; continue;
- }
-
- if( typeof arg.a[i] != 'object' ) {
- arr[i] = arg.a[i];
-
- } else if( typeof arg.a[i] == 'object'
- && arg.a[i]._isfieldmapper) {
-
- arr[i] = arg.a[i];
-
- } else {
- arr[i] = object2Array(arg.a[i]);
- }
- }
- arg.a = arr;
- }
-
- return "/*--S " + arg.classname + " --*/" + js2JSON(arg.a) + "/*--E " + arg.classname + " --*/";
-
- } else {
-
- if (arg.constructor == Array) {
- o = '';
- for (i = 0; i < arg.length; ++i) {
- v = js2JSON(arg[i]);
- if (o) {
- o += ',';
- }
- if (v !== u) {
- o += v;
- } else {
- o += 'null';
- }
- }
- return '[' + o + ']';
-
- } else if (typeof arg.toString != 'undefined') {
- o = '';
- for (i in arg) {
- v = js2JSON(arg[i]);
- if (v !== u) {
- if (o) {
- o += ',';
- }
- o += js2JSON(i) + ':' + v;
- }
- }
-
- o = '{' + o + '}';
- return o;
-
- } else {
- return;
- }
- }
- }
- return 'null';
-
- case 'unknown':
- case 'number':
- return arg;
-
- case 'undefined':
- case 'function':
- return u;
-
- case 'string':
- default:
- return '"' + String(arg).replace(/(["\\])/g, '\\$1') + '"';
- }
-
-}
+++ /dev/null
-/*
- * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
- * Digest Algorithm, as defined in RFC 1321.
- * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
- * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
- * Distributed under the BSD License
- * See http://pajhome.org.uk/crypt/md5 for more info.
- */
-
-/*
- * Configurable variables. You may need to tweak these to be compatible with
- * the server-side, but the defaults work in most cases.
- */
-var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
-var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
-var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
-
-/*
- * These are the functions you'll usually want to call
- * They take string arguments and return either hex or base-64 encoded strings
- */
-function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
-function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
-function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
-function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
-function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
-function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
-
-/*
- * Perform a simple self-test to see if the VM is working
- */
-function md5_vm_test()
-{
- return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
-}
-
-/*
- * Calculate the MD5 of an array of little-endian words, and a bit length
- */
-function core_md5(x, len)
-{
- /* append padding */
- x[len >> 5] |= 0x80 << ((len) % 32);
- x[(((len + 64) >>> 9) << 4) + 14] = len;
-
- var a = 1732584193;
- var b = -271733879;
- var c = -1732584194;
- var d = 271733878;
-
- for(var i = 0; i < x.length; i += 16)
- {
- var olda = a;
- var oldb = b;
- var oldc = c;
- var oldd = d;
-
- a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
- d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
- c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
- b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
- a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
- d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
- c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
- b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
- a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
- d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
- c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
- b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
- a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
- d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
- c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
- b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
-
- a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
- d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
- c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
- b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
- a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
- d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
- c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
- b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
- a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
- d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
- c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
- b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
- a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
- d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
- c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
- b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
-
- a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
- d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
- c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
- b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
- a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
- d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
- c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
- b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
- a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
- d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
- c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
- b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
- a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
- d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
- c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
- b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
-
- a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
- d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
- c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
- b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
- a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
- d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
- c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
- b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
- a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
- d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
- c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
- b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
- a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
- d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
- c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
- b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
-
- a = safe_add(a, olda);
- b = safe_add(b, oldb);
- c = safe_add(c, oldc);
- d = safe_add(d, oldd);
- }
- return Array(a, b, c, d);
-
-}
-
-/*
- * These functions implement the four basic operations the algorithm uses.
- */
-function md5_cmn(q, a, b, x, s, t)
-{
- return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
-}
-function md5_ff(a, b, c, d, x, s, t)
-{
- return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
-}
-function md5_gg(a, b, c, d, x, s, t)
-{
- return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
-}
-function md5_hh(a, b, c, d, x, s, t)
-{
- return md5_cmn(b ^ c ^ d, a, b, x, s, t);
-}
-function md5_ii(a, b, c, d, x, s, t)
-{
- return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
-}
-
-/*
- * Calculate the HMAC-MD5, of a key and some data
- */
-function core_hmac_md5(key, data)
-{
- var bkey = str2binl(key);
- if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
-
- var ipad = Array(16), opad = Array(16);
- for(var i = 0; i < 16; i++)
- {
- ipad[i] = bkey[i] ^ 0x36363636;
- opad[i] = bkey[i] ^ 0x5C5C5C5C;
- }
-
- var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
- return core_md5(opad.concat(hash), 512 + 128);
-}
-
-/*
- * Add integers, wrapping at 2^32. This uses 16-bit operations internally
- * to work around bugs in some JS interpreters.
- */
-function safe_add(x, y)
-{
- var lsw = (x & 0xFFFF) + (y & 0xFFFF);
- var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
- return (msw << 16) | (lsw & 0xFFFF);
-}
-
-/*
- * Bitwise rotate a 32-bit number to the left.
- */
-function bit_rol(num, cnt)
-{
- return (num << cnt) | (num >>> (32 - cnt));
-}
-
-/*
- * Convert a string to an array of little-endian words
- * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
- */
-function str2binl(str)
-{
- var bin = Array();
- var mask = (1 << chrsz) - 1;
- for(var i = 0; i < str.length * chrsz; i += chrsz)
- bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
- return bin;
-}
-
-/*
- * Convert an array of little-endian words to a string
- */
-function binl2str(bin)
-{
- var str = "";
- var mask = (1 << chrsz) - 1;
- for(var i = 0; i < bin.length * 32; i += chrsz)
- str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
- return str;
-}
-
-/*
- * Convert an array of little-endian words to a hex string.
- */
-function binl2hex(binarray)
-{
- var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
- var str = "";
- for(var i = 0; i < binarray.length * 4; i++)
- {
- str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
- hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
- }
- return str;
-}
-
-/*
- * Convert an array of little-endian words to a base-64 string
- */
-function binl2b64(binarray)
-{
- var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- var str = "";
- for(var i = 0; i < binarray.length * 4; i += 3)
- {
- var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
- | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
- | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
- for(var j = 0; j < 4; j++)
- {
- if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
- else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
- }
- }
- return str;
-}
+++ /dev/null
-/** @file oils_app_session.js
- * @brief AppRequest and AppSession.
- * The AppSession class does most of the communication work and the AppRequest
- * contains the top level client API.
- */
-
-/** The default wait time when a client calls recv. It
- * may be overrided by passing in a value to the recv method
- */
-AppRequest.DEF_RECV_TIMEOUT = 10000;
-
-/** Provide a pre-built AppSession object and the payload of the REQUEST
- * message you wish to send
- */
-function AppRequest( session, payload ) {
-
- /** Our controling session */
- this.session = session;
-
- /** This requests message thread trace */
- this.thread_trace = null;
-
- /** This request REQUEST payload */
- this.payload = payload;
-
- /** True if this request has completed is request cycle */
- this.is_complete = false;
-
- /** Stores responses received from requests */
- this.recv_queue = new Array();
-}
-
-/** returns true if this AppRequest has completed its request cycle. */
-AppRequest.prototype.complete = function() {
- if( this.is_complete ) { return true; }
- this.session.queue_wait(0);
- return this.is_complete;
-}
-
-/** When called on an AppRequest object, its status will be
- * set to complete regardless of its previous status
- */
-AppRequest.prototype.set_complete = function() {
- this.is_complete = true;
-}
-
-/** Returns the current thread trace */
-AppRequest.prototype.get_thread_trace = function() {
- return this.thread_trace;
-}
-
-/** Pushes some payload onto the recv queue */
-AppRequest.prototype.push_queue = function( payload ) {
- this.recv_queue.push( payload );
-}
-
-/** Returns the current payload of this request */
-AppRequest.prototype.get_payload = function() {
- return this.payload;
-}
-
-/** Removes this request from the our AppSession's request bucket
- * Call this method when you are finished with a particular request
- */
-AppRequest.prototype.finish = function() {
- this.session.remove_request( this );
-}
-
-
-/** Retrieves the current thread trace from the associated AppSession object,
- * increments that session's thread trace, sets this AppRequest's thread trace
- * to the new value. The request is then sent.
- */
-AppRequest.prototype.make_request = function() {
- var tt = this.session.get_thread_trace();
- this.session.set_thread_trace( ++tt );
- this.thread_trace = tt;
- this.session.add_request( this );
- this.session.send( oilsMessage.REQUEST, tt, this.payload );
-}
-
-/** Checks the receive queue for message payloads. If any are found, the first
- * is returned. Otherwise, this method will wait at most timeout seconds for
- * a message to appear in the receive queue. Once it arrives it is returned.
- * If no messages arrive in the timeout provided, null is returned.
-
- * NOTE: timeout is in * milliseconds *
- */
-
-AppRequest.prototype.recv = function( /*int*/ timeout ) {
-
-
- if( this.recv_queue.length > 0 ) {
- return this.recv_queue.shift();
- }
-
- if( this.is_complete ) { return null; }
-
- if( timeout == null ) {
- timeout = AppRequest.DEF_RECV_TIMEOUT;
- }
-
- while( timeout > 0 ) {
-
- var start = new Date().getTime();
- this.session.queue_wait( timeout );
-
- if( this.recv_queue.length > 0 ) {
- return this.recv_queue.shift();
- }
-
- // shortcircuit the call if we're already complete
- if( this.complete() ) { return null; }
-
- new Logger().debug( "AppRequest looping in recv "
- + this.get_thread_trace() + " with timeout " + timeout, Logger.DEBUG );
-
- var end = new Date().getTime();
- timeout -= ( end - start );
- }
-
- return null;
-}
-
-/** Resend this AppRequest's REQUEST message, useful for recovering
- * from disconnects, etc.
- */
-AppRequest.prototype.resend = function() {
-
- new Logger().debug( "Resending msg with thread trace: "
- + this.get_thread_trace(), Logger.DEBUG );
- this.session.send( oilsMessage.REQUEST, this.get_thread_trace(), this.payload );
-}
-
-
-
-
-// -----------------------------------------------------------------------------
-// -----------------------------------------------------------------------------
-// AppSession code
-// -----------------------------------------------------------------------------
-
-/** Global cach of AppSession objects */
-AppSession.session_cache = new Array();
-
-// -----------------------------------------------------------------------------
-// Session states
-// -----------------------------------------------------------------------------
-/** True when we're attempting to connect to a remte service */
-AppSession.CONNECTING = 0;
-/** True when we have successfully connected to a remote service */
-AppSession.CONNECTED = 1;
-/** True when we have been disconnected from a remote service */
-AppSession.DISCONNECTED = 2;
-/** The current default method protocol */
-AppSession.PROTOCOL = 1;
-
-/** Our connection with the outside world */
-AppSession.transport_handle = null;
-
-
-/** Returns the session with the given session id */
-AppSession.find_session = function(session_id) {
- return AppSession.session_cache[session_id];
-}
-
-/** Adds the given session to the global cache */
-AppSession.push_session = function(session) {
- AppSession.session_cache[session.get_session_id()] = session;
-}
-
-/** Deletes the session with the given session id from the global cache */
-AppSession.delete_session = function(session_id) {
- AppSession.session_cache[session_id] = null;
-}
-
-/** Builds a new session.
- * @param remote_service The remote service we want to make REQUEST's of
- */
-function AppSession( remote_service ) {
-
- if (arguments.length == 3) {
- // it used to be AppSession( username, password, remote_service )
- remote_service = arguments[2];
- }
-
- /** Our logger object */
- this.logger = new Logger();
-
- random_num = Math.random() + "";
- random_num.replace( '.', '' );
-
- /** Our session id */
- this.session_id = new Date().getTime() + "" + random_num;
-
- //this.auth = new userAuth( username, password );
-
- /** Our AppRequest queue */
- this.request_queue = new Array();
-
- /** Our connectivity state */
- this.state = AppSession.DISCONNECTED;
-
- var config = new Config();
-
- /** The remote ID of the service we are communicating with as retrieved
- * from the config file
- */
- this.orig_remote_id = config.get_value( "remote_service/" + remote_service );
- if( ! this.orig_remote_id ) {
- throw new oils_ex_config( "No remote service id for: " + remote_service );
- }
-
- /** The current remote ID of the service we are communicating with */
- this.remote_id = this.orig_remote_id;
-
- /** Our current request threadtrace, which is incremented with each
- * newly sent AppRequest */
- this.thread_trace = 0;
-
- /** Our queue of AppRequest objects */
- this.req_queue = new Array();
-
- /** Our queue of AppRequests that are awaiting a resend of their payload */
- this.resend_queue = new Array();
-
- // Build the transport_handle if if doesn't already exist
- if( AppSession.transport_handle == null ) {
- this.build_transport();
- }
-
- AppSession.push_session( this );
-
-}
-
-/** The transport implementation is loaded from the config file and magically
- * eval'ed into an object. All connection settings come from the client
- * config.
- * * This should only be called by the AppSession constructor and only when
- * the transport_handle is null.
- */
-AppSession.prototype.build_transport = function() {
-
- var config = new Config();
- var transport_impl = config.get_value( "transport/transport_impl" );
- if( ! transport_impl ) {
- throw new oils_ex_config( "No transport implementation defined in config file" );
- }
-
- var username = config.get_value( "transport/username" );
- var password = config.get_value( "transport/password" );
- var this_host = config.get_value( "system/hostname" );
- var resource = this_host + "_" + new Date().getTime();
- var server = config.get_value( "transport/primary" );
- var port = config.get_value( "transport/port" );
- var tim = config.get_value( "transport/connect_timeout" );
- var timeout = tim * 1000;
-
- var eval_string =
- "AppSession.transport_handle = new " + transport_impl + "( username, password, resource );";
-
- eval( eval_string );
-
- if( AppSession.transport_handle == null ) {
- throw new oils_ex_config( "Transport implementation defined in config file is not valid" );
- }
-
- if( !AppSession.transport_handle.connect( server, port, timeout ) ) {
- throw new oils_ex_transport( "Connection attempt to remote service timed out" );
- }
-
- if( ! AppSession.transport_handle.connected() ) {
- throw new oils_ex_transport( "AppSession is unable to connect to the remote service" );
- }
-}
-
-
-/** Adds the given AppRequest object to this AppSession's request queue */
-AppSession.prototype.add_request = function( req_obj ) {
- new Logger().debug( "Adding AppRequest: " + req_obj.get_thread_trace(), Logger.DEBUG );
- this.req_queue[req_obj.get_thread_trace()] = req_obj;
-}
-
-/** Removes the AppRequest object from this AppSession's request queue */
-AppSession.prototype.remove_request = function( req_obj ) {
- this.req_queue[req_obj.get_thread_trace()] = null;
-}
-
-/** Returns the AppRequest with the given thread_trace */
-AppSession.prototype.get_request = function( thread_trace ) {
- return this.req_queue[thread_trace];
-}
-
-
-/** Returns this AppSession's session id */
-AppSession.prototype.get_session_id = function() {
- return this.session_id;
-}
-
-/** Resets the remote_id for the transport to the original remote_id retrieved
- * from the config file
- */
-AppSession.prototype.reset_remote = function() {
- this.remote_id = this.orig_remote_id;
-}
-
-/** Returns the current message thread trace */
-AppSession.prototype.get_thread_trace = function() {
- return this.thread_trace;
-}
-
-/** Sets the current thread trace */
-AppSession.prototype.set_thread_trace = function( tt ) {
- this.thread_trace = tt;
-}
-
-/** Returns the state that this session is in (i.e. CONNECTED) */
-AppSession.prototype.get_state = function() {
- return this.state;
-}
-
-/** Sets the session state. The state should be one of the predefined
- * session AppSession session states.
- */
-AppSession.prototype.set_state = function(state) {
- this.state = state;
-}
-
-/** Returns the current remote_id for this session */
-AppSession.prototype.get_remote_id = function() {
- return this.remote_id;
-}
-
-/** Sets the current remote_id for this session */
-AppSession.prototype.set_remote_id = function( id ) {
- this.remote_id = id;
-}
-
-/** Pushes an AppRequest object onto the resend queue */
-AppSession.prototype.push_resend = function( app_request ) {
- this.resend_queue.push( app_request );
-}
-
-/** Destroys the current session. This will disconnect from the
- * remote service, remove all AppRequests from the request
- * queue, and finally remove this session from the global cache
- */
-AppSession.prototype.destroy = function() {
-
- new Logger().debug( "Destroying AppSession: " + this.get_session_id(), Logger.DEBUG );
-
- // disconnect from the remote service
- if( this.get_state() != AppSession.DISCONNECTED ) {
- this.disconnect();
- }
- // remove us from the global cache
- AppSession.delete_session( this.get_session_id() );
-
- // Remove app request references
- for( var index in this.req_queue ) {
- this.req_queue[index] = null;
- }
-}
-
-/** This forces a resend of all AppRequests that are currently
- * in the resend queue
- */
-AppSession.prototype.flush_resend = function() {
-
- if( this.resend_queue.length > 0 ) {
- new Logger().debug( "Resending "
- + this.resend_queue.length + " messages", Logger.INFO );
- }
-
- var req = this.resend_queue.shift();
-
- while( req != null ) {
- req.resend();
- req = this.resend_queue.shift();
- }
-}
-
-/** This method tracks down the AppRequest with the given thread_trace and
- * pushes the payload into that AppRequest's recieve queue.
- */
-AppSession.prototype.push_queue = function( dom_payload, thread_trace ) {
-
- var req = this.get_request( thread_trace );
- if( ! req ) {
- new Logger().debug( "No AppRequest exists for TT: " + thread_trace, Logger.ERROR );
- return;
- }
- req.push_queue( dom_payload );
-}
-
-
-/** Connect to the remote service. The connect timeout is read from the config.
- * This method returns null if the connection fails. It returns a reference
- * to this AppSession object otherwise.
- */
-AppSession.prototype.connect = function() {
-
- if( this.get_state() == AppSession.CONNECTED ) {
- return this;
- }
-
- var config = new Config();
- var rem = config.get_value( "transport/connect_timeout" );
- if( ! rem ) {
- throw new oils_ex_config( "Unable to retreive timeout value from config" );
- }
-
- var remaining = rem * 1000; // milliseconds
-
- this.reset_remote();
- this.set_state( AppSession.CONNECTING );
- this.send( oilsMessage.CONNECT, 0, "" );
-
- new Logger().debug( "CONNECTING with timeout: " + remaining, Logger.DEBUG );
-
- while( this.get_state() != AppSession.CONNECTED && remaining > 0 ) {
-
- var starttime = new Date().getTime();
- this.queue_wait( remaining );
- var endtime = new Date().getTime();
- remaining -= (endtime - starttime);
- }
-
- if( ! this.get_state() == AppSession.CONNECTED ) {
- return null;
- }
-
- return this;
-}
-
-/** Disconnects from the remote service */
-AppSession.prototype.disconnect = function() {
-
- if( this.get_state() == AppSession.DISCONNECTED ) {
- return;
- }
-
- this.send( oilsMessage.DISCONNECT, this.get_thread_trace(), "" );
- this.set_state( AppSession.DISCONNECTED );
- this.reset_remote();
-}
-
-
-/** Builds a new message with the given type and thread_trace. If the message
- * is a REQUEST, then the payload is added as well.
- * This method will verify that the session is in the CONNECTED state before
- * sending any REQUEST's by attempting to do a connect.
- *
- * Note: msg_type and thread_trace must be provided.
- */
-AppSession.prototype.send = function( msg_type, thread_trace, payload ) {
-
- if( msg_type == null || thread_trace == null ) {
- throw new oils_ex_args( "Not enough arguments provided to AppSession.send method" );
- }
-
- // go ahead and make sure there's nothing new to process
- this.queue_wait(0);
-
- var msg;
- msg = new oilsMessage( msg_type, AppSession.PROTOCOL );
-
- msg.setThreadTrace( thread_trace );
-
- if( msg_type == oilsMessage.REQUEST ) {
- if( ! payload ) {
- throw new oils_ex_args( "No payload provided for REQUEST message in AppSession.send" );
- }
- msg.add( payload );
- }
-
-
- // Make sure we're connected
- if( (msg_type != oilsMessage.DISCONNECT) && (msg_type != oilsMessage.CONNECT) &&
- (this.get_state() != AppSession.CONNECTED) ) {
- if( ! this.connect() ) {
- throw new oils_ex_session( this.get_session_id() + " | Unable to connect to remote service after redirect" );
- }
- }
-
- this.logger.debug( "AppSession sending tt: "
- + thread_trace + " to " + this.get_remote_id()
- + " " + msg_type , Logger.INFO );
-
- AppSession.transport_handle.send( this.get_remote_id(), this.get_session_id(), msg.toString(true) );
-
-}
-
-
-/** Waits up to 'timeout' milliseconds for some data to arrive.
- * Any data that arrives will be process according to its
- * payload and message type. This method will return after
- * any data has arrived.
- * @param timeout How many milliseconds to wait or data to arrive
- */
-AppSession.prototype.queue_wait = function( timeout ) {
- this.flush_resend(); // necessary if running parallel sessions
- new Logger().debug( "In queue_wait " + timeout, Logger.DEBUG );
- var tran_msg = AppSession.transport_handle.process_msg( timeout );
- this.flush_resend();
-}
-
-
-
+++ /dev/null
-/** @file oils_config.js
- * Config code and Logger code
- * The config module is simple. It parses an xml config file and
- * the values from the file are accessed via XPATH queries.
- */
-
-/** Searches up from Mozilla's chrome directory for the client
- * config file and returns the file object
- */
-function get_config_file() {
-
- var dirService = Components.classes["@mozilla.org/file/directory_service;1"].
- getService( Components.interfaces.nsIProperties );
-
- chromeDir = dirService.get( "AChrom", Components.interfaces.nsIFile );
- chromeDir.append(myPackageDir);
- chromeDir.append("content");
- chromeDir.append("conf");
- chromeDir.append("client_config.xml");
- return chromeDir;
-
-}
-
-
-/** Constructor. You may provide an optional path to the config file. **/
-function Config( config_file ) {
-
- if( Config.config != null ) { return Config.config; }
-
- config_file = get_config_file();
-
- // ------------------------------------------------------------------
- // Grab the data from the config file
- // ------------------------------------------------------------------
- var data = "";
- var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
- .createInstance(Components.interfaces.nsIFileInputStream);
-
- var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
- .createInstance(Components.interfaces.nsIScriptableInputStream);
-
- fstream.init(config_file, 1, 0, false);
- sstream.init(fstream);
- data += sstream.read(-1);
-
- sstream.close();
- fstream.close();
-
-
-
- var DOMParser = new Components.Constructor(
- "@mozilla.org/xmlextras/domparser;1", "nsIDOMParser" );
-
- this.config_doc = new DOMParser().parseFromString( data, "text/xml" );
-
- Config.config = this;
-
-}
-
-/** Returns the value stored in the config file found with the
- * given xpath expression
- * E.g. config.get_value( "/oils_config/dirs/log_dir" );
- * Note, the 'oils_config' node is the base of the xpath expression,
- * so something like this will also work:
- * config.get_value( "dirs/log_dir" );
- */
-Config.prototype.get_value = function( xpath_query ) {
-
- var evaluator = Components.classes["@mozilla.org/dom/xpath-evaluator;1"].
- createInstance( Components.interfaces.nsIDOMXPathEvaluator );
-
- var xpath_obj = evaluator.evaluate( xpath_query, this.config_doc.documentElement, null, 0, null );
- if( ! xpath_obj ) { return null; }
-
- var node = xpath_obj.iterateNext();
- if( node == null ) {
- throw new oils_ex_config( "No config option matching " + xpath_query );
- }
-
- return node.firstChild.nodeValue;
-}
-
-
-
-
-
-
-// ------------------------------------------------------------------
-// Logger code.
-// ------------------------------------------------------------------
-/** The global logging object */
-Logger.logger = null;
-/** No logging level */
-Logger.NONE = 0;
-/** Error log level */
-Logger.ERROR = 1;
-/** Info log level */
-Logger.INFO = 2;
-/* Debug log level */
-Logger.DEBUG = 3;
-
-/** There exists a single logger object that all components share.
- * Calling var logger = new Logger() will return the same one
- * with each call. This is so we only need one file handle for
- * each type of log file.
- */
-function Logger() {
-
- if( Logger.logger != null ) { return Logger.logger }
-
- var config = new Config();
- this.log_level = config.get_value( "system/log_level" );
-
- this.stdout_log = config.get_value( "system/stdout_log" );
-
- if( ! this.stdout_log || this.stdout_log < 0 || this.stdout_log > 2 ) {
- throw new oils_ex_config( "stdout_log setting is invalid: " + this.stdout_log +
- ". Should be 0, 1, or 2." );
- }
-
- // ------------------------------------------------------------------
- // Load up all of the log files
- // ------------------------------------------------------------------
- var transport_file = config.get_value( "logs/transport" );
- if( transport_file == null ) {
- throw new oils_ex_config( "Unable to load transport log file: 'logs/transport'" );
- }
-
- var debug_file = config.get_value( "logs/debug" );
- if( debug_file == null ) {
- throw new oils_ex_config( "Unable to load debug log file: 'logs/debug'" );
- }
-
- var error_file = config.get_value( "logs/error" );
- if( error_file == null ) {
- throw new oils_ex_config( "Unable to load debug log file: 'logs/error'" );
- }
-
-
- // ------------------------------------------------------------------
- // Build the file objects
- // ------------------------------------------------------------------
- var transport_file_obj = Logger.get_log_file( transport_file );
-
- var debug_file_obj = Logger.get_log_file( debug_file );
-
- var error_file_obj = Logger.get_log_file( error_file );
-
-
- // ------------------------------------------------------------------
- // Build all of the file stream objects
- // ------------------------------------------------------------------
- this.transport_stream = Components.classes["@mozilla.org/network/file-output-stream;1"]
- .createInstance(Components.interfaces.nsIFileOutputStream);
-
- this.debug_stream = Components.classes["@mozilla.org/network/file-output-stream;1"]
- .createInstance(Components.interfaces.nsIFileOutputStream);
-
- this.error_stream = Components.classes["@mozilla.org/network/file-output-stream;1"]
- .createInstance(Components.interfaces.nsIFileOutputStream);
-
- // ------------------------------------------------------------------
- // Init all of the streams
- // use 0x02 | 0x10 to open file for appending.
- // ------------------------------------------------------------------
- this.transport_stream.init(transport_file_obj, 0x02 | 0x10 | 0x08, 0664, 0 );
- this.debug_stream.init( debug_file_obj, 0x02 | 0x10 | 0x08, 0664, 0 );
- this.error_stream.init( error_file_obj, 0x02 | 0x10 | 0x08, 0664, 0 );
-
- Logger.logger = this;
-
-}
-
-/** Internal. Returns a XPCOM nsIFile object for the log file we're interested in */
-Logger.get_log_file = function( log_name ) {
-
- var dirService = Components.classes["@mozilla.org/file/directory_service;1"].
- getService( Components.interfaces.nsIProperties );
-
- logFile = dirService.get( "AChrom", Components.interfaces.nsIFile );
- logFile.append(myPackageDir);
- logFile.append("content");
- logFile.append("log");
- logFile.append( log_name );
-
- if( ! logFile.exists() ) {
- logFile.create( 0, 0640 );
- }
-
- return logFile;
-}
-
-
-
-/** Internal. Builds a log message complete with data, etc. */
-Logger.prototype.build_string = function( message, level ) {
-
- if( ! (message && level) ) { return null; }
-
- var lev = "INFO";
- if( level == Logger.ERROR ) { lev = "ERROR"; }
- if( level == Logger.DEBUG ) { lev = "DEBUG"; }
-
- var date = new Date();
- var year = date.getYear();
- year += 1900;
-
- var month = ""+date.getMonth();
- if(month.length==1) {month="0"+month;}
- var day = ""+date.getDate();
- if(day.length==1) {day="0"+day;}
- var hour = ""+date.getHours();
- if(hour.length== 1){hour="0"+hour;}
- var min = ""+date.getMinutes();
- if(min.length==1){min="0"+min;}
- var sec = ""+date.getSeconds();
- if(sec.length==1){sec="0"+sec;}
- var mil = ""+date.getMilliseconds();
- if(mil.length==1){sec="0"+sec;}
-
- var date_string = year + "-" + month + "-" + day + " " +
- hour + ":" + min + ":" + sec + "." + mil;
-
- var str_array = message.split('\n');
- var ret_array = new Array();
- for( var i in str_array ) {
- ret_str = "[" + date_string + "] " + lev + " " + str_array[i] + "\n";
- ret_array.push( ret_str );
- }
-
- var line = "-------------------------\n";
- ret_array.unshift( line );
-
- return ret_array;
-}
-
-/** Internal. Does the actual writing */
-Logger.prototype._log = function( data, stream, level ) {
-
- if( ! data ) { return; }
- if( ! stream ) {
- throw oils_ex_logger( "No file stream open for log message: " + data );
- }
- if( ! level ) { level = Logger.DEBUG; }
-
- if( level > this.log_level ) { return; }
- var str_array = this.build_string( data, level );
- if( ! str_array ) { return; }
-
- for( var i in str_array ) {
- if( this.stdout_log > 0 ) { dump( str_array[i] ); }
- if( this.stdout_log < 2 ) { stream.write( str_array[i], str_array[i].length ); }
- }
-
- // write errors to the error log if they were destined for anywhere else
- if( level == Logger.ERROR && stream != this.error_stream ) {
- for( var i in str_array ) {
- if( this.stdout_log > 0 ) { dump( str_array[i] ); }
- if( this.stdout_log < 2 ) { this.error_stream.write( str_array[i], str_array[i].length ); }
- }
- }
-}
-
-
-
-/** Writes the message to the error log */
-Logger.prototype.error = function( message, level ) {
- this._log( message, this.error_stream, level );
-}
-
-
-/** Writes to the debug log */
-Logger.prototype.debug = function( message, level ) {
- this._log( message, this.debug_stream, level );
-}
-
-
-/** Writes to the transport log */
-Logger.prototype.transport = function( message, level ) {
- this._log( message, this.transport_stream, level );
-}
+++ /dev/null
-/** @file oils_dom_element.js
- * -----------------------------------------------------------------------------
- * This file holds all of the core OILS DOM elements.
- * -----------------------------------------------------------------------------
-
- * -----------------------------------------------------------------------------
- * Make sure you load md5.js into your script/html/etc. before loading this
- * file
- * -----------------------------------------------------------------------------
- *
- * -----------------------------------------------------------------------------
- * 1. Use these if you are running via xpcshell, but not if you are running
- * directly from mozilla.
- * 2. BTW. XMLSerializer doesn't like being run outside of mozilla, so
- * toString() fails.
- *
- * var DOMParser = new Components.Constructor(
- * "@mozilla.org/xmlextras/domparser;1", "nsIDOMParser" );
- *
- * var XMLSerializer = new Components.Constructor(
- * "@mozilla.org/xmlextras/xmlserializer;1", "nsIDOMSerializer" );
- * -----------------------------------------------------------------------------
- *
- *
- */
-
-/**
- * -----------------------------------------------------------------------------
- * DOM - Top level generic class
- * -----------------------------------------------------------------------------
- */
-
-function DOM() {
- this.doc = null;
- this.root = null;
- this.element = null;
-}
-
-/** Returns a string representation of the XML doc. If full_bool
- * is true, it will return the entire doc and not just the relevant
- * portions (i.e. our object's element).
- */
-DOM.prototype.toString = function(full_bool) {
- if( full_bool ) {
- return new XMLSerializer().serializeToString(this.doc);
- } else {
- return new XMLSerializer().serializeToString(this.element);
- }
-}
-
-/** Initializes a document and sets this.doc, this.root and this.element */
-DOM.prototype.init = function( elementName ) {
-
- this.doc = new DOMParser().parseFromString(
- "<?xml version='1.0' encoding='UTF-8'?><oils:root xmlns:oils='http://open-ils.org/namespaces/oils_v1'></oils:root>", "text/xml" );
- this.root = this.doc.documentElement;
- this.element = this.doc.createElement( "oils:" + elementName );
- return this.element;
-}
-
-/** Good for creating objects from raw xml. This builds a new doc and inserts
- * the node provided. So you can build a dummy object, then call replaceNode
- * with the new xml to build an object from XML on the fly.
- */
-DOM.prototype._replaceNode = function( name, new_element ) {
-
- var node = this.doc.importNode( new_element, true );
-
- if( node.nodeName != "oils:" + name ) {
- throw new oils_ex_dom( "Invalid Tag to " + name + "::replaceNode()" );
- }
-
- this.doc = new DOMParser().parseFromString(
- "<?xml version='1.0' encoding='UTF-8'?><oils:root xmlns:oils='http://open-ils.org/namespaces/oils_v1'></oils:root>", "text/xml" );
- this.root = this.doc.documentElement;
-
- this.root.appendChild( node );
- this.element = this.root.firstChild;
- return this;
-}
-
-
-
-// -----------------------------------------------------------------------------
-// domainObjectAttr
-// -----------------------------------------------------------------------------
-
-domainObjectAttr.prototype = new DOM();
-domainObjectAttr.prototype.constructor = domainObjectAttr;
-domainObjectAttr.baseClass = DOM.prototype.constructor;
-
-/** A domainObjectAttr is a single XML node with 'name' and 'value' attributes */
-function domainObjectAttr( name, value ) {
-
- var node = this.init( "domainObjectAttr" );
- if( ! name && value ) { return; }
- node.setAttribute( "name", name );
- node.setAttribute( "value", value );
- this.root.appendChild( node );
-}
-
-
-/** Returns the attribute name */
-domainObjectAttr.prototype.getName = function() {
- return this.element.getAttribute("name");
-}
-
-/** Returns the attribut value. */
-domainObjectAttr.prototype. getValue = function() {
- return this.element.getAttribute("value");
-}
-
-/** Sets the attribute value. */
-domainObjectAttr.prototype. setValue = function( value ) {
- return this.element.setAttribute("value", value );
-}
-
-/** Pass in the this.element component of a domainObjectAttr and this will
- * replace the old element with the new one
- */
-domainObjectAttr.prototype.replaceNode = function( domainObjectAttr_element ) {
- return this._replaceNode( "domainObjectAttr", domainObjectAttr_element );
-}
-
-// -----------------------------------------------------------------------------
-// userAuth
-// -----------------------------------------------------------------------------
-
-
-userAuth.prototype = new DOM();
-userAuth.prototype.constructor = userAuth;
-userAuth.baseClass = DOM.prototype.constructor;
-
-function userAuth( username, secret ) {
-
- var node = this.init( "userAuth" );
- if( !( username && secret) ) { return; }
- node.setAttribute( "username", username );
-
- //There is no way to specify the hash seed with the
- //md5 utility provided
- var hash = hex_md5( secret );
- node.setAttribute( "secret", hash );
- node.setAttribute( "hashseed", "" );
-
- this.root.appendChild( node );
-}
-
-userAuth.prototype.getUsername = function() {
- return this.element.getAttribute( "username" );
-}
-
-userAuth.prototype.getSecret = function() {
- return this.element.getAttribute( "secret" );
-}
-
-userAuth.prototype.getHashseed = function() {
- return this.element.getAttribute( "hashseed" );
-}
-
-userAuth.prototype.replaceNode = function( userAuth_element ) {
- return this._replaceNode( "userAuth", userAuth_element );
-}
-
-
-// -----------------------------------------------------------------------------
-// domainObject
-// -----------------------------------------------------------------------------
-
-domainObject.prototype = new DOM();
-domainObject.baseClass = DOM.prototype.constructor;
-domainObject.prototype.constructor = domainObject;
-
-/** Holds the XML for a DomainObject (see oils_domain_object.js or the DomainObject class) */
-function domainObject( name ) {
- this._init_domainObject( name );
-}
-
-/** Initializes the domainObject XML node */
-domainObject.prototype._init_domainObject = function( name ) {
-
- var node = this.init( "domainObject" );
-
- if( ! name ) { return; }
- node.setAttribute( "name", name );
- this.root.appendChild( node );
-
-}
-
-/** Pass in any DOM Element or DomainObject and this method will as the
- * new object as the next child of the root (domainObject) node
- */
-domainObject.prototype.add = function( new_DOM ) {
-
- this.element.appendChild(
- new_DOM.element.cloneNode( true ) );
-}
-
-/** Removes the original domainObject XML node and replaces it with the
- * one provided. This is useful for building new domainObject's from
- * raw xml. Just create a new one, then call replaceNode with the new XML.
- */
-domainObject.prototype.replaceNode = function( domainObject_element ) {
- return this._replaceNode( "domainObject", domainObject_element );
-}
-
-
-
-// -----------------------------------------------------------------------------
-// Param
-// -----------------------------------------------------------------------------
-
-
-param.prototype = new DOM();
-param.baseClass = DOM.prototype.constructor;
-param.prototype.constructor = param;
-
-function param( value ) {
- var node = this.init( "param" );
- node.appendChild( this.doc.createTextNode( value ) );
- this.root.appendChild( node );
-}
-
-param.prototype.getValue = function() {
- return this.element.textContent;
-}
-
-param.prototype.replaceNode = function( param_element ) {
- return this._replaceNode( "param", param_element );
-}
-
-
-// -----------------------------------------------------------------------------
-// domainObjectCollection
-// -----------------------------------------------------------------------------
-
-domainObjectCollection.prototype = new DOM();
-domainObjectCollection.prototype.constructor =
- domainObjectCollection;
-domainObjectCollection.baseClass = DOM.prototype.constructor;
-
-function domainObjectCollection( name ) {
- var node = this.init( "domainObjectCollection" );
- this.root.appendChild( node );
- if(name) { this._initCollection( name ); }
-}
-
-domainObjectCollection.prototype._initCollection = function( name ) {
- if( name ) {
- this.element.setAttribute( "name", name );
- }
-}
-
-domainObjectCollection.prototype.add = function( new_domainObject ) {
- this.element.appendChild(
- new_domainObject.element.cloneNode( true ) );
-}
-
-domainObjectCollection.prototype.replaceNode = function( new_node ) {
- return this._replaceNode( "domainObjectCollection", new_node );
-}
-
-
+++ /dev/null
-// -----------------------------------------------------------------------------
-// This houses all of the domain object code.
-// -----------------------------------------------------------------------------
-
-
-
-
-// -----------------------------------------------------------------------------
-// DomainObject
-
-DomainObject.prototype = new domainObject();
-DomainObject.prototype.constructor = DomainObject;
-DomainObject.prototype.baseClass = domainObject.prototype.constructor;
-
-/** Top level DomainObject class. This most provides convience methods
- * and a shared superclass
- */
-function DomainObject( name ) {
- if( name ) { this._init_domainObject( name ); }
-}
-
-/** Returns the actual element of the given domainObjectAttr. */
-DomainObject.prototype._findAttr = function ( name ) {
-
- var nodes = this.element.childNodes;
-
- if( ! nodes || nodes.length < 1 ) {
- throw new oils_ex_dom( "Invalid xml object in _findAttr: " + this.toString() );
- }
-
- var i=0;
- var node = nodes.item(i);
-
- while( node != null ) {
-
- if( node.nodeName == "oils:domainObjectAttr" &&
- node.getAttribute("name") == name ) {
- return node;
- }
-
- node = nodes.item(++i);
- }
-
- return null;
-}
-
-
-
-
-/** Returns the value stored in the given attribute */
-DomainObject.prototype.getAttr = function ( name ) {
-
- var node = this._findAttr( name );
- if( node ) { return node.getAttribute( "value" ); }
- else {
- throw new oils_ex_dom( "getAttr(); Getting nonexistent attribute: " + name );
- }
-}
-
-/** Updates the value held by the given attribute */
-DomainObject.prototype.setAttr = function ( name, value ) {
-
- var node = this._findAttr( name );
- if( node ) {
- node.setAttribute( "value", value );
- } else {
- throw new oils_ex_dom( "setAttr(); Setting nonexistent attribute: " + name );
- }
-}
-
-/** This takes a raw DOM Element node and creates the DomainObject that the node
- * embodies and returns the object. All new DomainObjects should be added to
- * this list if they require this type of dynamic functionality.
- * NOTE Much of this will be deprecated as move to a more JSON-centric wire protocol
- */
-DomainObject.newFromNode = function( node ) {
-
- switch( node.getAttribute("name") ) {
-
- case "oilsMethod":
- return new oilsMethod().replaceNode( node );
-
- case "oilsMessage":
- return new oilsMessage().replaceNode( node );
-
- case "oilsResponse":
- return new oilsResponse().replaceNode( node );
-
- case "oilsResult":
- return new oilsResult().replaceNode( node );
-
- case "oilsConnectStatus":
- return new oilsConnectStatus().replaceNode( node );
-
- case "oilsException":
- return new oilsException().replaceNode( node );
-
- case "oilsMethodException":
- return new oilsMethodException().replaceNode( node );
-
- case "oilsBrokenSession":
- return new oilsBrokenSession().replaceNode( node );
-
- case "oilsScalar":
- return new oilsScalar().replaceNode( node );
-
- case "oilsPair":
- return new oilsPair().replaceNode( node );
-
- case "oilsArray":
- return new oilsArray().replaceNode( node );
-
- case "oilsHash":
- return new oilsHash().replaceNode( node );
-
-
- }
-
-}
-
-
-
-// -----------------------------------------------------------------------------
-// oilsMethod
-
-oilsMethod.prototype = new DomainObject();
-oilsMethod.prototype.constructor = oilsMethod;
-oilsMethod.prototype.baseClass = DomainObject.prototype.constructor;
-
-/**
- * oilsMethod Constructor
- *
- * @param method_name The name of the method your are sending
- * to the remote server
- * @param params_array A Javascript array of the params (any
- * Javascript data type)
- */
-
-function oilsMethod( method_name, params_array ) {
- this._init_domainObject( "oilsMethod" );
- this.add( new domainObjectAttr( "method", method_name ) );
-
- if( params_array ) {
- var params = this.doc.createElement( "oils:params" );
- this.element.appendChild( params );
- params.appendChild( this.doc.createTextNode(
- js2JSON( params_array ) ) );
- }
-}
-
-
-/** Locates the params node of this method */
-oilsMethod.prototype._getParamsNode = function() {
-
- var nodes = this.element.childNodes;
- if( ! nodes || nodes.length < 1 ) { return null; }
- var x=0;
- var node = nodes.item(x);
- while( node != null ) {
- if( node.nodeName == "oils:params" ) {
- return node;
- }
- node = nodes.item(++x);
- }
-
- return null;
-}
-
-
-/** Returns an array of param objects */
-oilsMethod.prototype.getParams = function() {
- var node = this._getParamsNode();
- if(node != null ) {
- return JSON2js( node.textContent );
- }
-}
-
-
-
-// -----------------------------------------------------------------------------
-// oilsMessage
-
-// -----------------------------------------------------------------------------
-// oilsMessage message types
-// -----------------------------------------------------------------------------
-/** CONNECT Message type */
-oilsMessage.CONNECT = 'CONNECT';
-/** DISCONNECT Message type */
-oilsMessage.DISCONNECT = 'DISCONNECT';
-/** STATUS Message type */
-oilsMessage.STATUS = 'STATUS';
-/** REQUEST Message type */
-oilsMessage.REQUEST = 'REQUEST';
-/** RESULT Message type */
-oilsMessage.RESULT = 'RESULT';
-
-
-oilsMessage.prototype = new DomainObject();
-oilsMessage.prototype.constructor = oilsMessage;
-oilsMessage.prototype.baseClass = DomainObject.prototype.constructor;
-
-/** Core XML object for message passing */
-function oilsMessage( type, protocol ) {
-
- if( !( type && protocol) ) {
- type = oilsMessage.CONNECT;
- protocol = "1";
- }
-
- if( ! ( type == oilsMessage.CONNECT ||
- type == oilsMessage.DISCONNECT ||
- type == oilsMessage.STATUS ||
- type == oilsMessage.REQUEST ||
- type == oilsMessage.RESULT ) ) {
- throw new oils_ex_message( "Attempt to create oilsMessage with incorrect type: " + type );
- }
-
- this._init_domainObject( "oilsMessage" );
-
- this.add( new domainObjectAttr( "type", type ) );
- this.add( new domainObjectAttr( "threadTrace", 0 ) );
- this.add( new domainObjectAttr( "protocol", protocol ) );
-
- // user_auth used to be a parameter for oilsMessage
- //if( user_auth ) { this.add( user_auth ); }
-
-}
-
-/** Builds a new oilsMessage from raw xml.
- * Checks are taken to make sure the xml is supposed to be an oilsMessage.
- * If not, an oils_ex_dom exception is throw.
- */
-oilsMessage.newFromXML = function( xml ) {
-
- try {
-
- if( ! xml || xml == "" ) { throw 1; }
-
- var doc = new DOMParser().parseFromString( xml, "text/xml" );
- if( ! doc ) { throw 1; }
-
- var root = doc.documentElement;
- if( ! root ) { throw 1; }
-
- // -----------------------------------------------------------------------------
- // There are two options here. One is that we were provided the full message
- // xml (i.e. contains the <oils:root> tag. The other option is that we were
- // provided just the message xml portion (top level element is the
- // <oils:domainObject>
- // -----------------------------------------------------------------------------
-
- var element;
- if( root.nodeName == "oils:root" ) {
-
- element = root.firstChild;
- if( ! element ) { throw 1; }
-
- } else {
-
- if( root.nodeName == "oils:domainObject" ) {
- element = root;
-
- } else { throw 1; }
-
- }
-
-
- if( element.nodeName != "oils:domainObject" ) { throw 1; }
- if( element.getAttribute( "name" ) != "oilsMessage" ) { throw 1; }
-
- return new oilsMessage().replaceNode( element );
-
- } catch( E ) {
-
- if( E && E.message ) {
- throw new oils_ex_dom( "Bogus XML for creating oilsMessage: " + E.message + "\n" + xml );
-
- } else {
- throw new oils_ex_dom( "Bogus XML for creating oilsMessage:\n" + xml );
- }
- }
-
- return msg;
-}
-
-
-
-/** Adds a copy of the given DomainObject to the message */
-oilsMessage.prototype.addPayload = function( new_DomainObject ) {
- this.add( new_DomainObject );
-}
-
-
-/** Returns the top level DomainObject contained in this message
- *
- * Note: The object retuturned will be the actual object, not just a
- * generic DomainObject - e.g. oilsException.
- */
-oilsMessage.prototype.getPayload = function() {
-
- var nodes = this.element.childNodes;
- var x=0;
- var node = nodes.item(0);
-
- while( node != null ) {
-
- if( node.nodeName == "oils:domainObject" ) {
-
- new Logger().debug( "Building oilsMessage payload from\n" +
- new XMLSerializer().serializeToString( node ), Logger.DEBUG );
- return DomainObject.newFromNode( node );
- }
- node = nodes.item(++x);
- }
-
- return null;
-}
-
-oilsMessage.prototype.getUserAuth = function() {
-
- var nodes = this.element.getElementsByTagName( "oils:userAuth" );
- if( ! nodes ) { return null; }
-
- var auth_elem = nodes.item(0); // should only be one
- if ( ! auth_elem ) { return null; }
-
- return new userAuth().replaceNode( auth_elem );
-
-}
-
-/** Returns the type of the message */
-oilsMessage.prototype.getType = function() {
- return this.getAttr( "type" );
-}
-
-/** Returns the message protocol */
-oilsMessage.prototype.getProtocol = function() {
- return this.getAttr( "protocol" );
-}
-
-/** Returns the threadTrace */
-oilsMessage.prototype.getThreadTrace = function() {
- return this.getAttr( "threadTrace" );
-}
-
-/** Sets the thread trace - MUST be an integer */
-oilsMessage.prototype.setThreadTrace = function( trace ) {
- this.setAttr( "threadTrace", trace );
-}
-
-/** Increments the thread trace by 1 */
-oilsMessage.prototype.updateThreadTrace = function() {
- var tt = this.getThreadTrace();
- return this.setThreadTrace( ++tt );
-}
-
-
-
-
-
-// -----------------------------------------------------------------------------
-// oilsResponse
-
-
-// -----------------------------------------------------------------------------
-// Response codes
-// -----------------------------------------------------------------------------
-
-/**
- * Below are the various response statuses
- */
-oilsResponse.STATUS_CONTINUE = 100
-
-oilsResponse.STATUS_OK = 200
-oilsResponse.STATUS_ACCEPTED = 202
-oilsResponse.STATUS_COMPLETE = 205
-
-oilsResponse.STATUS_REDIRECTED = 307
-
-oilsResponse.STATUS_BADREQUEST = 400
-oilsResponse.STATUS_UNAUTHORIZED = 401
-oilsResponse.STATUS_FORBIDDEN = 403
-oilsResponse.STATUS_NOTFOUND = 404
-oilsResponse.STATUS_NOTALLOWED = 405
-oilsResponse.STATUS_TIMEOUT = 408
-oilsResponse.STATUS_EXPFAILED = 417
-oilsResponse.STATUS_INTERNALSERVERERROR = 500
-oilsResponse.STATUS_NOTIMPLEMENTED = 501
-oilsResponse.STATUS_VERSIONNOTSUPPORTED = 505
-
-
-oilsResponse.prototype = new DomainObject();
-oilsResponse.prototype.constructor = oilsResponse;
-oilsResponse.prototype.baseClass = DomainObject.prototype.constructor;
-
-/** Constructor. status is the text describing the message status and
- * statusCode must correspond to one of the oilsResponse status code numbers
- */
-function oilsResponse( name, status, statusCode ) {
- if( name && status && statusCode ) {
- this._initResponse( name, status, statusCode );
- }
-}
-
-/** Initializes the reponse XML */
-oilsResponse.prototype._initResponse = function( name, status, statusCode ) {
-
- this._init_domainObject( name );
- this.add( new domainObjectAttr( "status", status ));
- this.add( new domainObjectAttr( "statusCode", statusCode ) );
-}
-
-
-
-/** Returns the status of the response */
-oilsResponse.prototype.getStatus = function() {
- return this.getAttr( "status" );
-}
-
-/** Returns the statusCode of the response */
-oilsResponse.prototype.getStatusCode = function() {
- return this.getAttr("statusCode");
-}
-
-
-oilsConnectStatus.prototype = new oilsResponse();
-oilsConnectStatus.prototype.constructor = oilsConnectStatus;
-oilsConnectStatus.prototype.baseClass = oilsResponse.prototype.constructor;
-
-/** Constructor. These give us info on our connection attempts **/
-function oilsConnectStatus( status, statusCode ) {
- this._initResponse( "oilsConnectStatus", status, statusCode );
-}
-
-
-oilsResult.prototype = new oilsResponse();
-oilsResult.prototype.constructor = oilsResult;
-oilsResult.prototype.baseClass = oilsResponse.prototype.constructor;
-
-
-/** Constructor. These usually carry REQUEST responses */
-function oilsResult( status, statusCode ) {
- if( status && statusCode ) {
- this._initResponse( "oilsResult", status, statusCode );
- }
-}
-
-/** Returns the top level DomainObject within this result message.
- * Note: The object retuturned will be the actual object, not just a
- * generic DomainObject - e.g. oilsException.
- */
-oilsResult.prototype.getContent = function() {
-
- var nodes = this.element.childNodes;
- if( ! nodes || nodes.length < 1 ) {
- throw new oils_ex_dom("Content node for oilsResult is invalid\n" + this.toString() );
- }
- var x = 0;
- var node = nodes.item(x);
- while( node != null ) {
-
- if( node.nodeName == "oils:domainObject" ||
- node.nodeName == "oils:domainObjectCollection" ) {
-
- //return DomainObject.newFromNode( node );
- return JSON2js( node.textContent );
- }
- node = nodes.item(++x);
- }
-
- throw new oils_ex_dom("Content node for oilsResult is invalid\n" + this.toString() );
-}
-
-
-oilsException.prototype = new oilsResponse();
-oilsException.prototype.constructor = oilsException;
-oilsException.prototype.baseClass = oilsResponse.prototype.constructor;
-
-/** Top level exception */
-function oilsException( status, statusCode ) {
- if( status && statusCode ) {
- this._initResponse( "oilsException", status, statusCode );
- }
-}
-
-
-oilsMethodException.prototype = new oilsException();
-oilsMethodException.prototype.constructor = oilsMethodException;
-oilsMethodException.prototype.baseClass = oilsException.prototype.constructor;
-
-/** Method exception */
-function oilsMethodException( status, statusCode ) {
- if( status && statusCode ) {
- this._initResponse( "oilsMethodException", status, statusCode );
- }
-}
-
-oilsBrokenSession.prototype = new oilsException();
-oilsBrokenSession.prototype.constructor = oilsBrokenSession;
-oilsBrokenSession.prototype.baseClass = oilsException.prototype.constructor;
-
-/** broken session exception */
-function oilsBrokenSession( status, statusCode ) {
- if( status && statusCode ) {
- this._initResponse( "oilsBrokenSession", status, statusCode );
- }
-}
-
-
-// -----------------------------------------------------------------------------
-// oilsScalar
-
-
-oilsScalar.prototype = new DomainObject();
-oilsScalar.prototype.constructor = oilsScalar;
-oilsScalar.prototype.baseClass = DomainObject.prototype.constructor;
-
-/** Contains a single JSON item as its text content */
-function oilsScalar( value ) {
- this._init_domainObject( "oilsScalar" );
- this.element.appendChild( this.doc.createTextNode( value ) );
-}
-
-/** Returns the contained item as a Javascript object */
-oilsScalar.prototype.getValue = function() {
- return JSON2js( this.element.textContent );
-}
-
-
-// -----------------------------------------------------------------------------
-// oilsPair
-
-
-oilsPair.prototype = new DomainObject()
-oilsPair.prototype.constructor = oilsPair;
-oilsPair.prototype.baseClass = DomainObject.prototype.constructor;
-
-function oilsPair( key, value ) {
-
- this._init_domainObject( "oilsPair" );
- this.element.appendChild( this.doc.createTextNode( value ) );
- this.element.setAttribute( "key", key );
-}
-
-oilsPair.prototype.getKey = function() {
- return this.element.getAttribute( "key" );
-}
-
-oilsPair.prototype.getValue = function() {
- return this.element.textContent;
-}
-
-
-
-// -----------------------------------------------------------------------------
-// oilsArray - is a domainObjectCollection that stores a list of domainObject's
-// or domainObjectCollections.
-// -----------------------------------------------------------------------------
-
-oilsArray.prototype = new domainObjectCollection()
-oilsArray.prototype.constructor = oilsArray;
-oilsArray.prototype.baseClass = domainObjectCollection.prototype.constructor;
-
-function oilsArray( obj_list ) {
- this._initCollection( "oilsArray" );
- if(obj_list) { this.initArray( obj_list ); }
-}
-
-// -----------------------------------------------------------------------------
-// Adds the array of objects to the array, these should be actual objects, not
-// DOM nodes/elements, etc.
-// -----------------------------------------------------------------------------
-oilsArray.prototype.initArray = function( obj_list ) {
- if( obj_array != null && obj_array.length > 0 ) {
- for( var i= 0; i!= obj_array.length; i++ ) {
- this.add( obj_array[i] );
- }
- }
-}
-
-// -----------------------------------------------------------------------------
-// Returns an array of DomainObjects or domainObjectCollections. The objects
-// returned will already be 'cast' into the correct object. i.e. you will not
-// receieve an array of DomainObjects, but instead an array of oilsScalar's or
-// an array of oilsHashe's, etc.
-// -----------------------------------------------------------------------------
-oilsArray.prototype.getObjects = function() {
-
- var obj_list = new Array();
- var nodes = this.element.childNodes;
- var i=0;
- var node = nodes.item(i);
-
- while( node != null ) {
-
- if( node.nodeName == "oils:domainObject" ||
- node.nodeName == "oils:domainObjectCollection" ) {
- obj_list[i++] = DomainObject.newFromNode( node );
- }
- node = nodes.item(i);
- }
-
- return obj_list;
-}
-
-
-// -----------------------------------------------------------------------------
-// oilsHash - an oilsHash is an oilsArray except it only stores oilsPair's
-// -----------------------------------------------------------------------------
-
-oilsHash.prototype = new oilsArray();
-oilsHash.prototype.constructor = oilsHash;
-oilsHash.prototype.baseClass = oilsArray.prototype.constructor;
-
-function oilsHash( pair_array ) {
- this._initCollection("oilsHash");
- if(pair_array) { this.initArray( pair_array ); }
-}
-
-// -----------------------------------------------------------------------------
-// Returns the array of oilsPairs objects that this hash contains
-// -----------------------------------------------------------------------------
-oilsHash.prototype.getPairs = function() {
- return this.getObjects();
-}
-
-
+++ /dev/null
-// ------------------------------------------------------------------
-// Houses the jabber transport code
-//
-// 1. jabber_connection - high level jabber component
-// 2. jabber_message - message class
-// 3. jabber_socket - socket handling code (shouldn't have to
-// use this class directly)
-//
-// Requires oils_utils.js
-// ------------------------------------------------------------------
-
-
-
-
-
-// ------------------------------------------------------------------
-// JABBER_CONNECTION
-// High level transport code
-
-// ------------------------------------------------------------------
-// Constructor
-// ------------------------------------------------------------------
-jabber_connection.prototype = new transport_connection();
-jabber_connection.prototype.constructor = jabber_connection;
-jabber_connection.baseClass = transport_connection.prototype.constructor;
-
-/** Initializes a jabber_connection object */
-function jabber_connection( username, password, resource ) {
-
- this.username = username;
- this.password = password;
- this.resource = resource;
- this.socket = new jabber_socket();
-
- this.host = "";
-
-}
-
-/** Connects to the Jabber server. 'timeout' is the connect timeout
- * in milliseconds
- */
-jabber_connection.prototype.connect = function( host, port, timeout ) {
- this.host = host;
- return this.socket.connect(
- this.username, this.password, this.resource, host, port, timeout );
-}
-
-/** Sends a message to 'recipient' with the provided message
- * thread and body
- */
-jabber_connection.prototype.send = function( recipient, thread, body ) {
- var jid = this.username+"@"+this.host+"/"+this.resource;
- var msg = new jabber_message( jid, recipient, thread, body );
- return this.socket.tcp_send( msg.to_string() );
-}
-
-/** This method will wait at most 'timeout' milliseconds
- * for a Jabber message to arrive. If one arrives
- * it is returned to the caller, other it returns null
- */
-jabber_connection.prototype.recv = function( timeout ) {
- return this.socket.recv( timeout );
-}
-
-/** Disconnects from the jabber server */
-jabber_connection.prototype.disconnect = function() {
- return this.socket.disconnect();
-}
-
-/** Returns true if we are currently connected to the
- * Jabber server
- */
-jabber_connection.prototype.connected = function() {
- return this.socket.connected();
-}
-
-
-
-// ------------------------------------------------------------------
-// JABBER_MESSAGE
-// High level message handling code
-
-
-jabber_message.prototype = new transport_message();
-jabber_message.prototype.constructor = jabber_message;
-jabber_message.prototype.baseClass = transport_message.prototype.constructor;
-
-/** Builds a jabber_message object */
-function jabber_message( sender, recipient, thread, body ) {
-
- if( sender == null || recipient == null || recipient.length < 1 ) { return; }
-
- this.doc = new DOMParser().parseFromString("<message></message>", "text/xml");
- this.root = this.doc.documentElement;
- this.root.setAttribute( "from", sender );
- this.root.setAttribute( "to", recipient );
-
- var body_node = this.doc.createElement("body");
- body_node.appendChild( this.doc.createTextNode( body ) );
-
- var thread_node = this.doc.createElement("thread");
- thread_node.appendChild( this.doc.createTextNode( thread ) );
-
- this.root.appendChild( body_node );
- this.root.appendChild( thread_node );
-
-}
-
-/** Builds a new message from raw xml.
- * If the message is a Jabber error message, then msg.is_error_msg
- * is set to true;
- */
-jabber_message.prototype.from_xml = function( xml ) {
- var msg = new jabber_message();
- msg.doc = new DOMParser().parseFromString( xml, "text/xml" );
- msg.root = msg.doc.documentElement;
-
- if( msg.root.getAttribute( "type" ) == "error" ) {
- msg.is_error_msg = true;
- } else {
- this.is_error_msg = false;
- }
-
- return msg;
-}
-
-/** Returns the 'from' field of the message */
-jabber_message.prototype.get_sender = function() {
- return this.root.getAttribute( "from" );
-}
-
-/** Returns the jabber thread */
-jabber_message.prototype.get_thread = function() {
- var nodes = this.root.getElementsByTagName( "thread" );
- var thread_node = nodes.item(0);
- return thread_node.firstChild.nodeValue;
-}
-
-/** Returns the message body */
-jabber_message.prototype.get_body = function() {
- var nodes = this.root.getElementsByTagName( "body" );
- var body_node = nodes.item(0);
- new Logger().transport( "Get Body returning:\n" + body_node.textContent, Logger.DEBUG );
- return body_node.textContent;
-}
-
-/** Returns the message as a whole as an XML string */
-jabber_message.prototype.to_string = function() {
- return new XMLSerializer().serializeToString(this.root);
-}
-
-
-
-
-// ------------------------------------------------------------------
-// TRANSPORT_SOCKET
-
-/** Initializes a new jabber_socket object */
-function jabber_socket() {
-
- this.is_connected = false;
- this.outstream = "";
- this.instream = "";
- this.buffer = "";
- this.socket = "";
-
-}
-
-/** Connects to the jabber server */
-jabber_socket.prototype.connect =
- function( username, password, resource, host, port, timeout ) {
-
- var starttime = new Date().getTime();
-
- // there has to be at least some kind of timeout
- if( ! timeout || timeout < 100 ) { timeout = 1000; }
-
- try {
-
- this.xpcom_init( host, port );
- this.tcp_send( "<stream:stream to='"+host
- +"' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>" );
-
- if( !this.tcp_recv( timeout ) ) { throw 1; }
-
- } catch( E ) {
- throw new oils_ex_transport( "Could not open a socket to the transport server\n"
- + "Server: " + host + " Port: " + port );
- }
-
- // Send the auth packet
- this.tcp_send( "<iq id='123456789' type='set'><query xmlns='jabber:iq:auth'><username>"
- + username + "</username><password>" + password +
- "</password><resource>" + resource + "</resource></query></iq>" );
-
- var cur = new Date().getTime();
- var remaining = timeout - ( cur - starttime );
- this.tcp_recv( remaining );
-
- if( ! this.connected() ) {
- throw new oils_ex_transport( "Connection to transport server timed out" );
- }
-
- return true;
-
-
-}
-
-
-/** Sets up all of the xpcom components */
-jabber_socket.prototype.xpcom_init = function( host, port ) {
-
- var transportService =
- Components.classes["@mozilla.org/network/socket-transport-service;1"]
- .getService(Components.interfaces.nsISocketTransportService);
-
- this.transport = transportService.createTransport( null, 0, host, port, null);
-
- // ------------------------------------------------------------------
- // Build the stream objects
- // ------------------------------------------------------------------
- this.outstream = this.transport.openOutputStream(0,0,0);
-
- var stream = this.transport.openInputStream(0,0,0);
-
- this.instream = Components.classes["@mozilla.org/scriptableinputstream;1"]
- .createInstance(Components.interfaces.nsIScriptableInputStream);
-
- this.instream.init(stream);
-
-}
-
-/** Send data to the TCP pipe */
-jabber_socket.prototype.tcp_send = function( data ) {
- new Logger().transport( "Sending Data: \n" + data, Logger.INFO );
- this.outstream.write(data,data.length);
-}
-
-
-/** Accepts data coming directly from the socket. If we're not
- * connected, we pass it off to procecc_connect(). Otherwise,
- * this method adds the data to the local buffer.
- */
-jabber_socket.prototype.process_data = function( data ) {
-
- new Logger().transport( "Received TCP data: " + data, Logger.DEBUG );
-
- if( ! this.connected() ) {
- this.process_connect( data );
- return;
- }
-
- this.buffer += data;
-
-}
-
-/** Processes connect data to verify we are logged in correctly */
-jabber_socket.prototype.process_connect = function( data ) {
-
- var reg = /type=["\']result["\']/;
- var err = /error/;
-
- if( reg.exec( data ) ) {
- this.is_connected = true;
- } else {
- if( err.exec( data ) ) {
- //throw new oils_ex_transport( "Server returned: \n" + data );
- throw new oils_ex_jabber_auth( "Server returned: \n" + data );
- // Throw exception, return something...
- }
- }
-}
-
-/** Waits up to at most 'timeout' milliseconds for data to arrive
- * in the TCP buffer. If there is at least one byte of data
- * in the buffer, then all of the data that is in the buffer is sent
- * to the process_data method for processing and the method returns.
- */
-jabber_socket.prototype.tcp_recv = function( timeout ) {
-
- var count = this.instream.available();
- var did_receive = false;
-
- // ------------------------------------------------------------------
- // If there is any data in the tcp buffer, process it and return
- // ------------------------------------------------------------------
- if( count > 0 ) {
-
- did_receive = true;
- while( count > 0 ) {
- new Logger().transport(
- "before process data", Logger.DEBUG );
-
- this.process_data( this.instream.read( count ) );
-
- new Logger().transport(
- "after process data", Logger.DEBUG );
-
- count = this.instream.available();
-
- new Logger().transport(
- "received " + count + " bytes" , Logger.DEBUG );
- }
-
- } else {
-
- // ------------------------------------------------------------------
- // Do the timeout dance
- // ------------------------------------------------------------------
-
- // ------------------------------------------------------------------
- // If there is no data in the buffer, wait up to timeout seconds
- // for some data to arrive. Once it arrives, suck it all out
- // and send it on for processing
- // ------------------------------------------------------------------
-
- var now, then;
- now = new Date().getTime();
- then = now;
-
- // ------------------------------------------------------------------
- // Loop and poll for data every 50 ms.
- // ------------------------------------------------------------------
- while( ((now-then) <= timeout) && count <= 0 ) {
- sleep(50);
- count = this.instream.available();
- now = new Date().getTime();
- }
-
- // ------------------------------------------------------------------
- // if we finally get some data, process it.
- // ------------------------------------------------------------------
- if( count > 0 ) {
-
- did_receive = true;
- while( count > 0 ) { // pull in all of the data there is
- this.process_data( this.instream.read( count ) );
- count = this.instream.available();
- }
- }
- }
-
- return did_receive;
-
-}
-
-/** If a message is already sitting in the queue, it is returned.
- * If not, this method waits till at most 'timeout' milliseconds
- * for a full jabber message to arrive and then returns that.
- * If none ever arrives, returns null.
- */
-jabber_socket.prototype.recv = function( timeout ) {
-
- var now, then;
- now = new Date().getTime();
- then = now;
-
- var first_pass = true;
- while( ((now-then) <= timeout) ) {
-
- if( this.buffer.length == 0 || !first_pass ) {
- if( ! this.tcp_recv( timeout ) ) {
- return null;
- }
- }
- first_pass = false;
-
- //new Logger().transport( "\n\nTCP Buffer Before: \n" + this.buffer, Logger.DEBUG );
-
- var buf = this.buffer;
- this.buffer = "";
-
- new Logger().transport( "CURRENT BUFFER\n" + buf,
- Logger.DEBUG );
-
- buf = buf.replace( /\n/g, '' ); // remove pesky newlines
-
- var reg = /<message.*?>.*?<\/message>/;
- var iqr = /<iq.*?>.*?<\/iq>/;
- var out = reg.exec(buf);
-
- if( out ) {
-
- var msg_xml = out[0];
- this.buffer = buf.substring( msg_xml.length, buf.length );
- new Logger().transport( "Building Jabber message\n\n" + msg_xml, Logger.DEBUG );
- var jab_msg = new jabber_message().from_xml( msg_xml );
- if( jab_msg.is_error_msg ) {
- new Logger().transport( "Received Jabber error message \n\n" + msg_xml, Logger.ERROR );
- }
-
- return jab_msg;
-
-
- } else {
-
- out = iqr.exec(buf);
-
- if( out ) {
- var msg_xml = out[0];
- this.buffer = buf.substring( msg_xml.length, buf.length );
- process_iq_data( msg_xml );
- return;
-
- } else {
- this.buffer = buf;
- }
-
- }
- now = new Date().getTime();
- }
-
- return null;
-}
-
-jabber_socket.prototype.process_iq_data = function( data ) {
- new Logger().transport( "IQ Packet received... Not Implemented\n" + data, Logger.ERROR );
-}
-
-/** Disconnects from the jabber server and closes down shop */
-jabber_socket.prototype.disconnect = function() {
- this.tcp_send( "</stream:stream>" );
- this.instream.close();
- this.outstream.close();
-}
-
-/** True if connected */
-jabber_socket.prototype.connected = function() {
- return this.is_connected;
-}
-
-
-
-
-
+++ /dev/null
-// -----------------------------------------------------------------------------
-// Message stack code.
-// -----------------------------------------------------------------------------
-
-
-
-// -----------------------------------------------------------------------------
-// These just have to be defined for the 'static' methods to work
-// -----------------------------------------------------------------------------
-function Transport() {}
-function Message() {}
-function Application() {}
-
-/** Transport handler.
- * Takes a transport_message as parameter
- * Parses the incoming message data and builds one or more oilsMessage objects
- * from the XML. Each message is passed in turn to the Message.handler
- * method.
- */
-Transport.handler = function( msg ) {
-
- if( msg.is_error_msg ) {
- throw new oils_ex_session( "Receved error message from jabber server for recipient: " + msg.get_sender() );
- return;
- }
-
- var remote_id = msg.get_sender();
- var session_id = msg.get_thread();
- var body = msg.get_body();
-
- var session = AppSession.find_session( session_id );
-
- if( ! session ) {
- new Logger().debug( "No AppSession found with id: " + session_id );
- return;
- }
-
- session.set_remote_id( remote_id );
-
- var nodelist; // oilsMessage nodes
-
-
- // -----------------------------------------------------------------------------
- // Parse the incoming XML
- // -----------------------------------------------------------------------------
- try {
-
- var doc = new DOMParser().parseFromString( body, "text/xml" );
- nodelist = doc.documentElement.getElementsByTagName( "oils:domainObject" );
-
- if( ! nodelist || nodelist.length < 1 ) {
- nodelist = doc.documentElement.getElementsByTagName( "domainObject" );
- if( ! nodelist || nodelist.length < 1 ) { throw 1; }
- }
-
- } catch( E ) {
-
- var str = "Error parsing incoming message document";
-
- if( E ) { throw new oils_ex_dom( str + "\n" + E.message + "\n" + body );
- } else { throw new oils_ex_dom( str + "\n" + body ); }
-
- }
-
- // -----------------------------------------------------------------------------
- // Pass the messages up the chain.
- // -----------------------------------------------------------------------------
- try {
-
- var i = 0;
- var node = nodelist.item(i); // a single oilsMessage
-
- while( node != null ) {
-
- if( node.getAttribute("name") != "oilsMessage" ) {
- node = nodelist.item(++i);
- continue;
- }
-
- var oils_msg = new oilsMessage().replaceNode( node );
-
-
- // -----------------------------------------------------------------------------
- // this is really inefficient compared to the above line of code,
- // however, this resolves some namespace oddities in DOMParser -
- // namely, DOMParser puts dummy namesapaces in "a0" when, I'm assuming, it
- // can't find the definition for the namesapace included.
- // -----------------------------------------------------------------------------
- // var oils_msg = oilsMessage.newFromXML( new XMLSerializer().serializeToString( node ) );
-
- new Logger().transport( "Transport passing up:\n" + oils_msg.toString(true), Logger.INFO );
-
- // Pass the message off to the message layer
- Message.handler( session, oils_msg );
- node = nodelist.item(++i);
- }
-
- } catch( E ) {
-
- var str = "Processing Error";
-
- if( E ) { throw new oils_ex_session( str + "\n" + E.message + "\n" + body ); }
- else { throw new oils_ex_session( str + "\n" + body ); }
- }
-}
-
-/** Checks to see what type of message has arrived. If it is a 'STATUS' message,
- * the appropriate transport layer actions are taken. Otherwise (RESULT), the
- * message is passed to the Application.handler method.
- */
-Message.handler = function( session, msg ) {
-
- var msg_type = msg.getType();
- var domain_object_payload = msg.getPayload();
- var tt = msg.getThreadTrace();
-
- var code = domain_object_payload.getStatusCode();
-
- new Logger().debug( "Message.handler received " + msg_type + " from " +
- session.get_remote_id() + " with thread_trace " + tt + " and status " + code, Logger.INFO );
- new Logger().debug( "Message.handler received:\n" + domain_object_payload.toString(), Logger.DEBUG );
-
- if( msg_type == oilsMessage.STATUS ) {
-
- switch( code ) {
-
- case oilsResponse.STATUS_OK + "": {
- session.set_state( AppSession.CONNECTED );
- new Logger().debug( " * Connected Successfully: " + tt, Logger.INFO );
- return;
- }
-
- case oilsResponse.STATUS_TIMEOUT + "": {
- return Message.reset_session( session, tt, "Disconnected because of timeout" );
- }
-
- case oilsResponse.STATUS_REDIRECTED + "": {
- return Message.reset_session( session, tt, "Disconnected because of redirect" );
- }
-
- case oilsResponse.STATUS_EXPFAILED + "": {
- return Message.reset_session( session, tt, "Disconnected because of mangled session" );
- }
-
- case oilsResponse.STATUS_NOTALLOWED + "": {
- new Logger().debug( "Method Not Allowed", Logger.ERROR );
- session.destroy();
- break; // we want the exception to be thrown below
- }
-
- case oilsResponse.STATUS_CONTINUE +"": {
- return;
- }
-
- case oilsResponse.STATUS_COMPLETE + "": {
- var req = session.get_request(tt);
- if( req ) {
- req.set_complete();
- new Logger().debug( " * Request completed: " + tt, Logger.INFO );
- }
- return;
- }
-
- default: { break; }
- }
-
- }
-
- // throw any exceptions received from the server
- if( domain_object_payload instanceof oilsException ) {
- throw new oils_ex_session( domain_object_payload.getStatus() );
- }
-
- new Logger().debug( "Message Layer passing up:\n" + domain_object_payload.toString(), Logger.DEBUG );
-
- Application.handler( session, domain_object_payload, tt );
-
-}
-
-/** Utility method for cleaning up a session. Sets state to disconnected.
- * resets the remoted_id, pushes the current app_request onto the resend
- * queue. Logs a message.
- */
-Message.reset_session = function( session, thread_trace, message ) {
- session.set_state( AppSession.DISCONNECTED );
- session.reset_remote();
- var req = session.get_request( thread_trace );
- if( req && !req.complete() ) { session.push_resend( req ); }
- new Logger().debug( " * " + message + " : " + thread_trace, Logger.INFO );
-}
-
-
-/** Pushes all incoming messages onto the session message queue. **/
-Application.handler = function( session, domain_object_payload, thread_trace ) {
-
- new Logger().debug( "Application Pushing onto queue: "
- + thread_trace + "\n" + domain_object_payload.toString(), Logger.DEBUG );
-
- session.push_queue( domain_object_payload, thread_trace );
-}
-
-
-
-
-
+++ /dev/null
-/** @file oils_transport.js
- * Houses the top level transport 'abstract' classes
- * You can think of this like a header file which provides the
- * interface that any transport code must implement
- */
-
-
-// ------------------------------------------------------------------
-// TRANSPORT_CONNECTION
-
-/** Constructor */
-function transport_connection( username, password, resource ) { }
-
-/** Connects to the transport host */
-transport_connection.prototype.connect = function( host, /*int*/ port, /*int*/ timeout ) {}
-
-/** Sends a new message to recipient, with session_id and body */
-transport_connection.prototype.send = function( recipient, session_id, body ) {}
-
-
-/** Returns a transport_message. This function will return
- * immediately if there is a message available. Otherwise, it will
- * wait at most 'timeout' seconds for one to arrive. Returns
- * null if a message does not arrivae in time.
-
- * 'timeout' is specified in milliseconds
- */
-transport_connection.prototype.recv = function( /*int*/ timeout ) {}
-
-/** This method calls recv and then passes the contents on to the
- * message processing stack.
- */
-transport_connection.prototype.process_msg = function( /*int*/ timeout ) {
- var msg = this.recv( timeout );
- if( msg ) { Transport.handler( msg ); }
-}
-
-/** Disconnects from the transpot host */
-transport_connection.prototype.disconnect = function() {}
-
-/** Returns true if this connection instance is currently connected
- * to the transport host.
- */
-transport_connection.prototype.connected = function() {}
-
-
-
-// ------------------------------------------------------------------
-// TRANSPORT_MESSAGE
-
-
-/** Constructor */
-function transport_message( sender, recipient, session_id, body ) {}
-
-/** Returns the sender of the message */
-transport_message.prototype.get_sender = function() {}
-
-/** Returns the session id */
-transport_message.prototype.get_session = function() {}
-
-/** Returns the message body */
-transport_message.prototype.get_body = function() {}
-
-
+++ /dev/null
-// ------------------------------------------------------------------
-// Houses utility functions
-// ------------------------------------------------------------------
-
-/** Prints to console. If alert_bool = true, displays a popup as well */
-function _debug( message, alert_bool ) {
-
- dump( "\n" + new Date() + "\n--------------------------------\n" +
- message + "\n-----------------------------------\n" );
- if( alert_bool == true ) { alert( message ) };
-
-}
-
-
-/** Provides millisec sleep times, enjoy... */
-function sleep(gap){
-
- var threadService = Components.classes["@mozilla.org/thread;1"].
- getService(Components.interfaces.nsIThread);
-
- var th = threadService.currentThread;
- th.sleep(gap);
-}
-
-
-
-/** Top level exception classe */
-function oils_ex() {}
-
-/** Initializes an exception */
-oils_ex.prototype.init_ex = function( name, message ) {
- if( !(name && message) ) { return; }
- this.name = name;
- this.message = name + " : " + message;
- new Logger().debug( "***\n" + this.message + "\n***", Logger.ERROR );
-}
-
-/** Returns a string representation of an exception */
-oils_ex.prototype.toString = function() {
- return this.message;
-}
-
-
-oils_ex_transport.prototype = new oils_ex();
-oils_ex_transport.prototype.constructor = oils_ex_transport;
-oils_ex_transport.baseClass = oils_ex.prototype.constructor;
-
-/** Thrown when the transport connection has problems*/
-function oils_ex_transport( message ) {
- this.init_ex( "Transport Exception", message );
-}
-
-
-oils_ex_transport_auth.prototype = new oils_ex_transport();
-oils_ex_transport_auth.prototype.constructor = oils_ex_transport_auth;
-oils_ex_transport_auth.baseClass = oils_ex_transport.prototype.constructor;
-
-/** Thrown when the initial transport connection fails */
-function oils_ex_transport_auth( message ) {
- this.init_ex( "Transport Authentication Error", message );
-}
-
-oils_ex_dom.prototype = new oils_ex();
-oils_ex_dom.prototype.constructor = oils_ex_dom;
-oils_ex_dom.baseClass = oils_ex.prototype.constructor;
-
-/** Thrown when there is an XML problem */
-function oils_ex_dom( message ) {
- this.init_ex( "DOM Error", message );
-}
-
-oils_ex_message.prototype = new oils_ex();
-oils_ex_message.prototype.constructor = oils_ex_message;
-oils_ex_message.baseClass = oils_ex.prototype.constructor;
-
-/** Thrown when there is a message problem */
-function oils_ex_message( message ) {
- this.init_ex( "OILS Message Layer Error", message ) ;
-}
-
-oils_ex_config.prototype = new oils_ex();
-oils_ex_config.prototype.constructor = oils_ex_config;
-oils_ex_config.prototype.baseClass = oils_ex.prototype.constructor;
-
-/** Thrown when values cannot be retrieved from the config file */
-function oils_ex_config( message ) {
- this.init_ex( "OILS Config Exception", message );
-}
-
-oils_ex_logger.prototype = new oils_ex();
-oils_ex_logger.prototype.constructor = oils_ex_logger;
-oils_ex_logger.prototype.baseClass = oils_ex.prototype.constructor;
-
-/** Thrown where there are logging problems */
-function oils_ex_logger( message ) {
- this.init_ex( "OILS Logger Exception", message );
-}
-
-
-oils_ex_args.prototype = new oils_ex();
-oils_ex_args.prototype.constructor = oils_ex_args;
-oils_ex_args.prototype.baseClass = oils_ex.prototype.constructor;
-
-/** Thrown when when a method does not receive all of the required arguments */
-function oils_ex_args( message ) {
- this.init_ex( "Method Argument Exception", message );
-}
-
-
-oils_ex_session.prototype = new oils_ex();
-oils_ex_session.prototype.constructor = oils_ex_session;
-oils_ex_session.prototype.baseClass = oils_ex.prototype.constructor;
-
-/** Thrown where there is a session processing problem */
-function oils_ex_session( message ) {
- this.init_ex( "Session Exception", message );
-}
+++ /dev/null
-LDLIBS += -lopensrf -lobjson -lxml2
-CFLAGS += -D_GNU_SOURCE
-
-all: chopchop
-
-chopchop: osrf_chat.o osrf_chat_main.o
- $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) osrf_chat.o osrf_chat_main.o -o $@
-
-osrf_chat.o: osrf_chat.c osrf_chat.h
-osrf_chat_main.o: osrf_chat_main.c
-
-install:
- cp chopchop $(BINDIR)
-
-clean:
- /bin/rm -f *.o chopchop
-
+++ /dev/null
-/*
-Copyright (C) 2005 Georgia Public Library Service
-Bill Erickson <billserickson@gmail.com>
-
-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; either version 2
-of the License, or (at your option) any later version.
-
-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.
-*/
-
-#include "osrf_chat.h"
-#include <string.h>
-#include <stdio.h>
-#include <time.h>
-
-int __osrfChatXMLErrorOcurred = 0;
-int __osrfChatClientSentDisconnect = 0;
-
-/* shorter version of strcmp */
-static int eq(const char* a, const char* b) { return (a && b && !strcmp(a,b)); }
-//#define eq(a,b) ((a && b && !strcmp(a,b)) ? 1 : 0)
-
-/* gnarly debug function */
-static void chatdbg( osrfChatServer* server ) {
-
- if(!server) return;
- return; /* heavy logging, should only be used in heavy debug mode */
-
- growing_buffer* buf = buffer_init(256);
-
- buffer_add(buf, "---------------------------------------------------------------------\n");
-
- buffer_fadd(buf,
- "ChopChop Debug:\n"
- "Connections: %lu\n"
- "Named nodes in hash: %lu\n"
- "Domain: %s\n"
- "Port: %d\n"
- "S2S Port: %d\n"
- "-------------------------------------------------------\n",
- osrfListGetCount(server->nodeList), osrfHashGetCount(server->nodeHash),
- server->domain, server->port, server->s2sport );
-
- osrfListIterator* itr = osrfNewListIterator(server->nodeList);
- osrfChatNode* node;
-
- while( (node = osrfListIteratorNext(itr)) ) {
-
- buffer_fadd( buf,
- "sockid: %d\n"
- "Remote: %s\n"
- "State: %d\n"
- "XMLState: %d\n"
- "In Parse: %d\n"
- "to: %s\n"
- "Resource: %s\n"
- "Username: %s\n"
- "Domain: %s\n"
- "Authkey: %s\n"
- "type: %d\n"
- "-------------------------------------------------------\n",
- node->sockid, node->remote, node->state, node->xmlstate, node->inparse,
- node->to, node->resource, node->username, node->domain, node->authkey, node->type );
- }
-
- osrfLogDebug( OSRF_LOG_MARK, "DEBUG:\n%s", buf->buf );
- buffer_free(buf);
- osrfListIteratorFree(itr);
-}
-
-osrfChatServer* osrfNewChatServer( char* domain, char* secret, int s2sport ) {
- if(!(domain && secret)) return NULL;
-
- osrfChatServer* server = safe_malloc(sizeof(osrfChatServer));
-
- server->nodeHash = osrfNewHash();
- server->nodeList = osrfNewList();
- server->deadNodes = osrfNewList();
- server->nodeList->freeItem = &osrfChatNodeFree;
- server->domain = strdup(domain);
- server->s2sport = s2sport;
-
- server->mgr = safe_malloc(sizeof(socket_manager));
- server->mgr->data_received = &osrfChatHandleData;
- server->mgr->blob = server;
- server->mgr->on_socket_closed = &osrfChatSocketClosed;
-
- if(secret) server->secret = strdup(secret);
- return server;
-}
-
-void osrfChatCleanupClients( osrfChatServer* server ) {
- if(!server) return;
- osrfListFree(server->deadNodes);
- server->deadNodes = osrfNewList();
-}
-
-
-
-osrfChatNode* osrfNewChatNode( int sockid, char* domain ) {
- if(sockid < 1 || !domain) return NULL;
- osrfChatNode* node = safe_malloc(sizeof(osrfChatNode));
- node->state = OSRF_CHAT_STATE_NONE;
- node->msgs = NULL; /* only s2s nodes cache messages */
- node->parserCtx = xmlCreatePushParserCtxt(osrfChatSaxHandler, node, "", 0, NULL);
- node->msgDoc = xmlNewDoc(BAD_CAST "1.0");
- node->domain = strdup(domain);
- xmlKeepBlanksDefault(0);
- node->authkey = NULL;
- node->username = NULL;
- node->resource = NULL;
- node->to = NULL;
- node->type = 0;
- return node;
-}
-
-
-osrfChatNode* osrfNewChatS2SNode( char* domain, char* remote ) {
- if(!(domain && remote)) return NULL;
- osrfChatNode* n = osrfNewChatNode( 1, domain );
- n->state = OSRF_CHAT_STATE_S2S_CHALLENGE;
- n->sockid = -1;
- n->remote = strdup(remote);
- n->msgs = osrfNewList();
- n->msgs->freeItem = &osrfChatS2SMessageFree;
- n->type = 1;
- return n;
-}
-
-void osrfChatS2SMessageFree(void* n) { free(n); }
-
-void osrfChatNodeFree( void* node ) {
- if(!node) return;
- osrfChatNode* n = (osrfChatNode*) node;
-
- /* we can't free messages that are mid-parse because the
- we can't free the parser context */
- if(n->inparse) {
- n->inparse = 0;
- osrfListPush(n->parent->deadNodes, n);
- return;
- }
-
- free(n->remote);
- free(n->to);
- free(n->username);
- free(n->resource);
- free(n->domain);
- free(n->authkey);
-
- osrfListFree(n->msgs);
-
- if(n->parserCtx) {
- xmlFreeDoc(n->parserCtx->myDoc);
- xmlFreeParserCtxt(n->parserCtx);
- }
-
- xmlFreeDoc(n->msgDoc);
- free(n);
-}
-
-
-
-int osrfChatServerConnect( osrfChatServer* cs, int port, int s2sport, char* listenAddr ) {
- if(!(cs && port && listenAddr)) return -1;
- cs->port = port;
- cs->s2sport = s2sport;
- if( socket_open_tcp_server(cs->mgr, port, listenAddr ) < 0 )
- return -1;
- if( socket_open_tcp_server(cs->mgr, s2sport, listenAddr ) < 0 )
- return -1;
- return 0;
-}
-
-
-int osrfChatServerWait( osrfChatServer* server ) {
- if(!server) return -1;
- while(1) {
- if(socket_wait_all(server->mgr, -1) < 0)
- osrfLogWarning( OSRF_LOG_MARK, "jserver_wait(): socket_wait_all() returned error");
- }
- return -1;
-}
-
-
-void osrfChatServerFree(osrfChatServer* server ) {
- if(!server) return;
- osrfHashFree(server->nodeHash);
- osrfListFree(server->nodeList);
- free(server->mgr);
- free(server->secret);
-}
-
-
-void osrfChatHandleData( void* cs,
- socket_manager* mgr, int sockid, char* data, int parent_id ) {
-
- if(!(cs && mgr && sockid && data)) return;
-
- osrfChatServer* server = (osrfChatServer*) cs;
-
- osrfChatNode* node = osrfListGetIndex( server->nodeList, sockid );
-
- if(node)
- osrfLogDebug( OSRF_LOG_MARK, "Found node for sockid %d with state %d", sockid, node->state);
-
- if(!node) {
- osrfLogDebug( OSRF_LOG_MARK, "Adding new connection for sockid %d", sockid );
- node = osrfChatAddNode( server, sockid );
- }
-
- if(node) {
- if( (osrfChatPushData( server, node, data ) == -1) ) {
- osrfLogError( OSRF_LOG_MARK,
- "Node at socket %d with remote address %s and destination %s, "
- "received bad XML [%s], disconnecting...", sockid, node->remote, node->to, data );
- osrfChatSendRaw( node, OSRF_CHAT_PARSE_ERROR );
- osrfChatRemoveNode( server, node );
- }
- }
-
- osrfChatCleanupClients(server); /* clean up old dead clients */
-}
-
-
-void osrfChatSocketClosed( void* blob, int sockid ) {
- if(!blob) return;
- osrfChatServer* server = (osrfChatServer*) blob;
- osrfChatNode* node = osrfListGetIndex(server->nodeList, sockid);
- osrfChatRemoveNode( server, node );
-}
-
-osrfChatNode* osrfChatAddNode( osrfChatServer* server, int sockid ) {
- if(!(server && sockid)) return NULL;
- osrfChatNode* node = osrfNewChatNode(sockid, server->domain);
- node->parent = server;
- node->sockid = sockid;
- osrfListSet( server->nodeList, node, sockid );
- return node;
-}
-
-void osrfChatRemoveNode( osrfChatServer* server, osrfChatNode* node ) {
- if(!(server && node)) return;
- socket_disconnect(server->mgr, node->sockid);
- if(node->remote)
- osrfHashRemove( server->nodeHash, node->remote );
- osrfListRemove( server->nodeList, node->sockid ); /* this will free it */
-}
-
-int osrfChatSendRaw( osrfChatNode* node, char* msgXML ) {
- if(!(node && msgXML)) return -1;
- /* wait at most 3 second for this client to take our data */
- return socket_send_timeout( node->sockid, msgXML, 3000000 );
-}
-
-void osrfChatNodeFinish( osrfChatServer* server, osrfChatNode* node ) {
- if(!(server && node)) return;
- osrfChatSendRaw( node, "</stream:stream>");
- osrfChatRemoveNode( server, node );
-}
-
-
-int osrfChatSend( osrfChatServer* cs, osrfChatNode* node, char* toAddr, char* fromAddr, char* msgXML ) {
- if(!(cs && node && toAddr && msgXML)) return -1;
-
- int l = strlen(toAddr);
- char dombuf[l];
- bzero(dombuf, l);
- jid_get_domain( toAddr, dombuf, l );
-
- if( eq( dombuf, cs->domain ) ) { /* this is to a user we host */
-
- osrfLogInfo( OSRF_LOG_MARK, "Sending message on local connection\nfrom: %s\nto: %s", fromAddr, toAddr );
- osrfChatNode* tonode = osrfHashGet(cs->nodeHash, toAddr);
- if(tonode) {
-
- /* if we can't send to the recipient (recipient is gone or too busy,
- * we drop the recipient and inform the sender that the recipient
- * is no more */
- if( osrfChatSendRaw( tonode, msgXML ) < 0 ) {
-
- osrfChatRemoveNode( cs, tonode );
- char* xml = va_list_to_string( OSRF_CHAT_NO_RECIPIENT, toAddr, fromAddr );
-
- osrfLogError( OSRF_LOG_MARK, "Node failed to function. "
- "Responding to caller with error: %s", toAddr);
-
-
- if( osrfChatSendRaw( node, xml ) < 0 ) {
- osrfLogError(OSRF_LOG_MARK, "Sending node is now gone..removing");
- osrfChatRemoveNode( cs, node );
- }
- free(xml);
- }
-
- } else {
-
- /* send an error message saying we don't have this connection */
- osrfLogInfo( OSRF_LOG_MARK, "We have no connection for %s", toAddr);
- char* xml = va_list_to_string( OSRF_CHAT_NO_RECIPIENT, toAddr, fromAddr );
- if( osrfChatSendRaw( node, xml ) < 0 )
- osrfChatRemoveNode( cs, node );
- free(xml);
- }
-
- } else {
-
- osrfChatNode* tonode = osrfHashGet(cs->nodeHash, dombuf);
- if(tonode) {
- if( tonode->state == OSRF_CHAT_STATE_CONNECTED ) {
- osrfLogDebug( OSRF_LOG_MARK, "Routing message to server %s", dombuf);
-
- if( osrfChatSendRaw( tonode, msgXML ) < 0 ) {
- osrfLogError( OSRF_LOG_MARK, "Node failed to function: %s", toAddr);
- char* xml = va_list_to_string( OSRF_CHAT_NO_RECIPIENT, toAddr, fromAddr );
- if( osrfChatSendRaw( node, xml ) < 0 )
- osrfChatRemoveNode( cs, node );
- free(xml);
- osrfChatRemoveNode( cs, tonode );
- }
-
- } else {
- osrfLogInfo( OSRF_LOG_MARK, "Received s2s message and we're still trying to connect...caching");
- osrfListPush( tonode->msgs, strdup(msgXML) );
- }
-
- } else {
-
- if( osrfChatInitS2S( cs, dombuf, toAddr, msgXML ) != 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "We are unable to connect to remote server %s for recipient %s", dombuf, toAddr);
- char* xml = va_list_to_string( OSRF_CHAT_NO_RECIPIENT, toAddr, fromAddr );
- osrfChatSendRaw( node, xml );
- free(xml);
- }
- }
- }
-
- return 0;
-}
-
-
-/*
-void osrfChatCacheS2SMessage( char* toAddr, char* msgXML, osrfChatNode* snode ) {
- if(!(toAddr && msgXML)) return;
- osrfChatS2SMessage* msg = safe_malloc(sizeof(osrfChatS2SMessage));
- msg->toAddr = strdup(toAddr);
- msg->msgXML = strdup(msgXML);
- osrfLogInfo( OSRF_LOG_MARK, "Pushing client message onto s2s queue waiting for connect... ");
- osrfListPush( snode->msgs, msgXML );
-}
-*/
-
-
-int osrfChatInitS2S( osrfChatServer* cs, char* remote, char* toAddr, char* msgXML ) {
- if(!(cs && remote && toAddr && msgXML)) return -1;
-
- osrfLogInfo( OSRF_LOG_MARK, "Initing server2server connection to domain %s", remote );
- osrfChatNode* snode = osrfNewChatS2SNode( cs->domain, remote );
- snode->parent = cs;
-
- /* try to connect to the remote site */
- snode->sockid = socket_open_tcp_client(cs->mgr, cs->s2sport, remote);
- if(snode->sockid < 1) {
- osrfLogWarning( OSRF_LOG_MARK, "Unable to connect to remote server at %s", remote );
- return -1;
- }
-
- /* store the message we were supposed to deliver until we're fully connected */
- //osrfChatCacheS2SMessage( toAddr, msgXML, snode );
- osrfListPush( snode->msgs, strdup(msgXML) );
- osrfHashSet(cs->nodeHash, snode, remote );
- osrfListSet(cs->nodeList, snode, snode->sockid );
-
- /* send the initial s2s request */
- osrfChatSendRaw( snode, OSRF_CHAT_S2S_INIT );
-
- osrfLogDebug( OSRF_LOG_MARK, "Added new s2s node...");
- chatdbg(cs);
-
- return 0;
-}
-
-
-/* commence SAX handling code */
-
-int osrfChatPushData( osrfChatServer* server, osrfChatNode* node, char* data ) {
- if(!(node && data)) return -1;
-
- chatdbg(server);
-
- osrfLogDebug( OSRF_LOG_MARK, "pushing data into xml parser for node %d with state %d:\n%s",
- node->sockid, node->state, data);
- node->inparse = 1;
- xmlParseChunk(node->parserCtx, data, strlen(data), 0);
- node->inparse = 0;
-
- if(__osrfChatXMLErrorOcurred) {
- __osrfChatXMLErrorOcurred = 0;
- return -1;
- }
-
- /* we can't do cleanup of the XML handlers while in the middle of a
- data push, so set flags in the data push and doe the cleanup here */
- /*
- if(__osrfChatClientSentDisconnect) {
- __osrfChatClientSentDisconnect = 0;
- osrfChatNodeFinish( server, node );
- }
- */
-
- return 0;
-}
-
-
-void osrfChatStartStream( void* blob ) {
- osrfLogDebug( OSRF_LOG_MARK, "Starting new client stream...");
-}
-
-
-void osrfChatStartElement( void* blob, const xmlChar *name, const xmlChar **atts ) {
- if(!(blob && name)) return;
- osrfChatNode* node = (osrfChatNode*) blob;
-
- int status = -1;
- char* nm = (char*) name;
-
- osrfLogDebug( OSRF_LOG_MARK, "Starting element %s with namespace %s and node state %d",
- nm, xmlSaxAttr(atts, "xmlns"), node->state );
-
- switch( node->state ) {
-
- case OSRF_CHAT_STATE_NONE:
- status = osrfChatHandleNewConnection( node, nm, atts );
- osrfLogDebug( OSRF_LOG_MARK, "After NewConnection we have state %d", node->state);
- break;
-
- case OSRF_CHAT_STATE_CONNECTING:
- status = osrfChatHandleConnecting( node, nm, atts );
- break;
-
- case OSRF_CHAT_STATE_CONNECTED:
- status = osrfChatHandleConnected( node, nm, atts );
- break;
-
- case OSRF_CHAT_STATE_S2S_CHALLENGE:
- status = osrfChatHandleS2SChallenge( node, nm, atts );
- break;
-
- case OSRF_CHAT_STATE_S2S_RESPONSE: /* server waiting for client response to challenge */
- if(eq(nm, "db:result")) {
- char* remote = xmlSaxAttr(atts, "from");
- if(remote) node->remote = strdup(remote); /* copy off the client's id */
- status = 0;
- node->xmlstate |= OSRF_CHAT_STATE_INS2SRESULT;
- } else status = -1;
- break;
-
- case OSRF_CHAT_STATE_S2S_VERIFY: /* client : waiting for server verify message */
- if(eq(nm, "db:verify")) {
- char* id = xmlSaxAttr( atts, "id" );
- if(id) {
- char* xml = va_list_to_string( OSRF_CHAT_S2S_VERIFY_RESPONSE,
- node->remote, node->domain, id );
- osrfChatSendRaw( node, xml );
- free(xml);
- node->state = OSRF_CHAT_STATE_S2S_VERIFY_FINAL;
- status = 0;
- }
- }
- break;
-
- case OSRF_CHAT_STATE_S2S_VERIFY_RESPONSE: /* server waiting for client verify response */
- case OSRF_CHAT_STATE_S2S_VERIFY_FINAL: /* client waitig for final verify */
- status = osrfChatHandleS2SConnected( node, nm, atts );
- break;
-
- }
-
- if(status != 0)
- osrfChatParseError( node, "We don't know how to handle the XML data received" );
-}
-
-#define CHAT_CHECK_VARS(x,y,z) if(!(x && y)) return -1; if(z) osrfLogDebug( OSRF_LOG_MARK, z);
-
-
-
-int osrfChatHandleS2SConnected( osrfChatNode* node, const char* name, const xmlChar**atts ) {
- CHAT_CHECK_VARS(node, name, "osrfChatHandleS2SConnected" );
-
- int status = -1;
-
- if(eq(name,"db:verify")) { /* server receives verify from client */
- char* xml = va_list_to_string(OSRF_CHAT_S2S_VERIFY_FINAL, node->domain, node->remote );
- osrfChatSendRaw(node, xml );
- free(xml);
- status = 0;
- }
-
- if(eq(name, "db:result")) {
- /* send all the messages that we have queued for this server */
- node->state = OSRF_CHAT_STATE_CONNECTED;
- osrfListIterator* itr = osrfNewListIterator(node->msgs);
-
- char* xml;
- while( (xml = (char*) osrfListIteratorNext(itr)) ) {
- xmlDocPtr doc = xmlParseMemory(xml, strlen(xml));
- if(doc) {
- char* from = (char*) xmlGetProp(xmlDocGetRootElement(doc), BAD_CAST "from");
- char* to = (char*) xmlGetProp(xmlDocGetRootElement(doc), BAD_CAST "to");
- osrfChatSend( node->parent, node, to, from, xml );
- osrfLogDebug( OSRF_LOG_MARK, "Sending cached message from %s to %s", from, to);
- xmlFree(to); xmlFree(from);
- xmlFreeDoc(doc);
- }
- }
-
- osrfListIteratorFree(itr);
- osrfListFree(node->msgs);
- node->msgs = NULL;
- status = 0;
- }
-
- if(status == 0) {
- osrfLogInfo( OSRF_LOG_MARK, "Successfully made S2S connection to %s", node->remote );
- node->state = OSRF_CHAT_STATE_CONNECTED;
- node->xmlstate = 0;
- }
-
- return status;
-}
-
-
-/** check the namespace of the stream message to see if it's a server or client connection */
-int osrfChatHandleNewConnection( osrfChatNode* node, const char* name, const xmlChar** atts ) {
- CHAT_CHECK_VARS(node, name, "osrfChatHandleNewConnection()");
-
- if(!eq(name, "stream:stream")) return -1;
-
- node->authkey = osrfChatMkAuthKey();
- char* ns = xmlSaxAttr(atts, "xmlns");
- if(!ns) return -1;
-
- if(eq(ns, "jabber:client")) { /* client connection */
-
- char* domain = xmlSaxAttr( atts, "to" );
- if(!domain) return -1;
-
- if(!eq(domain, node->domain)) {
- osrfLogWarning( OSRF_LOG_MARK,
- "Client attempting to connect to invalid domain %s. Our domain is %s", domain, node->domain);
- return -1;
- }
-
- char* buf = va_list_to_string( OSRF_CHAT_START_STREAM, domain, node->authkey );
- node->state = OSRF_CHAT_STATE_CONNECTING;
-
- osrfLogDebug( OSRF_LOG_MARK, "Server node %d setting state to OSRF_CHAT_STATE_CONNECTING[%d]",
- node->sockid, node->state );
-
- osrfLogDebug( OSRF_LOG_MARK, "Server responding to connect message with\n%s\n", buf );
- osrfChatSendRaw( node, buf );
- free(buf);
- return 0;
- }
-
- /* server to server init */
- if(eq(ns, "jabber:server")) { /* client connection */
- osrfLogInfo( OSRF_LOG_MARK, "We received a new server 2 server connection, generating auth key...");
- char* xml = va_list_to_string( OSRF_CHAT_S2S_CHALLENGE, node->authkey );
- osrfChatSendRaw( node, xml );
- free(xml);
- node->state = OSRF_CHAT_STATE_S2S_RESPONSE; /* the next message should be the response */
- node->type = 1;
- return 0;
- }
-
- return -1;
-}
-
-
-
-char* osrfChatMkAuthKey() {
- char keybuf[112];
- bzero(keybuf, 112);
- snprintf(keybuf, 111, "%d%ld%s", (int) time(NULL), (long) getpid(), getenv("HOSTNAME"));
- return strdup(shahash(keybuf));
-}
-
-int osrfChatHandleConnecting( osrfChatNode* node, const char* name, const xmlChar** atts ) {
- CHAT_CHECK_VARS(node, name, "osrfChatHandleConnecting()");
- osrfLogDebug( OSRF_LOG_MARK, "Handling connect node %s", name );
-
- if(eq(name, "iq")) node->xmlstate |= OSRF_CHAT_STATE_INIQ;
- else if(eq(name,"username")) node->xmlstate |= OSRF_CHAT_STATE_INUSERNAME;
- else if(eq(name,"resource")) node->xmlstate |= OSRF_CHAT_STATE_INRESOURCE;
- return 0;
-}
-
-int osrfChatHandleConnected( osrfChatNode* node, const char* name, const xmlChar** atts ) {
- CHAT_CHECK_VARS(node, name, "osrfChatHandleConnected()");
-
- if(eq(name,"message")) {
-
- /* drop the old message and start with a new one */
- xmlNodePtr root = xmlNewNode(NULL, name);
- xmlAddAttrs(root, atts);
- xmlNodePtr oldRoot = xmlDocSetRootElement(node->msgDoc, root);
- free(node->to);
-
- char* to = xmlSaxAttr(atts, "to");
- if(!to) to = "";
-
- node->to = strdup(to);
- if(oldRoot) xmlFreeNode(oldRoot);
- node->xmlstate = OSRF_CHAT_STATE_INMESSAGE;
-
- } else {
-
- /* all non "message" nodes are simply added to the message */
- xmlNodePtr nodep = xmlNewNode(NULL, name);
- xmlAddAttrs(nodep, atts);
- xmlAddChild(xmlDocGetRootElement(node->msgDoc), nodep);
- }
-
- return 0;
-}
-
-/* takes s2s secret, hashdomain, and the s2s auth token */
-static char* osrfChatGenerateS2SKey( char* secret, char* hashdomain, char* authtoken ) {
- if(!(secret && hashdomain && authtoken)) return NULL;
- osrfLogInfo( OSRF_LOG_MARK, "Generating s2s key with auth token: %s", authtoken );
- char* a = shahash(secret);
- osrfLogDebug( OSRF_LOG_MARK, "S2S secret hash: %s", a);
- char* b = va_list_to_string("%s%s", a, hashdomain);
- char* c = shahash(b);
- osrfLogDebug( OSRF_LOG_MARK, "S2S intermediate hash: %s", c);
- char* d = va_list_to_string("%s%s", c, authtoken);
- char* e = strdup(shahash(d));
- free(b); free(d);
- return e;
-}
-
-int osrfChatHandleS2SChallenge( osrfChatNode* node, const char* name, const xmlChar** atts ) {
- CHAT_CHECK_VARS(node, name, "osrfChatHandleS2SChallenge()");
-
-/* here we respond to the stream challenge */
- if(eq(name, "stream:stream")) {
- char* id = xmlSaxAttr(atts, "id");
- if(id) {
- /* we use our domain in the s2s challenge hash */
- char* d = osrfChatGenerateS2SKey(node->parent->secret, node->domain, id );
- char* e = va_list_to_string(OSRF_CHAT_S2S_RESPONSE, node->remote, node->domain, d );
- osrfLogInfo( OSRF_LOG_MARK, "Answering s2s challenge with key: %s", e );
- osrfChatSendRaw( node, e );
- free(d); free(e);
- node->state = OSRF_CHAT_STATE_S2S_VERIFY;
- return 0;
- }
- }
-
- return -1;
-}
-
-/*
-int osrfChatHandleS2SResponse( osrfChatNode* node, const char* name, const xmlChar** atts ) {
- CHAT_CHECK_VARS(node, name, "osrfChatHandleS2SResponse()");
-
- if(eq(name, "db:result")) {
- node->xmlstate |= OSRF_CHAT_STATE_INS2SRESULT;
- return 0;
- }
-
- return -1;
-}
-*/
-
-
-
-void osrfChatEndElement( void* blob, const xmlChar* name ) {
- if(!(blob && name)) return;
- osrfChatNode* node = (osrfChatNode*) blob;
-
- char* nm = (char*) name;
-
- if(eq(nm,"stream:stream")) {
- osrfChatNodeFinish( node->parent, node );
- return;
- }
-
- if( node->state == OSRF_CHAT_STATE_CONNECTED ) {
- if(eq(nm, "message")) {
-
- xmlNodePtr msg = xmlDocGetRootElement(node->msgDoc);
- if(msg && node->type == 0)
- xmlSetProp(msg, BAD_CAST "from", BAD_CAST node->remote );
- char* string = xmlDocToString(node->msgDoc, 0 );
-
- char* from = (char*) xmlGetProp(msg, BAD_CAST "from");
- osrfLogDebug( OSRF_LOG_MARK, "Routing message to %s\n%s\n", node->to, from, string );
- osrfChatSend( node->parent, node, node->to, from, string );
- xmlFree(from);
- free(string);
- }
- }
-
- if( node->state == OSRF_CHAT_STATE_CONNECTING ) {
- if( node->xmlstate & OSRF_CHAT_STATE_INIQ ) {
-
- if(eq(nm, "iq")) {
- node->xmlstate &= ~OSRF_CHAT_STATE_INIQ;
- node->remote = va_list_to_string(
- "%s@%s/%s", node->username, node->domain, node->resource );
-
- osrfLogInfo( OSRF_LOG_MARK, "%s successfully logged in", node->remote );
-
- osrfLogDebug( OSRF_LOG_MARK, "Setting remote address to %s", node->remote );
- osrfChatSendRaw( node, OSRF_CHAT_LOGIN_OK );
- if(osrfHashGet( node->parent->nodeHash, node->remote ) ) {
- osrfLogWarning( OSRF_LOG_MARK, "New node replaces existing node for remote id %s", node->remote);
- osrfHashRemove(node->parent->nodeHash, node->remote);
- }
- osrfHashSet( node->parent->nodeHash, node, node->remote );
- node->state = OSRF_CHAT_STATE_CONNECTED;
- }
- }
- }
-}
-
-
-void osrfChatHandleCharacter( void* blob, const xmlChar *ch, int len) {
- if(!(blob && ch && len)) return;
- osrfChatNode* node = (osrfChatNode*) blob;
-
- /*
- osrfLogDebug( OSRF_LOG_MARK, "Char Handler: state %d, xmlstate %d, chardata %s",
- node->state, node->xmlstate, (char*) ch );
- */
-
- if( node->state == OSRF_CHAT_STATE_CONNECTING ) {
- if( node->xmlstate & OSRF_CHAT_STATE_INIQ ) {
-
- if( node->xmlstate & OSRF_CHAT_STATE_INUSERNAME ) {
- free(node->username);
- node->username = strndup((char*) ch, len);
- node->xmlstate &= ~OSRF_CHAT_STATE_INUSERNAME;
- }
-
- if( node->xmlstate & OSRF_CHAT_STATE_INRESOURCE ) {
- free(node->resource);
- node->resource = strndup((char*) ch, len);
- node->xmlstate &= ~OSRF_CHAT_STATE_INRESOURCE;
- }
- }
-
- return;
- }
-
- if( node->state == OSRF_CHAT_STATE_CONNECTED ) {
- xmlNodePtr last = xmlGetLastChild(xmlDocGetRootElement(node->msgDoc));
- xmlNodePtr txt = xmlNewTextLen(ch, len);
- xmlAddChild(last, txt);
- return;
- }
-
- if( node->state == OSRF_CHAT_STATE_S2S_RESPONSE &&
- (node->xmlstate & OSRF_CHAT_STATE_INS2SRESULT) ) {
-
- char* key = strndup((char*) ch, len);
- osrfLogDebug( OSRF_LOG_MARK, "Got s2s key from %s : %s", node->remote, key );
- char* e = osrfChatGenerateS2SKey(node->parent->secret, node->remote, node->authkey );
- osrfLogInfo( OSRF_LOG_MARK, "\nReceived s2s key from server: %s\nKey should be: %s", key, e );
-
- if(eq(key, e)) {
- char* msg = va_list_to_string(OSRF_CHAT_S2S_VERIFY_REQUEST,
- node->authkey, node->domain, node->remote, e );
- osrfChatSendRaw(node, msg );
- free(msg);
- node->state = OSRF_CHAT_STATE_S2S_VERIFY_RESPONSE;
- node->xmlstate = 0;
-
- } else {
- osrfLogWarning( OSRF_LOG_MARK, "Server2Server keys do not match!");
- }
-
- /* do the hash dance again */
- }
-
- /* XXX free 'e' and 'key' ?? */
-
-}
-
-
-void osrfChatParseError( void* blob, const char* msg, ... ) {
-
- __osrfChatXMLErrorOcurred = 1;
-}
-
-
-
-
+++ /dev/null
-/*
-Copyright (C) 2005 Georgia Public Library Service
-Bill Erickson <billserickson@gmail.com>
-
-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; either version 2
-of the License, or (at your option) any later version.
-
-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.
-*/
-
-#ifndef OSRF_CHAT_H
-#define OSRF_CHAT_H
-
-
-/* opensrf headers */
-#include "opensrf/utils.h"
-#include "opensrf/osrf_hash.h"
-#include "opensrf/osrf_list.h"
-#include "opensrf/log.h"
-#include "opensrf/xml_utils.h"
-#include "opensrf/socket_bundle.h"
-#include "opensrf/sha.h"
-#include "opensrf/transport_message.h"
-
-/* libxml2 headers */
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/globals.h>
-#include <libxml/xmlerror.h>
-
-/* client to server XML */
-#define OSRF_CHAT_START_STREAM "<?xml version='1.0'?><stream:stream "\
- "xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' "\
- "from='%s' version='1.0' id='%s'>"
-
-#define OSRF_CHAT_PARSE_ERROR "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' "\
- "version='1.0'><stream:error xmlns:stream='http://etherx.jabber.org/streams'>"\
- "<xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>" \
- "<text xmlns='urn:ietf:params:xml:ns:xmpp-streams'>syntax error</text></stream:error></stream:stream>"
-
-#define OSRF_CHAT_LOGIN_OK "<iq xmlns='jabber:client' id='0123456789' type='result'/>"
-
-#define OSRF_CHAT_NO_RECIPIENT "<message xmlns='jabber:client' type='error' from='%s' to='%s'>"\
- "<error type='cancel' code='404'><item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"\
- "</error><body>NOT ADDING BODY</body></message>"
-
-/* ---------------------------------------------------------------------------------- */
-/* server to server XML */
-
-// client to server init
-#define OSRF_CHAT_S2S_INIT "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' "\
- "xmlns='jabber:server' xmlns:db='jabber:server:dialback'>"
-
-// server to client challenge
-#define OSRF_CHAT_S2S_CHALLENGE "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' "\
- "xmlns='jabber:server' id='%s' xmlns:db='jabber:server:dialback'>"
-
-// client to server challenge response
-#define OSRF_CHAT_S2S_RESPONSE "<db:result xmlns:db='jabber:server:dialback' to='%s' from='%s'>%s</db:result>"
-
-// server to client verify
-#define OSRF_CHAT_S2S_VERIFY_REQUEST "<db:verify xmlns:db='jabber:server:dialback' id='%s' from='%s' to='%s'>%s</db:verify>"
-
-// client to server verify response
-#define OSRF_CHAT_S2S_VERIFY_RESPONSE "<db:verify xmlns:db='jabber:server:dialback' type='valid' to='%s' from='%s' id='%s'/>"
-
-//server to client final verification
-#define OSRF_CHAT_S2S_VERIFY_FINAL "<db:result xmlns:db='jabber:server:dialback' type='valid' from='%s' to ='%s'/>"
-
-
-/* c2s states */
-#define OSRF_CHAT_STATE_NONE 0 /* blank node */
-#define OSRF_CHAT_STATE_CONNECTING 1 /* we have received the opening stream */
-#define OSRF_CHAT_STATE_CONNECTED 2 /* we have sent the OK/result message */
-
-/* s2s states */
-#define OSRF_CHAT_STATE_S2S_CHALLENGE 4 /* client : waiting for the challenge */
-#define OSRF_CHAT_STATE_S2S_RESPONSE 5 /* server : waiting for the challenge response */
-#define OSRF_CHAT_STATE_S2S_VERIFY 6 /* client : waiting for verify message */
-#define OSRF_CHAT_STATE_S2S_VERIFY_RESPONSE 7 /* server : waiting for verify response */
-#define OSRF_CHAT_STATE_S2S_VERIFY_FINAL 8 /* client : waiting for final verify response */
-
-/* xml parser states */
-#define OSRF_CHAT_STATE_INMESSAGE 1
-#define OSRF_CHAT_STATE_INIQ 2
-#define OSRF_CHAT_STATE_INUSERNAME 4
-#define OSRF_CHAT_STATE_INRESOURCE 8
-#define OSRF_CHAT_STATE_INS2SRESULT 16
-#define OSRF_CHAT_STATE_INS2SVERIFY 32
-
-
-struct __osrfChatNodeStruct {
-
- int sockid; /* our socket id */
-
- int type; /* 0 for client, 1 for server */
-
- /* for clients this is the full JID of the client that connected to this server.
- for servers it's the domain (network id) of the server we're connected to */
- char* remote;
-
-
- int state; /* for the various stages of connectivity and parsing */
- int xmlstate; /* what part of the message are we currently parsing */
- int inparse; /* true if we are currently parsing a chunk of XML. If so, we can't
- free the node. we have to cache it and free it later */
-
- char* to; /* The JID where the current message is being routed */
-
- char* domain; /* the domain, resource, and username of our connecting entity. */
- char* resource; /* for s2s nodes, resource and username will be empty . */
- char* username;
-
- char* authkey; /* when doing any auth negotiation, this is the auth seed hash */
- osrfList* msgs; /* if we're a server node we may have a pool of messages waiting to be delivered */
-
- xmlParserCtxtPtr parserCtx;
- xmlDocPtr msgDoc;
- struct __osrfChatServerStruct* parent;
-
-};
-typedef struct __osrfChatNodeStruct osrfChatNode;
-
-/*
-struct __osrfChatS2SMessageStruct {
- char* toAddr;
- char* msgXML;
-};
-typedef struct __osrfChatS2SMessageStruct osrfChatS2SMessage;
-*/
-
-struct __osrfChatServerStruct {
- osrfHash* nodeHash; /* sometimes we need hash (remote id) lookup, sometimes we need socket id lookup */
- osrfList* nodeList;
- osrfList* deadNodes; /* collection of nodes to free when we get a chance */
- socket_manager* mgr;
- char* secret; /* shared S2S secret */
- char* domain; /* the domain this server hosts */
- int s2sport;
- int port;
-};
-
-typedef struct __osrfChatServerStruct osrfChatServer;
-
-
-void osrfChatCacheS2SMessage( char* toAddr, char* msgXML, osrfChatNode* snode );
-
-osrfChatNode* osrfNewChatS2SNode( char* domain, char* remote );
-osrfChatNode* osrfNewChatNode( int sockid, char* domain );
-void osrfChatNodeFree( void* node );
-
-/* @param s2sSecret The Server to server secret. OK to leave NULL if no
- server to server communication is expected
- */
-osrfChatServer* osrfNewChatServer( char* domain, char* s2sSecret, int s2sport );
-
-int osrfChatServerConnect( osrfChatServer* cs, int port, int s2sport, char* listenAddr );
-
-int osrfChatServerWait( osrfChatServer* server );
-void osrfChatServerFree(osrfChatServer* cs);
-
-void osrfChatHandleData( void* cs,
- socket_manager* mgr, int sockid, char* data, int parent_id );
-
-
-/* removes dead nodes that have been cached due to mid-parse removals */
-void osrfChatCleanupClients( osrfChatServer* server );
-
-
-osrfChatNode* osrfChatAddNode( osrfChatServer* server, int sockid );
-
-
-void osrfChatRemoveNode( osrfChatServer* server, osrfChatNode* node );
-
-/** pushes new data into the nodes parser */
-int osrfChatPushData( osrfChatServer* server, osrfChatNode* node, char* data );
-
-
-void osrfChatSocketClosed( void* blob, int sockid );
-
-/**
- Sends msgXML to the client with remote 'toAddr'. if we have no connection
- to 'toAddr' and the domain for 'toAddr' is different than our hosted domain
- we attempt to send the message to the domain found in 'toAddr'.
- */
-int osrfChatSend( osrfChatServer* cs, osrfChatNode* node, char* toAddr, char* fromAddr, char* msgXML );
-
-int osrfChatSendRaw( osrfChatNode* node, char* xml );
-
-
-void osrfChatNodeFinish( osrfChatServer* server, osrfChatNode* node );
-
-/* initializes the negotiation of a server to server connection */
-int osrfChatInitS2S( osrfChatServer* cs, char* remote, char* toAddr, char* msgXML );
-
-
-void osrfChatStartStream( void* blob );
-void osrfChatStartElement( void* blob, const xmlChar *name, const xmlChar **atts );
-void osrfChatEndElement( void* blob, const xmlChar* name );
-void osrfChatHandleCharacter(void* blob, const xmlChar *ch, int len);
-void osrfChatParseError( void* blob, const char* msg, ... );
-
-int osrfChatHandleNewConnection( osrfChatNode* node, const char* name, const xmlChar** atts );
-int osrfChatHandleConnecting( osrfChatNode* node, const char* name, const xmlChar** atts );
-int osrfChatHandleConnected( osrfChatNode* node, const char* name, const xmlChar** atts );
-int osrfChatHandleS2SInit( osrfChatNode* node, const char* name, const xmlChar** atts );
-int osrfChatHandleS2SChallenge( osrfChatNode* node, const char* name, const xmlChar** atts );
-int osrfChatHandleS2SResponse( osrfChatNode* node, const char* name, const xmlChar** atts );
-
-int osrfChatHandleS2SConnected( osrfChatNode* node, const char* nm, const xmlChar**atts );
-
-void osrfChatS2SMessageFree(void* n);
-
-
-
-/* generates a random sha1 hex key */
-char* osrfChatMkAuthKey();
-
-static xmlSAXHandler osrfChatSaxHandlerStruct = {
- NULL, /* internalSubset */
- NULL, /* isStandalone */
- NULL, /* hasInternalSubset */
- NULL, /* hasExternalSubset */
- NULL, /* resolveEntity */
- NULL, /* getEntity */
- NULL, /* entityDecl */
- NULL, /* notationDecl */
- NULL, /* attributeDecl */
- NULL, /* elementDecl */
- NULL, /* unparsedEntityDecl */
- NULL, /* setDocumentLocator */
- osrfChatStartStream, /* startDocument */
- NULL, /* endDocument */
- osrfChatStartElement, /* startElement */
- osrfChatEndElement, /* endElement */
- NULL, /* reference */
- osrfChatHandleCharacter, /* characters */
- NULL, /* ignorableWhitespace */
- NULL, /* processingInstruction */
- NULL, /* comment */
- osrfChatParseError, /* xmlParserWarning */
- osrfChatParseError, /* xmlParserError */
- NULL, /* xmlParserFatalError : unused */
- NULL, /* getParameterEntity */
- NULL, /* cdataBlock; */
- NULL, /* externalSubset; */
- 1,
- NULL,
- NULL, /* startElementNs */
- NULL, /* endElementNs */
- NULL /* xmlStructuredErrorFunc */
-};
-
-static const xmlSAXHandlerPtr osrfChatSaxHandler = &osrfChatSaxHandlerStruct;
-
-
-#endif
-
-
+++ /dev/null
-#include "osrf_chat.h"
-#include "opensrf/osrfConfig.h"
-#include <stdio.h>
-#include "opensrf/log.h"
-#include <syslog.h>
-
-
-int main( int argc, char* argv[] ) {
-
- if( argc < 3 ) {
- fprintf( stderr, "Usage: %s <config_file> <config_context>\n", argv[0] );
- exit(0);
- }
-
- osrfConfig* cfg = osrfConfigInit( argv[1], argv[2] );
- if( !cfg ) {
- fprintf( stderr, "Unable to load configuration file %s\n", argv[1] );
- return -1;
- }
-
- init_proc_title( argc, argv );
- set_proc_title( "ChopChop" );
-
- char* domain = osrfConfigGetValue(cfg, "/domain");
- char* secret = osrfConfigGetValue(cfg, "/secret");
- char* sport = osrfConfigGetValue(cfg, "/port");
- char* s2sport = osrfConfigGetValue(cfg, "/s2sport");
- char* listenaddr = osrfConfigGetValue(cfg, "/listen_address");
- char* llevel = osrfConfigGetValue(cfg, "/loglevel");
- char* lfile = osrfConfigGetValue(cfg, "/logfile");
- char* facility = osrfConfigGetValue(cfg, "/syslog");
-
- if(!domain)
- fputs( "No domain specified in configuration file\n", stderr );
-
- if(!secret)
- fputs( "No secret specified in configuration file\n", stderr );
-
- if(!sport)
- fputs( "No port specified in configuration file\n", stderr );
-
- if(!listenaddr)
- fputs( "No listen_address specified in configuration file\n", stderr );
-
- if(!llevel)
- fputs( "No loglevel specified in configuration file\n", stderr );
-
- if(!lfile)
- fputs( "No logfile specified in configuration file\n", stderr );
-
- if(!s2sport)
- fputs( "No s2sport specified in configuration file\n", stderr );
-
- if(!(domain && secret && sport && listenaddr && llevel && lfile && s2sport)) {
- fprintf(stderr, "Configuration error for ChopChop - missing key ingredient\n");
- return -1;
- }
-
- int port = atoi(sport);
- int s2port = atoi(s2sport);
- int level = atoi(llevel);
-
- if(!strcmp(lfile, "syslog")) {
- osrfLogInit( OSRF_LOG_TYPE_SYSLOG, "chopchop", level );
- osrfLogSetSyslogFacility(osrfLogFacilityToInt(facility));
-
- } else {
- osrfLogInit( OSRF_LOG_TYPE_FILE, "chopchop", level );
- osrfLogSetFile( lfile );
- }
-
- fprintf(stderr, "Attempting to launch ChopChop with:\n"
- "domain: %s\nport: %s\nlisten address: %s\nlog level: %s\nlog file: %s\n",
- domain, sport, listenaddr, llevel, lfile );
-
- osrfChatServer* server = osrfNewChatServer(domain, secret, s2port);
-
- if( osrfChatServerConnect( server, port, s2port, listenaddr ) != 0 ) {
- osrfLogError( OSRF_LOG_MARK, "ChopChop unable to bind to port %d on %s", port, listenaddr);
- return -1;
- }
-
- daemonize();
- osrfChatServerWait( server );
-
- osrfChatServerFree( server );
- osrfConfigFree(cfg);
-
- return 0;
-
-}
-
+++ /dev/null
-# OSRF_LOG_PARAMS log all incoming method params at OSRF_INFO log level.
-# OSRF_STRICT_PARAMS instructs the app handler to return an error if the number of method arguments
-# provided to any method is not at least as large as the 'argc' setting for the method
-
-CFLAGS += -DASSUME_STATELESS -DOSRF_LOG_PARAMS -DOSRF_STRICT_PARAMS -rdynamic -fno-strict-aliasing
-LDLIBS += -lxml2 -lobjson -ldl -lmemcache
-
-TARGETS = osrf_message.o \
- osrf_app_session.o \
- osrf_stack.o \
- osrf_system.o \
- osrf_settings.o \
- osrf_prefork.o \
- osrfConfig.o \
- osrf_application.o \
- osrf_cache.o \
- osrf_transgroup.o \
- osrf_list.o \
- osrf_hash.o \
- xml_utils.o
-
-HEADERS = osrf_message.h \
- osrf_app_session.h \
- osrf_stack.h \
- osrf_system.h \
- osrf_settings.h \
- osrf_prefork.h \
- osrfConfig.h \
- osrf_application.h \
- osrf_cache.h \
- osrf_transgroup.h \
- osrf_list.h \
- osrf_hash.h \
- xml_utils.h
-
-all: xml_utils.o $(TARGETS) copy
-
-xml_utils.o:
- cp ../utils/xml_utils.h .
- cp ../utils/xml_utils.c .
- $(CC) -c $(CFLAGS) xml_utils.c -o $@
-
-copy:
- cp $(HEADERS) $(TMPDIR)/
-
-osrf_message.o: osrf_message.c osrf_message.h
-osrf_app_session.o: osrf_app_session.c osrf_app_session.h
-osrf_stack.o: osrf_stack.c osrf_stack.h
-osrf_system.o: osrf_system.c osrf_system.h
-osrf_settings.o: osrf_settings.c osrf_settings.h
-osrf_prefork.o: osrf_prefork.c osrf_prefork.h
-osrfConfig.o: osrfConfig.c osrfConfig.h xml_utils.o
-osrf_application.o: osrf_application.c osrf_application.h
-osrf_cache.o: osrf_cache.c osrf_cache.h
-osrf_list.o: osrf_list.c osrf_list.h
-#osrf_big_list.o: osrf_big_list.c osrf_big_list.h
-osrf_hash.o: osrf_hash.c osrf_hash.h
-#osrf_big_hash.o: osrf_big_hash.c osrf_big_hash.h
-
-
-clean:
- /bin/rm -f *.o libopensrf_stack.so xml_utils.h xml_utils.c opensrf
-
+++ /dev/null
-#include "osrf_system.h"
-#include "osrf_hash.h"
-#include "osrf_list.h"
-
-int main( int argc, char* argv[] ) {
-
- if( argc < 4 ) {
- fprintf(stderr, "Usage: %s <host> <bootstrap_config> <config_context>\n", argv[0]);
- return 1;
- }
-
- fprintf(stderr, "Loading OpenSRF host %s with bootstrap config %s "
- "and config context %s\n", argv[1], argv[2], argv[3] );
-
- /* these must be strdup'ed because init_proc_title / set_proc_title
- are evil and overwrite the argv memory */
- char* host = strdup( argv[1] );
- char* config = strdup( argv[2] );
- char* context = strdup( argv[3] );
-
- init_proc_title( argc, argv );
- set_proc_title( "OpenSRF System-C" );
-
- osrfSystemBootstrap( host, config, context );
-
- free(host);
- free(config);
- free(context);
-
- return 0;
-}
-
-
+++ /dev/null
-/* defines the currently used bootstrap config file */
-#include "osrfConfig.h"
-
-static osrfConfig* osrfConfigDefault = NULL;
-
-
-void osrfConfigSetDefaultConfig(osrfConfig* cfg) {
- if(cfg) {
- if( osrfConfigDefault )
- osrfConfigFree( osrfConfigDefault );
- osrfConfigDefault = cfg;
- }
-}
-
-void osrfConfigFree(osrfConfig* cfg) {
- if(cfg) {
- jsonObjectFree(cfg->config);
- free(cfg->configContext);
- free(cfg);
- }
-}
-
-
-int osrfConfigHasDefaultConfig() {
- return ( osrfConfigDefault != NULL );
-}
-
-
-void osrfConfigCleanup() {
- osrfConfigFree(osrfConfigDefault);
- osrfConfigDefault = NULL;
-}
-
-
-void osrfConfigReplaceConfig(osrfConfig* cfg, const jsonObject* obj) {
- if(!cfg || !obj) return;
- jsonObjectFree(cfg->config);
- cfg->config = jsonObjectClone(obj);
-}
-
-osrfConfig* osrfConfigInit(char* configFile, char* configContext) {
- if(!configFile) return NULL;
-
- osrfConfig* cfg = safe_malloc(sizeof(osrfConfig));
- if(configContext) cfg->configContext = strdup(configContext);
- else cfg->configContext = NULL;
-
- xmlDocPtr doc = xmlParseFile(configFile);
- if(!doc) {
- osrfLogWarning( OSRF_LOG_MARK, "Unable to parse XML config file %s", configFile);
- return NULL;
- }
-
- cfg->config = xmlDocToJSON(doc);
- xmlFreeDoc(doc);
-
- if(!cfg->config) {
- osrfLogWarning( OSRF_LOG_MARK, "xmlDocToJSON failed for config %s", configFile);
- return NULL;
- }
-
- return cfg;
-}
-
-char* osrfConfigGetValue(osrfConfig* cfg, char* path, ...) {
-
- if(!path) return NULL;
- if(!cfg) cfg = osrfConfigDefault;
- if(!cfg) { osrfLogWarning( OSRF_LOG_MARK, "No Config object in osrfConfigGetValue()"); return NULL; }
-
- VA_LIST_TO_STRING(path);
-
- jsonObject* obj;
- char* val = NULL;
-
- if(cfg->configContext) {
- obj = jsonObjectFindPath( cfg->config, "//%s%s", cfg->configContext, VA_BUF);
- if(obj) val = jsonObjectToSimpleString(jsonObjectGetIndex(obj, 0));
-
- } else {
- obj = jsonObjectFindPath( cfg->config, VA_BUF);
- if(obj) val = jsonObjectToSimpleString(obj);
- }
-
- jsonObjectFree(obj);
- return val;
-}
-
-
-int osrfConfigGetValueList(osrfConfig* cfg, osrfStringArray* arr, char* path, ...) {
-
- if(!arr || !path) return 0;
- if(!cfg) cfg = osrfConfigDefault;
- if(!cfg) { osrfLogWarning( OSRF_LOG_MARK, "No Config object!"); return -1;}
-
- VA_LIST_TO_STRING(path);
-
- jsonObject* obj;
- if(cfg->configContext) {
- obj = jsonObjectFindPath( cfg->config, "//%s%s", cfg->configContext, VA_BUF);
- } else {
- obj = jsonObjectFindPath( cfg->config, VA_BUF);
- }
-
- int count = 0;
-
- if(obj && obj->type == JSON_ARRAY ) {
-
- int i;
- for( i = 0; i < obj->size; i++ ) {
-
- char* val = jsonObjectToSimpleString(jsonObjectGetIndex(obj, i));
- if(val) {
- count++;
- osrfStringArrayAdd(arr, val);
- free(val);
- }
- }
- }
-
- jsonObjectFree(obj);
- return count;
-}
-
+++ /dev/null
-/*
-Copyright (C) 2005 Georgia Public Library Service
-Bill Erickson <highfalutin@gmail.com>
-
-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; either version 2
-of the License, or (at your option) any later version.
-
-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.
-*/
-
-#ifndef _OSRF_CONFIG_H
-#define _OSRF_CONFIG_H
-
-#include "xml_utils.h"
-#include "opensrf/utils.h"
-#include "opensrf/string_array.h"
-#include "objson/object.h"
-
-typedef struct {
- jsonObject* config;
- char* configContext;
-} osrfConfig;
-
-
-/**
- Parses a new config file. Caller is responsible for freeing the returned
- config object when finished.
- @param configFile The XML config file to parse.
- @param configContext Optional root of the subtree in the config file where
- we will look for values. If it's not provided, searches will be
- performed from the root of the config file
- @return The config object if the file parses successfully. Otherwise
- it returns NULL;
-*/
-osrfConfig* osrfConfigInit(char* configFile, char* configContext);
-
-/**
- @return True if we have a default config defined
-*/
-int osrfConfigHasDefaultConfig();
-
-/**
- Replaces the config object's objson object. This is useful
- if you have an ojbson object already and not an XML config
- file to parse.
- @param cfg The config object to alter
- @param obj The objson objet to use when searching values
-*/
-void osrfConfigReplaceConfig(osrfConfig* cfg, const jsonObject* obj);
-
-/** Deallocates a config object
- @param cfg The config object to free
-*/
-void osrfConfigFree(osrfConfig* cfg);
-
-
-/* Assigns the default config file. This file will be used whenever
- NULL is passed to config retrieval functions
- @param cfg The config object to use as the default config
-*/
-void osrfConfigSetDefaultConfig(osrfConfig* cfg);
-
-/* frees the default config if one exists */
-void osrfConfigCleanup();
-
-
-/**
- Returns the value in the config found at 'path'.
- If the value found at 'path' is a long or a double,
- the value is stringified and then returned.
- The caller must free the returned char*
-
- if there is a configContext, then it will be appended to
- the front of the path like so: //<configContext>/<path>
- if no configContext was provided to osfConfigSetFile, then
- the path is interpreted literally.
- @param cfg The config file to search or NULL if the default
- config should be used
- @param path The search path
-*/
-char* osrfConfigGetValue(osrfConfig* cfg, char* path, ...);
-
-/**
- Puts the list of values found at 'path' into the pre-allocated
- string array.
- Note that the config node found at 'path' must be an array.
- @param cfg The config file to search or NULL if the default
- config should be used
- @param arr An allocated string_array where the values will
- be stored
- @param path The search path
- @return the number of values added to the string array;
-*/
-
-int osrfConfigGetValueList(osrfConfig* cfg, osrfStringArray* arr, char* path, ...);
-
-
-#endif
+++ /dev/null
-#include "osrf_app_session.h"
-#include <time.h>
-
-/* the global app_session cache */
-osrfHash* osrfAppSessionCache = NULL;
-
-
-// --------------------------------------------------------------------------
-// --------------------------------------------------------------------------
-// Request API
-// --------------------------------------------------------------------------
-
-/** Allocation and initializes a new app_request object */
-osrf_app_request* _osrf_app_request_init(
- osrf_app_session* session, osrf_message* msg ) {
-
- osrf_app_request* req =
- (osrf_app_request*) safe_malloc(sizeof(osrf_app_request));
-
- req->session = session;
- req->request_id = msg->thread_trace;
- req->complete = 0;
- req->payload = msg;
- req->result = NULL;
-
- return req;
-
-}
-
-
-void osrfAppSessionCleanup() {
- osrfHashFree(osrfAppSessionCache);
-}
-
-
-
-/** Frees memory used by an app_request object */
-void _osrf_app_request_free( void * req ){
- if( req == NULL ) return;
- osrfAppRequest* r = (osrfAppRequest*) req;
- if( r->payload ) osrf_message_free( r->payload );
- free( r );
-}
-
-/** Pushes the given message onto the list of 'responses' to this request */
-void _osrf_app_request_push_queue( osrf_app_request* req, osrf_message* result ){
- if(req == NULL || result == NULL) return;
- osrfLogDebug( OSRF_LOG_MARK, "App Session pushing request [%d] onto request queue", result->thread_trace );
- if(req->result == NULL) {
- req->result = result;
-
- } else {
-
- osrf_message* ptr = req->result;
- osrf_message* ptr2 = req->result->next;
- while( ptr2 ) {
- ptr = ptr2;
- ptr2 = ptr2->next;
- }
- ptr->next = result;
- }
-}
-
-/** Removes this app_request from our session request set */
-void osrf_app_session_request_finish(
- osrf_app_session* session, int req_id ){
-
- if(session == NULL) return;
- osrf_app_request* req = OSRF_LIST_GET_INDEX( session->request_queue, req_id );
- if(req == NULL) return;
- osrfListRemove( req->session->request_queue, req->request_id );
-}
-
-
-void osrf_app_session_request_reset_timeout( osrf_app_session* session, int req_id ) {
- if(session == NULL) return;
- osrfLogDebug( OSRF_LOG_MARK, "Resetting request timeout %d", req_id );
- osrf_app_request* req = OSRF_LIST_GET_INDEX( session->request_queue, req_id );
- if(req == NULL) return;
- req->reset_timeout = 1;
-}
-
-/** Checks the receive queue for messages. If any are found, the first
- * is popped off and returned. Otherwise, this method will wait at most timeout
- * seconds for a message to appear in the receive queue. Once it arrives it is returned.
- * If no messages arrive in the timeout provided, null is returned.
- */
-osrf_message* _osrf_app_request_recv( osrf_app_request* req, int timeout ) {
-
- if(req == NULL) return NULL;
-
- if( req->result != NULL ) {
- /* pop off the first message in the list */
- osrf_message* tmp_msg = req->result;
- req->result = req->result->next;
- return tmp_msg;
- }
-
- time_t start = time(NULL);
- time_t remaining = (time_t) timeout;
-
- while( remaining >= 0 ) {
- /* tell the session to wait for stuff */
- osrfLogDebug( OSRF_LOG_MARK, "In app_request receive with remaining time [%d]", (int) remaining );
-
- osrf_app_session_queue_wait( req->session, 0, NULL );
-
- if( req->result != NULL ) { /* if we received anything */
- /* pop off the first message in the list */
- osrfLogDebug( OSRF_LOG_MARK, "app_request_recv received a message, returning it");
- osrf_message* ret_msg = req->result;
- osrf_message* tmp_msg = ret_msg->next;
- req->result = tmp_msg;
- return ret_msg;
- }
-
- if( req->complete )
- return NULL;
-
- osrf_app_session_queue_wait( req->session, (int) remaining, NULL );
-
- if( req->result != NULL ) { /* if we received anything */
- /* pop off the first message in the list */
- osrfLogDebug( OSRF_LOG_MARK, "app_request_recv received a message, returning it");
- osrf_message* ret_msg = req->result;
- osrf_message* tmp_msg = ret_msg->next;
- req->result = tmp_msg;
- return ret_msg;
- }
- if( req->complete )
- return NULL;
-
- if(req->reset_timeout) {
- remaining = (time_t) timeout;
- req->reset_timeout = 0;
- osrfLogDebug( OSRF_LOG_MARK, "Recevied a timeout reset");
- } else {
- remaining -= (int) (time(NULL) - start);
- }
- }
-
- osrfLogInfo( OSRF_LOG_MARK, "Returning NULL from app_request_recv after timeout");
- return NULL;
-}
-
-/** Resend this requests original request message */
-int _osrf_app_request_resend( osrf_app_request* req ) {
- if(req == NULL) return 0;
- if(!req->complete) {
- osrfLogDebug( OSRF_LOG_MARK, "Resending request [%d]", req->request_id );
- return _osrf_app_session_send( req->session, req->payload );
- }
- return 1;
-}
-
-
-
-// --------------------------------------------------------------------------
-// --------------------------------------------------------------------------
-// Session API
-// --------------------------------------------------------------------------
-
-/** returns a session from the global session hash */
-osrf_app_session* osrf_app_session_find_session( char* session_id ) {
- if(session_id) return osrfHashGet(osrfAppSessionCache, session_id);
- return NULL;
-}
-
-
-/** adds a session to the global session cache */
-void _osrf_app_session_push_session( osrf_app_session* session ) {
- if(!session) return;
- if( osrfAppSessionCache == NULL ) osrfAppSessionCache = osrfNewHash();
- if( osrfHashGet( osrfAppSessionCache, session->session_id ) ) return;
- osrfHashSet( osrfAppSessionCache, session, session->session_id );
-}
-
-/** Allocates a initializes a new app_session */
-
-osrf_app_session* osrfAppSessionClientInit( char* remote_service ) {
- return osrf_app_client_session_init( remote_service );
-}
-
-osrf_app_session* osrf_app_client_session_init( char* remote_service ) {
-
- osrf_app_session* session = safe_malloc(sizeof(osrf_app_session));
-
- session->transport_handle = osrf_system_get_transport_client();
- if( session->transport_handle == NULL ) {
- osrfLogWarning( OSRF_LOG_MARK, "No transport client for service 'client'");
- free( session );
- return NULL;
- }
-
- char target_buf[512];
- target_buf[ 0 ] = '\0';
-
- osrfStringArray* arr = osrfNewStringArray(8);
- osrfConfigGetValueList(NULL, arr, "/domains/domain");
- char* domain = osrfStringArrayGetString(arr, 0);
- char* router_name = osrfConfigGetValue(NULL, "/router_name");
-
- int len = snprintf( target_buf, 512, "%s@%s/%s", router_name, domain, remote_service );
- osrfStringArrayFree(arr);
- //free(domain);
- free(router_name);
-
- if( len >= sizeof( target_buf ) ) {
- osrfLogWarning( OSRF_LOG_MARK, "Buffer overflow for remote_id");
- free( session );
- return NULL;
- }
-
- session->request_queue = osrfNewList();
- session->request_queue->freeItem = &_osrf_app_request_free;
- session->remote_id = strdup(target_buf);
- session->orig_remote_id = strdup(session->remote_id);
- session->remote_service = strdup(remote_service);
-
- #ifdef ASSUME_STATELESS
- session->stateless = 1;
- osrfLogDebug( OSRF_LOG_MARK, "%s session is stateless", remote_service );
- #else
- session->stateless = 0;
- osrfLogDebug( OSRF_LOG_MARK, "%s session is NOT stateless", remote_service );
- #endif
-
- /* build a chunky, random session id */
- char id[256];
- memset(id,0,256);
-
- sprintf(id, "%f.%d%ld", get_timestamp_millis(), (int)time(NULL), (long) getpid());
- session->session_id = strdup(id);
- osrfLogDebug( OSRF_LOG_MARK, "Building a new client session with id [%s] [%s]",
- session->remote_service, session->session_id );
-
- session->thread_trace = 0;
- session->state = OSRF_SESSION_DISCONNECTED;
- session->type = OSRF_SESSION_CLIENT;
- //session->next = NULL;
- _osrf_app_session_push_session( session );
- return session;
-}
-
-osrf_app_session* osrf_app_server_session_init(
- char* session_id, char* our_app, char* remote_id ) {
-
- osrfLogDebug( OSRF_LOG_MARK, "Initing server session with session id %s, service %s,"
- " and remote_id %s", session_id, our_app, remote_id );
-
- osrf_app_session* session = osrf_app_session_find_session( session_id );
- if(session) return session;
-
- session = safe_malloc(sizeof(osrf_app_session));
-
- session->transport_handle = osrf_system_get_transport_client();
- if( session->transport_handle == NULL ) {
- osrfLogWarning( OSRF_LOG_MARK, "No transport client for service '%s'", our_app );
- return NULL;
- }
-
- int stateless = 0;
- char* statel = osrf_settings_host_value("/apps/%s/stateless", our_app );
- if(statel) stateless = atoi(statel);
- free(statel);
-
-
- session->request_queue = osrfNewList();
- session->request_queue->freeItem = &_osrf_app_request_free;
- session->remote_id = strdup(remote_id);
- session->orig_remote_id = strdup(remote_id);
- session->session_id = strdup(session_id);
- session->remote_service = strdup(our_app);
- session->stateless = stateless;
-
- #ifdef ASSUME_STATELESS
- session->stateless = 1;
- #endif
-
- session->thread_trace = 0;
- session->state = OSRF_SESSION_DISCONNECTED;
- session->type = OSRF_SESSION_SERVER;
-
- _osrf_app_session_push_session( session );
- return session;
-
-}
-
-
-
-/** frees memory held by a session */
-void _osrf_app_session_free( osrf_app_session* session ){
- if(session==NULL)
- return;
-
- if( session->userDataFree && session->userData )
- session->userDataFree(session->userData);
-
- free(session->remote_id);
- free(session->orig_remote_id);
- free(session->session_id);
- free(session->remote_service);
- osrfListFree(session->request_queue);
- free(session);
-}
-
-int osrfAppSessionMakeRequest(
- osrf_app_session* session, jsonObject* params,
- char* method_name, int protocol, string_array* param_strings ) {
-
- return osrf_app_session_make_req( session, params,
- method_name, protocol, param_strings );
-}
-
-int osrf_app_session_make_req(
- osrf_app_session* session, jsonObject* params,
- char* method_name, int protocol, string_array* param_strings ) {
- if(session == NULL) return -1;
-
- osrfLogMkXid();
-
- osrf_message* req_msg = osrf_message_init( REQUEST, ++(session->thread_trace), protocol );
- osrf_message_set_method(req_msg, method_name);
- if(params) {
- osrf_message_set_params(req_msg, params);
-
- } else {
-
- if(param_strings) {
- int i;
- for(i = 0; i!= param_strings->size ; i++ ) {
- osrf_message_add_param(req_msg,
- string_array_get_string(param_strings,i));
- }
- }
- }
-
- osrf_app_request* req = _osrf_app_request_init( session, req_msg );
- if(_osrf_app_session_send( session, req_msg ) ) {
- osrfLogWarning( OSRF_LOG_MARK, "Error sending request message [%d]", session->thread_trace );
- return -1;
- }
-
- osrfLogDebug( OSRF_LOG_MARK, "Pushing [%d] onto requeust queue for session [%s] [%s]",
- req->request_id, session->remote_service, session->session_id );
- osrfListSet( session->request_queue, req, req->request_id );
- return req->request_id;
-}
-
-void osrf_app_session_set_complete( osrf_app_session* session, int request_id ) {
- if(session == NULL)
- return;
-
- osrf_app_request* req = OSRF_LIST_GET_INDEX( session->request_queue, request_id );
- if(req) req->complete = 1;
-}
-
-int osrf_app_session_request_complete( osrf_app_session* session, int request_id ) {
- if(session == NULL)
- return 0;
- osrf_app_request* req = OSRF_LIST_GET_INDEX( session->request_queue, request_id );
- if(req)
- return req->complete;
- return 0;
-}
-
-
-/** Resets the remote connection id to that of the original*/
-void osrf_app_session_reset_remote( osrf_app_session* session ){
- if( session==NULL )
- return;
-
- free(session->remote_id);
- osrfLogDebug( OSRF_LOG_MARK, "App Session [%s] [%s] resetting remote id to %s",
- session->remote_service, session->session_id, session->orig_remote_id );
-
- session->remote_id = strdup(session->orig_remote_id);
-}
-
-void osrf_app_session_set_remote( osrf_app_session* session, char* remote_id ) {
- if(session == NULL)
- return;
- if( session->remote_id )
- free(session->remote_id );
- session->remote_id = strdup( remote_id );
-}
-
-/** pushes the given message into the result list of the app_request
- with the given request_id */
-int osrf_app_session_push_queue(
- osrf_app_session* session, osrf_message* msg ){
- if(session == NULL || msg == NULL) return 0;
-
- osrf_app_request* req = OSRF_LIST_GET_INDEX( session->request_queue, msg->thread_trace );
- if(req == NULL) return 0;
- _osrf_app_request_push_queue( req, msg );
-
- return 0;
-}
-
-int osrfAppSessionConnect( osrf_app_session* session ) {
- return osrf_app_session_connect(session);
-}
-
-
-/** Attempts to connect to the remote service */
-int osrf_app_session_connect(osrf_app_session* session){
-
- if(session == NULL)
- return 0;
-
- if(session->state == OSRF_SESSION_CONNECTED) {
- return 1;
- }
-
- int timeout = 5; /* XXX CONFIG VALUE */
-
- osrfLogDebug( OSRF_LOG_MARK, "AppSession connecting to %s", session->remote_id );
-
- /* defaulting to protocol 1 for now */
- osrf_message* con_msg = osrf_message_init( CONNECT, session->thread_trace, 1 );
- osrf_app_session_reset_remote( session );
- session->state = OSRF_SESSION_CONNECTING;
- int ret = _osrf_app_session_send( session, con_msg );
- osrf_message_free(con_msg);
- if(ret) return 0;
-
- time_t start = time(NULL);
- time_t remaining = (time_t) timeout;
-
- while( session->state != OSRF_SESSION_CONNECTED && remaining >= 0 ) {
- osrf_app_session_queue_wait( session, remaining, NULL );
- remaining -= (int) (time(NULL) - start);
- }
-
- if(session->state == OSRF_SESSION_CONNECTED)
- osrfLogDebug( OSRF_LOG_MARK, " * Connected Successfully to %s", session->remote_service );
-
- if(session->state != OSRF_SESSION_CONNECTED)
- return 0;
-
- return 1;
-}
-
-
-
-/** Disconnects from the remote service */
-int osrf_app_session_disconnect( osrf_app_session* session){
- if(session == NULL)
- return 1;
-
- if(session->state == OSRF_SESSION_DISCONNECTED)
- return 1;
-
- if(session->stateless && session->state != OSRF_SESSION_CONNECTED) {
- osrfLogDebug( OSRF_LOG_MARK,
- "Exiting disconnect on stateless session %s",
- session->session_id);
- return 1;
- }
-
- osrfLogDebug(OSRF_LOG_MARK, "AppSession disconnecting from %s", session->remote_id );
-
- osrf_message* dis_msg = osrf_message_init( DISCONNECT, session->thread_trace, 1 );
- _osrf_app_session_send( session, dis_msg );
- session->state = OSRF_SESSION_DISCONNECTED;
-
- osrf_message_free( dis_msg );
- osrf_app_session_reset_remote( session );
- return 1;
-}
-
-int osrf_app_session_request_resend( osrf_app_session* session, int req_id ) {
- osrf_app_request* req = OSRF_LIST_GET_INDEX( session->request_queue, req_id );
- return _osrf_app_request_resend( req );
-}
-
-
-int osrfAppSessionSendBatch( osrfAppSession* session, osrf_message* msgs[], int size ) {
-
- if( !(session && msgs && size > 0) ) return 0;
- int retval = 0;
-
- osrfMessage* msg = msgs[0];
-
- if(msg) {
-
- osrf_app_session_queue_wait( session, 0, NULL );
-
- if(session->state != OSRF_SESSION_CONNECTED) {
-
- if(session->stateless) { /* stateless session always send to the root listener */
- osrf_app_session_reset_remote(session);
-
- } else {
-
- /* do an auto-connect if necessary */
- if( ! session->stateless &&
- (msg->m_type != CONNECT) &&
- (msg->m_type != DISCONNECT) &&
- (session->state != OSRF_SESSION_CONNECTED) ) {
-
- if(!osrf_app_session_connect( session ))
- return 0;
- }
- }
- }
- }
-
- char* string = osrfMessageSerializeBatch(msgs, size);
-
- if( string ) {
-
- transport_message* t_msg = message_init(
- string, "", session->session_id, session->remote_id, NULL );
- message_set_osrf_xid( t_msg, osrfLogGetXid() );
-
- retval = client_send_message( session->transport_handle, t_msg );
-
- if( retval ) osrfLogError(OSRF_LOG_MARK, "client_send_message failed");
-
- osrfLogInfo(OSRF_LOG_MARK, "[%s] sent %d bytes of data to %s",
- session->remote_service, strlen(string), t_msg->recipient );
-
- osrfLogDebug(OSRF_LOG_MARK, "Sent: %s", string );
-
- free(string);
- message_free( t_msg );
- }
-
- return retval;
-}
-
-
-
-int _osrf_app_session_send( osrf_app_session* session, osrf_message* msg ){
- if( !(session && msg) ) return 0;
- osrfMessage* a[1];
- a[0] = msg;
- return osrfAppSessionSendBatch( session, a, 1 );
-}
-
-
-
-
-/** Waits up to 'timeout' seconds for some data to arrive.
- * Any data that arrives will be processed according to its
- * payload and message type. This method will return after
- * any data has arrived.
- */
-int osrf_app_session_queue_wait( osrf_app_session* session, int timeout, int* recvd ){
- if(session == NULL) return 0;
- int ret_val = 0;
- osrfLogDebug(OSRF_LOG_MARK, "AppSession in queue_wait with timeout %d", timeout );
- ret_val = osrf_stack_entry_point(session->transport_handle, timeout, recvd);
- return ret_val;
-}
-
-/** Disconnects (if client) and removes the given session from the global session cache
- * ! This free's all attached app_requests !
- */
-void osrfAppSessionFree( osrfAppSession* ses ) {
- osrf_app_session_destroy( ses );
-}
-
-
-void osrf_app_session_destroy( osrf_app_session* session ){
- if(session == NULL) return;
-
- osrfLogDebug(OSRF_LOG_MARK, "AppSession [%s] [%s] destroying self and deleting requests",
- session->remote_service, session->session_id );
- if(session->type == OSRF_SESSION_CLIENT
- && session->state != OSRF_SESSION_DISCONNECTED ) { /* disconnect if we're a client */
- osrf_message* dis_msg = osrf_message_init( DISCONNECT, session->thread_trace, 1 );
- _osrf_app_session_send( session, dis_msg );
- osrf_message_free(dis_msg);
- }
-
- osrfHashRemove( osrfAppSessionCache, session->session_id );
- _osrf_app_session_free( session );
-}
-
-osrf_message* osrfAppSessionRequestRecv(
- osrf_app_session* session, int req_id, int timeout ) {
- return osrf_app_session_request_recv( session, req_id, timeout );
-}
-osrf_message* osrf_app_session_request_recv(
- osrf_app_session* session, int req_id, int timeout ) {
- if(req_id < 0 || session == NULL)
- return NULL;
- osrf_app_request* req = OSRF_LIST_GET_INDEX( session->request_queue, req_id );
- return _osrf_app_request_recv( req, timeout );
-}
-
-
-
-int osrfAppRequestRespond( osrfAppSession* ses, int requestId, jsonObject* data ) {
- if(!ses || ! data ) return -1;
-
- osrf_message* msg = osrf_message_init( RESULT, requestId, 1 );
- osrf_message_set_status_info( msg, NULL, "OK", OSRF_STATUS_OK );
- char* json = jsonObjectToJSON( data );
-
- osrf_message_set_result_content( msg, json );
- _osrf_app_session_send( ses, msg );
-
- free(json);
- osrf_message_free( msg );
-
- return 0;
-}
-
-
-int osrfAppRequestRespondComplete(
- osrfAppSession* ses, int requestId, jsonObject* data ) {
-
- osrf_message* payload = osrf_message_init( RESULT, requestId, 1 );
- osrf_message_set_status_info( payload, NULL, "OK", OSRF_STATUS_OK );
-
- osrf_message* status = osrf_message_init( STATUS, requestId, 1);
- osrf_message_set_status_info( status, "osrfConnectStatus", "Request Complete", OSRF_STATUS_COMPLETE );
-
- if (data) {
- char* json = jsonObjectToJSON( data );
- osrf_message_set_result_content( payload, json );
- free(json);
-
- osrfMessage* ms[2];
- ms[0] = payload;
- ms[1] = status;
-
- osrfAppSessionSendBatch( ses, ms, 2 );
-
- osrf_message_free( payload );
- } else {
- osrfAppSessionSendBatch( ses, &status, 1 );
- }
-
- osrf_message_free( status );
-
- return 0;
-}
-
-int osrfAppSessionStatus( osrfAppSession* ses, int type, char* name, int reqId, char* message ) {
-
- if(ses) {
- osrf_message* msg = osrf_message_init( STATUS, reqId, 1);
- osrf_message_set_status_info( msg, name, message, type );
- _osrf_app_session_send( ses, msg );
- osrf_message_free( msg );
- return 0;
- }
- return -1;
-}
-
-
-
-
-
-
+++ /dev/null
-#ifndef _OSRF_APP_SESSION
-#define _OSRF_APP_SESSION
-
-#include "opensrf/transport_client.h"
-#include "objson/object.h"
-#include "osrf_message.h"
-#include "osrf_system.h"
-#include "opensrf/string_array.h"
-#include "osrfConfig.h"
-#include "osrf_hash.h"
-#include "osrf_list.h"
-
-#include "objson/object.h"
-#include "objson/json_parser.h"
-
-
-
-#define DEF_RECV_TIMEOUT 6 /* receive timeout */
-#define DEF_QUEUE_SIZE
-
-enum OSRF_SESSION_STATE { OSRF_SESSION_CONNECTING, OSRF_SESSION_CONNECTED, OSRF_SESSION_DISCONNECTED };
-enum OSRF_SESSION_TYPE { OSRF_SESSION_SERVER, OSRF_SESSION_CLIENT };
-
-/* entry point for data into the stack. gets set in osrf_stack.c */
-int (*osrf_stack_entry_point) (transport_client* client, int timeout, int* recvd );
-
-struct osrf_app_request_struct {
- /** Our controlling session */
- struct osrf_app_session_struct* session;
-
- /** our "id" */
- int request_id;
- /** True if we have received a 'request complete' message from our request */
- int complete;
- /** Our original request payload */
- osrf_message* payload;
- /** List of responses to our request */
- osrf_message* result;
-
- /* if set to true, then a call that is waiting on a response, will reset the
- timeout and set this variable back to false */
- int reset_timeout;
-};
-typedef struct osrf_app_request_struct osrf_app_request;
-typedef struct osrf_app_request_struct osrfAppRequest;
-
-struct osrf_app_session_struct {
-
- /** Our messag passing object */
- transport_client* transport_handle;
- /** Cache of active app_request objects */
-
- //osrf_app_request* request_queue;
-
- osrfList* request_queue;
-
- /** The original remote id of the remote service we're talking to */
- char* orig_remote_id;
- /** The current remote id of the remote service we're talking to */
- char* remote_id;
-
- /** Who we're talking to if we're a client.
- what app we're serving if we're a server */
- char* remote_service;
-
- /** The current request thread_trace */
- int thread_trace;
- /** Our ID */
- char* session_id;
-
- /* true if this session does not require connect messages */
- int stateless;
-
- /** The connect state */
- enum OSRF_SESSION_STATE state;
-
- /** SERVER or CLIENT */
- enum OSRF_SESSION_TYPE type;
-
- /* let the user use the session to store their own session data */
- void* userData;
-
- void (*userDataFree) (void*);
-};
-typedef struct osrf_app_session_struct osrf_app_session;
-typedef struct osrf_app_session_struct osrfAppSession;
-
-
-
-// --------------------------------------------------------------------------
-// PUBLIC API ***
-// --------------------------------------------------------------------------
-
-/** Allocates a initializes a new app_session */
-osrf_app_session* osrfAppSessionClientInit( char* remote_service );
-osrf_app_session* osrf_app_client_session_init( char* remote_service );
-
-/** Allocates and initializes a new server session. The global session cache
- * is checked to see if this session already exists, if so, it's returned
- */
-osrf_app_session* osrf_app_server_session_init(
- char* session_id, char* our_app, char* remote_id );
-
-/** returns a session from the global session hash */
-osrf_app_session* osrf_app_session_find_session( char* session_id );
-
-/** Builds a new app_request object with the given payload andn returns
- * the id of the request. This id is then used to perform work on the
- * requeset.
- */
-int osrfAppSessionMakeRequest(
- osrf_app_session* session, jsonObject* params,
- char* method_name, int protocol, string_array* param_strings);
-
-int osrf_app_session_make_req(
- osrf_app_session* session, jsonObject* params,
- char* method_name, int protocol, string_array* param_strings);
-
-/** Sets the given request to complete state */
-void osrf_app_session_set_complete( osrf_app_session* session, int request_id );
-
-/** Returns true if the given request is complete */
-int osrf_app_session_request_complete( osrf_app_session* session, int request_id );
-
-/** Does a recv call on the given request */
-osrf_message* osrfAppSessionRequestRecv(
- osrf_app_session* session, int request_id, int timeout );
-osrf_message* osrf_app_session_request_recv(
- osrf_app_session* session, int request_id, int timeout );
-
-/** Removes the request from the request set and frees the reqest */
-void osrf_app_session_request_finish( osrf_app_session* session, int request_id );
-
-/** Resends the orginal request with the given request id */
-int osrf_app_session_request_resend( osrf_app_session*, int request_id );
-
-/** Resets the remote connection target to that of the original*/
-void osrf_app_session_reset_remote( osrf_app_session* );
-
-/** Sets the remote target to 'remote_id' */
-void osrf_app_session_set_remote( osrf_app_session* session, char* remote_id );
-
-/** pushes the given message into the result list of the app_request
- * whose request_id matches the messages thread_trace
- */
-int osrf_app_session_push_queue( osrf_app_session*, osrf_message* msg );
-
-/** Attempts to connect to the remote service. Returns 1 on successful
- * connection, 0 otherwise.
- */
-int osrf_app_session_connect( osrf_app_session* );
-int osrfAppSessionConnect( osrf_app_session* );
-
-/** Sends a disconnect message to the remote service. No response is expected */
-int osrf_app_session_disconnect( osrf_app_session* );
-
-/** Waits up to 'timeout' seconds for some data to arrive.
- * Any data that arrives will be processed according to its
- * payload and message type. This method will return after
- * any data has arrived.
- */
-int osrf_app_session_queue_wait( osrf_app_session*, int timeout, int* recvd );
-
-/** Disconnects (if client), frees any attached app_reuqests, removes the session from the
- * global session cache and frees the session. Needless to say, only call this when the
- * session is completey done.
- */
-void osrf_app_session_destroy ( osrf_app_session* );
-void osrfAppSessionFree( osrfAppSession* );
-
-
-
-// --------------------------------------------------------------------------
-// --------------------------------------------------------------------------
-// Request functions
-// --------------------------------------------------------------------------
-
-/** Allocations and initializes a new app_request object */
-osrf_app_request* _osrf_app_request_init( osrf_app_session* session, osrf_message* msg );
-
-/** Frees memory used by an app_request object */
-void _osrf_app_request_free( void * req );
-
-/** Pushes the given message onto the list of 'responses' to this request */
-void _osrf_app_request_push_queue( osrf_app_request*, osrf_message* payload );
-
-/** Checks the receive queue for messages. If any are found, the first
- * is popped off and returned. Otherwise, this method will wait at most timeout
- * seconds for a message to appear in the receive queue. Once it arrives it is returned.
- * If no messages arrive in the timeout provided, null is returned.
- */
-osrf_message* _osrf_app_request_recv( osrf_app_request* req, int timeout );
-
-/** Resend this requests original request message */
-int _osrf_app_request_resend( osrf_app_request* req );
-
-
-/* tells the request to reset it's wait timeout */
-void osrf_app_session_request_reset_timeout( osrf_app_session* session, int req_id );
-
-// --------------------------------------------------------------------------
-// --------------------------------------------------------------------------
-// Session functions
-// --------------------------------------------------------------------------
-
-/** Returns the app_request with the given thread_trace (request_id) */
-osrf_app_request* _osrf_app_session_get_request( osrf_app_session*, int thread_trace );
-
-/** frees memory held by a session. Note: We delete all requests in the request list */
-void _osrf_app_session_free( osrf_app_session* );
-
-/** adds a session to the global session cache */
-void _osrf_app_session_push_session( osrf_app_session* );
-
-/** Adds an app_request to the request set */
-void _osrf_app_session_push_request( osrf_app_session*, osrf_app_request* req );
-
-/** Removes an app_request from this session request set, freeing the request object */
-void _osrf_app_session_remove_request( osrf_app_session*, osrf_app_request* req );
-
-/** Send the given message */
-int _osrf_app_session_send( osrf_app_session*, osrf_message* msg );
-
-int osrfAppSessionSendBatch( osrf_app_session*, osrf_message* msgs[], int size );
-
-int osrfAppRequestRespond( osrfAppSession* ses, int requestId, jsonObject* data );
-int osrfAppRequestRespondComplete( osrfAppSession* ses, int requestId, jsonObject* data );
-
-int osrfAppSessionStatus( osrfAppSession* ses, int type, char* name, int reqId, char* message );
-
-void osrfAppSessionCleanup();
-
-
-
-#endif
+++ /dev/null
-#include "osrf_application.h"
-#include "objson/object.h"
-
-//osrfApplication* __osrfAppList = NULL;
-
-osrfHash* __osrfAppHash = NULL;
-
-
-int osrfAppRegisterApplication( char* appName, char* soFile ) {
- if(!appName || ! soFile) return -1;
- char* error;
-
- if(!__osrfAppHash) __osrfAppHash = osrfNewHash();
-
- osrfLogInfo( OSRF_LOG_MARK, "Registering application %s with file %s", appName, soFile );
-
- osrfApplication* app = safe_malloc(sizeof(osrfApplication));
- app->handle = dlopen (soFile, RTLD_NOW);
- app->onExit = NULL;
-
- if(!app->handle) {
- osrfLogWarning( OSRF_LOG_MARK, "Failed to dlopen library file %s: %s", soFile, dlerror() );
- dlerror(); /* clear the error */
- free(app);
- return -1;
- }
-
- app->methods = osrfNewHash();
- osrfHashSet( __osrfAppHash, app, appName );
-
- /* see if we can run the initialize method */
- int (*init) (void);
- *(void **) (&init) = dlsym(app->handle, "osrfAppInitialize");
-
- if( (error = dlerror()) != NULL ) {
- osrfLogWarning( OSRF_LOG_MARK,
- "! Unable to locate method symbol [osrfAppInitialize] for app %s: %s", appName, error );
-
- } else {
-
- /* run the method */
- int ret;
- if( (ret = (*init)()) ) {
- osrfLogWarning( OSRF_LOG_MARK, "Application %s returned non-zero value from "
- "'osrfAppInitialize', not registering...", appName );
- //free(app->name); /* need a method to remove an application from the list */
- //free(app);
- return ret;
- }
- }
-
- __osrfAppRegisterSysMethods(appName);
-
- osrfLogInfo( OSRF_LOG_MARK, "Application %s registered successfully", appName );
-
- osrfLogSetAppname(appName);
-
- osrfAppSetOnExit(app, appName);
-
- return 0;
-}
-
-
-void osrfAppSetOnExit(osrfApplication* app, char* appName) {
- if(!(app && appName)) return;
-
- /* see if we can run the initialize method */
- char* error;
- void (*onExit) (void);
- *(void **) (&onExit) = dlsym(app->handle, "osrfAppChildExit");
-
- if( (error = dlerror()) != NULL ) {
- osrfLogDebug(OSRF_LOG_MARK, "No exit handler defined for %s", appName);
- return;
- }
-
- osrfLogInfo(OSRF_LOG_MARK, "registering exit handler for %s", appName);
- app->onExit = (*onExit);
- //if( (ret = (*onExit)()) ) {
-}
-
-
-int osrfAppRunChildInit(char* appname) {
- osrfApplication* app = _osrfAppFindApplication(appname);
- if(!app) return -1;
-
- char* error;
- int ret;
- int (*childInit) (void);
-
- *(void**) (&childInit) = dlsym(app->handle, "osrfAppChildInit");
-
- if( (error = dlerror()) != NULL ) {
- osrfLogInfo( OSRF_LOG_MARK, "No child init defined for app %s : %s", appname, error);
- return 0;
- }
-
- if( (ret = (*childInit)()) ) {
- osrfLogError(OSRF_LOG_MARK, "App %s child init failed", appname);
- return -1;
- }
-
- osrfLogInfo(OSRF_LOG_MARK, "%s child init succeeded", appname);
- return 0;
-}
-
-
-void osrfAppRunExitCode() {
- osrfHashIterator* itr = osrfNewHashIterator(__osrfAppHash);
- osrfApplication* app;
- while( (app = osrfHashIteratorNext(itr)) ) {
- if( app->onExit ) {
- osrfLogInfo(OSRF_LOG_MARK, "Running onExit handler for app %s", itr->current);
- app->onExit();
- }
- }
-}
-
-
-int osrfAppRegisterMethod( char* appName, char* methodName,
- char* symbolName, char* notes, int argc, int options ) {
-
- return osrfAppRegisterExtendedMethod(
- appName,
- methodName,
- symbolName,
- notes,
- argc,
- options,
- NULL
- );
-
-}
-
-int osrfAppRegisterExtendedMethod( char* appName, char* methodName,
- char* symbolName, char* notes, int argc, int options, void * user_data ) {
-
- if( !appName || ! methodName ) return -1;
-
- osrfApplication* app = _osrfAppFindApplication(appName);
- if(!app) {
- osrfLogWarning( OSRF_LOG_MARK, "Unable to locate application %s", appName );
- return -1;
- }
-
- osrfLogDebug( OSRF_LOG_MARK, "Registering method %s for app %s", methodName, appName );
-
- osrfMethod* method = _osrfAppBuildMethod(
- methodName, symbolName, notes, argc, options, user_data );
- method->options = options;
-
- /* plug the method into the list of methods */
- osrfHashSet( app->methods, method, method->name );
-
- if( options & OSRF_METHOD_STREAMING ) { /* build the atomic counterpart */
- int newops = options | OSRF_METHOD_ATOMIC;
- osrfMethod* atomicMethod = _osrfAppBuildMethod(
- methodName, symbolName, notes, argc, newops, NULL );
- osrfHashSet( app->methods, atomicMethod, atomicMethod->name );
- atomicMethod->userData = method->userData;
- }
-
- return 0;
-}
-
-
-
-osrfMethod* _osrfAppBuildMethod( char* methodName,
- char* symbolName, char* notes, int argc, int options, void* user_data ) {
-
- osrfMethod* method = safe_malloc(sizeof(osrfMethod));
-
- if(methodName) method->name = strdup(methodName);
- if(symbolName) method->symbol = strdup(symbolName);
- if(notes) method->notes = strdup(notes);
- if(user_data) method->userData = user_data;
-
- method->argc = argc;
- method->options = options;
-
- if(options & OSRF_METHOD_ATOMIC) { /* add ".atomic" to the end of the name */
- char mb[strlen(method->name) + 8];
- sprintf(mb, "%s.atomic", method->name);
- free(method->name);
- method->name = strdup(mb);
- method->options |= OSRF_METHOD_STREAMING;
- }
-
- return method;
-}
-
-
-int __osrfAppRegisterSysMethods( char* app ) {
-
- osrfAppRegisterMethod(
- app, OSRF_SYSMETHOD_INTROSPECT, NULL,
- "Return a list of methods whose names have the same initial "
- "substring as that of the provided method name PARAMS( methodNameSubstring )",
- 1, OSRF_METHOD_SYSTEM | OSRF_METHOD_STREAMING );
-
- osrfAppRegisterMethod(
- app, OSRF_SYSMETHOD_INTROSPECT_ALL, NULL,
- "Returns a complete list of methods. PARAMS()", 0,
- OSRF_METHOD_SYSTEM | OSRF_METHOD_STREAMING );
-
- osrfAppRegisterMethod(
- app, OSRF_SYSMETHOD_ECHO, NULL,
- "Echos all data sent to the server back to the client. PARAMS([a, b, ...])", 0,
- OSRF_METHOD_SYSTEM | OSRF_METHOD_STREAMING );
-
- return 0;
-}
-
-osrfApplication* _osrfAppFindApplication( char* name ) {
- if(!name) return NULL;
- return (osrfApplication*) osrfHashGet(__osrfAppHash, name);
-}
-
-osrfMethod* __osrfAppFindMethod( osrfApplication* app, char* methodName ) {
- if(!app || ! methodName) return NULL;
- return (osrfMethod*) osrfHashGet( app->methods, methodName );
-}
-
-osrfMethod* _osrfAppFindMethod( char* appName, char* methodName ) {
- if(!appName || ! methodName) return NULL;
- return __osrfAppFindMethod( _osrfAppFindApplication(appName), methodName );
-}
-
-
-int osrfAppRunMethod( char* appName, char* methodName,
- osrfAppSession* ses, int reqId, jsonObject* params ) {
-
- if( !(appName && methodName && ses) ) return -1;
-
- char* error;
- osrfApplication* app;
- osrfMethod* method;
- osrfMethodContext context;
-
- context.session = ses;
- context.params = params;
- context.request = reqId;
- context.responses = NULL;
-
- /* this is the method we're gonna run */
- int (*meth) (osrfMethodContext*);
-
- if( !(app = _osrfAppFindApplication(appName)) )
- return osrfAppRequestRespondException( ses,
- reqId, "Application not found: %s", appName );
-
- if( !(method = __osrfAppFindMethod( app, methodName )) )
- return osrfAppRequestRespondException( ses, reqId,
- "Method [%s] not found for service %s", methodName, appName );
-
- context.method = method;
-
- #ifdef OSRF_STRICT_PARAMS
- if( method->argc > 0 ) {
- if(!params || params->type != JSON_ARRAY || params->size < method->argc )
- return osrfAppRequestRespondException( ses, reqId,
- "Not enough params for method %s / service %s", methodName, appName );
- }
- #endif
-
- int retcode = 0;
-
- if( method->options & OSRF_METHOD_SYSTEM ) {
- retcode = __osrfAppRunSystemMethod(&context);
-
- } else {
-
- /* open and now run the method */
- *(void **) (&meth) = dlsym(app->handle, method->symbol);
-
- if( (error = dlerror()) != NULL ) {
- return osrfAppRequestRespondException( ses, reqId,
- "Unable to execute method [%s] for service %s", methodName, appName );
- }
-
- retcode = (*meth) (&context);
- }
-
- if(retcode < 0)
- return osrfAppRequestRespondException(
- ses, reqId, "An unknown server error occurred" );
-
- return __osrfAppPostProcess( &context, retcode );
-
-}
-
-
-int osrfAppRespond( osrfMethodContext* ctx, jsonObject* data ) {
- return _osrfAppRespond( ctx, data, 0 );
-}
-
-int osrfAppRespondComplete( osrfMethodContext* context, jsonObject* data ) {
- return _osrfAppRespond( context, data, 1 );
-}
-
-int _osrfAppRespond( osrfMethodContext* ctx, jsonObject* data, int complete ) {
- if(!(ctx && ctx->method)) return -1;
-
- if( ctx->method->options & OSRF_METHOD_ATOMIC ) {
- osrfLogDebug( OSRF_LOG_MARK,
- "Adding responses to stash for atomic method %s", ctx->method->name );
-
- if( ctx->responses == NULL )
- ctx->responses = jsonParseString("[]");
-
- if ( data != NULL )
- jsonObjectPush( ctx->responses, jsonObjectClone(data) );
- }
-
-
- if( !(ctx->method->options & OSRF_METHOD_ATOMIC) &&
- !(ctx->method->options & OSRF_METHOD_CACHABLE) ) {
-
- if(complete)
- osrfAppRequestRespondComplete( ctx->session, ctx->request, data );
- else
- osrfAppRequestRespond( ctx->session, ctx->request, data );
- return 0;
- }
-
- return 0;
-}
-
-
-
-
-int __osrfAppPostProcess( osrfMethodContext* ctx, int retcode ) {
- if(!(ctx && ctx->method)) return -1;
-
- osrfLogDebug( OSRF_LOG_MARK, "Postprocessing method %s with retcode %d",
- ctx->method->name, retcode );
-
- if(ctx->responses) { /* we have cached responses to return (no responses have been sent) */
-
- osrfAppRequestRespondComplete( ctx->session, ctx->request, ctx->responses );
- jsonObjectFree(ctx->responses);
- ctx->responses = NULL;
-
- } else {
-
- if( retcode > 0 )
- osrfAppSessionStatus( ctx->session, OSRF_STATUS_COMPLETE,
- "osrfConnectStatus", ctx->request, "Request Complete" );
- }
-
- return 0;
-}
-
-int osrfAppRequestRespondException( osrfAppSession* ses, int request, char* msg, ... ) {
- if(!ses) return -1;
- if(!msg) msg = "";
- VA_LIST_TO_STRING(msg);
- osrfLogWarning( OSRF_LOG_MARK, "Returning method exception with message: %s", VA_BUF );
- osrfAppSessionStatus( ses, OSRF_STATUS_NOTFOUND, "osrfMethodException", request, VA_BUF );
- return 0;
-}
-
-
-static void __osrfAppSetIntrospectMethod( osrfMethodContext* ctx, osrfMethod* method, jsonObject* resp ) {
- if(!(ctx && resp)) return;
-
- jsonObjectSetKey(resp, "api_name", jsonNewObject(method->name));
- jsonObjectSetKey(resp, "method", jsonNewObject(method->symbol));
- jsonObjectSetKey(resp, "service", jsonNewObject(ctx->session->remote_service));
- jsonObjectSetKey(resp, "notes", jsonNewObject(method->notes));
- jsonObjectSetKey(resp, "argc", jsonNewNumberObject(method->argc));
-
- jsonObjectSetKey(resp, "sysmethod",
- jsonNewNumberObject( (method->options & OSRF_METHOD_SYSTEM) ? 1 : 0 ));
- jsonObjectSetKey(resp, "atomic",
- jsonNewNumberObject( (method->options & OSRF_METHOD_ATOMIC) ? 1 : 0 ));
- jsonObjectSetKey(resp, "cachable",
- jsonNewNumberObject( (method->options & OSRF_METHOD_CACHABLE) ? 1 : 0 ));
-
- jsonObjectSetClass(resp, "method");
-}
-
-
-
-int __osrfAppRunSystemMethod(osrfMethodContext* ctx) {
- OSRF_METHOD_VERIFY_CONTEXT(ctx);
-
- if( !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT_ALL ) ||
- !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT_ALL_ATOMIC )) {
-
- return osrfAppIntrospectAll(ctx);
- }
-
-
- if( !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT ) ||
- !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT_ATOMIC )) {
-
- return osrfAppIntrospect(ctx);
- }
-
- if( !strcmp(ctx->method->name, OSRF_SYSMETHOD_ECHO ) ||
- !strcmp(ctx->method->name, OSRF_SYSMETHOD_ECHO_ATOMIC )) {
-
- return osrfAppEcho(ctx);
- }
-
-
- osrfAppRequestRespondException( ctx->session,
- ctx->request, "System method implementation not found");
-
- return 0;
-}
-
-
-int osrfAppIntrospect( osrfMethodContext* ctx ) {
-
- jsonObject* resp = NULL;
- char* methodSubstring = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0) );
- osrfApplication* app = _osrfAppFindApplication( ctx->session->remote_service );
- int len = 0;
-
- if(!methodSubstring) return 1; /* respond with no methods */
-
- if(app) {
-
- osrfHashIterator* itr = osrfNewHashIterator(app->methods);
- osrfMethod* method;
-
- while( (method = osrfHashIteratorNext(itr)) ) {
- if( (len = strlen(methodSubstring)) <= strlen(method->name) ) {
- if( !strncmp( method->name, methodSubstring, len) ) {
- resp = jsonNewObject(NULL);
- __osrfAppSetIntrospectMethod( ctx, method, resp );
- osrfAppRespond(ctx, resp);
- jsonObjectFree(resp);
- }
- }
- }
- osrfHashIteratorFree(itr);
- return 1;
- }
-
- return -1;
-
-}
-
-
-int osrfAppIntrospectAll( osrfMethodContext* ctx ) {
- jsonObject* resp = NULL;
- osrfApplication* app = _osrfAppFindApplication( ctx->session->remote_service );
-
- if(app) {
- osrfHashIterator* itr = osrfNewHashIterator(app->methods);
- osrfMethod* method;
- while( (method = osrfHashIteratorNext(itr)) ) {
- resp = jsonNewObject(NULL);
- __osrfAppSetIntrospectMethod( ctx, method, resp );
- osrfAppRespond(ctx, resp);
- jsonObjectFree(resp);
- }
- osrfHashIteratorFree(itr);
- return 1;
- }
-
- return -1;
-}
-
-int osrfAppEcho( osrfMethodContext* ctx ) {
- OSRF_METHOD_VERIFY_CONTEXT(ctx);
- int i;
- for( i = 0; i < ctx->params->size; i++ ) {
- jsonObject* str = jsonObjectGetIndex(ctx->params,i);
- osrfAppRespond(ctx, str);
- }
- return 1;
-}
-
+++ /dev/null
-#include <stdio.h>
-#include <dlfcn.h>
-#include "opensrf/utils.h"
-#include "opensrf/log.h"
-#include "objson/object.h"
-#include "osrf_app_session.h"
-#include "osrf_hash.h"
-
-
-/**
- All OpenSRF methods take the signature
- int methodName( osrfMethodContext* );
- If a negative number is returned, it means an unknown error occured and an exception
- will be returned to the client automatically.
- If a positive number is returned, it means that libopensrf should send a 'Request Complete'
- message following any messages sent by the method.
- If 0 is returned, it tells libopensrf that the method completed successfully and
- there is no need to send any further data to the client.
- */
-
-
-
-/**
- This macro verifies methods receive the correct parameters */
-#define _OSRF_METHOD_VERIFY_CONTEXT(d) \
- if(!d) return -1; \
- if(!d->session) { osrfLogError( OSRF_LOG_MARK, "Session is NULL in app reqeust" ); return -1; }\
- if(!d->method) { osrfLogError( OSRF_LOG_MARK, "Method is NULL in app reqeust" ); return -1; }\
- if(d->method->argc) {\
- if(!d->params) { osrfLogError( OSRF_LOG_MARK, "Params is NULL in app reqeust %s", d->method->name ); return -1; }\
- if( d->params->type != JSON_ARRAY ) { \
- osrfLogError( OSRF_LOG_MARK, "'params' is not a JSON array for method %s", d->method->name);\
- return -1; }\
- }\
- if( !d->method->name ) { osrfLogError( OSRF_LOG_MARK, "Method name is NULL"); return -1; }
-
-#ifdef OSRF_LOG_PARAMS
-#define OSRF_METHOD_VERIFY_CONTEXT(d) \
- _OSRF_METHOD_VERIFY_CONTEXT(d); \
- char* __j = jsonObjectToJSON(d->params);\
- if(__j) { \
- osrfLogInfo( OSRF_LOG_MARK, "CALL: %s %s - %s", d->session->remote_service, d->method->name, __j);\
- free(__j); \
- }
-#else
-#define OSRF_METHOD_VERIFY_CONTEXT(d) _OSRF_METHOD_VERIFY_CONTEXT(d);
-#endif
-
-
-
-/* used internally to make sure the method description provided is OK */
-#define OSRF_METHOD_VERIFY_DESCRIPTION(app, d) \
- if(!app) return -1; \
- if(!d) return -1;\
- if(!d->name) { osrfLogError( OSRF_LOG_MARK, "No method name provided in description" ), return -1; } \
- if(!d->symbol) { osrfLogError( OSRF_LOG_MARK, "No method symbol provided in description" ), return -1; } \
- if(!d->notes) d->notes = ""; \
- if(!d->paramNotes) d->paramNotes = "";\
- if(!d->returnNotes) d->returnNotes = "";
-
-
-
-
-/* Some well known parameters */
-#define OSRF_SYSMETHOD_INTROSPECT "opensrf.system.method"
-#define OSRF_SYSMETHOD_INTROSPECT_ATOMIC "opensrf.system.method.atomic"
-#define OSRF_SYSMETHOD_INTROSPECT_ALL "opensrf.system.method.all"
-#define OSRF_SYSMETHOD_INTROSPECT_ALL_ATOMIC "opensrf.system.method.all.atomic"
-#define OSRF_SYSMETHOD_ECHO "opensrf.system.echo"
-#define OSRF_SYSMETHOD_ECHO_ATOMIC "opensrf.system.echo.atomic"
-
-#define OSRF_METHOD_SYSTEM 1
-#define OSRF_METHOD_STREAMING 2
-#define OSRF_METHOD_ATOMIC 4
-#define OSRF_METHOD_CACHABLE 8
-
-
-
-struct _osrfApplicationStruct {
- void* handle; /* the lib handle */
- osrfHash* methods;
- void (*onExit) (void);
-};
-typedef struct _osrfApplicationStruct osrfApplication;
-
-
-struct _osrfMethodStruct {
- char* name; /* the method name */
- char* symbol; /* the symbol name (function) */
- char* notes; /* public method documentation */
- int argc; /* how many args this method expects */
- //char* paramNotes; /* Description of the params expected for this method */
- int options; /* describes the various options for this method */
- void* userData; /* You can put your weeeeeeed in it ... */
-
- /*
- int sysmethod;
- int streaming;
- int atomic;
- int cachable;
- */
-};
-typedef struct _osrfMethodStruct osrfMethod;
-
-struct _osrfMethodContextStruct {
- osrfAppSession* session; /* the current session */
- osrfMethod* method; /* the requested method */
- jsonObject* params; /* the params to the method */
- int request; /* request id */
- jsonObject* responses; /* array of cached responses. */
-};
-typedef struct _osrfMethodContextStruct osrfMethodContext;
-
-
-
-/**
- Register an application
- @param appName The name of the application
- @param soFile The library (.so) file that implements this application
- @return 0 on success, -1 on error
- */
-int osrfAppRegisterApplication( char* appName, char* soFile );
-
-/**
- Register a method
- Any method with the OSRF_METHOD_STREAMING option set will have a ".atomic"
- version of the method registered automatically
- @param appName The name of the application that implements the method
- @param methodName The fully qualified name of the method
- @param symbolName The symbol name (function) that implements the method
- @param notes Public documentation for this method.
- @params argc The number of arguments this method expects
- @param streaming True if this is a streaming method that requires an atomic version
- @return 0 on success, -1 on error
- */
-int osrfAppRegisterMethod( char* appName, char* methodName,
- char* symbolName, char* notes, int argc, int options );
-
-
-int osrfAppRegisterExtendedMethod( char* appName, char* methodName,
- char* symbolName, char* notes, int argc, int options, void* );
-
-osrfMethod* _osrfAppBuildMethod( char* methodName,
- char* symbolName, char* notes, int argc, int options, void* );
-
-/**
- Finds the given app in the list of apps
- @param name The name of the application
- @return The application pointer or NULL if there is no such application
- */
-osrfApplication* _osrfAppFindApplication( char* name );
-
-/**
- Finds the given method for the given app
- @param appName The application
- @param methodName The method to find
- @return A method pointer or NULL if no such method
- exists for the given application
- */
-osrfMethod* _osrfAppFindMethod( char* appName, char* methodName );
-
-/**
- Finds the given method for the given app
- @param app The application object
- @param methodName The method to find
- @return A method pointer or NULL if no such method
- exists for the given application
- */
-osrfMethod* __osrfAppFindMethod( osrfApplication* app, char* methodName );
-
-
-/**
- Runs the specified method for the specified application.
- @param appName The name of the application who's method to run
- @param methodName The name of the method to run
- @param ses The app session attached to this request
- @params reqId The request id for this request
- @param params The method parameters
- */
-int osrfAppRunMethod( char* appName, char* methodName,
- osrfAppSession* ses, int reqId, jsonObject* params );
-
-
-/**
- Trys to run the requested method as a system method.
- A system method is a well known method that all
- servers implement.
- @param context The current method context
- @return 0 if the method is run successfully, return < 0 means
- the method was not run, return > 0 means the method was run
- and the application code now needs to send a 'request complete'
- message
- */
-int __osrfAppRunSystemMethod(osrfMethodContext* context);
-
-/**
- Registers all of the system methods for this app so that they may be
- treated the same as other methods */
-int __osrfAppRegisterSysMethods( char* app );
-
-
-
-/**
- Responds to the client with a method exception
- @param ses The current session
- @param request The request id
- @param msg The debug message to send to the client
- @return 0 on successfully sending of the message, -1 otherwise
- */
-int osrfAppRequestRespondException( osrfAppSession* ses, int request, char* msg, ... );
-
-int __osrfAppPostProcess( osrfMethodContext* context, int retcode );
-
-
-int osrfAppRespond( osrfMethodContext* context, jsonObject* data );
-int _osrfAppRespond( osrfMethodContext* context, jsonObject* data, int complete );
-int osrfAppRespondComplete( osrfMethodContext* context, jsonObject* data );
-
-/* OSRF_METHOD_ATOMIC and/or OSRF_METHOD_CACHABLE and/or 0 for no special options */
-//int osrfAppProcessMethodOptions( char* method );
-
-int osrfAppIntrospect( osrfMethodContext* ctx );
-int osrfAppIntrospectAll( osrfMethodContext* ctx );
-int osrfAppEcho( osrfMethodContext* ctx );
-
-
-/**
- * Tells the backend process to run its child init function */
-int osrfAppRunChildInit(char* appname);
-void osrfAppSetOnExit(osrfApplication* app, char* appName);
-void osrfAppRunExitCode();
-
-
+++ /dev/null
-#include "osrf_big_hash.h"
-
-osrfBigHash* osrfNewBigHash() {
- osrfBigHash* hash = safe_malloc(sizeof(osrfBigHash));
- hash->hash = (Pvoid_t) NULL;
- hash->freeItem = NULL;
- return hash;
-}
-
-void* osrfBigHashSet( osrfBigHash* hash, void* item, const char* key, ... ) {
- if(!(hash && item && key )) return NULL;
-
- Word_t* value;
- VA_LIST_TO_STRING(key);
- uint8_t idx[strlen(VA_BUF) + 1];
- strcpy( idx, VA_BUF );
-
- void* olditem = osrfBigHashRemove( hash, VA_BUF );
-
- JSLI(value, hash->hash, idx);
- if(value) *value = (Word_t) item;
- return olditem;
-
-}
-
-void* osrfBigHashRemove( osrfBigHash* hash, const char* key, ... ) {
- if(!(hash && key )) return NULL;
-
- VA_LIST_TO_STRING(key);
-
- Word_t* value;
- uint8_t idx[strlen(VA_BUF) + 1];
- strcpy( idx, VA_BUF );
- void* item = NULL;
- int retcode;
-
- JSLG( value, hash->hash, idx);
-
- if( value ) {
- item = (void*) *value;
- if(item) {
- if( hash->freeItem ) {
- hash->freeItem( (char*) idx, item );
- item = NULL;
- }
- }
- }
-
-
- JSLD( retcode, hash->hash, idx );
-
- return item;
-}
-
-
-void* osrfBigHashGet( osrfBigHash* hash, const char* key, ... ) {
- if(!(hash && key )) return NULL;
-
- VA_LIST_TO_STRING(key);
-
- Word_t* value;
- uint8_t idx[strlen(VA_BUF) + 1];
- strcpy( idx, VA_BUF );
-
- JSLG( value, hash->hash, idx );
- if(value) return (void*) *value;
- return NULL;
-}
-
-
-osrfStringArray* osrfBigHashKeys( osrfBigHash* hash ) {
- if(!hash) return NULL;
-
- Word_t* value;
- uint8_t idx[OSRF_HASH_MAXKEY];
- strcpy(idx, "");
- char* key;
- osrfStringArray* strings = osrfNewStringArray(8);
-
- JSLF( value, hash->hash, idx );
-
- while( value ) {
- key = (char*) idx;
- osrfStringArrayAdd( strings, key );
- JSLN( value, hash->hash, idx );
- }
-
- return strings;
-}
-
-
-unsigned long osrfBigHashGetCount( osrfBigHash* hash ) {
- if(!hash) return -1;
-
- Word_t* value;
- unsigned long count = 0;
- uint8_t idx[OSRF_HASH_MAXKEY];
-
- strcpy( (char*) idx, "");
- JSLF(value, hash->hash, idx);
-
- while(value) {
- count++;
- JSLN( value, hash->hash, idx );
- }
-
- return count;
-}
-
-void osrfBigHashFree( osrfBigHash* hash ) {
- if(!hash) return;
-
- int i;
- osrfStringArray* keys = osrfBigHashKeys( hash );
-
- for( i = 0; i != keys->size; i++ ) {
- char* key = (char*) osrfStringArrayGetString( keys, i );
- osrfBigHashRemove( hash, key );
- }
-
- osrfStringArrayFree(keys);
- free(hash);
-}
-
-
-
-osrfBigHashIterator* osrfNewBigHashIterator( osrfBigHash* hash ) {
- if(!hash) return NULL;
- osrfBigHashIterator* itr = safe_malloc(sizeof(osrfBigHashIterator));
- itr->hash = hash;
- itr->current = NULL;
- return itr;
-}
-
-void* osrfBigHashIteratorNext( osrfBigHashIterator* itr ) {
- if(!(itr && itr->hash)) return NULL;
-
- Word_t* value;
- uint8_t idx[OSRF_HASH_MAXKEY];
-
- if( itr->current == NULL ) { /* get the first item in the list */
- strcpy(idx, "");
- JSLF( value, itr->hash->hash, idx );
-
- } else {
- strcpy(idx, itr->current);
- JSLN( value, itr->hash->hash, idx );
- }
-
- if(value) {
- free(itr->current);
- itr->current = strdup((char*) idx);
- return (void*) *value;
- }
-
- return NULL;
-
-}
-
-void osrfBigHashIteratorFree( osrfBigHashIterator* itr ) {
- if(!itr) return;
- free(itr->current);
- free(itr);
-}
-
-void osrfBigHashIteratorReset( osrfBigHashIterator* itr ) {
- if(!itr) return;
- free(itr->current);
- itr->current = NULL;
-}
-
-
-
+++ /dev/null
-#ifndef OSRF_HASH_H
-#define OSRF_HASH_H
-
-#include <Judy.h>
-#include "opensrf/utils.h"
-#include "opensrf/string_array.h"
-
-#define OSRF_HASH_MAXKEY 256
-
-struct __osrfBigHashStruct {
- Pvoid_t hash; /* the hash */
- void (*freeItem) (char* key, void* item); /* callback for freeing stored items */
-};
-typedef struct __osrfBigHashStruct osrfBigHash;
-
-
-struct __osrfBigHashIteratorStruct {
- char* current;
- osrfBigHash* hash;
-};
-typedef struct __osrfBigHashIteratorStruct osrfBigHashIterator;
-
-/**
- Allocates a new hash object
- */
-osrfBigHash* osrfNewBigHash();
-
-/**
- Sets the given key with the given item
- if "freeItem" is defined and an item already exists at the given location,
- then old item is freed and the new item is put into place.
- if "freeItem" is not defined and an item already exists, the old item
- is returned.
- @return The old item if exists and there is no 'freeItem', returns NULL
- otherwise
- */
-void* osrfBigHashSet( osrfBigHash* hash, void* item, const char* key, ... );
-
-/**
- Removes an item from the hash.
- if 'freeItem' is defined it is used and NULL is returned,
- else the freed item is returned
- */
-void* osrfBigHashRemove( osrfBigHash* hash, const char* key, ... );
-
-void* osrfBigHashGet( osrfBigHash* hash, const char* key, ... );
-
-
-/**
- @return A list of strings representing the keys of the hash.
- caller is responsible for freeing the returned string array
- with osrfStringArrayFree();
- */
-osrfStringArray* osrfBigHashKeys( osrfBigHash* hash );
-
-/**
- Frees a hash
- */
-void osrfBigHashFree( osrfBigHash* hash );
-
-/**
- @return The number of items in the hash
- */
-unsigned long osrfBigHashGetCount( osrfBigHash* hash );
-
-
-
-
-/**
- Creates a new list iterator with the given list
- */
-osrfBigHashIterator* osrfNewBigHashIterator( osrfBigHash* hash );
-
-/**
- Returns the next non-NULL item in the list, return NULL when
- the end of the list has been reached
- */
-void* osrfBigHashIteratorNext( osrfBigHashIterator* itr );
-
-/**
- Deallocates the given list
- */
-void osrfBigHashIteratorFree( osrfBigHashIterator* itr );
-
-void osrfBigHashIteratorReset( osrfBigHashIterator* itr );
-
-#endif
+++ /dev/null
-#include "osrf_big_list.h"
-
-
-osrfBigList* osrfNewBigList() {
- osrfBigList* list = safe_malloc(sizeof(osrfBigList));
- list->list = (Pvoid_t) NULL;
- list->size = 0;
- list->freeItem = NULL;
- return list;
-}
-
-
-int osrfBigListPush( osrfBigList* list, void* item ) {
- if(!(list && item)) return -1;
- Word_t* value;
- unsigned long index = -1;
- JLL(value, list->list, index );
- osrfBigListSet( list, item, index+1 );
- return 0;
-}
-
-
-void* osrfBigListSet( osrfBigList* list, void* item, unsigned long position ) {
- if(!list || position < 0) return NULL;
-
- Word_t* value;
- void* olditem = osrfBigListRemove( list, position );
-
- JLI( value, list->list, position );
- *value = (Word_t) item;
- __osrfBigListSetSize( list );
-
- return olditem;
-}
-
-
-void* osrfBigListGetIndex( osrfBigList* list, unsigned long position ) {
- if(!list) return NULL;
-
- Word_t* value;
- JLG( value, list->list, position );
- if(value) return (void*) *value;
- return NULL;
-}
-
-void osrfBigListFree( osrfBigList* list ) {
- if(!list) return;
-
- Word_t* value;
- unsigned long index = -1;
- JLL(value, list->list, index );
- int retcode;
-
- while (value != NULL) {
- if(list->freeItem)
- list->freeItem( (void*) *value );
- JLD(retcode, list->list, index);
- JLP(value, list->list, index);
- }
-
- free(list);
-}
-
-void* osrfBigListRemove( osrfBigList* list, int position ) {
- if(!list) return NULL;
-
- int retcode;
- Word_t* value;
- JLG( value, list->list, position );
- void* olditem = NULL;
-
- if( value ) {
-
- olditem = (void*) *value;
- if( olditem ) {
- JLD(retcode, list->list, position );
- if(retcode == 1) {
- if(list->freeItem) {
- list->freeItem( olditem );
- olditem = NULL;
- }
- __osrfBigListSetSize( list );
- }
- }
- }
-
- return olditem;
-}
-
-
-int osrfBigListFind( osrfBigList* list, void* addr ) {
- if(!(list && addr)) return -1;
-
- Word_t* value;
- unsigned long index = -1;
- JLL(value, list->list, index );
-
- while (value != NULL) {
- if( (void*) *value == addr )
- return index;
- JLP(value, list->list, index);
- }
-
- return -1;
-}
-
-
-
-void __osrfBigListSetSize( osrfBigList* list ) {
- if(!list) return;
-
- Word_t* value;
- unsigned long index = -1;
- JLL(value, list->list, index );
- list->size = index + 1;
-}
-
-
-unsigned long osrfBigListGetCount( osrfBigList* list ) {
- if(!list) return -1;
- unsigned long retcode = -1;
- JLC( retcode, list->list, 0, -1 );
- return retcode;
-}
-
-
-void* osrfBigListPop( osrfBigList* list ) {
- if(!list) return NULL;
- return osrfBigListRemove( list, list->size - 1 );
-}
-
-
-osrfBigBigListIterator* osrfNewBigListIterator( osrfBigList* list ) {
- if(!list) return NULL;
- osrfBigBigListIterator* itr = safe_malloc(sizeof(osrfBigBigListIterator));
- itr->list = list;
- itr->current = 0;
- return itr;
-}
-
-void* osrfBigBigListIteratorNext( osrfBigBigListIterator* itr ) {
- if(!(itr && itr->list)) return NULL;
-
- Word_t* value;
- if(itr->current >= itr->list->size) return NULL;
- JLF( value, itr->list->list, itr->current );
- if(value) {
- itr->current++;
- return (void*) *value;
- }
- return NULL;
-}
-
-void osrfBigBigListIteratorFree( osrfBigBigListIterator* itr ) {
- if(!itr) return;
- free(itr);
-}
-
-
-
-void osrfBigBigListIteratorReset( osrfBigBigListIterator* itr ) {
- if(!itr) return;
- itr->current = 0;
-}
-
-
-void osrfBigListVanillaFree( void* item ) {
- free(item);
-}
-
-void osrfBigListSetDefaultFree( osrfBigList* list ) {
- if(!list) return;
- list->freeItem = osrfBigListVanillaFree;
-}
+++ /dev/null
-#ifndef OSRF_BIG_LIST_H
-#define OSRF_BIG_LIST_H
-
-
-#include <stdio.h>
-#include "opensrf/utils.h"
-#include <Judy.h>
-
-/**
- Items are stored as void*'s so it's up to the user to
- manage the data wisely. Also, if the 'freeItem' callback is defined for the list,
- then, it will be used on any item that needs to be freed, so don't mix data
- types in the list if you want magic freeing */
-
-struct __osrfBigListStruct {
- Pvoid_t list; /* the list */
- int size; /* how many items in the list including NULL items between non-NULL items */
- void (*freeItem) (void* item); /* callback for freeing stored items */
-};
-typedef struct __osrfBigListStruct osrfBigList;
-
-
-struct __osrfBigBigListIteratorStruct {
- osrfBigList* list;
- unsigned long current;
-};
-typedef struct __osrfBigBigListIteratorStruct osrfBigBigListIterator;
-
-
-/**
- Creates a new list iterator with the given list
- */
-osrfBigBigListIterator* osrfNewBigListIterator( osrfBigList* list );
-
-/**
- Returns the next non-NULL item in the list, return NULL when
- the end of the list has been reached
- */
-void* osrfBigBigListIteratorNext( osrfBigBigListIterator* itr );
-
-/**
- Deallocates the given list
- */
-void osrfBigBigListIteratorFree( osrfBigBigListIterator* itr );
-
-void osrfBigBigListIteratorReset( osrfBigBigListIterator* itr );
-
-
-/**
- Allocates a new list
- @param compress If true, the list will compress empty slots on delete. If item positionality
- is not important, then using this feature is reccomended to keep the list from growing indefinitely.
- if item positionality is not important.
- @return The allocated list
- */
-osrfBigList* osrfNewBigList();
-
-/**
- Pushes an item onto the end of the list. This always finds the highest index
- in the list and pushes the new item into the list after it.
- @param list The list
- @param item The item to push
- @return 0 on success, -1 on failure
- */
-int osrfBigListPush( osrfBigList* list, void* item );
-
-
-/**
- * Removes the last item in the list
- * See osrfBigListRemove for details on how the removed item is handled
- * @return The item, unless 'freeItem' exists, then returns NULL
- */
-void* osrfBigListPop( osrfBigList* list );
-
-/**
- Puts the given item into the list at the specified position. If there
- is already an item at the given position and the list has it's
- "freeItem" function defined, then it will be used to free said item.
- If no 'freeItem' callback is defined, then the displaced item will
- be returned;
- @param list The list
- @param item The item to put into the list
- @param position The position to place the item in
- @return NULL in successfully inserting the new item and freeing
- any displaced items. Returns the displaced item if no "freeItem"
- callback is defined.
- */
-void* osrfBigListSet( osrfBigList* list, void* item, unsigned long position );
-
-/**
- Returns the item at the given position
- @param list The list
- @param postiont the position
- */
-void* osrfBigListGetIndex( osrfBigList* list, unsigned long position );
-
-/**
- Frees the list and all list items (if the list has a "freeItem" function defined )
- @param list The list
- */
-void osrfBigListFree( osrfBigList* list );
-
-/**
- Removes the list item at the given index
- @param list The list
- @param position The position of the item to remove
- @return A pointer to the item removed if "freeItem" is not defined
- for this list, returns NULL if it is.
- */
-void* osrfBigListRemove( osrfBigList* list, int position );
-
-/**
- Finds the list item whose void* is the same as the one passed in
- @param list The list
- @param addr The pointer connected to the list item we're to find
- @return the index of the item, or -1 if the item was not found
- */
-int osrfBigListFind( osrfBigList* list, void* addr );
-
-
-void __osrfBigListSetSize( osrfBigList* list );
-
-
-/**
- @return The number of non-null items in the list
- */
-unsigned long osrfBigListGetCount( osrfBigList* list );
-
-/**
- * May be used as a default memory freeing call
- * Just calls free() on list items
- */
-void osrfBigListVanillaFree( void* item );
-
-/**
- * Tells the list to just call 'free()' on each item when
- * an item or the whole list is destroyed
- */
-void osrfBigListSetDefaultFree( osrfBigList* list );
-
-
-#endif
+++ /dev/null
-/*
-Copyright (C) 2005 Georgia Public Library Service
-Bill Erickson <highfalutin@gmail.com>
-
-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; either version 2
-of the License, or (at your option) any later version.
-
-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.
-*/
-
-#include "osrf_cache.h"
-
-struct memcache* __osrfCache = NULL;
-time_t __osrfCacheMaxSeconds = -1;
-
-int osrfCacheInit( char* serverStrings[], int size, time_t maxCacheSeconds ) {
- if( !(serverStrings && size > 0) ) return -1;
-
- int i;
- __osrfCache = mc_new();
- __osrfCacheMaxSeconds = maxCacheSeconds;
-
- for( i = 0; i < size && serverStrings[i]; i++ )
- mc_server_add4( __osrfCache, serverStrings[i] );
-
- return 0;
-}
-
-int osrfCachePutObject( char* key, const jsonObject* obj, time_t seconds ) {
- if( !(key && obj) ) return -1;
- char* s = jsonObjectToJSON( obj );
- osrfLogInternal( OSRF_LOG_MARK, "osrfCachePut(): Putting object: %s", s);
- if( seconds < 0 ) seconds = __osrfCacheMaxSeconds;
-
- mc_set(__osrfCache, key, strlen(key), s, strlen(s), seconds, 0);
- free(s);
- return 0;
-}
-
-int osrfCachePutString( char* key, const char* value, time_t seconds ) {
- if( !(key && value) ) return -1;
- if( seconds < 0 ) seconds = __osrfCacheMaxSeconds;
- osrfLogInternal( OSRF_LOG_MARK, "osrfCachePutString(): Putting string: %s", value);
- mc_set(__osrfCache, key, strlen(key), value, strlen(value), seconds, 0);
- return 0;
-}
-
-jsonObject* osrfCacheGetObject( char* key, ... ) {
- jsonObject* obj = NULL;
- if( key ) {
- VA_LIST_TO_STRING(key);
- char* data = (char*) mc_aget( __osrfCache, VA_BUF, strlen(VA_BUF) );
- if( data ) {
- osrfLogInternal( OSRF_LOG_MARK, "osrfCacheGetObject(): Returning object: %s", data);
- obj = jsonParseString( data );
- return obj;
- }
- osrfLogWarning(OSRF_LOG_MARK, "No cache data exists with key %s", VA_BUF);
- }
- return NULL;
-}
-
-char* osrfCacheGetString( char* key, ... ) {
- if( key ) {
- VA_LIST_TO_STRING(key);
- char* data = (char*) mc_aget(__osrfCache, VA_BUF, strlen(VA_BUF) );
- osrfLogInternal( OSRF_LOG_MARK, "osrfCacheGetObject(): Returning object: %s", data);
- if(!data) osrfLogWarning(OSRF_LOG_MARK, "No cache data exists with key %s", VA_BUF);
- return data;
- }
- return NULL;
-}
-
-
-int osrfCacheRemove( char* key, ... ) {
- if( key ) {
- VA_LIST_TO_STRING(key);
- return mc_delete(__osrfCache, VA_BUF, strlen(VA_BUF), 0 );
- }
- return -1;
-}
-
-
-int osrfCacheSetExpire( time_t seconds, char* key, ... ) {
- if( key ) {
- VA_LIST_TO_STRING(key);
- jsonObject* o = osrfCacheGetObject( VA_BUF );
- //osrfCacheRemove(VA_BUF);
- return osrfCachePutObject( VA_BUF, o, seconds );
- }
- return -1;
-}
-
-
+++ /dev/null
-/*
-Copyright (C) 2005 Georgia Public Library Service
-Bill Erickson <highfalutin@gmail.com>
-
-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; either version 2
-of the License, or (at your option) any later version.
-
-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.
-*/
-
-
-#include "objson/object.h"
-#include "objson/json_parser.h"
-#include "memcache.h"
-#include "log.h"
-
-/**
- osrfCache is a globally shared cache API
- */
-
-
-/**
- Initialize the cache.
- @param serverStrings An array of "ip:port" strings to use as cache servers
- @param size The size of the serverStrings array
- @param maxCacheSeconds The maximum amount of time an object / string may
- be cached. Negative number means there is no limit
- */
-int osrfCacheInit( char* serverStrings[], int size, time_t maxCacheSeconds );
-
-
-/**
- Puts an object into the cache
- @param key The cache key
- @param obj The object to cache
- @param seconds The amount of time to cache the data, negative number means
- to cache up to 'maxCacheSeconds' as set by osrfCacheInit()
- @return 0 on success, -1 on error
- */
-int osrfCachePutObject( char* key, const jsonObject* obj, time_t seconds );
-
-/**
- Puts a string into the cache
- @param key The cache key
- @param value The string to cache
- @param seconds The amount of time to cache the data, negative number means
- to cache up to 'maxCacheSeconds' as set by osrfCacheInit()
- @return 0 on success, -1 on error
- */
-int osrfCachePutString( char* key, const char* value, time_t seconds);
-
-/**
- Grabs an object from the cache.
- @param key The cache key
- @return The object (which must be freed) if it exists, otherwise returns NULL
- */
-jsonObject* osrfCacheGetObject( char* key, ... );
-
-/**
- Grabs a string from the cache.
- @param key The cache key
- @return The string (which must be freed) if it exists, otherwise returns NULL
- */
-char* osrfCacheGetString( char* key, ... );
-
-/**
- Removes the item with the given key from the cache.
- @return 0 on success, -1 on error.
- */
-int osrfCacheRemove( char* key, ... );
-
-/**
- * Sets the expire time to 'seconds' for the given key
- */
-int osrfCacheSetExpire( time_t seconds, char* key, ... );
-
-
-
+++ /dev/null
-#include "osrf_hash.h"
-
-osrfHash* osrfNewHash() {
- osrfHash* hash;
- OSRF_MALLOC(hash, sizeof(osrfHash));
- hash->hash = osrfNewList();
- hash->keys = osrfNewStringArray(64);
- return hash;
-}
-
-
-/* algorithm proposed by Donald E. Knuth
- * in The Art Of Computer Programming Volume 3 (more or less..)*/
-/*
-static unsigned int osrfHashMakeKey(char* str) {
- if(!str) return 0;
- unsigned int len = strlen(str);
- unsigned int h = len;
- unsigned int i = 0;
- for(i = 0; i < len; str++, i++)
- h = ((h << 5) ^ (h >> 27)) ^ (*str);
- return (h & (OSRF_HASH_LIST_SIZE-1));
-}
-*/
-
-
-/* macro version of the above function */
-#define OSRF_HASH_MAKE_KEY(str,num) \
- do {\
- char* __k = str;\
- unsigned int __len = strlen(__k); \
- unsigned int __h = __len;\
- unsigned int __i = 0;\
- for(__i = 0; __i < __len; __k++, __i++)\
- __h = ((__h << 5) ^ (__h >> 27)) ^ (*__k);\
- num = (__h & (OSRF_HASH_LIST_SIZE-1));\
- } while(0)
-
-
-
-/* returns the index of the item and points l to the sublist the item
- * lives in if the item and points n to the hashnode the item
- * lives in if the item is found. Otherwise -1 is returned */
-static unsigned int osrfHashFindItem( osrfHash* hash, char* key, osrfList** l, osrfHashNode** n ) {
- if(!(hash && key)) return -1;
-
-
- unsigned int i = 0;
- OSRF_HASH_MAKE_KEY(key,i);
-
- osrfList* list = OSRF_LIST_GET_INDEX( hash->hash, i );
- if( !list ) { return -1; }
-
- int k;
- osrfHashNode* node = NULL;
- for( k = 0; k < list->size; k++ ) {
- node = OSRF_LIST_GET_INDEX(list, k);
- if( node && node->key && !strcmp(node->key, key) )
- break;
- node = NULL;
- }
-
- if(!node) return -1;
-
- if(l) *l = list;
- if(n) *n = node;
- return k;
-}
-
-osrfHashNode* osrfNewHashNode(char* key, void* item) {
- if(!(key && item)) return NULL;
- osrfHashNode* n;
- OSRF_MALLOC(n, sizeof(osrfHashNode));
- n->key = strdup(key);
- n->item = item;
- return n;
-}
-
-void* osrfHashNodeFree(osrfHash* hash, osrfHashNode* node) {
- if(!(node && hash)) return NULL;
- void* item = NULL;
- if( hash->freeItem )
- hash->freeItem( node->key, node->item );
- else item = node->item;
- free(node->key);
- free(node);
- return item;
-}
-
-void* osrfHashSet( osrfHash* hash, void* item, const char* key, ... ) {
- if(!(hash && item && key )) return NULL;
-
- VA_LIST_TO_STRING(key);
- void* olditem = osrfHashRemove( hash, VA_BUF );
-
- unsigned int bucketkey = 0;
- OSRF_HASH_MAKE_KEY(VA_BUF,bucketkey);
-
- osrfList* bucket;
- if( !(bucket = OSRF_LIST_GET_INDEX(hash->hash, bucketkey)) ) {
- bucket = osrfNewList();
- osrfListSet( hash->hash, bucket, bucketkey );
- }
-
- osrfHashNode* node = osrfNewHashNode(VA_BUF, item);
- osrfListPushFirst( bucket, node );
-
- if(!osrfStringArrayContains(hash->keys, VA_BUF))
- osrfStringArrayAdd( hash->keys, VA_BUF );
-
- hash->size++;
- return olditem;
-}
-
-void* osrfHashRemove( osrfHash* hash, const char* key, ... ) {
- if(!(hash && key )) return NULL;
-
- VA_LIST_TO_STRING(key);
-
- osrfList* list = NULL;
- osrfHashNode* node;
- int index = osrfHashFindItem( hash, (char*) VA_BUF, &list, &node );
- if( index == -1 ) return NULL;
-
- osrfListRemove( list, index );
- hash->size--;
-
- void* item = osrfHashNodeFree(hash, node);
- osrfStringArrayRemove(hash->keys, VA_BUF);
- return item;
-}
-
-
-void* osrfHashGet( osrfHash* hash, const char* key, ... ) {
- if(!(hash && key )) return NULL;
- VA_LIST_TO_STRING(key);
-
- osrfHashNode* node = NULL;
- int index = osrfHashFindItem( hash, (char*) VA_BUF, NULL, &node );
- if( index == -1 ) return NULL;
- return node->item;
-}
-
-
-osrfStringArray* osrfHashKeysInc( osrfHash* hash ) {
- if(!hash) return NULL;
- return hash->keys;
-}
-
-osrfStringArray* osrfHashKeys( osrfHash* hash ) {
- if(!hash) return NULL;
-
- int i, k;
- osrfList* list;
- osrfHashNode* node;
- osrfStringArray* strings = osrfNewStringArray(8);
-
- for( i = 0; i != hash->hash->size; i++ ) {
- list = OSRF_LIST_GET_INDEX( hash->hash, i );
- if(list) {
- for( k = 0; k != list->size; k++ ) {
- node = OSRF_LIST_GET_INDEX( list, k );
- if( node ) osrfStringArrayAdd( strings, node->key );
- }
- }
- }
-
- return strings;
-}
-
-
-unsigned long osrfHashGetCount( osrfHash* hash ) {
- if(!hash) return -1;
- return hash->size;
-}
-
-void osrfHashFree( osrfHash* hash ) {
- if(!hash) return;
-
- int i, j;
- osrfList* list;
- osrfHashNode* node;
-
- for( i = 0; i != hash->hash->size; i++ ) {
- if( ( list = OSRF_LIST_GET_INDEX( hash->hash, i )) ) {
- for( j = 0; j != list->size; j++ ) {
- if( (node = OSRF_LIST_GET_INDEX( list, j )) ) {
- OSRF_HASH_NODE_FREE(hash, node);
- }
- }
- osrfListFree(list);
- }
- }
-
- osrfListFree(hash->hash);
- osrfStringArrayFree(hash->keys);
- free(hash);
-}
-
-
-
-osrfHashIterator* osrfNewHashIterator( osrfHash* hash ) {
- if(!hash) return NULL;
- //osrfHashIterator* itr = safe_malloc(sizeof(osrfHashIterator));
- osrfHashIterator* itr;
- OSRF_MALLOC(itr, sizeof(osrfHashIterator));
- itr->hash = hash;
- itr->current = NULL;
- itr->keys = osrfHashKeysInc(hash);
- return itr;
-}
-
-void* osrfHashIteratorNext( osrfHashIterator* itr ) {
- if(!(itr && itr->hash)) return NULL;
- if( itr->currentIdx >= itr->keys->size ) return NULL;
- free(itr->current);
- itr->current = strdup(
- osrfStringArrayGetString(itr->keys, itr->currentIdx++));
- char* val = osrfHashGet( itr->hash, itr->current );
- return val;
-}
-
-void osrfHashIteratorFree( osrfHashIterator* itr ) {
- if(!itr) return;
- free(itr->current);
- //osrfStringArrayFree(itr->keys);
- free(itr);
-}
-
-void osrfHashIteratorReset( osrfHashIterator* itr ) {
- if(!itr) return;
- free(itr->current);
- //osrfStringArrayFree(itr->keys);
- itr->keys = osrfHashKeysInc(itr->hash);
- itr->currentIdx = 0;
- itr->current = NULL;
-}
-
-
-int osrfHashIteratorHasNext( osrfHashIterator* itr ) {
- return ( itr->currentIdx < itr->keys->size ) ? 1 : 0;
-}
+++ /dev/null
-#ifndef OSRF_HASH_H
-#define OSRF_HASH_H
-
-#include "opensrf/utils.h"
-#include "opensrf/string_array.h"
-#include "osrf_list.h"
-
-/* 0x100 is a good size for small hashes */
-//#define OSRF_HASH_LIST_SIZE 0x100 /* size of the main hash list */
-#define OSRF_HASH_LIST_SIZE 0x10 /* size of the main hash list */
-
-
-/* used internally */
-#define OSRF_HASH_NODE_FREE(h, n) \
- if(h && n) { \
- if(h->freeItem) h->freeItem(n->key, n->item);\
- free(n->key); free(n); \
- }
-
-
-struct __osrfHashStruct {
- osrfList* hash; /* this hash */
- void (*freeItem) (char* key, void* item); /* callback for freeing stored items */
- unsigned int size;
- osrfStringArray* keys;
-};
-typedef struct __osrfHashStruct osrfHash;
-
-struct _osrfHashNodeStruct {
- char* key;
- void* item;
-};
-typedef struct _osrfHashNodeStruct osrfHashNode;
-
-
-struct __osrfHashIteratorStruct {
- char* current;
- int currentIdx;
- osrfHash* hash;
- osrfStringArray* keys;
-};
-typedef struct __osrfHashIteratorStruct osrfHashIterator;
-
-osrfHashNode* osrfNewHashNode(char* key, void* item);
-void* osrfHashNodeFree(osrfHash*, osrfHashNode*);
-
-/**
- Allocates a new hash object
- */
-osrfHash* osrfNewHash();
-
-/**
- Sets the given key with the given item
- if "freeItem" is defined and an item already exists at the given location,
- then old item is freed and the new item is put into place.
- if "freeItem" is not defined and an item already exists, the old item
- is returned.
- @return The old item if exists and there is no 'freeItem', returns NULL
- otherwise
- */
-void* osrfHashSet( osrfHash* hash, void* item, const char* key, ... );
-
-/**
- Removes an item from the hash.
- if 'freeItem' is defined it is used and NULL is returned,
- else the freed item is returned
- */
-void* osrfHashRemove( osrfHash* hash, const char* key, ... );
-
-void* osrfHashGet( osrfHash* hash, const char* key, ... );
-
-
-/**
- @return A list of strings representing the keys of the hash.
- caller is responsible for freeing the returned string array
- with osrfStringArrayFree();
- */
-osrfStringArray* osrfHashKeys( osrfHash* hash );
-
-osrfStringArray* osrfHashKeysInc( osrfHash* hash );
-
-/**
- Frees a hash
- */
-void osrfHashFree( osrfHash* hash );
-
-/**
- @return The number of items in the hash
- */
-unsigned long osrfHashGetCount( osrfHash* hash );
-
-
-
-
-/**
- Creates a new list iterator with the given list
- */
-osrfHashIterator* osrfNewHashIterator( osrfHash* hash );
-
-int osrfHashIteratorHasNext( osrfHashIterator* itr );
-
-/**
- Returns the next non-NULL item in the list, return NULL when
- the end of the list has been reached
- */
-void* osrfHashIteratorNext( osrfHashIterator* itr );
-
-/**
- Deallocates the given list
- */
-void osrfHashIteratorFree( osrfHashIterator* itr );
-
-void osrfHashIteratorReset( osrfHashIterator* itr );
-
-#endif
+++ /dev/null
-#include "osrf_list.h"
-
-osrfList* osrfNewList() {
- osrfList* list;
- OSRF_MALLOC(list, sizeof(osrfList));
- list->arrsize = OSRF_LIST_DEFAULT_SIZE;
- OSRF_MALLOC(list->arrlist, list->arrsize * sizeof(void*));
- return list;
-}
-
-osrfList* osrfNewListSize( unsigned int size ) {
- osrfList* list;
- OSRF_MALLOC(list, sizeof(osrfList));
- if( size <= 0 ) size = 16;
- list->arrsize = size;
- OSRF_MALLOC( list->arrlist, list->arrsize * sizeof(void*) );
- return list;
-}
-
-
-int osrfListPush( osrfList* list, void* item ) {
- if(!(list)) return -1;
- osrfListSet( list, item, list->size );
- return 0;
-}
-
-int osrfListPushFirst( osrfList* list, void* item ) {
- if(!(list && item)) return -1;
- int i;
- for( i = 0; i < list->size; i++ )
- if(!list->arrlist[i]) break;
- osrfListSet( list, item, i );
- return list->size;
-}
-
-void* osrfListSet( osrfList* list, void* item, unsigned int position ) {
- if(!list || position < 0) return NULL;
-
- int i;
- int newsize = list->arrsize;
- void** newarr;
-
- while( position >= newsize )
- newsize += OSRF_LIST_INC_SIZE;
-
- if( newsize > list->arrsize ) { /* expand the list if necessary */
- OSRF_MALLOC(newarr, newsize * sizeof(void*));
- for( i = 0; i < list->arrsize; i++ )
- newarr[i] = list->arrlist[i];
- free(list->arrlist);
- list->arrlist = newarr;
- list->arrsize = newsize;
- }
-
- void* olditem = osrfListRemove( list, position );
- list->arrlist[position] = item;
- if( list->size <= position ) list->size = position + 1;
- return olditem;
-}
-
-
-void* osrfListGetIndex( const osrfList* list, unsigned int position ) {
- if(!list || position >= list->size || position < 0) return NULL;
- return list->arrlist[position];
-}
-
-void osrfListFree( osrfList* list ) {
- if(!list) return;
-
- if( list->freeItem ) {
- int i; void* val;
- for( i = 0; i < list->size; i++ ) {
- if( (val = list->arrlist[i]) )
- list->freeItem(val);
- }
- }
-
- free(list->arrlist);
- free(list);
-}
-
-void* osrfListRemove( osrfList* list, unsigned int position ) {
- if(!list || position >= list->size || position < 0) return NULL;
-
- void* olditem = list->arrlist[position];
- list->arrlist[position] = NULL;
- if( list->freeItem ) {
- list->freeItem(olditem);
- olditem = NULL;
- }
-
- if( position == list->size - 1 ) list->size--;
- return olditem;
-}
-
-
-int osrfListFind( const osrfList* list, void* addr ) {
- if(!(list && addr)) return -1;
- int index;
- for( index = 0; index < list->size; index++ ) {
- if( list->arrlist[index] == addr )
- return index;
- }
- return -1;
-}
-
-
-unsigned int osrfListGetCount( const osrfList* list ) {
- if(!list) return -1;
- return list->size;
-}
-
-
-void* osrfListPop( osrfList* list ) {
- if(!list) return NULL;
- return osrfListRemove( list, list->size - 1 );
-}
-
-
-osrfListIterator* osrfNewListIterator( const osrfList* list ) {
- if(!list) return NULL;
- osrfListIterator* itr;
- OSRF_MALLOC(itr, sizeof(osrfListIterator));
- itr->list = list;
- itr->current = 0;
- return itr;
-}
-
-void* osrfListIteratorNext( osrfListIterator* itr ) {
- if(!(itr && itr->list)) return NULL;
- if(itr->current >= itr->list->size) return NULL;
- return itr->list->arrlist[itr->current++];
-}
-
-void osrfListIteratorFree( osrfListIterator* itr ) {
- if(!itr) return;
- free(itr);
-}
-
-
-void osrfListIteratorReset( osrfListIterator* itr ) {
- if(!itr) return;
- itr->current = 0;
-}
-
-
-void osrfListVanillaFree( void* item ) {
- free(item);
-}
-
-void osrfListSetDefaultFree( osrfList* list ) {
- if(!list) return;
- list->freeItem = osrfListVanillaFree;
-}
+++ /dev/null
-#ifndef OSRF_LIST_H
-#define OSRF_LIST_H
-
-#include "opensrf/utils.h"
-
-#define OSRF_LIST_DEFAULT_SIZE 48 /* most opensrf lists are small... */
-#define OSRF_LIST_INC_SIZE 256
-#define OSRF_LIST_MAX_SIZE 10240
-
-
-#define OSRF_LIST_GET_INDEX(l, i) (!l || i >= l->size) ? NULL: l->arrlist[i]
-
-/**
- Items are stored as void*'s so it's up to the user to
- manage the data wisely. Also, if the 'freeItem' callback is defined for the list,
- then, it will be used on any item that needs to be freed, so don't mix data
- types in the list if you want magic freeing */
-
-struct __osrfListStruct {
- unsigned int size; /* how many items in the list including NULL items between non-NULL items */
- void (*freeItem) (void* item); /* callback for freeing stored items */
- void** arrlist;
- int arrsize; /* how big is the currently allocated array */
-};
-typedef struct __osrfListStruct osrfList;
-
-
-struct __osrfListIteratorStruct {
- const osrfList* list;
- unsigned int current;
-};
-typedef struct __osrfListIteratorStruct osrfListIterator;
-
-osrfList* osrfNewListSize( unsigned int size );
-
-
-/**
- Creates a new list iterator with the given list
- */
-osrfListIterator* osrfNewListIterator( const osrfList* list );
-
-/**
- Returns the next non-NULL item in the list, return NULL when
- the end of the list has been reached
- */
-void* osrfListIteratorNext( osrfListIterator* itr );
-
-/**
- Deallocates the given list
- */
-void osrfListIteratorFree( osrfListIterator* itr );
-
-void osrfListIteratorReset( osrfListIterator* itr );
-
-
-/**
- Allocates a new list
- @param compress If true, the list will compress empty slots on delete. If item positionality
- is not important, then using this feature is reccomended to keep the list from growing indefinitely.
- if item positionality is not important.
- @return The allocated list
- */
-osrfList* osrfNewList();
-
-/**
- Pushes an item onto the end of the list. This always finds the highest index
- in the list and pushes the new item into the list after it.
- @param list The list
- @param item The item to push
- @return 0 on success, -1 on failure
- */
-int osrfListPush( osrfList* list, void* item );
-
-
-/**
- * Removes the last item in the list
- * See osrfListRemove for details on how the removed item is handled
- * @return The item, unless 'freeItem' exists, then returns NULL
- */
-void* osrfListPop( osrfList* list );
-
-/**
- Puts the given item into the list at the specified position. If there
- is already an item at the given position and the list has it's
- "freeItem" function defined, then it will be used to free said item.
- If no 'freeItem' callback is defined, then the displaced item will
- be returned;
- @param list The list
- @param item The item to put into the list
- @param position The position to place the item in
- @return NULL in successfully inserting the new item and freeing
- any displaced items. Returns the displaced item if no "freeItem"
- callback is defined.
- */
-void* osrfListSet( osrfList* list, void* item, unsigned int position );
-
-/**
- Returns the item at the given position
- @param list The list
- @param postiont the position
- */
-void* osrfListGetIndex( const osrfList* list, unsigned int position );
-
-/**
- Frees the list and all list items (if the list has a "freeItem" function defined )
- @param list The list
- */
-void osrfListFree( osrfList* list );
-
-/**
- Removes the list item at the given index
- @param list The list
- @param position The position of the item to remove
- @return A pointer to the item removed if "freeItem" is not defined
- for this list, returns NULL if it is.
- */
-void* osrfListRemove( osrfList* list, unsigned int position );
-
-/**
- Finds the list item whose void* is the same as the one passed in
- @param list The list
- @param addr The pointer connected to the list item we're to find
- @return the index of the item, or -1 if the item was not found
- */
-int osrfListFind( const osrfList* list, void* addr );
-
-
-void __osrfListSetSize( osrfList* list );
-
-
-/**
- @return The number of non-null items in the list
- */
-unsigned int osrfListGetCount( const osrfList* list );
-
-/**
- * May be used as a default memory freeing call
- * Just calls free() on list items
- */
-void osrfListVanillaFree( void* item );
-
-/**
- * Tells the list to just call 'free()' on each item when
- * an item or the whole list is destroyed
- */
-void osrfListSetDefaultFree( osrfList* list );
-
-/**
- * Inserts the new item at the first free (null) slot
- * in the array. Item is shoved onto the end of the
- * list if there are no null slots */
-int osrfListPushFirst( osrfList* list, void* item );
-
-
-#endif
+++ /dev/null
-#include "osrf_message.h"
-
-osrf_message* osrf_message_init( enum M_TYPE type, int thread_trace, int protocol ) {
-
- osrf_message* msg = (osrf_message*) safe_malloc(sizeof(osrf_message));
- msg->m_type = type;
- msg->thread_trace = thread_trace;
- msg->protocol = protocol;
- msg->next = NULL;
- msg->is_exception = 0;
- msg->_params = NULL;
- msg->_result_content = NULL;
-
- return msg;
-}
-
-
-void osrf_message_set_method( osrf_message* msg, char* method_name ) {
- if( msg == NULL || method_name == NULL ) return;
- msg->method_name = strdup( method_name );
-}
-
-
-void osrf_message_add_object_param( osrf_message* msg, jsonObject* o ) {
- if(!msg|| !o) return;
- if(!msg->_params)
- msg->_params = jsonParseString("[]");
- char* j = jsonObjectToJSON(o);
- jsonObjectPush(msg->_params, jsonParseString(j));
- free(j);
-}
-
-void osrf_message_set_params( osrf_message* msg, jsonObject* o ) {
- if(!msg || !o) return;
-
- if(o->type != JSON_ARRAY) {
- osrfLogDebug( OSRF_LOG_MARK, "passing non-array to osrf_message_set_params(), fixing...");
- jsonObject* clone = jsonObjectClone(o);
- o = jsonNewObject(NULL);
- jsonObjectPush(o, clone);
- if(msg->_params) jsonObjectFree(msg->_params);
- msg->_params = o;
- return;
- }
-
- if(msg->_params) jsonObjectFree(msg->_params);
- msg->_params = jsonObjectClone(o);
-}
-
-
-/* only works if parse_json_params is false */
-void osrf_message_add_param( osrf_message* msg, char* param_string ) {
- if(msg == NULL || param_string == NULL) return;
- if(!msg->_params) msg->_params = jsonParseString("[]");
- jsonObjectPush(msg->_params, jsonParseString(param_string));
-}
-
-
-void osrf_message_set_status_info(
- osrf_message* msg, char* status_name, char* status_text, int status_code ) {
- if(!msg) return;
-
- if( status_name != NULL )
- msg->status_name = strdup( status_name );
-
- if( status_text != NULL )
- msg->status_text = strdup( status_text );
-
- msg->status_code = status_code;
-}
-
-
-void osrf_message_set_result_content( osrf_message* msg, char* json_string ) {
- if( msg == NULL || json_string == NULL) return;
- msg->result_string = strdup(json_string);
- if(json_string) msg->_result_content = jsonParseString(json_string);
-}
-
-
-
-void osrfMessageFree( osrfMessage* msg ) {
- osrf_message_free( msg );
-}
-
-void osrf_message_free( osrf_message* msg ) {
- if( msg == NULL )
- return;
-
- if( msg->status_name != NULL )
- free(msg->status_name);
-
- if( msg->status_text != NULL )
- free(msg->status_text);
-
- if( msg->_result_content != NULL )
- jsonObjectFree( msg->_result_content );
-
- if( msg->result_string != NULL )
- free( msg->result_string);
-
- if( msg->method_name != NULL )
- free(msg->method_name);
-
- if( msg->_params != NULL )
- jsonObjectFree(msg->_params);
-
- free(msg);
-}
-
-
-char* osrfMessageSerializeBatch( osrfMessage* msgs [], int count ) {
- if( !msgs ) return NULL;
-
- char* j;
- int i = 0;
- osrfMessage* msg = NULL;
- jsonObject* wrapper = jsonNewObject(NULL);
-
- while( ((msg = msgs[i]) && (i++ < count)) )
- jsonObjectPush(wrapper, osrfMessageToJSON( msg ));
-
- j = jsonObjectToJSON(wrapper);
- jsonObjectFree(wrapper);
-
- return j;
-}
-
-
-char* osrf_message_serialize(osrf_message* msg) {
-
- if( msg == NULL ) return NULL;
- char* j = NULL;
-
- jsonObject* json = osrfMessageToJSON( msg );
-
- if(json) {
- jsonObject* wrapper = jsonNewObject(NULL);
- jsonObjectPush(wrapper, json);
- j = jsonObjectToJSON(wrapper);
- jsonObjectFree(wrapper);
- }
-
- return j;
-}
-
-
-jsonObject* osrfMessageToJSON( osrfMessage* msg ) {
-
- jsonObject* json = jsonNewObject(NULL);
- jsonObjectSetClass(json, "osrfMessage");
- jsonObject* payload;
- char sc[64]; memset(sc,0,64);
-
- char* str;
-
- INT_TO_STRING(msg->thread_trace);
- jsonObjectSetKey(json, "threadTrace", jsonNewObject(INTSTR));
-
- switch(msg->m_type) {
-
- case CONNECT:
- jsonObjectSetKey(json, "type", jsonNewObject("CONNECT"));
- break;
-
- case DISCONNECT:
- jsonObjectSetKey(json, "type", jsonNewObject("DISCONNECT"));
- break;
-
- case STATUS:
- jsonObjectSetKey(json, "type", jsonNewObject("STATUS"));
- payload = jsonNewObject(NULL);
- jsonObjectSetClass(payload, msg->status_name);
- jsonObjectSetKey(payload, "status", jsonNewObject(msg->status_text));
- sprintf(sc,"%d",msg->status_code);
- jsonObjectSetKey(payload, "statusCode", jsonNewObject(sc));
- jsonObjectSetKey(json, "payload", payload);
- break;
-
- case REQUEST:
- jsonObjectSetKey(json, "type", jsonNewObject("REQUEST"));
- payload = jsonNewObject(NULL);
- jsonObjectSetClass(payload, "osrfMethod");
- jsonObjectSetKey(payload, "method", jsonNewObject(msg->method_name));
- str = jsonObjectToJSON(msg->_params);
- jsonObjectSetKey(payload, "params", jsonParseString(str));
- free(str);
- jsonObjectSetKey(json, "payload", payload);
-
- break;
-
- case RESULT:
- jsonObjectSetKey(json, "type", jsonNewObject("RESULT"));
- payload = jsonNewObject(NULL);
- jsonObjectSetClass(payload,"osrfResult");
- jsonObjectSetKey(payload, "status", jsonNewObject(msg->status_text));
- sprintf(sc,"%d",msg->status_code);
- jsonObjectSetKey(payload, "statusCode", jsonNewObject(sc));
- str = jsonObjectToJSON(msg->_result_content);
- jsonObjectSetKey(payload, "content", jsonParseString(str));
- free(str);
- jsonObjectSetKey(json, "payload", payload);
- break;
- }
-
- return json;
-}
-
-
-int osrf_message_deserialize(char* string, osrf_message* msgs[], int count) {
-
- if(!string || !msgs || count <= 0) return 0;
- int numparsed = 0;
-
- jsonObject* json = jsonParseString(string);
-
- if(!json) {
- osrfLogWarning( OSRF_LOG_MARK,
- "osrf_message_deserialize() unable to parse data: \n%s\n", string);
- return 0;
- }
-
- int x;
-
- for( x = 0; x < json->size && x < count; x++ ) {
-
- jsonObject* message = jsonObjectGetIndex(json, x);
-
- if(message && message->type != JSON_NULL &&
- message->classname && !strcmp(message->classname, "osrfMessage")) {
-
- osrf_message* new_msg = safe_malloc(sizeof(osrf_message));
-
- jsonObject* tmp = jsonObjectGetKey(message, "type");
-
- char* t;
- if( ( t = jsonObjectGetString(tmp)) ) {
-
- if(!strcmp(t, "CONNECT")) new_msg->m_type = CONNECT;
- if(!strcmp(t, "DISCONNECT")) new_msg->m_type = DISCONNECT;
- if(!strcmp(t, "STATUS")) new_msg->m_type = STATUS;
- if(!strcmp(t, "REQUEST")) new_msg->m_type = REQUEST;
- if(!strcmp(t, "RESULT")) new_msg->m_type = RESULT;
- }
-
- tmp = jsonObjectGetKey(message, "threadTrace");
- if(tmp) {
- char* tt = jsonObjectToSimpleString(tmp);
- if(tt) {
- new_msg->thread_trace = atoi(tt);
- free(tt);
- }
- /*
- if(tmp->type == JSON_NUMBER)
- new_msg->thread_trace = (int) jsonObjectGetNumber(tmp);
- if(tmp->type == JSON_STRING)
- new_msg->thread_trace = atoi(jsonObjectGetString(tmp));
- */
- }
-
-
- tmp = jsonObjectGetKey(message, "protocol");
-
- if(tmp) {
- char* proto = jsonObjectToSimpleString(tmp);
- if(proto) {
- new_msg->protocol = atoi(proto);
- free(proto);
- }
-
- /*
- if(tmp->type == JSON_NUMBER)
- new_msg->protocol = (int) jsonObjectGetNumber(tmp);
- if(tmp->type == JSON_STRING)
- new_msg->protocol = atoi(jsonObjectGetString(tmp));
- */
- }
-
- tmp = jsonObjectGetKey(message, "payload");
- if(tmp) {
- if(tmp->classname)
- new_msg->status_name = strdup(tmp->classname);
-
- jsonObject* tmp0 = jsonObjectGetKey(tmp,"method");
- if(jsonObjectGetString(tmp0))
- new_msg->method_name = strdup(jsonObjectGetString(tmp0));
-
- tmp0 = jsonObjectGetKey(tmp,"params");
- if(tmp0) {
- char* s = jsonObjectToJSON(tmp0);
- new_msg->_params = jsonParseString(s);
- if(new_msg->_params && new_msg->_params->type == JSON_NULL)
- new_msg->_params->type = JSON_ARRAY;
- free(s);
- }
-
- tmp0 = jsonObjectGetKey(tmp,"status");
- if(jsonObjectGetString(tmp0))
- new_msg->status_text = strdup(jsonObjectGetString(tmp0));
-
- tmp0 = jsonObjectGetKey(tmp,"statusCode");
- if(tmp0) {
- if(jsonObjectGetString(tmp0))
- new_msg->status_code = atoi(jsonObjectGetString(tmp0));
- if(tmp0->type == JSON_NUMBER)
- new_msg->status_code = (int) jsonObjectGetNumber(tmp0);
- }
-
- tmp0 = jsonObjectGetKey(tmp,"content");
- if(tmp0) {
- char* s = jsonObjectToJSON(tmp0);
- new_msg->_result_content = jsonParseString(s);
- free(s);
- }
-
- }
- msgs[numparsed++] = new_msg;
- }
- }
-
- jsonObjectFree(json);
- return numparsed;
-}
-
-
-
-jsonObject* osrfMessageGetResult( osrfMessage* msg ) {
- if(msg) return msg->_result_content;
- return NULL;
-}
-
+++ /dev/null
-#include "opensrf/string_array.h"
-#include "opensrf/utils.h"
-#include "opensrf/log.h"
-#include "objson/object.h"
-#include "objson/json_parser.h"
-
-
-/* libxml stuff for the config reader */
-#include <libxml/xmlmemory.h>
-#include <libxml/parser.h>
-#include <libxml/xpath.h>
-#include <libxml/xpathInternals.h>
-#include <libxml/tree.h>
-
-
-
-#ifndef osrf_message_h
-#define osrf_message_h
-
-#define OSRF_XML_NAMESPACE "http://open-ils.org/xml/namespaces/oils_v1"
-
-#define OSRF_STATUS_CONTINUE 100
-
-#define OSRF_STATUS_OK 200
-#define OSRF_STATUS_ACCEPTED 202
-#define OSRF_STATUS_COMPLETE 205
-
-#define OSRF_STATUS_REDIRECTED 307
-
-#define OSRF_STATUS_BADREQUEST 400
-#define OSRF_STATUS_UNAUTHORIZED 401
-#define OSRF_STATUS_FORBIDDEN 403
-#define OSRF_STATUS_NOTFOUND 404
-#define OSRF_STATUS_NOTALLOWED 405
-#define OSRF_STATUS_TIMEOUT 408
-#define OSRF_STATUS_EXPFAILED 417
-
-#define OSRF_STATUS_INTERNALSERVERERROR 500
-#define OSRF_STATUS_NOTIMPLEMENTED 501
-#define OSRF_STATUS_VERSIONNOTSUPPORTED 505
-
-
-enum M_TYPE { CONNECT, REQUEST, RESULT, STATUS, DISCONNECT };
-
-#define OSRF_MAX_PARAMS 128;
-
-struct osrf_message_struct {
-
- enum M_TYPE m_type;
- int thread_trace;
- int protocol;
-
- /* if we're a STATUS message */
- char* status_name;
-
- /* if we're a STATUS or RESULT */
- char* status_text;
- int status_code;
-
- int is_exception;
-
- /* if we're a RESULT */
- jsonObject* _result_content;
-
- /* unparsed json string */
- char* result_string;
-
- /* if we're a REQUEST */
- char* method_name;
-
- jsonObject* _params;
-
- /* in case anyone wants to make a list of us.
- we won't touch this variable */
- struct osrf_message_struct* next;
-
- char* full_param_string;
-
-};
-typedef struct osrf_message_struct osrf_message;
-typedef struct osrf_message_struct osrfMessage;
-
-
-osrf_message* osrf_message_init( enum M_TYPE type, int thread_trace, int protocol );
-//void osrf_message_set_request_info( osrf_message*, char* param_name, json* params );
-void osrf_message_set_status_info( osrf_message*, char* status_name, char* status_text, int status_code );
-void osrf_message_set_result_content( osrf_message*, char* json_string );
-void osrfMessageFree( osrfMessage* );
-void osrf_message_free( osrf_message* );
-char* osrf_message_to_xml( osrf_message* );
-char* osrf_message_serialize(osrf_message*);
-
-/* count is the max number of messages we'll put into msgs[] */
-int osrf_message_deserialize(char* json, osrf_message* msgs[], int count);
-
-
-
-/** Pushes any message retreived from the xml into the 'msgs' array.
- * it is assumed that 'msgs' has beenn pre-allocated.
- * Returns the number of message that are in the buffer.
- */
-int osrf_message_from_xml( char* xml, osrf_message* msgs[] );
-
-void osrf_message_set_params( osrf_message* msg, jsonObject* o );
-void osrf_message_set_method( osrf_message* msg, char* method_name );
-void osrf_message_add_object_param( osrf_message* msg, jsonObject* o );
-void osrf_message_add_param( osrf_message*, char* param_string );
-
-
-jsonObject* osrfMessageGetResult( osrfMessage* msg );
-
-/**
- Returns the message as a jsonObject
- @return The jsonObject which must be freed by the caller.
- */
-jsonObject* osrfMessageToJSON( osrfMessage* msg );
-
-char* osrfMessageSerializeBatch( osrfMessage* msgs [], int count );
-
-
-#endif
+++ /dev/null
-#include "osrf_prefork.h"
-#include <signal.h>
-#include "osrf_app_session.h"
-#include "osrf_application.h"
-
-/* true if we just deleted a child. This will allow us to make sure we're
- not trying to use freed memory */
-int child_dead;
-
-int main();
-void sigchld_handler( int sig );
-
-int osrf_prefork_run(char* appname) {
-
- if(!appname) {
- osrfLogError( OSRF_LOG_MARK, "osrf_prefork_run requires an appname to run!");
- return -1;
- }
-
- set_proc_title( "OpenSRF Listener [%s]", appname );
-
- int maxr = 1000;
- int maxc = 10;
- int minc = 3;
-
- osrfLogInfo( OSRF_LOG_MARK, "Loading config in osrf_forker for app %s", appname);
-
- jsonObject* max_req = osrf_settings_host_value_object("/apps/%s/unix_config/max_requests", appname);
- jsonObject* min_children = osrf_settings_host_value_object("/apps/%s/unix_config/min_children", appname);
- jsonObject* max_children = osrf_settings_host_value_object("/apps/%s/unix_config/max_children", appname);
-
- char* keepalive = osrf_settings_host_value("/apps/%s/keepalive", appname);
- time_t kalive;
- if( keepalive ) {
- kalive = atoi(keepalive);
- free(keepalive);
- } else {
- kalive = 5; /* give it a default */
- }
-
- osrfLogInfo(OSRF_LOG_MARK, "keepalive setting = %d seconds", kalive);
-
-
-
- if(!max_req) osrfLogWarning( OSRF_LOG_MARK, "Max requests not defined, assuming 1000");
- else maxr = (int) jsonObjectGetNumber(max_req);
-
- if(!min_children) osrfLogWarning( OSRF_LOG_MARK, "Min children not defined, assuming 3");
- else minc = (int) jsonObjectGetNumber(min_children);
-
- if(!max_children) osrfLogWarning( OSRF_LOG_MARK, "Max children not defined, assuming 10");
- else maxc = (int) jsonObjectGetNumber(max_children);
-
- jsonObjectFree(max_req);
- jsonObjectFree(min_children);
- jsonObjectFree(max_children);
- /* --------------------------------------------------- */
-
- char* resc = va_list_to_string("%s_listener", appname);
-
- if(!osrf_system_bootstrap_client_resc( NULL, NULL, resc )) {
- osrfLogError( OSRF_LOG_MARK, "Unable to bootstrap client for osrf_prefork_run()");
- free(resc);
- return -1;
- }
-
- free(resc);
-
- prefork_simple* forker = prefork_simple_init(
- osrfSystemGetTransportClient(), maxr, minc, maxc);
-
- forker->appname = strdup(appname);
- forker->keepalive = kalive;
-
- if(forker == NULL) {
- osrfLogError( OSRF_LOG_MARK, "osrf_prefork_run() failed to create prefork_simple object");
- return -1;
- }
-
- prefork_launch_children(forker);
-
- osrf_prefork_register_routers(appname);
-
- osrfLogInfo( OSRF_LOG_MARK, "Launching osrf_forker for app %s", appname);
- prefork_run(forker);
-
- osrfLogWarning( OSRF_LOG_MARK, "prefork_run() retuned - how??");
- prefork_free(forker);
- return 0;
-
-}
-
-void osrf_prefork_register_routers( char* appname ) {
-
- osrfStringArray* arr = osrfNewStringArray(4);
-
- int c = osrfConfigGetValueList( NULL, arr, "/routers/router" );
- char* routerName = osrfConfigGetValue( NULL, "/router_name" );
- transport_client* client = osrfSystemGetTransportClient();
-
- osrfLogInfo( OSRF_LOG_MARK, "router name is %s and we have %d routers to connect to", routerName, c );
-
- while( c ) {
- char* domain = osrfStringArrayGetString(arr, --c);
- if(domain) {
-
- char* jid = va_list_to_string( "%s@%s/router", routerName, domain );
- osrfLogInfo( OSRF_LOG_MARK, "Registering with router %s", jid );
-
- transport_message* msg = message_init("registering", NULL, NULL, jid, NULL );
- message_set_router_info( msg, NULL, NULL, appname, "register", 0 );
-
- client_send_message( client, msg );
- message_free( msg );
- free(jid);
- }
- }
-
- free(routerName);
- osrfStringArrayFree(arr);
-}
-
-int prefork_child_init_hook(prefork_child* child) {
-
- if(!child) return -1;
- osrfLogDebug( OSRF_LOG_MARK, "Child init hook for child %d", child->pid);
- char* resc = va_list_to_string("%s_drone",child->appname);
-
- /* if we're a source-client, tell the logger now that we're a new process*/
- char* isclient = osrfConfigGetValue(NULL, "/client");
- if( isclient && !strcasecmp(isclient,"true") )
- osrfLogSetIsClient(1);
- free(isclient);
-
-
- /* we want to remove traces of our parents socket connection
- * so we can have our own */
- osrfSystemIgnoreTransportClient();
-
- if(!osrf_system_bootstrap_client_resc( NULL, NULL, resc)) {
- osrfLogError( OSRF_LOG_MARK, "Unable to bootstrap client for osrf_prefork_run()");
- free(resc);
- return -1;
- }
-
- free(resc);
-
- if( ! osrfAppRunChildInit(child->appname) ) {
- osrfLogDebug(OSRF_LOG_MARK, "Prefork child_init succeeded\n");
- } else {
- osrfLogError(OSRF_LOG_MARK, "Prefork child_init failed\n");
- return -1;
- }
-
- set_proc_title( "OpenSRF Drone [%s]", child->appname );
- return 0;
-}
-
-void prefork_child_process_request(prefork_child* child, char* data) {
- if( !child ) return;
-
- transport_client* client = osrfSystemGetTransportClient();
-
- if(!client_connected(client)) {
- osrfSystemIgnoreTransportClient();
- osrfLogWarning(OSRF_LOG_MARK, "Reconnecting child to opensrf after disconnect...");
- if(!osrf_system_bootstrap_client(NULL, NULL)) {
- osrfLogError( OSRF_LOG_MARK,
- "Unable to bootstrap client in prefork_child_process_request()");
- sleep(1);
- osrf_prefork_child_exit(child);
- }
- }
-
- /* construct the message from the xml */
- transport_message* msg = new_message_from_xml( data );
-
- osrfAppSession* session = osrf_stack_transport_handler(msg, child->appname);
- if(!session) return;
-
- if( session->stateless && session->state != OSRF_SESSION_CONNECTED ) {
- osrfAppSessionFree( session );
- return;
- }
-
- osrfLogDebug( OSRF_LOG_MARK, "Entering keepalive loop for session %s", session->session_id );
- int keepalive = child->keepalive;
- int retval;
- int recvd;
- time_t start;
- time_t end;
-
- while(1) {
-
- osrfLogDebug(OSRF_LOG_MARK,
- "osrf_prefork calling queue_wait [%d] in keepalive loop", keepalive);
- start = time(NULL);
- retval = osrf_app_session_queue_wait(session, keepalive, &recvd);
- end = time(NULL);
-
- osrfLogDebug(OSRF_LOG_MARK, "Data received == %d", recvd);
-
- if(retval) {
- osrfLogError(OSRF_LOG_MARK, "queue-wait returned non-success %d", retval);
- break;
- }
-
- /* see if the client disconnected from us */
- if(session->state != OSRF_SESSION_CONNECTED) break;
-
- /* if no data was reveived within the timeout interval */
- if( !recvd && (end - start) >= keepalive ) {
- osrfLogInfo(OSRF_LOG_MARK, "No request was reveived in %d seconds, exiting stateful session", keepalive);
- osrfAppSessionStatus(
- session,
- OSRF_STATUS_TIMEOUT,
- "osrfConnectStatus",
- 0, "Disconnected on timeout" );
-
- break;
- }
- }
-
- osrfLogDebug( OSRF_LOG_MARK, "Exiting keepalive loop for session %s", session->session_id );
- osrfAppSessionFree( session );
- return;
-}
-
-
-prefork_simple* prefork_simple_init( transport_client* client,
- int max_requests, int min_children, int max_children ) {
-
- if( min_children > max_children ) {
- osrfLogError( OSRF_LOG_MARK, "min_children (%d) is greater "
- "than max_children (%d)", min_children, max_children );
- return NULL;
- }
-
- if( max_children > ABS_MAX_CHILDREN ) {
- osrfLogError( OSRF_LOG_MARK, "max_children (%d) is greater than ABS_MAX_CHILDREN (%d)",
- max_children, ABS_MAX_CHILDREN );
- return NULL;
- }
-
- osrfLogInfo(OSRF_LOG_MARK, "Prefork launching child with max_request=%d,"
- "min_children=%d, max_children=%d", max_requests, min_children, max_children );
-
- /* flesh out the struct */
- prefork_simple* prefork = (prefork_simple*) safe_malloc(sizeof(prefork_simple));
- prefork->max_requests = max_requests;
- prefork->min_children = min_children;
- prefork->max_children = max_children;
- prefork->first_child = NULL;
- prefork->connection = client;
-
- return prefork;
-}
-
-prefork_child* launch_child( prefork_simple* forker ) {
-
- pid_t pid;
- int data_fd[2];
- int status_fd[2];
-
- /* Set up the data pipes and add the child struct to the parent */
- if( pipe(data_fd) < 0 ) { /* build the data pipe*/
- osrfLogError( OSRF_LOG_MARK, "Pipe making error" );
- return NULL;
- }
-
- if( pipe(status_fd) < 0 ) {/* build the status pipe */
- osrfLogError( OSRF_LOG_MARK, "Pipe making error" );
- return NULL;
- }
-
- osrfLogInternal( OSRF_LOG_MARK, "Pipes: %d %d %d %d", data_fd[0], data_fd[1], status_fd[0], status_fd[1] );
- prefork_child* child = prefork_child_init( forker->max_requests, data_fd[0],
- data_fd[1], status_fd[0], status_fd[1] );
-
- child->appname = strdup(forker->appname);
- child->keepalive = forker->keepalive;
-
-
- add_prefork_child( forker, child );
-
- if( (pid=fork()) < 0 ) {
- osrfLogError( OSRF_LOG_MARK, "Forking Error" );
- return NULL;
- }
-
- if( pid > 0 ) { /* parent */
-
- signal(SIGCHLD, sigchld_handler);
- (forker->current_num_children)++;
- child->pid = pid;
-
- osrfLogDebug( OSRF_LOG_MARK, "Parent launched %d", pid );
- /* *no* child pipe FD's can be closed or the parent will re-use fd's that
- the children are currently using */
- return child;
- }
-
- else { /* child */
-
- osrfLogInternal( OSRF_LOG_MARK, "I am new child with read_data_fd = %d and write_status_fd = %d",
- child->read_data_fd, child->write_status_fd );
-
- child->pid = getpid();
- close( child->write_data_fd );
- close( child->read_status_fd );
-
- /* do the initing */
- if( prefork_child_init_hook(child) == -1 ) {
- osrfLogError(OSRF_LOG_MARK,
- "Forker child going away because we could not connect to OpenSRF...");
- osrf_prefork_child_exit(child);
- }
-
- prefork_child_wait( child );
- osrf_prefork_child_exit(child); /* just to be sure */
- }
- return NULL;
-}
-
-void osrf_prefork_child_exit(prefork_child* child) {
- osrfAppRunExitCode();
- exit(0);
-}
-
-void prefork_launch_children( prefork_simple* forker ) {
- if(!forker) return;
- int c = 0;
- while( c++ < forker->min_children )
- launch_child( forker );
-}
-
-
-void sigchld_handler( int sig ) {
- signal(SIGCHLD, sigchld_handler);
- child_dead = 1;
-}
-
-
-void reap_children( prefork_simple* forker ) {
-
- pid_t child_pid;
- int status;
-
- while( (child_pid=waitpid(-1,&status,WNOHANG)) > 0)
- del_prefork_child( forker, child_pid );
-
- /* replenish */
- while( forker->current_num_children < forker->min_children )
- launch_child( forker );
-
- child_dead = 0;
-}
-
-void prefork_run(prefork_simple* forker) {
-
- if( forker->first_child == NULL )
- return;
-
- transport_message* cur_msg = NULL;
-
-
- while(1) {
-
- if( forker->first_child == NULL ) {/* no more children */
- osrfLogWarning( OSRF_LOG_MARK, "No more children..." );
- return;
- }
-
- osrfLogDebug( OSRF_LOG_MARK, "Forker going into wait for data...");
- cur_msg = client_recv( forker->connection, -1 );
-
- //fprintf(stderr, "Got Data %f\n", get_timestamp_millis() );
-
- if( cur_msg == NULL ) continue;
-
- int honored = 0; /* true if we've serviced the request */
- int no_recheck = 0;
-
- while( ! honored ) {
-
- if(!no_recheck) check_children( forker, 0 );
- no_recheck = 0;
-
- osrfLogDebug( OSRF_LOG_MARK, "Server received inbound data" );
- int k;
- prefork_child* cur_child = forker->first_child;
-
- /* Look for an available child */
- for( k = 0; k < forker->current_num_children; k++ ) {
-
- osrfLogInternal( OSRF_LOG_MARK, "Searching for available child. cur_child->pid = %d", cur_child->pid );
- osrfLogInternal( OSRF_LOG_MARK, "Current num children %d and loop %d", forker->current_num_children, k);
-
- if( cur_child->available ) {
- osrfLogDebug( OSRF_LOG_MARK, "forker sending data to %d", cur_child->pid );
-
- message_prepare_xml( cur_msg );
- char* data = cur_msg->msg_xml;
- if( ! data || strlen(data) < 1 ) break;
-
- cur_child->available = 0;
- osrfLogInternal( OSRF_LOG_MARK, "Writing to child fd %d", cur_child->write_data_fd );
-
- int written = 0;
- //fprintf(stderr, "Writing Data %f\n", get_timestamp_millis() );
- if( (written = write( cur_child->write_data_fd, data, strlen(data) + 1 )) < 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "Write returned error %d", errno);
- cur_child = cur_child->next;
- continue;
- }
-
- //fprintf(stderr, "Wrote %d bytes to child\n", written);
-
- forker->first_child = cur_child->next;
- honored = 1;
- break;
- } else
- cur_child = cur_child->next;
- }
-
- /* if none available, add a new child if we can */
- if( ! honored ) {
- osrfLogDebug( OSRF_LOG_MARK, "Not enough children, attempting to add...");
-
- if( forker->current_num_children < forker->max_children ) {
- osrfLogDebug( OSRF_LOG_MARK, "Launching new child with current_num = %d",
- forker->current_num_children );
-
- prefork_child* new_child = launch_child( forker );
- if( new_child ) {
-
- message_prepare_xml( cur_msg );
- char* data = cur_msg->msg_xml;
-
- if( data ) {
- int len = strlen(data);
-
- if( len > 0 ) {
- new_child->available = 0;
- osrfLogDebug( OSRF_LOG_MARK, "Writing to new child fd %d : pid %d",
- new_child->write_data_fd, new_child->pid );
-
- if( write( new_child->write_data_fd, data, len + 1 ) >= 0 ) {
- forker->first_child = new_child->next;
- honored = 1;
- }
- }
- }
- }
-
- }
- }
-
- if( !honored ) {
- osrfLogWarning( OSRF_LOG_MARK, "No children available, waiting...");
-
- check_children( forker, 1 ); /* non-poll version */
- /* tell the loop no to call check_children again, since we're calling it now */
- no_recheck = 1;
- }
-
- if( child_dead )
- reap_children(forker);
-
-
- //fprintf(stderr, "Parent done with request %f\n", get_timestamp_millis() );
-
- } // honored?
-
- message_free( cur_msg );
-
- } /* top level listen loop */
-
-}
-
-
-/** XXX Add a flag which tells select() to wait forever on children
- * in the best case, this will be faster than calling usleep(x), and
- * in the worst case it won't be slower and will do less logging...
- */
-
-void check_children( prefork_simple* forker, int forever ) {
-
- //check_begin:
-
- int select_ret;
- fd_set read_set;
- FD_ZERO(&read_set);
- int max_fd = 0;
- int n;
-
-
- if( child_dead )
- reap_children(forker);
-
- prefork_child* cur_child = forker->first_child;
-
- int i;
- for( i = 0; i!= forker->current_num_children; i++ ) {
-
- if( cur_child->read_status_fd > max_fd )
- max_fd = cur_child->read_status_fd;
- FD_SET( cur_child->read_status_fd, &read_set );
- cur_child = cur_child->next;
- }
-
- FD_CLR(0,&read_set);/* just to be sure */
-
- if( forever ) {
- osrfLogWarning(OSRF_LOG_MARK, "We have no children available - waiting for one to show up...");
-
- if( (select_ret=select( max_fd + 1 , &read_set, NULL, NULL, NULL)) == -1 ) {
- osrfLogWarning( OSRF_LOG_MARK, "Select returned error %d on check_children", errno );
- }
- osrfLogInfo(OSRF_LOG_MARK, "select() completed after waiting on children to become available");
-
- } else {
-
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- if( (select_ret=select( max_fd + 1 , &read_set, NULL, NULL, &tv)) == -1 ) {
- osrfLogWarning( OSRF_LOG_MARK, "Select returned error %d on check_children", errno );
- }
- }
-
- if( select_ret == 0 )
- return;
-
- /* see if one of a child has told us it's done */
- cur_child = forker->first_child;
- int j;
- int num_handled = 0;
- for( j = 0; j!= forker->current_num_children && num_handled < select_ret ; j++ ) {
-
- if( FD_ISSET( cur_child->read_status_fd, &read_set ) ) {
- //printf( "Server received status from a child %d\n", cur_child->pid );
- osrfLogDebug( OSRF_LOG_MARK, "Server received status from a child %d", cur_child->pid );
-
- num_handled++;
-
- /* now suck off the data */
- char buf[64];
- memset( buf, 0, 64);
- if( (n=read(cur_child->read_status_fd, buf, 63)) < 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "Read error afer select in child status read with errno %d", errno);
- }
-
- osrfLogDebug( OSRF_LOG_MARK, "Read %d bytes from status buffer: %s", n, buf );
- cur_child->available = 1;
- }
- cur_child = cur_child->next;
- }
-
-}
-
-
-void prefork_child_wait( prefork_child* child ) {
-
- int i,n;
- growing_buffer* gbuf = buffer_init( READ_BUFSIZE );
- char buf[READ_BUFSIZE];
- memset( buf, 0, READ_BUFSIZE );
-
- for( i = 0; i < child->max_requests; i++ ) {
-
- n = -1;
- int gotdata = 0;
- clr_fl(child->read_data_fd, O_NONBLOCK );
-
- while( (n=read(child->read_data_fd, buf, READ_BUFSIZE-1)) > 0 ) {
- osrfLogDebug(OSRF_LOG_MARK, "Prefork child read %d bytes of data", n);
- if(!gotdata)
- set_fl(child->read_data_fd, O_NONBLOCK );
- buffer_add( gbuf, buf );
- memset( buf, 0, READ_BUFSIZE );
- gotdata = 1;
- }
-
- if( errno == EAGAIN ) n = 0;
-
- if( errno == EPIPE ) {
- osrfLogDebug(OSRF_LOG_MARK, "C child attempted read on broken pipe, exiting...");
- break;
- }
-
- if( n < 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "Prefork child read returned error with errno %d", errno );
- break;
-
- } else if( gotdata ) {
- osrfLogDebug(OSRF_LOG_MARK, "Prefork child got a request.. processing..");
- prefork_child_process_request(child, gbuf->buf);
- buffer_reset( gbuf );
- }
-
- if( i < child->max_requests - 1 )
- write( child->write_status_fd, "available" /*less than 64 bytes*/, 9 );
- }
-
- buffer_free(gbuf);
-
- osrfLogDebug( OSRF_LOG_MARK, "Child with max-requests=%d, num-served=%d exiting...[%ld]",
- child->max_requests, i, (long) getpid() );
-
- osrf_prefork_child_exit(child); /* just to be sure */
-}
-
-
-void add_prefork_child( prefork_simple* forker, prefork_child* child ) {
-
- if( forker->first_child == NULL ) {
- forker->first_child = child;
- child->next = child;
- return;
- }
-
- /* we put the child in as the last because, regardless,
- we have to do the DLL splice dance, and this is the
- simplest way */
-
- prefork_child* start_child = forker->first_child;
- while(1) {
- if( forker->first_child->next == start_child )
- break;
- forker->first_child = forker->first_child->next;
- }
-
- /* here we know that forker->first_child is the last element
- in the list and start_child is the first. Insert the
- new child between them*/
-
- forker->first_child->next = child;
- child->next = start_child;
- return;
-}
-
-prefork_child* find_prefork_child( prefork_simple* forker, pid_t pid ) {
-
- if( forker->first_child == NULL ) { return NULL; }
- prefork_child* start_child = forker->first_child;
- do {
- if( forker->first_child->pid == pid )
- return forker->first_child;
- } while( (forker->first_child = forker->first_child->next) != start_child );
-
- return NULL;
-}
-
-
-void del_prefork_child( prefork_simple* forker, pid_t pid ) {
-
- if( forker->first_child == NULL ) { return; }
-
- (forker->current_num_children)--;
- osrfLogDebug( OSRF_LOG_MARK, "Deleting Child: %d", pid );
-
- prefork_child* start_child = forker->first_child; /* starting point */
- prefork_child* cur_child = start_child; /* current pointer */
- prefork_child* prev_child = start_child; /* the trailing pointer */
-
- /* special case where there is only one in the list */
- if( start_child == start_child->next ) {
- if( start_child->pid == pid ) {
- forker->first_child = NULL;
-
- close( start_child->read_data_fd );
- close( start_child->write_data_fd );
- close( start_child->read_status_fd );
- close( start_child->write_status_fd );
-
- prefork_child_free( start_child );
- }
- return;
- }
-
-
- /* special case where the first item in the list needs to be removed */
- if( start_child->pid == pid ) {
-
- /* find the last one so we can remove the start_child */
- do {
- prev_child = cur_child;
- cur_child = cur_child->next;
- }while( cur_child != start_child );
-
- /* now cur_child == start_child */
- prev_child->next = cur_child->next;
- forker->first_child = prev_child;
-
- close( cur_child->read_data_fd );
- close( cur_child->write_data_fd );
- close( cur_child->read_status_fd );
- close( cur_child->write_status_fd );
-
- prefork_child_free( cur_child );
- return;
- }
-
- do {
- prev_child = cur_child;
- cur_child = cur_child->next;
-
- if( cur_child->pid == pid ) {
- prev_child->next = cur_child->next;
-
- close( cur_child->read_data_fd );
- close( cur_child->write_data_fd );
- close( cur_child->read_status_fd );
- close( cur_child->write_status_fd );
-
- prefork_child_free( cur_child );
- return;
- }
-
- } while(cur_child != start_child);
-}
-
-
-
-
-prefork_child* prefork_child_init(
- int max_requests, int read_data_fd, int write_data_fd,
- int read_status_fd, int write_status_fd ) {
-
- prefork_child* child = (prefork_child*) safe_malloc(sizeof(prefork_child));
- child->max_requests = max_requests;
- child->read_data_fd = read_data_fd;
- child->write_data_fd = write_data_fd;
- child->read_status_fd = read_status_fd;
- child->write_status_fd = write_status_fd;
- child->available = 1;
-
- return child;
-}
-
-
-int prefork_free( prefork_simple* prefork ) {
-
- while( prefork->first_child != NULL ) {
- osrfLogInfo( OSRF_LOG_MARK, "Killing children and sleeping 1 to reap..." );
- kill( 0, SIGKILL );
- sleep(1);
- }
-
- client_free(prefork->connection);
- free(prefork->appname);
- free( prefork );
- return 1;
-}
-
-int prefork_child_free( prefork_child* child ) {
- free(child->appname);
- close(child->read_data_fd);
- close(child->write_status_fd);
- free( child );
- return 1;
-}
-
+++ /dev/null
-#include <sys/types.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/select.h>
-#include <sys/wait.h>
-
-#include "opensrf/utils.h"
-#include "opensrf/transport_message.h"
-#include "opensrf/transport_client.h"
-#include "osrf_stack.h"
-#include "osrf_settings.h"
-#include "osrfConfig.h"
-
-//#define READ_BUFSIZE 4096
-#define READ_BUFSIZE 1024
-#define MAX_BUFSIZE 10485760 /* 10M enough? ;) */
-#define ABS_MAX_CHILDREN 256
-
-/* we receive data. we find the next child in
- line that is available. pass the data down that childs pipe and go
- back to listening for more data.
- when we receive SIGCHLD, we check for any dead children and clean up
- their respective prefork_child objects, close pipes, etc.
-
- we build a select fd_set with all the child pipes (going to the parent)
- when a child is done processing a request, it writes a small chunk of
- data to the parent to alert the parent that the child is again available
- */
-
-struct prefork_simple_struct {
- int max_requests;
- int min_children;
- int max_children;
- int fd;
- int data_to_child;
- int data_to_parent;
- int current_num_children;
- int keepalive; /* keepalive time for stateful sessions */
- char* appname;
- struct prefork_child_struct* first_child;
- transport_client* connection;
-};
-typedef struct prefork_simple_struct prefork_simple;
-
-struct prefork_child_struct {
- pid_t pid;
- int read_data_fd;
- int write_data_fd;
- int read_status_fd;
- int write_status_fd;
- int min_children;
- int available;
- int max_requests;
- char* appname;
- int keepalive;
- struct prefork_child_struct* next;
-};
-
-typedef struct prefork_child_struct prefork_child;
-
-int osrf_prefork_run(char* appname);
-
-prefork_simple* prefork_simple_init( transport_client* client,
- int max_requests, int min_children, int max_children );
-
-prefork_child* launch_child( prefork_simple* forker );
-void prefork_launch_children( prefork_simple* forker );
-
-void prefork_run(prefork_simple* forker);
-
-void add_prefork_child( prefork_simple* forker, prefork_child* child );
-prefork_child* find_prefork_child( prefork_simple* forker, pid_t pid );
-void del_prefork_child( prefork_simple* forker, pid_t pid );
-
-void check_children( prefork_simple* forker, int forever );
-
-void prefork_child_process_request(prefork_child*, char* data);
-int prefork_child_init_hook(prefork_child*);
-
-prefork_child* prefork_child_init(
- int max_requests, int read_data_fd, int write_data_fd,
- int read_status_fd, int write_status_fd );
-
-/* listens on the 'data_to_child' fd and wait for incoming data */
-void prefork_child_wait( prefork_child* child );
-
-int prefork_free( prefork_simple* );
-int prefork_child_free( prefork_child* );
-
-
-void osrf_prefork_register_routers( char* appname );
-
-void osrf_prefork_child_exit( prefork_child* );
+++ /dev/null
-#include "osrf_settings.h"
-
-osrf_host_config* config = NULL;
-
-char* osrf_settings_host_value(char* format, ...) {
- VA_LIST_TO_STRING(format);
- jsonObject* o = jsonObjectFindPath(config->config, VA_BUF);
- char* val = jsonObjectToSimpleString(o);
- jsonObjectFree(o);
- return val;
-}
-
-jsonObject* osrf_settings_host_value_object(char* format, ...) {
- VA_LIST_TO_STRING(format);
-
- if( ! config ) {
- const char * msg = "config pointer is NULL";
- fprintf( stderr, "osrf_settings_host_value_object: %s\n", msg );
- osrfLogError( OSRF_LOG_MARK, msg );
- exit( 99 );
- }
-
- return jsonObjectFindPath(config->config, VA_BUF);
-}
-
-
-int osrf_settings_retrieve(char* hostname) {
-
- if(!config) {
-
- osrf_app_session* session = osrf_app_client_session_init("opensrf.settings");
- jsonObject* params = jsonNewObject(NULL);
- jsonObjectPush(params, jsonNewObject(hostname));
- int req_id = osrf_app_session_make_req(
- session, params, "opensrf.settings.host_config.get", 1, NULL );
- osrf_message* omsg = osrf_app_session_request_recv( session, req_id, 60 );
- jsonObjectFree(params);
-
- if(omsg && omsg->_result_content) {
- config = osrf_settings_new_host_config(hostname);
- config->config = jsonObjectClone(omsg->_result_content);
- osrf_message_free(omsg);
- }
-
- osrf_app_session_request_finish( session, req_id );
- osrf_app_session_destroy( session );
-
- if(!config) {
- osrfLogError( OSRF_LOG_MARK, "Unable to load config for host %s", hostname);
- return -1;
- }
- }
-
- return 0;
-}
-
-osrf_host_config* osrf_settings_new_host_config(char* hostname) {
- if(!hostname) return NULL;
- osrf_host_config* c = safe_malloc(sizeof(osrf_host_config));
- c->hostname = strdup(hostname);
- return c;
-}
-
-void osrf_settings_free_host_config(osrf_host_config* c) {
- if(!c) c = config;
- if(!c) return;
- free(c->hostname);
- jsonObjectFree(c->config);
- free(c);
-}
+++ /dev/null
-#ifndef OSRF_SETTINGS_H
-#define OSRF_SETTINGS_H
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <time.h>
-#include <stdarg.h>
-
-#include "opensrf/log.h"
-#include "opensrf/utils.h"
-#include "objson/object.h"
-#include "objson/json_parser.h"
-#include "osrf_app_session.h"
-
-
-typedef struct {
- char* hostname;
- jsonObject* config;
-} osrf_host_config;
-
-
-osrf_host_config* osrf_settings_new_host_config(char* hostname);
-void osrf_settings_free_host_config(osrf_host_config*);
-char* osrf_settings_host_value(char* path, ...);
-jsonObject* osrf_settings_host_value_object(char* format, ...);
-int osrf_settings_retrieve(char* hostname);
-
-#endif
-
+++ /dev/null
-#include "osrf_stack.h"
-#include "osrf_application.h"
-
-osrf_message* _do_client( osrf_app_session*, osrf_message* );
-osrf_message* _do_server( osrf_app_session*, osrf_message* );
-
-/* tell osrf_app_session where the stack entry is */
-int (*osrf_stack_entry_point) (transport_client*, int, int*) = &osrf_stack_process;
-
-int osrf_stack_process( transport_client* client, int timeout, int* msg_received ) {
- if( !client ) return -1;
- transport_message* msg = NULL;
- if(msg_received) *msg_received = 0;
-
- while( (msg = client_recv( client, timeout )) ) {
- if(msg_received) *msg_received = 1;
- osrfLogDebug( OSRF_LOG_MARK, "Received message from transport code from %s", msg->sender );
- osrf_stack_transport_handler( msg, NULL );
- timeout = 0;
- }
-
- if( client->error ) {
- osrfLogWarning(OSRF_LOG_MARK, "transport_client had trouble reading from the socket..");
- return -1;
- }
-
- if( ! client_connected( client ) ) return -1;
-
- return 0;
-}
-
-
-
-// -----------------------------------------------------------------------------
-// Entry point into the stack
-// -----------------------------------------------------------------------------
-osrfAppSession* osrf_stack_transport_handler( transport_message* msg, char* my_service ) {
-
- if(!msg) return NULL;
-
- osrfLogSetXid(msg->osrf_xid);
-
- osrfLogDebug( OSRF_LOG_MARK, "Transport handler received new message \nfrom %s "
- "to %s with body \n\n%s\n", msg->sender, msg->recipient, msg->body );
-
- if( msg->is_error && ! msg->thread ) {
- osrfLogWarning( OSRF_LOG_MARK, "!! Received jabber layer error for %s ... exiting\n", msg->sender );
- message_free( msg );
- return NULL;
- }
-
- if(! msg->thread && ! msg->is_error ) {
- osrfLogWarning( OSRF_LOG_MARK, "Received a non-error message with no thread trace... dropping");
- message_free( msg );
- return NULL;
- }
-
- osrf_app_session* session = osrf_app_session_find_session( msg->thread );
-
- if( !session && my_service )
- session = osrf_app_server_session_init( msg->thread, my_service, msg->sender);
-
- if( !session ) return NULL;
-
- if(!msg->is_error)
- osrfLogDebug( OSRF_LOG_MARK, "Session [%s] found or built", session->session_id );
-
- osrf_app_session_set_remote( session, msg->sender );
- osrf_message* arr[OSRF_MAX_MSGS_PER_PACKET];
- memset(arr, 0, OSRF_MAX_MSGS_PER_PACKET );
- int num_msgs = osrf_message_deserialize(msg->body, arr, OSRF_MAX_MSGS_PER_PACKET);
-
- osrfLogDebug( OSRF_LOG_MARK, "We received %d messages from %s", num_msgs, msg->sender );
-
- double starttime = get_timestamp_millis();
-
- int i;
- for( i = 0; i != num_msgs; i++ ) {
-
- /* if we've received a jabber layer error message (probably talking to
- someone who no longer exists) and we're not talking to the original
- remote id for this server, consider it a redirect and pass it up */
- if(msg->is_error) {
- osrfLogWarning( OSRF_LOG_MARK, " !!! Received Jabber layer error message" );
-
- if(strcmp(session->remote_id,session->orig_remote_id)) {
- osrfLogWarning( OSRF_LOG_MARK, "Treating jabber error as redirect for tt [%d] "
- "and session [%s]", arr[i]->thread_trace, session->session_id );
-
- arr[i]->m_type = STATUS;
- arr[i]->status_code = OSRF_STATUS_REDIRECTED;
-
- } else {
- osrfLogWarning( OSRF_LOG_MARK, " * Jabber Error is for top level remote id [%s], no one "
- "to send my message too!!!", session->remote_id );
- }
- }
-
- osrf_stack_message_handler( session, arr[i] );
- }
-
- double duration = get_timestamp_millis() - starttime;
- osrfLogInfo(OSRF_LOG_MARK, "Message processing duration %f", duration);
-
- message_free( msg );
- osrfLogDebug( OSRF_LOG_MARK, "after msg delete");
-
- return session;
-}
-
-int osrf_stack_message_handler( osrf_app_session* session, osrf_message* msg ) {
- if(session == NULL || msg == NULL)
- return 0;
-
- osrf_message* ret_msg = NULL;
-
- if( session->type == OSRF_SESSION_CLIENT )
- ret_msg = _do_client( session, msg );
- else
- ret_msg= _do_server( session, msg );
-
- if(ret_msg) {
- osrfLogDebug( OSRF_LOG_MARK, "passing message %d / session %s to app handler",
- msg->thread_trace, session->session_id );
- osrf_stack_application_handler( session, ret_msg );
- } else
- osrf_message_free(msg);
-
- return 1;
-
-}
-
-/** If we return a message, that message should be passed up the stack,
- * if we return NULL, we're finished for now...
- */
-osrf_message* _do_client( osrf_app_session* session, osrf_message* msg ) {
- if(session == NULL || msg == NULL)
- return NULL;
-
- osrf_message* new_msg;
-
- if( msg->m_type == STATUS ) {
-
- switch( msg->status_code ) {
-
- case OSRF_STATUS_OK:
- osrfLogDebug( OSRF_LOG_MARK, "We connected successfully");
- session->state = OSRF_SESSION_CONNECTED;
- osrfLogDebug( OSRF_LOG_MARK, "State: %x => %s => %d", session, session->session_id, session->state );
- return NULL;
-
- case OSRF_STATUS_COMPLETE:
- osrf_app_session_set_complete( session, msg->thread_trace );
- return NULL;
-
- case OSRF_STATUS_CONTINUE:
- osrf_app_session_request_reset_timeout( session, msg->thread_trace );
- return NULL;
-
- case OSRF_STATUS_REDIRECTED:
- osrf_app_session_reset_remote( session );
- session->state = OSRF_SESSION_DISCONNECTED;
- osrf_app_session_request_resend( session, msg->thread_trace );
- return NULL;
-
- case OSRF_STATUS_EXPFAILED:
- osrf_app_session_reset_remote( session );
- session->state = OSRF_SESSION_DISCONNECTED;
- return NULL;
-
- case OSRF_STATUS_TIMEOUT:
- osrf_app_session_reset_remote( session );
- session->state = OSRF_SESSION_DISCONNECTED;
- osrf_app_session_request_resend( session, msg->thread_trace );
- return NULL;
-
-
- default:
- new_msg = osrf_message_init( RESULT, msg->thread_trace, msg->protocol );
- osrf_message_set_status_info( new_msg,
- msg->status_name, msg->status_text, msg->status_code );
- osrfLogWarning( OSRF_LOG_MARK, "The stack doesn't know what to do with "
- "the provided message code: %d, name %s. Passing UP.",
- msg->status_code, msg->status_name );
- new_msg->is_exception = 1;
- osrf_app_session_set_complete( session, msg->thread_trace );
- osrf_message_free(msg);
- return new_msg;
- }
-
- return NULL;
-
- } else if( msg->m_type == RESULT )
- return msg;
-
- return NULL;
-
-}
-
-
-/** If we return a message, that message should be passed up the stack,
- * if we return NULL, we're finished for now...
- */
-osrf_message* _do_server( osrf_app_session* session, osrf_message* msg ) {
-
- if(session == NULL || msg == NULL) return NULL;
-
- osrfLogDebug( OSRF_LOG_MARK, "Server received message of type %d", msg->m_type );
-
- switch( msg->m_type ) {
-
- case STATUS:
- return NULL;
-
- case DISCONNECT:
- /* session will be freed by the forker */
- osrfLogDebug(OSRF_LOG_MARK, "Client sent explicit disconnect");
- session->state = OSRF_SESSION_DISCONNECTED;
- return NULL;
-
- case CONNECT:
- osrfAppSessionStatus( session, OSRF_STATUS_OK,
- "osrfConnectStatus", msg->thread_trace, "Connection Successful" );
- session->state = OSRF_SESSION_CONNECTED;
- return NULL;
-
- case REQUEST:
-
- osrfLogDebug( OSRF_LOG_MARK, "server passing message %d to application handler "
- "for session %s", msg->thread_trace, session->session_id );
- return msg;
-
- default:
- osrfLogWarning( OSRF_LOG_MARK, "Server cannot handle message of type %d", msg->m_type );
- session->state = OSRF_SESSION_DISCONNECTED;
- return NULL;
-
- }
-}
-
-
-
-int osrf_stack_application_handler( osrf_app_session* session, osrf_message* msg ) {
- if(session == NULL || msg == NULL) return 0;
-
- if(msg->m_type == RESULT && session->type == OSRF_SESSION_CLIENT) {
- osrf_app_session_push_queue( session, msg );
- return 1;
- }
-
- if(msg->m_type != REQUEST) return 1;
-
- char* method = msg->method_name;
- char* app = session->remote_service;
- jsonObject* params = msg->_params;
-
- osrfAppRunMethod( app, method, session, msg->thread_trace, params );
- osrfMessageFree(msg);
-
- return 1;
-}
-
-
+++ /dev/null
-#include "opensrf/transport_client.h"
-#include "osrf_message.h"
-#include "osrf_app_session.h"
-
-#ifndef OSRF_STACK_H
-#define OSRF_STACK_H
-
-/* the max number of oilsMessage blobs present in any one root packet */
-#define OSRF_MAX_MSGS_PER_PACKET 256
-// -----------------------------------------------------------------------------
-
-int osrf_stack_process( transport_client* client, int timeout, int* msg_received );
-osrfAppSession* osrf_stack_transport_handler( transport_message* msg, char* my_service );
-int osrf_stack_message_handler( osrf_app_session* session, osrf_message* msg );
-int osrf_stack_application_handler( osrf_app_session* session, osrf_message* msg );
-
-
-
-#endif
+++ /dev/null
-#include "osrf_system.h"
-#include <signal.h>
-#include "osrf_application.h"
-#include "osrf_prefork.h"
-
-static int _osrfSystemInitCache( void );
-
-static transport_client* osrfGlobalTransportClient = NULL;
-
-transport_client* osrfSystemGetTransportClient( void ) {
- return osrfGlobalTransportClient;
-}
-
-void osrfSystemIgnoreTransportClient() {
- osrfGlobalTransportClient = NULL;
-}
-
-transport_client* osrf_system_get_transport_client( void ) {
- return osrfGlobalTransportClient;
-}
-
-int osrf_system_bootstrap_client( char* config_file, char* contextnode ) {
- return osrf_system_bootstrap_client_resc(config_file, contextnode, NULL);
-}
-
-int osrfSystemBootstrapClientResc( char* config_file, char* contextnode, char* resource ) {
- return osrf_system_bootstrap_client_resc( config_file, contextnode, resource );
-}
-
-
-static int _osrfSystemInitCache( void ) {
-
- jsonObject* cacheServers = osrf_settings_host_value_object("/cache/global/servers/server");
- char* maxCache = osrf_settings_host_value("/cache/global/max_cache_time");
-
- if( cacheServers && maxCache) {
-
- if( cacheServers->type == JSON_ARRAY ) {
- int i;
- char* servers[cacheServers->size];
- for( i = 0; i != cacheServers->size; i++ ) {
- servers[i] = jsonObjectGetString( jsonObjectGetIndex(cacheServers, i) );
- osrfLogInfo( OSRF_LOG_MARK, "Adding cache server %s", servers[i]);
- }
- osrfCacheInit( servers, cacheServers->size, atoi(maxCache) );
-
- } else {
- char* servers[] = { jsonObjectGetString(cacheServers) };
- osrfLogInfo( OSRF_LOG_MARK, "Adding cache server %s", servers[0]);
- osrfCacheInit( servers, 1, atoi(maxCache) );
- }
-
- } else {
- osrfLogError( OSRF_LOG_MARK, "Missing config value for /cache/global/servers/server _or_ "
- "/cache/global/max_cache_time");
- }
-
- return 0;
-}
-
-
-int osrfSystemBootstrap( char* hostname, char* configfile, char* contextNode ) {
- if( !(hostname && configfile && contextNode) ) return -1;
-
- /* first we grab the settings */
- if(!osrfSystemBootstrapClientResc(configfile, contextNode, "settings_grabber" )) {
- osrfLogError( OSRF_LOG_MARK, "Unable to bootstrap");
- return -1;
- }
-
- osrf_settings_retrieve(hostname);
- osrf_system_disconnect_client();
-
- jsonObject* apps = osrf_settings_host_value_object("/activeapps/appname");
- osrfStringArray* arr = osrfNewStringArray(8);
-
- _osrfSystemInitCache();
-
- if(apps) {
- int i = 0;
-
- if(apps->type == JSON_STRING) {
- osrfStringArrayAdd(arr, jsonObjectGetString(apps));
-
- } else {
- jsonObject* app;
- while( (app = jsonObjectGetIndex(apps, i++)) )
- osrfStringArrayAdd(arr, jsonObjectGetString(app));
- }
-
- char* appname = NULL;
- i = 0;
- while( (appname = osrfStringArrayGetString(arr, i++)) ) {
-
- char* lang = osrf_settings_host_value("/apps/%s/language", appname);
-
- if(lang && !strcasecmp(lang,"c")) {
-
- char* libfile = osrf_settings_host_value("/apps/%s/implementation", appname);
-
- if(! (appname && libfile) ) {
- osrfLogWarning( OSRF_LOG_MARK, "Missing appname / libfile in settings config");
- continue;
- }
-
- osrfLogInfo( OSRF_LOG_MARK, "Launching application %s with implementation %s", appname, libfile);
-
- pid_t pid;
-
- if( (pid = fork()) ) {
- // storage pid in local table for re-launching dead children...
- osrfLogInfo( OSRF_LOG_MARK, "Launched application child %ld", (long) pid);
-
- } else {
-
- fprintf(stderr, " * Running application %s\n", appname);
- if( osrfAppRegisterApplication( appname, libfile ) == 0 )
- osrf_prefork_run(appname);
-
- osrfLogDebug( OSRF_LOG_MARK, "Server exiting for app %s and library %s\n", appname, libfile );
- exit(0);
- }
- } // language == c
- }
- }
-
- /** daemonize me **/
-
- /* background and let our children do their thing */
- daemonize();
- while(1) {
- errno = 0;
- pid_t pid = wait(NULL);
- if(-1 == pid) {
- if(errno == ECHILD)
- osrfLogError(OSRF_LOG_MARK, "We have no more live services... exiting");
- else
- osrfLogError(OSRF_LOG_MARK, "Exiting top-level system loop with error: %s", strerror(errno));
- break;
- } else {
- osrfLogError(OSRF_LOG_MARK, "We lost a top-level service process with PID %ld", pid);
- }
- }
-
-
- return 0;
-}
-
-int osrf_system_bootstrap_client_resc( char* config_file, char* contextnode, char* resource ) {
-
- int failure = 0;
-
- if(osrfSystemGetTransportClient()) {
- osrfLogInfo(OSRF_LOG_MARK, "Client is already bootstrapped");
- return 1; /* we already have a client connection */
- }
-
- if( !( config_file && contextnode ) && ! osrfConfigHasDefaultConfig() ) {
- osrfLogError( OSRF_LOG_MARK, "No Config File Specified\n" );
- return -1;
- }
-
- if( config_file ) {
- osrfConfig* cfg = osrfConfigInit( config_file, contextnode );
- if(cfg)
- osrfConfigSetDefaultConfig(cfg);
- else
- return 0; /* Can't load configuration? Bail out */
- }
-
-
- char* log_file = osrfConfigGetValue( NULL, "/logfile");
- char* log_level = osrfConfigGetValue( NULL, "/loglevel" );
- osrfStringArray* arr = osrfNewStringArray(8);
- osrfConfigGetValueList(NULL, arr, "/domains/domain");
-
- char* username = osrfConfigGetValue( NULL, "/username" );
- char* password = osrfConfigGetValue( NULL, "/passwd" );
- char* port = osrfConfigGetValue( NULL, "/port" );
- char* unixpath = osrfConfigGetValue( NULL, "/unixpath" );
- char* facility = osrfConfigGetValue( NULL, "/syslog" );
- char* actlog = osrfConfigGetValue( NULL, "/actlog" );
-
- if(!log_file) {
- fprintf(stderr, "No log file specified in configuration file %s\n",
- config_file);
- free(log_level);
- free(username);
- free(password);
- free(port);
- free(unixpath);
- free(facility);
- free(actlog);
- return -1;
- }
-
- /* if we're a source-client, tell the logger */
- char* isclient = osrfConfigGetValue(NULL, "/client");
- if( isclient && !strcasecmp(isclient,"true") )
- osrfLogSetIsClient(1);
- free(isclient);
-
- int llevel = 0;
- int iport = 0;
- if(port) iport = atoi(port);
- if(log_level) llevel = atoi(log_level);
-
- if(!strcmp(log_file, "syslog")) {
- osrfLogInit( OSRF_LOG_TYPE_SYSLOG, contextnode, llevel );
- osrfLogSetSyslogFacility(osrfLogFacilityToInt(facility));
- if(actlog) osrfLogSetSyslogActFacility(osrfLogFacilityToInt(actlog));
-
- } else {
- osrfLogInit( OSRF_LOG_TYPE_FILE, contextnode, llevel );
- osrfLogSetFile( log_file );
- }
-
-
- /* Get a domain, if one is specified */
- const char* domain = osrfStringArrayGetString( arr, 0 ); /* just the first for now */
- if(!domain) {
- fprintf(stderr, "No domain specified in configuration file %s\n", config_file);
- osrfLogError( OSRF_LOG_MARK, "No domain specified in configuration file %s\n", config_file);
- failure = 1;
- }
-
- if(!username) {
- fprintf(stderr, "No username specified in configuration file %s\n", config_file);
- osrfLogError( OSRF_LOG_MARK, "No username specified in configuration file %s\n", config_file);
- failure = 1;
- }
-
- if(!password) {
- fprintf(stderr, "No password specified in configuration file %s\n", config_file);
- osrfLogError( OSRF_LOG_MARK, "No password specified in configuration file %s\n", config_file);
- failure = 1;
- }
-
- if((iport <= 0) && !unixpath) {
- fprintf(stderr, "No unixpath or valid port in configuration file %s\n", config_file);
- osrfLogError( OSRF_LOG_MARK, "No unixpath or valid port in configuration file %s\n",
- config_file);
- failure = 1;
- }
-
- if (failure) {
- osrfStringArrayFree(arr);
- free(log_level);
- free(username);
- free(password);
- free(port);
- free(unixpath);
- free(facility);
- free(actlog);
- return 0;
- }
-
- osrfLogInfo( OSRF_LOG_MARK, "Bootstrapping system with domain %s, port %d, and unixpath %s",
- domain, iport, unixpath ? unixpath : "(none)" );
- transport_client* client = client_init( domain, iport, unixpath, 0 );
-
- const char* host;
- host = getenv("HOSTNAME");
-
- char tbuf[32];
- tbuf[0] = '\0';
- snprintf(tbuf, 32, "%f", get_timestamp_millis());
-
- if(!host) host = "";
- if(!resource) resource = "";
-
- int len = strlen(resource) + 256;
- char buf[len];
- buf[0] = '\0';
- snprintf(buf, len - 1, "%s_%s_%s_%ld", resource, host, tbuf, (long) getpid() );
-
- if(client_connect( client, username, password, buf, 10, AUTH_DIGEST )) {
- /* child nodes will leak the parents client... but we can't free
- it without disconnecting the parents client :( */
- osrfGlobalTransportClient = client;
- }
-
- osrfStringArrayFree(arr);
- free(actlog);
- free(facility);
- free(log_level);
- free(log_file);
- free(username);
- free(password);
- free(port);
- free(unixpath);
-
- if(osrfGlobalTransportClient)
- return 1;
-
- return 0;
-}
-
-int osrf_system_disconnect_client( void ) {
- client_disconnect( osrfGlobalTransportClient );
- client_free( osrfGlobalTransportClient );
- osrfGlobalTransportClient = NULL;
- return 0;
-}
-
-int osrf_system_shutdown( void ) {
- osrfConfigCleanup();
- osrf_system_disconnect_client();
- osrf_settings_free_host_config(NULL);
- osrfAppSessionCleanup();
- osrfLogCleanup();
- return 1;
-}
-
-
-
-
+++ /dev/null
-#ifndef OSRF_SYSTEM_H
-#define OSRF_SYSTEM_H
-
-#include "opensrf/transport_client.h"
-#include "opensrf/utils.h"
-#include "opensrf/log.h"
-#include "osrf_settings.h"
-#include "osrfConfig.h"
-#include "osrf_cache.h"
-
-
-
-/** Connects to jabber. Returns 1 on success, 0 on failure
- contextnode is the location in the config file where we collect config info
-*/
-
-
-int osrf_system_bootstrap_client( char* config_file, char* contextnode );
-
-/* bootstraps a client adding the given resource string to the host/pid, etc. resource string */
-/**
- Sets up the global connection.
- @param configFile The OpenSRF bootstrap config file
- @param contextNode The location in the config file where we'll find the necessary info
- @param resource The login resource. If NULL a default will be created
- @return 1 on successs, 0 on failure.
- */
-int osrfSystemBootstrapClientResc( char* configFile, char* contextNode, char* resource );
-int osrf_system_bootstrap_client_resc( char* config_file, char* contextnode, char* resource );
-
-/**
- Bootstrap the server.
- @param hostname The name of this host. This is the name that will be used to
- load the settings.
- @param configfile The OpenSRF bootstrap config file
- @param contextnode The config context
- @return 0 on success, -1 on error
- */
-int osrfSystemBootstrap( char* hostName, char* configfile, char* contextNode );
-
-transport_client* osrfSystemGetTransportClient( void );
-transport_client* osrf_system_get_transport_client( void );
-
-/* disconnects and destroys the current client connection */
-int osrf_system_disconnect_client();
-int osrf_system_shutdown( void );
-
-
-/* this will clear the global transport client pointer without
- * actually destroying the socket. this is useful for allowing
- * children to have their own socket, even though their parent
- * already created a socket
- */
-void osrfSystemIgnoreTransportClient();
-
-
-#endif
+++ /dev/null
-#include "osrf_transgroup.h"
-#include <sys/select.h>
-
-
-osrfTransportGroupNode* osrfNewTransportGroupNode(
- char* domain, int port, char* username, char* password, char* resource ) {
-
- if(!(domain && port && username && password && resource)) return NULL;
-
- osrfTransportGroupNode* node = safe_malloc(sizeof(osrfTransportGroupNode));
- node->domain = strdup(domain);
- node->port = port;
- node->username = strdup(username);
- node->password = strdup(password);
- node->domain = strdup(domain);
- node->resource = strdup(resource);
- node->active = 0;
- node->lastsent = 0;
- node->connection = client_init( domain, port, NULL, 0 );
-
- return node;
-}
-
-
-osrfTransportGroup* osrfNewTransportGroup( osrfTransportGroupNode* nodes[], int count ) {
- if(!nodes || count < 1) return NULL;
-
- osrfTransportGroup* grp = safe_malloc(sizeof(osrfTransportGroup));
- grp->nodes = osrfNewHash();
- grp->itr = osrfNewHashIterator(grp->nodes);
-
- int i;
- for( i = 0; i != count; i++ ) {
- if(!(nodes[i] && nodes[i]->domain) ) return NULL;
- osrfHashSet( grp->nodes, nodes[i], nodes[i]->domain );
- osrfLogDebug( OSRF_LOG_MARK, "Adding domain %s to TransportGroup", nodes[i]->domain);
- }
-
- return grp;
-}
-
-
-/* connect all of the nodes to their servers */
-int osrfTransportGroupConnectAll( osrfTransportGroup* grp ) {
- if(!grp) return -1;
- int active = 0;
-
- osrfTransportGroupNode* node;
- osrfHashIteratorReset(grp->itr);
-
- while( (node = osrfHashIteratorNext(grp->itr)) ) {
- osrfLogInfo( OSRF_LOG_MARK, "TransportGroup attempting to connect to domain %s",
- node->connection->session->server);
-
- if(client_connect( node->connection, node->username,
- node->password, node->resource, 10, AUTH_DIGEST )) {
- node->active = 1;
- active++;
- osrfLogInfo( OSRF_LOG_MARK, "TransportGroup successfully connected to domain %s",
- node->connection->session->server);
- } else {
- osrfLogWarning( OSRF_LOG_MARK, "TransportGroup unable to connect to domain %s",
- node->connection->session->server);
- }
- }
-
- osrfHashIteratorReset(grp->itr);
- return active;
-}
-
-void osrfTransportGroupDisconnectAll( osrfTransportGroup* grp ) {
- if(!grp) return;
-
- osrfTransportGroupNode* node;
- osrfHashIteratorReset(grp->itr);
-
- while( (node = osrfHashIteratorNext(grp->itr)) ) {
- osrfLogInfo( OSRF_LOG_MARK, "TransportGroup disconnecting from domain %s",
- node->connection->session->server);
- client_disconnect(node->connection);
- node->active = 0;
- }
-
- osrfHashIteratorReset(grp->itr);
-}
-
-
-int osrfTransportGroupSendMatch( osrfTransportGroup* grp, transport_message* msg ) {
- if(!(grp && msg)) return -1;
-
- char domain[256];
- bzero(domain, 256);
- jid_get_domain( msg->recipient, domain, 255 );
-
- osrfTransportGroupNode* node = osrfHashGet(grp->nodes, domain);
- if(node) {
- if( (client_send_message( node->connection, msg )) == 0 )
- return 0;
- }
-
- osrfLogWarning( OSRF_LOG_MARK, "Error sending message to domain %s", domain );
- return -1;
-}
-
-int osrfTransportGroupSend( osrfTransportGroup* grp, transport_message* msg ) {
-
- if(!(grp && msg)) return -1;
- int bufsize = 256;
-
- char domain[bufsize];
- bzero(domain, bufsize);
- jid_get_domain( msg->recipient, domain, bufsize - 1 );
-
- char msgrecip[bufsize];
- bzero(msgrecip, bufsize);
- jid_get_username(msg->recipient, msgrecip, bufsize - 1);
-
- char msgres[bufsize];
- bzero(msgres, bufsize);
- jid_get_resource(msg->recipient, msgres, bufsize - 1);
-
- char* firstdomain = NULL;
- char newrcp[1024];
-
- int updateRecip = 1;
- /* if we don't host this domain, don't update the recipient but send it as is */
- if(!osrfHashGet(grp->nodes, domain)) updateRecip = 0;
-
- osrfTransportGroupNode* node;
-
- do {
-
- node = osrfHashIteratorNext(grp->itr);
- if(!node) osrfHashIteratorReset(grp->itr);
-
- node = osrfHashIteratorNext(grp->itr);
- if(!node) return -1;
-
- if(firstdomain == NULL) {
- firstdomain = node->domain;
-
- } else {
- if(!strcmp(firstdomain, node->domain)) { /* we've made a full loop */
- osrfLogWarning( OSRF_LOG_MARK, "We've tried to send to all domains.. giving up");
- return -1;
- }
- }
-
- /* update the recipient domain if necessary */
-
- if(updateRecip) {
- bzero(newrcp, 1024);
- sprintf(newrcp, "%s@%s/%s", msgrecip, node->domain, msgres);
- free(msg->recipient);
- msg->recipient = strdup(newrcp);
- }
-
- if( (client_send_message( node->connection, msg )) == 0 )
- return 0;
-
- } while(1);
-
- return -1;
-}
-
-static int __osrfTGWait( fd_set* fdset, int maxfd, int timeout ) {
- if(!(fdset && maxfd)) return 0;
-
- struct timeval tv;
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
- int retval = 0;
-
- if( timeout < 0 ) {
- if( (retval = select( maxfd + 1, fdset, NULL, NULL, NULL)) == -1 )
- return 0;
-
- } else {
- if( (retval = select( maxfd + 1, fdset, NULL, NULL, &tv)) == -1 )
- return 0;
- }
-
- return retval;
-}
-
-
-transport_message* osrfTransportGroupRecvAll( osrfTransportGroup* grp, int timeout ) {
- if(!grp) return NULL;
-
- int maxfd = 0;
- fd_set fdset;
- FD_ZERO( &fdset );
-
- osrfTransportGroupNode* node;
- osrfHashIterator* itr = osrfNewHashIterator(grp->nodes);
-
- while( (node = osrfHashIteratorNext(itr)) ) {
- if(node->active) {
- int fd = node->connection->session->sock_id;
- if( fd < maxfd ) maxfd = fd;
- FD_SET( fd, &fdset );
- }
- }
- osrfHashIteratorReset(itr);
-
- if( __osrfTGWait( &fdset, maxfd, timeout ) ) {
- while( (node = osrfHashIteratorNext(itr)) ) {
- if(node->active) {
- int fd = node->connection->session->sock_id;
- if( FD_ISSET( fd, &fdset ) ) {
- return client_recv( node->connection, 0 );
- }
- }
- }
- }
-
- osrfHashIteratorFree(itr);
- return NULL;
-}
-
-transport_message* osrfTransportGroupRecv( osrfTransportGroup* grp, char* domain, int timeout ) {
- if(!(grp && domain)) return NULL;
-
- osrfTransportGroupNode* node = osrfHashGet(grp->nodes, domain);
- if(!node && node->connection && node->connection->session) return NULL;
- int fd = node->connection->session->sock_id;
-
- fd_set fdset;
- FD_ZERO( &fdset );
- FD_SET( fd, &fdset );
-
- int active = __osrfTGWait( &fdset, fd, timeout );
- if(active) return client_recv( node->connection, 0 );
-
- return NULL;
-}
-
-void osrfTransportGroupSetInactive( osrfTransportGroup* grp, char* domain ) {
- if(!(grp && domain)) return;
- osrfTransportGroupNode* node = osrfHashGet(grp->nodes, domain );
- if(node) node->active = 0;
-}
-
-
+++ /dev/null
-#include "opensrf/transport_client.h"
-#include "opensrf/transport_message.h"
-#include "osrf_list.h"
-#include "osrf_hash.h"
-#include "osrfConfig.h"
-#include "opensrf/utils.h"
-#include <time.h>
-
-/**
- Maintains a set of transport clients
- */
-
-struct __osrfTransportGroupStruct {
- osrfHash* nodes; /* our hash of nodes keyed by domain */
- osrfHashIterator* itr; /* points to the next node in the list */
-};
-typedef struct __osrfTransportGroupStruct osrfTransportGroup;
-
-
-struct __osrfTransportGroupNode {
- transport_client* connection; /* our connection to the network */
- char* domain; /* the domain we're connected to */
- char* username; /* username used to connect to the group of servers */
- char* password; /* password used to connect to the group of servers */
- char* resource; /* the login resource */
- int port; /* port used to connect to the group of servers */
-
- int active; /* true if we're able to send data on this connection */
- time_t lastsent; /* the last time we sent a message */
-};
-typedef struct __osrfTransportGroupNode osrfTransportGroupNode;
-
-
-/**
- Creates a new group node
- @param domain The domain we're connecting to
- @param port The port to connect on
- @param username The login name
- @param password The login password
- @param resource The login resource
- @return A new transport group node
- */
-osrfTransportGroupNode* osrfNewTransportGroupNode(
- char* domain, int port, char* username, char* password, char* resource );
-
-
-/**
- Allocates and initializes a new transport group.
- The first node in the array is the default node for client connections.
- @param nodes The nodes in the group.
- */
-osrfTransportGroup* osrfNewTransportGroup( osrfTransportGroupNode* nodes[], int count );
-
-/**
- Attempts to connect all of the nodes in this group.
- @param grp The transport group
- @return The number of nodes successfully connected
- */
-int osrfTransportGroupConnectAll( osrfTransportGroup* grp );
-
-void osrfTransportGroupDisconnectAll( osrfTransportGroup* grp );
-
-
-/**
- Sends a transport message by going to the next domain in the set.
- if we have a connection for the recipient domain, then we consider it to be
- a 'local' message. Local messages have their recipient domains re-written to
- match the domain of the next server in the set and they are sent directly to
- that server. If we do not have a connection for the recipient domain, it is
- considered a 'remote' message and the message is sent directly (unchanged)
- to the next connection in the set.
-
- @param grp The transport group
- @param msg The message to send
- @return 0 on normal successful send.
- Returns -1 if the message cannot be sent.
- */
-int osrfTransportGroupSend( osrfTransportGroup* grp, transport_message* msg );
-
-/**
- Sends the message to the exact recipient. No failover is attempted.
- @return 0 on success, -1 on error.
- */
-int osrfTransportGroupSendMatch( osrfTransportGroup* grp, transport_message* msg );
-
-
-int _osrfTGServerSend( osrfTransportGroup* grp, char* domain, transport_message* msg );
-int _osrfTGClientSend( osrfTransportGroup* grp, char* domain, transport_message* msg );
-
-/**
- Waits on all connections for inbound data.
- @param grp The transport group
- @param timeout How long to wait for data. 0 means check for data
- but don't wait, a negative number means to wait indefinitely
- @return The received message or NULL if the timeout occurred before a
- message was received
- */
-transport_message* osrfTransportGroupRecvAll( osrfTransportGroup* grp, int timeout );
-
-/**
- Waits for data from a single domain
- @param grp The transport group
- @param domain The domain to wait for data on
- @param timeout see osrfTransportGroupRecvAll
- */
-transport_message* osrfTransportGroupRecv( osrfTransportGroup* grp, char* domain, int timeout );
-
-/**
- Tells the group that a message to the given domain failed
- domain did not make it through;
- @param grp The transport group
- @param comain The failed domain
- */
-void osrfTransportGroupSetInactive( osrfTransportGroup* grp, char* domain );
-
-
-/**
- Finds a node in our list of nodes
- */
-osrfTransportGroupNode* __osrfTransportGroupFindNode( osrfTransportGroup* grp, char* domain );
-
-
+++ /dev/null
-
-TARGETS = transport_message.o transport_session.o transport_client.o
-HEADERS = transport_message.h transport_session.h transport_client.h
-
-TARGET = libopensrf_transport.so
-
-all: $(TARGETS) copy
-
-copy:
- cp $(HEADERS) $(TMPDIR)
-
-transport_session.o: transport_session.c transport_session.h
-transport_message.o: transport_message.c transport_message.h
-transport_client.o: transport_client.c transport_client.h
-
-
-clean:
- /bin/rm -f *.o
+++ /dev/null
-#include "transport_client.h"
-#include "signal.h"
-
-pid_t pid;
-void sig_int( int sig ) {
- fprintf(stderr, "Killing child %d\n", pid );
- kill( pid, SIGKILL );
-}
-
-/* connects and registers with the router */
-int main( int argc, char** argv ) {
-
- if( argc < 5 ) {
- osrfLogError( OSRF_LOG_MARK, "Usage: %s <username> <host> <resource> <recipient> \n", argv[0] );
- return 99;
- }
-
- transport_message* send;
- transport_client* client = client_init( argv[2], 5222, 0 );
-
- // try to connect, allow 15 second connect timeout
- if( client_connect( client, argv[1], "jkjkasdf", argv[3], 15, AUTH_DIGEST ) )
- osrfLogInfo(OSRF_LOG_MARK, "Connected...\n");
- else {
- osrfLogError( OSRF_LOG_MARK, "NOT Connected...\n" );
- return -1;
- }
-
- if( (pid=fork()) ) { /* parent */
-
- signal(SIGINT, sig_int);
- fprintf(stderr, "Listener: %ld\n", (long) getpid() );
- char buf[300];
- memset(buf, 0, 300);
- printf("=> ");
-
- while( fgets( buf, 299, stdin) ) {
-
- // remove newline
- buf[strlen(buf)-1] = '\0';
-
- if( strcmp(buf, "exit")==0) {
- client_free( client );
- break;
- }
-
- send = message_init( buf, "", "123454321", argv[4], NULL );
- client_send_message( client, send );
- message_free( send );
- printf("\n=> ");
- memset(buf, 0, 300);
- }
- fprintf(stderr, "Killing child %d\n", pid );
- kill( pid, SIGKILL );
- return 0;
-
- } else {
-
- fprintf(stderr, "Sender: %ld\n", (long) getpid() );
-
- transport_message* recv;
- while( (recv=client_recv( client, -1)) ) {
- if( recv->is_error )
- fprintf( stderr, "\nReceived Error\t: ------------------\nFrom:\t\t"
- "%s\nRouterFrom:\t%s\nBody:\t\t%s\nType %s\nCode %d\n=> ",
- recv->sender, recv->router_from, recv->body, recv->error_type, recv->error_code );
- else
- fprintf( stderr, "\nReceived\t: ------------------\nFrom:\t\t"
- "%s\nRouterFrom:\t%s\nBody:\t\t%s\n=> ", recv->sender, recv->router_from, recv->body );
-
- message_free( recv );
- }
-
- }
- return 0;
-
-}
-
-
-
-
+++ /dev/null
-#include "transport_client.h"
-#include "signal.h"
-
-
-/*
-void print_stuff(void* blah, char* data) {
- fprintf(stderr, "Received from socket: %s\n", data);
-}
-*/
-
-/* connects and registers with the router */
-int main( int argc, char** argv ) {
-
-
-
- if( argc < 5 ) {
- osrfLogError(OSRF_LOG_MARK, "Usage: %s <server> <port> <name> <secret>", argv[0] );
- return -1;
- }
-
- int port = atoi(argv[2]);
- transport_client* client = client_init( argv[1], port, 1 );
-
- // try to connect, allow 15 second connect timeout
- if( client_connect( client, argv[3], argv[4], "", 15, 1 ) )
- osrfLogInfo(OSRF_LOG_MARK, "Connected...\n");
- else {
- osrfLogError(OSRF_LOG_MARK, "NOT Connected...\n" );
- return -1;
- }
-
- transport_message* recv;
- while( (recv=client_recv( client, -1)) ) {
- if( recv->is_error )
- fprintf( stderr, "\nReceived Error\t: ------------------\nFrom:\t\t"
- "%s\nRouterFrom:\t%s\nBody:\t\t%s\nType %s\nCode %d\n=> ",
- recv->sender, recv->router_from, recv->body, recv->error_type, recv->error_code );
- else
- fprintf( stderr, "\nReceived\t: ------------------\nFrom:\t\t"
- "%s\nRouterFrom:\t%s\nBody:\t\t%s\n=> ", recv->sender, recv->router_from, recv->body );
- transport_message* send = message_init( "Hello...", "", "123454321", recv->sender, argv[3] );
- client_send_message( client, send );
- message_free( recv );
- message_free( send );
- }
- return 0;
-
-}
-
-
-
-
+++ /dev/null
-#include "transport_client.h"
-
-
-//int main( int argc, char** argv );
-
-/*
-int main( int argc, char** argv ) {
-
- transport_message* recv;
- transport_message* send;
-
- transport_client* client = client_init( "spacely.georgialibraries.org", 5222 );
-
- // try to connect, allow 15 second connect timeout
- if( client_connect( client, "admin", "asdfjkjk", "system", 15 ) ) {
- printf("Connected...\n");
- } else {
- printf( "NOT Connected...\n" ); exit(99);
- }
-
- while( (recv = client_recv( client, -1 )) ) {
-
- if( recv->body ) {
- int len = strlen(recv->body);
- char buf[len + 20];
- memset( buf, 0, len + 20);
- sprintf( buf, "Echoing...%s", recv->body );
- send = message_init( buf, "Echoing Stuff", "12345", recv->sender, "" );
- } else {
- send = message_init( " * ECHOING * ", "Echoing Stuff", "12345", recv->sender, "" );
- }
-
- if( send == NULL ) { printf("something's wrong"); }
- client_send_message( client, send );
-
- message_free( send );
- message_free( recv );
- }
-
- printf( "ended recv loop\n" );
-
- return 0;
-
-}
-*/
-
-
-transport_client* client_init( const char* server, int port, const char* unix_path, int component ) {
-
- if(server == NULL) return NULL;
-
- /* build and clear the client object */
- size_t c_size = sizeof( transport_client);
- transport_client* client = safe_malloc( c_size );
-
- /* build and clear the message list */
- size_t l_size = sizeof( transport_message_list );
- client->m_list = safe_malloc( l_size );
-
- client->m_list->next = NULL;
- client->m_list->message = NULL;
- client->m_list->type = MESSAGE_LIST_HEAD;
-
- /* build the session */
-
- client->session = init_transport( server, port, unix_path, client, component );
-
- client->session->message_callback = client_message_handler;
- client->error = 0;
-
- return client;
-}
-
-
-int client_connect( transport_client* client,
- char* username, char* password, char* resource,
- int connect_timeout, enum TRANSPORT_AUTH_TYPE auth_type ) {
- if(client == NULL) return 0;
- return session_connect( client->session, username,
- password, resource, connect_timeout, auth_type );
-}
-
-
-int client_disconnect( transport_client* client ) {
- if( client == NULL ) { return 0; }
- return session_disconnect( client->session );
-}
-
-int client_connected( transport_client* client ) {
- if(client == NULL) return 0;
- return client->session->state_machine->connected;
-}
-
-int client_send_message( transport_client* client, transport_message* msg ) {
- if(client == NULL) return 0;
- if( client->error ) return -1;
- return session_send_msg( client->session, msg );
-}
-
-
-transport_message* client_recv( transport_client* client, int timeout ) {
- if( client == NULL ) { return NULL; }
-
- transport_message_node* node;
- transport_message* msg;
-
-
- /* see if there are any message in the messages queue */
- if( client->m_list->next != NULL ) {
- /* pop off the first one... */
- node = client->m_list->next;
- client->m_list->next = node->next;
- msg = node->message;
- free( node );
- return msg;
- }
-
- if( timeout == -1 ) { /* wait potentially forever for data to arrive */
-
- while( client->m_list->next == NULL ) {
- // if( ! session_wait( client->session, -1 ) ) {
- int x;
- if( (x = session_wait( client->session, -1 )) ) {
- osrfLogDebug(OSRF_LOG_MARK, "session_wait returned failure code %d\n", x);
- client->error = 1;
- return NULL;
- }
- }
-
- } else { /* wait at most timeout seconds */
-
-
- /* if not, loop up to 'timeout' seconds waiting for data to arrive */
- time_t start = time(NULL);
- time_t remaining = (time_t) timeout;
-
- int counter = 0;
-
- int wait_ret;
- while( client->m_list->next == NULL && remaining >= 0 ) {
-
- if( (wait_ret= session_wait( client->session, remaining)) ) {
- client->error = 1;
- osrfLogDebug(OSRF_LOG_MARK, "session_wait returned failure code %d: setting error=1\n", wait_ret);
- return NULL;
- }
-
- ++counter;
-
-#ifdef _ROUTER
- // session_wait returns -1 if there is no more data and we're a router
- if( remaining == 0 ) { // && wait_ret == -1 ) {
- break;
- }
-#else
- if( remaining == 0 ) // or infinite loop
- break;
-#endif
-
- remaining -= (int) (time(NULL) - start);
- }
-
- }
-
- /* again, see if there are any messages in the message queue */
- if( client->m_list->next != NULL ) {
- /* pop off the first one... */
- node = client->m_list->next;
- client->m_list->next = node->next;
- msg = node->message;
- free( node );
- return msg;
-
- } else {
- return NULL;
- }
-}
-
-/* throw the message into the message queue */
-void client_message_handler( void* client, transport_message* msg ){
-
- if(client == NULL) return;
- if(msg == NULL) return;
-
- transport_client* cli = (transport_client*) client;
-
- size_t len = sizeof(transport_message_node);
- transport_message_node* node =
- (transport_message_node*) safe_malloc(len);
- node->type = MESSAGE_LIST_ITEM;
- node->message = msg;
-
-
- /* find the last node and put this onto the end */
- transport_message_node* tail = cli->m_list;
- transport_message_node* current = tail->next;
-
- while( current != NULL ) {
- tail = current;
- current = current->next;
- }
- tail->next = node;
-}
-
-
-int client_free( transport_client* client ){
- if(client == NULL) return 0;
-
- session_free( client->session );
- transport_message_node* current = client->m_list->next;
- transport_message_node* next;
-
- /* deallocate the list of messages */
- while( current != NULL ) {
- next = current->next;
- message_free( current->message );
- free(current);
- current = next;
- }
-
- free( client->m_list );
- free( client );
- return 1;
-}
-
+++ /dev/null
-#include "transport_session.h"
-#include "opensrf/utils.h"
-#include "opensrf/log.h"
-
-#include <time.h>
-
-#ifndef TRANSPORT_CLIENT_H
-#define TRANSPORT_CLIENT_H
-
-#define MESSAGE_LIST_HEAD 1
-#define MESSAGE_LIST_ITEM 2
-
-
-// ---------------------------------------------------------------------------
-// Represents a node in a linked list. The node holds a pointer to the next
-// node (which is null unless set), a pointer to a transport_message, and
-// and a type variable (which is not really curently necessary).
-// ---------------------------------------------------------------------------
-struct message_list_struct {
- struct message_list_struct* next;
- transport_message* message;
- int type;
-};
-
-typedef struct message_list_struct transport_message_list;
-typedef struct message_list_struct transport_message_node;
-
-// ---------------------------------------------------------------------------
-// Our client struct. We manage a list of messages and a controlling session
-// ---------------------------------------------------------------------------
-struct transport_client_struct {
- transport_message_list* m_list;
- transport_session* session;
- int error;
-};
-typedef struct transport_client_struct transport_client;
-
-// ---------------------------------------------------------------------------
-// Allocates and initializes and transport_client. This does no connecting
-// The user must call client_free(client) when finished with the allocated
-// object.
-// if port > 0 => connect via TCP
-// else if unix_path != NULL => connect via UNIX socket
-// ---------------------------------------------------------------------------
-transport_client* client_init( const char* server, int port, const char* unix_path, int component );
-
-
-// ---------------------------------------------------------------------------
-// Connects to the Jabber server with the provided information. Returns 1 on
-// success, 0 otherwise.
-// ---------------------------------------------------------------------------
-int client_connect( transport_client* client,
- char* username, char* password, char* resource,
- int connect_timeout, enum TRANSPORT_AUTH_TYPE auth_type );
-
-
-int client_disconnect( transport_client* client );
-
-// ---------------------------------------------------------------------------
-// De-allocates memory associated with a transport_client object. Users
-// must use this method when finished with a client object.
-// ---------------------------------------------------------------------------
-int client_free( transport_client* client );
-
-// ---------------------------------------------------------------------------
-// Sends the given message. The message must at least have the recipient
-// field set.
-// ---------------------------------------------------------------------------
-int client_send_message( transport_client* client, transport_message* msg );
-
-// ---------------------------------------------------------------------------
-// Returns 1 if this client is currently connected to the server, 0 otherwise
-// ---------------------------------------------------------------------------
-int client_connected( transport_client* client );
-
-// ---------------------------------------------------------------------------
-// This is the message handler required by transport_session. This handler
-// takes all incoming messages and puts them into the back of a linked list
-// of messages.
-// ---------------------------------------------------------------------------
-void client_message_handler( void* client, transport_message* msg );
-
-// ---------------------------------------------------------------------------
-// If there are any message in the message list, the 'oldest' message is
-// returned. If not, this function will wait at most 'timeout' seconds
-// for a message to arrive. Specifying -1 means that this function will not
-// return unless a message arrives.
-// ---------------------------------------------------------------------------
-transport_message* client_recv( transport_client* client, int timeout );
-
-
-#endif
+++ /dev/null
-#include "transport_message.h"
-
-
-// ---------------------------------------------------------------------------------
-// Allocates and initializes a new transport_message
-// ---------------------------------------------------------------------------------
-transport_message* message_init( char* body,
- char* subject, char* thread, char* recipient, char* sender ) {
-
- transport_message* msg =
- (transport_message*) safe_malloc( sizeof(transport_message) );
-
- if( body == NULL ) { body = ""; }
- if( thread == NULL ) { thread = ""; }
- if( subject == NULL ) { subject = ""; }
- if( sender == NULL ) { sender = ""; }
- if( recipient == NULL ) { recipient = ""; }
-
- msg->body = strdup(body);
- msg->thread = strdup(thread);
- msg->subject = strdup(subject);
- msg->recipient = strdup(recipient);
- msg->sender = strdup(sender);
-
- if( msg->body == NULL || msg->thread == NULL ||
- msg->subject == NULL || msg->recipient == NULL ||
- msg->sender == NULL ) {
-
- osrfLogError(OSRF_LOG_MARK, "message_init(): Out of Memory" );
- return NULL;
- }
-
- return msg;
-}
-
-
-transport_message* new_message_from_xml( const char* msg_xml ) {
-
- if( msg_xml == NULL || strlen(msg_xml) < 1 )
- return NULL;
-
- transport_message* new_msg =
- (transport_message*) safe_malloc( sizeof(transport_message) );
-
- xmlKeepBlanksDefault(0);
- xmlDocPtr msg_doc = xmlReadDoc( BAD_CAST msg_xml, NULL, NULL, 0 );
- xmlNodePtr root = xmlDocGetRootElement(msg_doc);
-
- xmlChar* sender = xmlGetProp(root, BAD_CAST "from");
- xmlChar* recipient = xmlGetProp(root, BAD_CAST "to");
- xmlChar* subject = xmlGetProp(root, BAD_CAST "subject");
- xmlChar* thread = xmlGetProp( root, BAD_CAST "thread" );
- xmlChar* router_from = xmlGetProp( root, BAD_CAST "router_from" );
- xmlChar* router_to = xmlGetProp( root, BAD_CAST "router_to" );
- xmlChar* router_class= xmlGetProp( root, BAD_CAST "router_class" );
- xmlChar* broadcast = xmlGetProp( root, BAD_CAST "broadcast" );
- xmlChar* osrf_xid = xmlGetProp( root, BAD_CAST "osrf_xid" );
-
- if( osrf_xid ) {
- message_set_osrf_xid( new_msg, (char*) osrf_xid);
- xmlFree(osrf_xid);
- }
-
- if( router_from ) {
- new_msg->sender = strdup((char*)router_from);
- } else {
- if( sender ) {
- new_msg->sender = strdup((char*)sender);
- xmlFree(sender);
- }
- }
-
- if( recipient ) {
- new_msg->recipient = strdup((char*)recipient);
- xmlFree(recipient);
- }
- if(subject){
- new_msg->subject = strdup((char*)subject);
- xmlFree(subject);
- }
- if(thread) {
- new_msg->thread = strdup((char*)thread);
- xmlFree(thread);
- }
- if(router_from) {
- new_msg->router_from = strdup((char*)router_from);
- xmlFree(router_from);
- }
- if(router_to) {
- new_msg->router_to = strdup((char*)router_to);
- xmlFree(router_to);
- }
- if(router_class) {
- new_msg->router_class = strdup((char*)router_class);
- xmlFree(router_class);
- }
- if(broadcast) {
- if(strcmp(broadcast,"0") )
- new_msg->broadcast = 1;
- xmlFree(broadcast);
- }
-
- xmlNodePtr search_node = root->children;
- while( search_node != NULL ) {
-
- if( ! strcmp( (char*) search_node->name, "thread" ) ) {
- if( search_node->children && search_node->children->content )
- new_msg->thread = strdup( (char*) search_node->children->content );
- }
-
- if( ! strcmp( (char*) search_node->name, "subject" ) ) {
- if( search_node->children && search_node->children->content )
- new_msg->subject = strdup( (char*) search_node->children->content );
- }
-
- if( ! strcmp( (char*) search_node->name, "body" ) ) {
- if( search_node->children && search_node->children->content )
- new_msg->body = strdup((char*) search_node->children->content );
- }
-
- search_node = search_node->next;
- }
-
- if( new_msg->thread == NULL )
- new_msg->thread = strdup("");
- if( new_msg->subject == NULL )
- new_msg->subject = strdup("");
- if( new_msg->body == NULL )
- new_msg->body = strdup("");
-
- new_msg->msg_xml = xmlDocToString(msg_doc, 0);
- xmlFreeDoc(msg_doc);
- xmlCleanupParser();
-
- return new_msg;
-}
-
-void message_set_osrf_xid( transport_message* msg, char* osrf_xid ) {
- if(!msg) return;
- if( osrf_xid )
- msg->osrf_xid = strdup(osrf_xid);
- else msg->osrf_xid = strdup("");
-}
-
-void message_set_router_info( transport_message* msg, char* router_from,
- char* router_to, char* router_class, char* router_command, int broadcast_enabled ) {
-
- if(router_from)
- msg->router_from = strdup(router_from);
- else
- msg->router_from = strdup("");
-
- if(router_to)
- msg->router_to = strdup(router_to);
- else
- msg->router_to = strdup("");
-
- if(router_class)
- msg->router_class = strdup(router_class);
- else
- msg->router_class = strdup("");
-
- if(router_command)
- msg->router_command = strdup(router_command);
- else
- msg->router_command = strdup("");
-
- msg->broadcast = broadcast_enabled;
-
- if( msg->router_from == NULL || msg->router_to == NULL ||
- msg->router_class == NULL || msg->router_command == NULL )
- osrfLogError(OSRF_LOG_MARK, "message_set_router_info(): Out of Memory" );
-
- return;
-}
-
-
-
-/* encodes the message for traversal */
-int message_prepare_xml( transport_message* msg ) {
- if( msg->msg_xml != NULL ) { return 1; }
- msg->msg_xml = message_to_xml( msg );
- return 1;
-}
-
-
-// ---------------------------------------------------------------------------------
-//
-// ---------------------------------------------------------------------------------
-int message_free( transport_message* msg ){
- if( msg == NULL ) { return 0; }
-
- free(msg->body);
- free(msg->thread);
- free(msg->subject);
- free(msg->recipient);
- free(msg->sender);
- free(msg->router_from);
- free(msg->router_to);
- free(msg->router_class);
- free(msg->router_command);
- free(msg->osrf_xid);
- if( msg->error_type != NULL ) free(msg->error_type);
- if( msg->msg_xml != NULL ) free(msg->msg_xml);
- free(msg);
- return 1;
-}
-
-// ---------------------------------------------------------------------------------
-// Allocates a char* holding the XML representation of this jabber message
-// ---------------------------------------------------------------------------------
-char* message_to_xml( const transport_message* msg ) {
-
- int bufsize;
- //xmlChar* xmlbuf;
- char* encoded_body;
-
- xmlNodePtr message_node;
- xmlNodePtr body_node;
- xmlNodePtr thread_node;
- xmlNodePtr subject_node;
- xmlNodePtr error_node;
-
- xmlDocPtr doc;
-
- xmlKeepBlanksDefault(0);
-
- if( ! msg ) {
- osrfLogWarning(OSRF_LOG_MARK, "Passing NULL message to message_to_xml()");
- return 0;
- }
-
- doc = xmlReadDoc( BAD_CAST "<message/>", NULL, NULL, XML_PARSE_NSCLEAN );
- message_node = xmlDocGetRootElement(doc);
-
- if( msg->is_error ) {
- error_node = xmlNewChild(message_node, NULL, BAD_CAST "error" , NULL );
- xmlAddChild( message_node, error_node );
- xmlNewProp( error_node, BAD_CAST "type", BAD_CAST msg->error_type );
- char code_buf[16];
- memset( code_buf, 0, 16);
- sprintf(code_buf, "%d", msg->error_code );
- xmlNewProp( error_node, BAD_CAST "code", BAD_CAST code_buf );
- }
-
- /* set from and to */
- xmlNewProp( message_node, BAD_CAST "to", BAD_CAST msg->recipient );
- xmlNewProp( message_node, BAD_CAST "from", BAD_CAST msg->sender );
- xmlNewProp( message_node, BAD_CAST "router_from", BAD_CAST msg->router_from );
- xmlNewProp( message_node, BAD_CAST "router_to", BAD_CAST msg->router_to );
- xmlNewProp( message_node, BAD_CAST "router_class", BAD_CAST msg->router_class );
- xmlNewProp( message_node, BAD_CAST "router_command", BAD_CAST msg->router_command );
- xmlNewProp( message_node, BAD_CAST "osrf_xid", BAD_CAST msg->osrf_xid );
-
- if( msg->broadcast )
- xmlNewProp( message_node, BAD_CAST "broadcast", BAD_CAST "1" );
-
- /* Now add nodes where appropriate */
- char* body = msg->body;
- char* subject = msg->subject;
- char* thread = msg->thread;
-
- if( thread && strlen(thread) > 0 ) {
- thread_node = xmlNewChild(message_node, NULL, (xmlChar*) "thread", NULL );
- xmlNodePtr txt = xmlNewText((xmlChar*) thread);
- xmlAddChild(thread_node, txt);
- xmlAddChild(message_node, thread_node);
- }
-
- if( subject && strlen(subject) > 0 ) {
- subject_node = xmlNewChild(message_node, NULL, (xmlChar*) "subject", NULL );
- xmlNodePtr txt = xmlNewText((xmlChar*) subject);
- xmlAddChild(subject_node, txt);
- xmlAddChild( message_node, subject_node );
- }
-
- if( body && strlen(body) > 0 ) {
- body_node = xmlNewChild(message_node, NULL, (xmlChar*) "body", NULL);
- xmlNodePtr txt = xmlNewText((xmlChar*) body);
- xmlAddChild(body_node, txt);
- xmlAddChild( message_node, body_node );
- }
-
- xmlBufferPtr xmlbuf = xmlBufferCreate();
- xmlNodeDump( xmlbuf, doc, xmlDocGetRootElement(doc), 0, 0);
- char* xml = strdup((char*) (xmlBufferContent(xmlbuf)));
- xmlBufferFree(xmlbuf);
- xmlFreeDoc( doc );
- xmlCleanupParser();
- return xml;
-}
-
-
-
-void jid_get_username( const char* jid, char buf[], int size ) {
-
- if( jid == NULL ) { return; }
-
- /* find the @ and return whatever is in front of it */
- int len = strlen( jid );
- int i;
- for( i = 0; i != len; i++ ) {
- if( jid[i] == 64 ) { /*ascii @*/
- if(i > size) i = size;
- strncpy( buf, jid, i );
- return;
- }
- }
-}
-
-
-void jid_get_resource( const char* jid, char buf[], int size) {
- if( jid == NULL ) { return; }
- int len = strlen( jid );
- int i;
- for( i = 0; i!= len; i++ ) {
- if( jid[i] == 47 ) { /* ascii / */
- const char* start = jid + i + 1; /* right after the '/' */
- int rlen = len - (i+1);
- if(rlen > size) rlen = size;
- strncpy( buf, start, rlen );
- }
- }
-}
-
-void jid_get_domain( const char* jid, char buf[], int size ) {
-
- if(jid == NULL) return;
-
- int len = strlen(jid);
- int i;
- int index1 = 0;
- int index2 = 0;
-
- for( i = 0; i!= len; i++ ) {
- if(jid[i] == 64) /* ascii @ */
- index1 = i + 1;
- else if(jid[i] == 47 && index1 != 0) /* ascii / */
- index2 = i;
- }
-
- if( index1 > 0 && index2 > 0 && index2 > index1 ) {
- int dlen = index2 - index1;
- if(dlen > size) dlen = size;
- memcpy( buf, jid + index1, dlen );
- }
-}
-
-void set_msg_error( transport_message* msg, char* type, int err_code ) {
-
- if( type != NULL && strlen( type ) > 0 ) {
- msg->error_type = safe_malloc( strlen(type)+1);
- strcpy( msg->error_type, type );
- msg->error_code = err_code;
- }
- msg->is_error = 1;
-}
+++ /dev/null
-#include <string.h>
-#include <libxml/globals.h>
-#include <libxml/xmlerror.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/debugXML.h>
-#include <libxml/xmlmemory.h>
-
-#include "opensrf/utils.h"
-#include "opensrf/xml_utils.h"
-#include "opensrf/log.h"
-
-#ifndef TRANSPORT_MESSAGE_H
-#define TRANSPORT_MESSAGE_H
-
-
-
-// ---------------------------------------------------------------------------------
-// Jabber message object.
-// ---------------------------------------------------------------------------------
-struct transport_message_struct {
- char* body;
- char* subject;
- char* thread;
- char* recipient;
- char* sender;
- char* router_from;
- char* router_to;
- char* router_class;
- char* router_command;
- char* osrf_xid;
- int is_error;
- char* error_type;
- int error_code;
- int broadcast;
- char* msg_xml; /* the entire message as XML complete with entity encoding */
-};
-typedef struct transport_message_struct transport_message;
-
-// ---------------------------------------------------------------------------------
-// Allocates and returns a transport_message. All chars are safely re-allocated
-// within this method.
-// Returns NULL on error
-// ---------------------------------------------------------------------------------
-transport_message* message_init( char* body, char* subject,
- char* thread, char* recipient, char* sender );
-
-transport_message* new_message_from_xml( const char* msg_xml );
-
-
-void message_set_router_info( transport_message* msg, char* router_from,
- char* router_to, char* router_class, char* router_command, int broadcast_enabled );
-
-void message_set_osrf_xid( transport_message* msg, char* osrf_xid );
-
-// ---------------------------------------------------------------------------------
-// Formats the Jabber message as XML for encoding.
-// Returns NULL on error
-// ---------------------------------------------------------------------------------
-char* message_to_xml( const transport_message* msg );
-
-
-// ---------------------------------------------------------------------------------
-// Call this to create the encoded XML for sending on the wire.
-// This is a seperate function so that encoding will not necessarily have
-// to happen on all messages (i.e. typically only occurs outbound messages).
-// ---------------------------------------------------------------------------------
-int message_prepare_xml( transport_message* msg );
-
-// ---------------------------------------------------------------------------------
-// Deallocates the memory used by the transport_message
-// Returns 0 on error
-// ---------------------------------------------------------------------------------
-int message_free( transport_message* msg );
-
-// ---------------------------------------------------------------------------------
-// Prepares the shared XML document
-// ---------------------------------------------------------------------------------
-//int message_init_xml();
-
-// ---------------------------------------------------------------------------------
-// Determines the username of a Jabber ID. This expects a pre-allocated char
-// array for the return value.
-// ---------------------------------------------------------------------------------
-void jid_get_username( const char* jid, char buf[], int size );
-
-// ---------------------------------------------------------------------------------
-// Determines the resource of a Jabber ID. This expects a pre-allocated char
-// array for the return value.
-// ---------------------------------------------------------------------------------
-void jid_get_resource( const char* jid, char buf[], int size );
-
-/** Puts the domain portion of the given jid into the pre-allocated buffer */
-void jid_get_domain( const char* jid, char buf[], int size );
-
-void set_msg_error( transport_message*, char* error_type, int error_code);
-
-
-#endif
+++ /dev/null
-#include "transport_session.h"
-
-
-
-// ---------------------------------------------------------------------------------
-// returns a built and allocated transport_session object.
-// This codes does no network activity, only memory initilization
-// ---------------------------------------------------------------------------------
-transport_session* init_transport( const char* server,
- int port, const char* unix_path, void* user_data, int component ) {
-
- /* create the session struct */
- transport_session* session =
- (transport_session*) safe_malloc( sizeof(transport_session) );
-
- session->user_data = user_data;
-
- session->component = component;
-
- /* initialize the data buffers */
- session->body_buffer = buffer_init( JABBER_BODY_BUFSIZE );
- session->subject_buffer = buffer_init( JABBER_SUBJECT_BUFSIZE );
- session->thread_buffer = buffer_init( JABBER_THREAD_BUFSIZE );
- session->from_buffer = buffer_init( JABBER_JID_BUFSIZE );
- session->status_buffer = buffer_init( JABBER_STATUS_BUFSIZE );
- session->recipient_buffer = buffer_init( JABBER_JID_BUFSIZE );
- session->message_error_type = buffer_init( JABBER_JID_BUFSIZE );
- session->session_id = buffer_init( 64 );
-
- /* for OpenSRF extensions */
- session->router_to_buffer = buffer_init( JABBER_JID_BUFSIZE );
- session->router_from_buffer = buffer_init( JABBER_JID_BUFSIZE );
- session->osrf_xid_buffer = buffer_init( JABBER_JID_BUFSIZE );
- session->router_class_buffer = buffer_init( JABBER_JID_BUFSIZE );
- session->router_command_buffer = buffer_init( JABBER_JID_BUFSIZE );
-
-
- if( session->body_buffer == NULL || session->subject_buffer == NULL ||
- session->thread_buffer == NULL || session->from_buffer == NULL ||
- session->status_buffer == NULL || session->recipient_buffer == NULL ||
- session->router_to_buffer == NULL || session->router_from_buffer == NULL ||
- session->router_class_buffer == NULL || session->router_command_buffer == NULL ||
- session->session_id == NULL ) {
-
- osrfLogError(OSRF_LOG_MARK, "init_transport(): buffer_init returned NULL" );
- return 0;
- }
-
-
- /* initialize the jabber state machine */
- session->state_machine = (jabber_machine*) safe_malloc( sizeof(jabber_machine) );
-
- /* initialize the sax push parser */
- session->parser_ctxt = xmlCreatePushParserCtxt(SAXHandler, session, "", 0, NULL);
-
- /* initialize the transport_socket structure */
- session->sock_mgr = (socket_manager*) safe_malloc( sizeof(socket_manager) );
-
- session->sock_mgr->data_received = &grab_incoming;
- session->sock_mgr->blob = session;
-
- session->port = port;
- session->server = strdup(server);
- if(unix_path)
- session->unix_path = strdup(unix_path);
- else session->unix_path = NULL;
-
- session->sock_id = 0;
-
- return session;
-}
-
-
-
-/* XXX FREE THE BUFFERS */
-int session_free( transport_session* session ) {
- if( ! session ) { return 0; }
-
- if(session->sock_mgr)
- socket_manager_free(session->sock_mgr);
-
- if( session->state_machine ) free( session->state_machine );
- if( session->parser_ctxt) {
- xmlFreeDoc( session->parser_ctxt->myDoc );
- xmlFreeParserCtxt(session->parser_ctxt);
- }
-
- xmlCleanupCharEncodingHandlers();
- xmlDictCleanup();
- xmlCleanupParser();
-
- buffer_free(session->body_buffer);
- buffer_free(session->subject_buffer);
- buffer_free(session->thread_buffer);
- buffer_free(session->from_buffer);
- buffer_free(session->recipient_buffer);
- buffer_free(session->status_buffer);
- buffer_free(session->message_error_type);
- buffer_free(session->router_to_buffer);
- buffer_free(session->router_from_buffer);
- buffer_free(session->osrf_xid_buffer);
- buffer_free(session->router_class_buffer);
- buffer_free(session->router_command_buffer);
- buffer_free(session->session_id);
-
- free(session->server);
- free(session->unix_path);
-
- free( session );
- return 1;
-}
-
-
-int session_wait( transport_session* session, int timeout ) {
- if( ! session || ! session->sock_mgr ) {
- return 0;
- }
-
- int ret = socket_wait( session->sock_mgr, timeout, session->sock_id );
-
- if( ret ) {
- osrfLogDebug(OSRF_LOG_MARK, "socket_wait returned error code %d", ret);
- session->state_machine->connected = 0;
- }
- return ret;
-}
-
-int session_send_msg(
- transport_session* session, transport_message* msg ) {
-
- if( ! session ) { return -1; }
-
- if( ! session->state_machine->connected ) {
- osrfLogWarning(OSRF_LOG_MARK, "State machine is not connected in send_msg()");
- return -1;
- }
-
- message_prepare_xml( msg );
- //tcp_send( session->sock_obj, msg->msg_xml );
- return socket_send( session->sock_id, msg->msg_xml );
-
-}
-
-
-/* connects to server and connects to jabber */
-int session_connect( transport_session* session,
- const char* username, const char* password,
- const char* resource, int connect_timeout, enum TRANSPORT_AUTH_TYPE auth_type ) {
-
- int size1 = 0;
- int size2 = 0;
-
- if( ! session ) {
- osrfLogWarning(OSRF_LOG_MARK, "session is null in connect" );
- return 0;
- }
-
-
- //char* server = session->sock_obj->server;
- char* server = session->server;
-
- if( ! session->sock_id ) {
-
- if(session->port > 0) {
- if( (session->sock_id = socket_open_tcp_client(
- session->sock_mgr, session->port, session->server)) <= 0 )
- return 0;
-
- } else if(session->unix_path != NULL) {
- if( (session->sock_id = socket_open_unix_client(
- session->sock_mgr, session->unix_path)) <= 0 )
- return 0;
- }
- else {
- osrfLogWarning( OSRF_LOG_MARK, "Can't open session: no port or unix path" );
- return 0;
- }
- }
-
- if( session->component ) {
-
- /* the first Jabber connect stanza */
- char* our_hostname = getenv("HOSTNAME");
- size1 = 150 + strlen( server );
- char stanza1[ size1 ];
- memset( stanza1, 0, size1 );
- sprintf( stanza1,
- "<stream:stream version='1.0' xmlns:stream='http://etherx.jabber.org/streams' "
- "xmlns='jabber:component:accept' to='%s' from='%s' xml:lang='en'>",
- username, our_hostname );
-
- /* send the first stanze */
- session->state_machine->connecting = CONNECTING_1;
-
-// if( ! tcp_send( session->sock_obj, stanza1 ) ) {
- if( socket_send( session->sock_id, stanza1 ) ) {
- osrfLogWarning(OSRF_LOG_MARK, "error sending");
- return 0;
- }
-
- /* wait for reply */
- //tcp_wait( session->sock_obj, connect_timeout ); /* make the timeout smarter XXX */
- socket_wait(session->sock_mgr, connect_timeout, session->sock_id);
-
- /* server acknowledges our existence, now see if we can login */
- if( session->state_machine->connecting == CONNECTING_2 ) {
-
- int ss = session->session_id->n_used + strlen(password) + 5;
- char hashstuff[ss];
- memset(hashstuff,0,ss);
- sprintf( hashstuff, "%s%s", session->session_id->buf, password );
-
- char* hash = shahash( hashstuff );
- size2 = 100 + strlen( hash );
- char stanza2[ size2 ];
- memset( stanza2, 0, size2 );
- sprintf( stanza2, "<handshake>%s</handshake>", hash );
-
- //if( ! tcp_send( session->sock_obj, stanza2 ) ) {
- if( socket_send( session->sock_id, stanza2 ) ) {
- osrfLogWarning(OSRF_LOG_MARK, "error sending");
- return 0;
- }
- }
-
- } else { /* we're not a component */
-
- /* the first Jabber connect stanza */
- size1 = 100 + strlen( server );
- char stanza1[ size1 ];
- memset( stanza1, 0, size1 );
- sprintf( stanza1,
- "<stream:stream to='%s' xmlns='jabber:client' "
- "xmlns:stream='http://etherx.jabber.org/streams'>",
- server );
-
-
- /* send the first stanze */
- session->state_machine->connecting = CONNECTING_1;
- //if( ! tcp_send( session->sock_obj, stanza1 ) ) {
- if( socket_send( session->sock_id, stanza1 ) ) {
- osrfLogWarning(OSRF_LOG_MARK, "error sending");
- return 0;
- }
-
-
- /* wait for reply */
- //tcp_wait( session->sock_obj, connect_timeout ); /* make the timeout smarter XXX */
- socket_wait( session->sock_mgr, connect_timeout, session->sock_id ); /* make the timeout smarter XXX */
-
- if( auth_type == AUTH_PLAIN ) {
-
- /* the second jabber connect stanza including login info*/
- size2 = 150 + strlen( username ) + strlen(password) + strlen(resource);
- char stanza2[ size2 ];
- memset( stanza2, 0, size2 );
-
- sprintf( stanza2,
- "<iq id='123456789' type='set'><query xmlns='jabber:iq:auth'>"
- "<username>%s</username><password>%s</password><resource>%s</resource></query></iq>",
- username, password, resource );
-
- /* server acknowledges our existence, now see if we can login */
- if( session->state_machine->connecting == CONNECTING_2 ) {
- //if( ! tcp_send( session->sock_obj, stanza2 ) ) {
- if( socket_send( session->sock_id, stanza2 ) ) {
- osrfLogWarning(OSRF_LOG_MARK, "error sending");
- return 0;
- }
- }
-
- } else if( auth_type == AUTH_DIGEST ) {
-
- int ss = session->session_id->n_used + strlen(password) + 5;
- char hashstuff[ss];
- memset(hashstuff,0,ss);
- sprintf( hashstuff, "%s%s", session->session_id->buf, password );
-
- char* hash = shahash( hashstuff );
-
- /* the second jabber connect stanza including login info*/
- size2 = 150 + strlen( hash ) + strlen(password) + strlen(resource);
- char stanza2[ size2 ];
- memset( stanza2, 0, size2 );
-
- sprintf( stanza2,
- "<iq id='123456789' type='set'><query xmlns='jabber:iq:auth'>"
- "<username>%s</username><digest>%s</digest><resource>%s</resource></query></iq>",
- username, hash, resource );
-
- /* server acknowledges our existence, now see if we can login */
- if( session->state_machine->connecting == CONNECTING_2 ) {
- //if( ! tcp_send( session->sock_obj, stanza2 ) ) {
- if( socket_send( session->sock_id, stanza2 ) ) {
- osrfLogWarning(OSRF_LOG_MARK, "error sending");
- return 0;
- }
- }
-
- }
-
- } // not component
-
-
- /* wait for reply */
- //tcp_wait( session->sock_obj, connect_timeout );
- socket_wait( session->sock_mgr, connect_timeout, session->sock_id );
-
- if( session->state_machine->connected ) {
- /* yar! */
- return 1;
- }
-
- return 0;
-}
-
-// ---------------------------------------------------------------------------------
-// TCP data callback. Shove the data into the push parser.
-// ---------------------------------------------------------------------------------
-//void grab_incoming( void * session, char* data ) {
-void grab_incoming(void* blob, socket_manager* mgr, int sockid, char* data, int parent) {
- transport_session* ses = (transport_session*) blob;
- if( ! ses ) { return; }
- xmlParseChunk(ses->parser_ctxt, data, strlen(data), 0);
-}
-
-
-void startElementHandler(
- void *session, const xmlChar *name, const xmlChar **atts) {
-
- transport_session* ses = (transport_session*) session;
- if( ! ses ) { return; }
-
-
- if( strcmp( name, "message" ) == 0 ) {
- ses->state_machine->in_message = 1;
- buffer_add( ses->from_buffer, get_xml_attr( atts, "from" ) );
- buffer_add( ses->recipient_buffer, get_xml_attr( atts, "to" ) );
- buffer_add( ses->router_from_buffer, get_xml_attr( atts, "router_from" ) );
- buffer_add( ses->osrf_xid_buffer, get_xml_attr( atts, "osrf_xid" ) );
- buffer_add( ses->router_to_buffer, get_xml_attr( atts, "router_to" ) );
- buffer_add( ses->router_class_buffer, get_xml_attr( atts, "router_class" ) );
- buffer_add( ses->router_command_buffer, get_xml_attr( atts, "router_command" ) );
- char* broadcast = get_xml_attr( atts, "broadcast" );
- if( broadcast )
- ses->router_broadcast = atoi( broadcast );
-
- return;
- }
-
- if( ses->state_machine->in_message ) {
-
- if( strcmp( name, "body" ) == 0 ) {
- ses->state_machine->in_message_body = 1;
- return;
- }
-
- if( strcmp( name, "subject" ) == 0 ) {
- ses->state_machine->in_subject = 1;
- return;
- }
-
- if( strcmp( name, "thread" ) == 0 ) {
- ses->state_machine->in_thread = 1;
- return;
- }
-
- }
-
- if( strcmp( name, "presence" ) == 0 ) {
- ses->state_machine->in_presence = 1;
- buffer_add( ses->from_buffer, get_xml_attr( atts, "from" ) );
- buffer_add( ses->recipient_buffer, get_xml_attr( atts, "to" ) );
- return;
- }
-
- if( strcmp( name, "status" ) == 0 ) {
- ses->state_machine->in_status = 1;
- return;
- }
-
-
- if( strcmp( name, "stream:error" ) == 0 ) {
- ses->state_machine->in_error = 1;
- ses->state_machine->connected = 0;
- osrfLogWarning( OSRF_LOG_MARK, "Received <stream:error> message from Jabber server" );
- return;
- }
-
-
- /* first server response from a connect attempt */
- if( strcmp( name, "stream:stream" ) == 0 ) {
- if( ses->state_machine->connecting == CONNECTING_1 ) {
- ses->state_machine->connecting = CONNECTING_2;
- buffer_add( ses->session_id, get_xml_attr(atts, "id") );
- }
- }
-
- if( strcmp( name, "handshake" ) == 0 ) {
- ses->state_machine->connected = 1;
- ses->state_machine->connecting = 0;
- return;
- }
-
-
- if( strcmp( name, "error" ) == 0 ) {
- ses->state_machine->in_message_error = 1;
- buffer_add( ses->message_error_type, get_xml_attr( atts, "type" ) );
- ses->message_error_code = atoi( get_xml_attr( atts, "code" ) );
- osrfLogInfo( OSRF_LOG_MARK, "Received <error> message with type %s and code %s",
- get_xml_attr( atts, "type"), get_xml_attr( atts, "code") );
- return;
- }
-
- if( strcmp( name, "iq" ) == 0 ) {
- ses->state_machine->in_iq = 1;
-
- if( strcmp( get_xml_attr(atts, "type"), "result") == 0
- && ses->state_machine->connecting == CONNECTING_2 ) {
- ses->state_machine->connected = 1;
- ses->state_machine->connecting = 0;
- return;
- }
-
- if( strcmp( get_xml_attr(atts, "type"), "error") == 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "Error connecting to jabber" );
- return;
- }
- }
-}
-
-char* get_xml_attr( const xmlChar** atts, char* attr_name ) {
- int i;
- if (atts != NULL) {
- for(i = 0;(atts[i] != NULL);i++) {
- if( strcmp( atts[i++], attr_name ) == 0 ) {
- if( atts[i] != NULL ) {
- return (char*) atts[i];
- }
- }
- }
- }
- return NULL;
-}
-
-
-// ------------------------------------------------------------------
-// See which tags are ending
-// ------------------------------------------------------------------
-void endElementHandler( void *session, const xmlChar *name) {
- transport_session* ses = (transport_session*) session;
- if( ! ses ) { return; }
-
- if( strcmp( name, "message" ) == 0 ) {
-
-
- /* pass off the message info the callback */
- if( ses->message_callback ) {
-
- /* here it's ok to pass in the raw buffers because
- message_init allocates new space for the chars
- passed in */
- transport_message* msg = message_init(
- ses->body_buffer->buf,
- ses->subject_buffer->buf,
- ses->thread_buffer->buf,
- ses->recipient_buffer->buf,
- ses->from_buffer->buf );
-
- message_set_router_info( msg,
- ses->router_from_buffer->buf,
- ses->router_to_buffer->buf,
- ses->router_class_buffer->buf,
- ses->router_command_buffer->buf,
- ses->router_broadcast );
-
- message_set_osrf_xid( msg, ses->osrf_xid_buffer->buf );
-
- if( ses->message_error_type->n_used > 0 ) {
- set_msg_error( msg, ses->message_error_type->buf, ses->message_error_code );
- }
-
- if( msg == NULL ) { return; }
- ses->message_callback( ses->user_data, msg );
- }
-
- ses->state_machine->in_message = 0;
- reset_session_buffers( session );
- return;
- }
-
- if( strcmp( name, "body" ) == 0 ) {
- ses->state_machine->in_message_body = 0;
- return;
- }
-
- if( strcmp( name, "subject" ) == 0 ) {
- ses->state_machine->in_subject = 0;
- return;
- }
-
- if( strcmp( name, "thread" ) == 0 ) {
- ses->state_machine->in_thread = 0;
- return;
- }
-
- if( strcmp( name, "iq" ) == 0 ) {
- ses->state_machine->in_iq = 0;
- if( ses->message_error_code > 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "Error in IQ packet: code %d", ses->message_error_code );
- osrfLogWarning( OSRF_LOG_MARK, "Error 401 means not authorized" );
- }
- reset_session_buffers( session );
- return;
- }
-
- if( strcmp( name, "presence" ) == 0 ) {
- ses->state_machine->in_presence = 0;
- /*
- if( ses->presence_callback ) {
- // call the callback with the status, etc.
- }
- */
- reset_session_buffers( session );
- return;
- }
-
- if( strcmp( name, "status" ) == 0 ) {
- ses->state_machine->in_status = 0;
- return;
- }
-
- if( strcmp( name, "error" ) == 0 ) {
- ses->state_machine->in_message_error = 0;
- return;
- }
-
- if( strcmp( name, "error:error" ) == 0 ) {
- ses->state_machine->in_error = 0;
- return;
- }
-}
-
-int reset_session_buffers( transport_session* ses ) {
- buffer_reset( ses->body_buffer );
- buffer_reset( ses->subject_buffer );
- buffer_reset( ses->thread_buffer );
- buffer_reset( ses->from_buffer );
- buffer_reset( ses->recipient_buffer );
- buffer_reset( ses->router_from_buffer );
- buffer_reset( ses->osrf_xid_buffer );
- buffer_reset( ses->router_to_buffer );
- buffer_reset( ses->router_class_buffer );
- buffer_reset( ses->router_command_buffer );
- buffer_reset( ses->message_error_type );
- buffer_reset( ses->session_id );
-
- return 1;
-}
-
-// ------------------------------------------------------------------
-// takes data out of the body of the message and pushes it into
-// the appropriate buffer
-// ------------------------------------------------------------------
-void characterHandler(
- void *session, const xmlChar *ch, int len) {
-
- char data[len+1];
- memset( data, 0, len+1 );
- strncpy( data, (char*) ch, len );
- data[len] = 0;
-
- //printf( "Handling characters: %s\n", data );
- transport_session* ses = (transport_session*) session;
- if( ! ses ) { return; }
-
- /* set the various message parts */
- if( ses->state_machine->in_message ) {
-
- if( ses->state_machine->in_message_body ) {
- buffer_add( ses->body_buffer, data );
- }
-
- if( ses->state_machine->in_subject ) {
- buffer_add( ses->subject_buffer, data );
- }
-
- if( ses->state_machine->in_thread ) {
- buffer_add( ses->thread_buffer, data );
- }
- }
-
- /* set the presence status */
- if( ses->state_machine->in_presence && ses->state_machine->in_status ) {
- buffer_add( ses->status_buffer, data );
- }
-
- if( ses->state_machine->in_error ) {
- /* for now... */
- osrfLogWarning( OSRF_LOG_MARK, "ERROR Xml fragment: %s\n", ch );
- }
-
-}
-
-/* XXX change to warning handlers */
-void parseWarningHandler( void *session, const char* msg, ... ) {
-
- va_list args;
- va_start(args, msg);
- fprintf(stdout, "transport_session XML WARNING");
- vfprintf(stdout, msg, args);
- va_end(args);
- fprintf(stderr, "XML WARNING: %s\n", msg );
-}
-
-void parseErrorHandler( void *session, const char* msg, ... ){
-
- va_list args;
- va_start(args, msg);
- fprintf(stdout, "transport_session XML ERROR");
- vfprintf(stdout, msg, args);
- va_end(args);
- fprintf(stderr, "XML ERROR: %s\n", msg );
-
-}
-
-int session_disconnect( transport_session* session ) {
- if( session == NULL ) { return 0; }
- //tcp_send( session->sock_obj, "</stream:stream>");
- socket_send(session->sock_id, "</stream:stream>");
- socket_disconnect(session->sock_mgr, session->sock_id);
- return 0;
- //return tcp_disconnect( session->sock_obj );
-}
-
+++ /dev/null
-// ---------------------------------------------------------------------------------
-// Manages the Jabber session. Data is taken from the TCP object and pushed into
-// a SAX push parser as it arrives. When key Jabber documetn elements are met,
-// logic ensues.
-// ---------------------------------------------------------------------------------
-#include "transport_message.h"
-
-#include "opensrf/utils.h"
-#include "opensrf/log.h"
-#include "opensrf/socket_bundle.h"
-
-#include "sha.h"
-
-#include <string.h>
-#include <libxml/globals.h>
-#include <libxml/xmlerror.h>
-#include <libxml/parser.h>
-#include <libxml/parserInternals.h> /* only for xmlNewInputFromFile() */
-#include <libxml/tree.h>
-#include <libxml/debugXML.h>
-#include <libxml/xmlmemory.h>
-
-#ifndef TRANSPORT_SESSION_H
-#define TRANSPORT_SESSION_H
-
-#define CONNECTING_1 1 /* just starting the connection to Jabber */
-#define CONNECTING_2 2 /* First <stream> packet sent and <stream> packet received from server */
-
-/* Note. these are growing buffers, so all that's necessary is a sane starting point */
-#define JABBER_BODY_BUFSIZE 4096
-#define JABBER_SUBJECT_BUFSIZE 64
-#define JABBER_THREAD_BUFSIZE 64
-#define JABBER_JID_BUFSIZE 64
-#define JABBER_STATUS_BUFSIZE 16
-
-// ---------------------------------------------------------------------------------
-// Takes data from the socket handler and pushes it directly into the push parser
-// ---------------------------------------------------------------------------------
-//void grab_incoming( void * session, char* data );
-void grab_incoming(void* blob, socket_manager* mgr, int sockid, char* data, int parent);
-
-// ---------------------------------------------------------------------------------
-// Callback for handling the startElement event. Much of the jabber logic occurs
-// in this and the characterHandler callbacks.
-// Here we check for the various top level jabber elements: body, iq, etc.
-// ---------------------------------------------------------------------------------
-void startElementHandler(
- void *session, const xmlChar *name, const xmlChar **atts);
-
-// ---------------------------------------------------------------------------------
-// Callback for handling the endElement event. Updates the Jabber state machine
-// to let us know the element is over.
-// ---------------------------------------------------------------------------------
-void endElementHandler( void *session, const xmlChar *name);
-
-// ---------------------------------------------------------------------------------
-// This is where we extract XML text content. In particular, this is useful for
-// extracting Jabber message bodies.
-// ---------------------------------------------------------------------------------
-void characterHandler(
- void *session, const xmlChar *ch, int len);
-
-void parseWarningHandler( void *session, const char* msg, ... );
-void parseErrorHandler( void *session, const char* msg, ... );
-
-// ---------------------------------------------------------------------------------
-// Tells the SAX parser which functions will be used as event callbacks
-// ---------------------------------------------------------------------------------
-static xmlSAXHandler SAXHandlerStruct = {
- NULL, /* internalSubset */
- NULL, /* isStandalone */
- NULL, /* hasInternalSubset */
- NULL, /* hasExternalSubset */
- NULL, /* resolveEntity */
- NULL, /* getEntity */
- NULL, /* entityDecl */
- NULL, /* notationDecl */
- NULL, /* attributeDecl */
- NULL, /* elementDecl */
- NULL, /* unparsedEntityDecl */
- NULL, /* setDocumentLocator */
- NULL, /* startDocument */
- NULL, /* endDocument */
- startElementHandler, /* startElement */
- endElementHandler, /* endElement */
- NULL, /* reference */
- characterHandler, /* characters */
- NULL, /* ignorableWhitespace */
- NULL, /* processingInstruction */
- NULL, /* comment */
- parseWarningHandler, /* xmlParserWarning */
- parseErrorHandler, /* xmlParserError */
- NULL, /* xmlParserFatalError : unused */
- NULL, /* getParameterEntity */
- NULL, /* cdataBlock; */
- NULL, /* externalSubset; */
- 1,
- NULL,
- NULL, /* startElementNs */
- NULL, /* endElementNs */
- NULL /* xmlStructuredErrorFunc */
-};
-
-// ---------------------------------------------------------------------------------
-// Our SAX handler pointer.
-// ---------------------------------------------------------------------------------
-static const xmlSAXHandlerPtr SAXHandler = &SAXHandlerStruct;
-
-// ---------------------------------------------------------------------------------
-// Jabber state machine. This is how we know where we are in the Jabber
-// conversation.
-// ---------------------------------------------------------------------------------
-struct jabber_state_machine_struct {
- int connected;
- int connecting;
- int in_message;
- int in_message_body;
- int in_thread;
- int in_subject;
- int in_error;
- int in_message_error;
- int in_iq;
- int in_presence;
- int in_status;
-};
-typedef struct jabber_state_machine_struct jabber_machine;
-
-
-enum TRANSPORT_AUTH_TYPE { AUTH_PLAIN, AUTH_DIGEST };
-
-// ---------------------------------------------------------------------------------
-// Transport session. This maintains all the various parts of a session
-// ---------------------------------------------------------------------------------
-struct transport_session_struct {
-
- /* our socket connection */
- //transport_socket* sock_obj;
- socket_manager* sock_mgr;
-
- /* our Jabber state machine */
- jabber_machine* state_machine;
- /* our SAX push parser context */
- xmlParserCtxtPtr parser_ctxt;
-
- /* our text buffers for holding text data */
- growing_buffer* body_buffer;
- growing_buffer* subject_buffer;
- growing_buffer* thread_buffer;
- growing_buffer* from_buffer;
- growing_buffer* recipient_buffer;
- growing_buffer* status_buffer;
- growing_buffer* message_error_type;
- growing_buffer* session_id;
- int message_error_code;
-
- /* for OILS extenstions */
- growing_buffer* router_to_buffer;
- growing_buffer* router_from_buffer;
- growing_buffer* router_class_buffer;
- growing_buffer* router_command_buffer;
- growing_buffer* osrf_xid_buffer;
- int router_broadcast;
-
- /* this can be anything. It will show up in the
- callbacks for your convenience. Otherwise, it's
- left untouched. */
- void* user_data;
-
- char* server;
- char* unix_path;
- int port;
- int sock_id;
-
- int component; /* true if we're a component */
-
- /* the Jabber message callback */
- void (*message_callback) ( void* user_data, transport_message* msg );
- //void (iq_callback) ( void* user_data, transport_iq_message* iq );
-};
-typedef struct transport_session_struct transport_session;
-
-
-// ------------------------------------------------------------------
-// Allocates and initializes the necessary transport session
-// data structures.
-// If port > 0, then this session uses TCP connection. Otherwise,
-// if unix_path != NULL, it uses a UNIX domain socket.
-// ------------------------------------------------------------------
-transport_session* init_transport( const char* server, int port,
- const char* unix_path, void* user_data, int component );
-
-// ------------------------------------------------------------------
-// Returns the value of the given XML attribute
-// The xmlChar** construct is commonly returned from SAX event
-// handlers. Pass that in with the name of the attribute you want
-// to retrieve.
-// ------------------------------------------------------------------
-char* get_xml_attr( const xmlChar** atts, char* attr_name );
-
-// ------------------------------------------------------------------
-// Waits at most 'timeout' seconds for data to arrive from the
-// TCP handler. A timeout of -1 means to wait indefinitely.
-// ------------------------------------------------------------------
-int session_wait( transport_session* session, int timeout );
-
-// ---------------------------------------------------------------------------------
-// Sends the given Jabber message
-// ---------------------------------------------------------------------------------
-int session_send_msg( transport_session* session, transport_message* msg );
-
-// ---------------------------------------------------------------------------------
-// Returns 1 if this session is connected to the jabber server. 0 otherwise
-// ---------------------------------------------------------------------------------
-int session_connected( transport_session* );
-
-// ------------------------------------------------------------------
-// Deallocates session memory
-// ------------------------------------------------------------------
-int session_free( transport_session* session );
-
-// ------------------------------------------------------------------
-// Connects to the Jabber server. Waits at most connect_timeout
-// seconds before failing
-// ------------------------------------------------------------------
-int session_connect( transport_session* session,
- const char* username, const char* password,
- const char* resource, int connect_timeout,
- enum TRANSPORT_AUTH_TYPE auth_type );
-
-int session_disconnect( transport_session* session );
-
-int reset_session_buffers( transport_session* session );
-
-#endif
+++ /dev/null
-# --------------------------------------------------------------------
-# Copyright (C) 2005 Georgia Public Library Service
-# Bill Erickson <highfalutin@gmail.com>
-# Mike Rylander <mrylander@gmail.com>
-
-# 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; either version 2
-# of the License, or (at your option) any later version.
-
-# 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.
-# --------------------------------------------------------------------
-
-
-# --------------------------------------------------------------------
-#
-# -DSTRICT_JSON_WRITE if not defined, 'null' objects will be written
-# as empty strings. e.g. [null, null] => [,,]
-#
-# -DSTRICT_JSON_READ if not defiend, empty array and object values
-# (not keys) will be considered null.
-# e.g. [,,{"key":}] will be parsed as [null, null, {"key":null}]
-#
-# --------------------------------------------------------------------
-
-OBJS = md5.o utils.o json2xml.o object.o json_parser.o
-UTIL_DIR = ../utils
-DEST_INCLUDE = objson
-CFLAGS += -DSTRICT_JSON_WRITE #-DSTRICT_JSON_READ
-
-JSON_HEADERS = object.h json_parser.h json2xml.h
-
-all: test
-
-test: libobjson.so objson_test.o
-
-objson_test.o: objson_test.c
-object.o: object.h object.c
-json_parser.o: json_parser.h json_parser.c
-
-install:
- mkdir -p $(INCLUDEDIR)/$(DEST_INCLUDE)
- cp $(TMPDIR)/$(DEST_INCLUDE)/*.h $(INCLUDEDIR)/objson/
- cp $(TMPDIR)/libobjson.so $(LIBDIR)/libobjson.so
-
-libobjson.so: $(OBJS)
- $(CC) -shared -W1 $(OBJS) -o $(TMPDIR)/libobjson.so
- $(CC) -shared -W1 $(OBJS) -o libobjson.so
- mkdir -p $(TMPDIR)/$(DEST_INCLUDE)/
- cp $(JSON_HEADERS) $(TMPDIR)/$(DEST_INCLUDE)/
-
-utils.o: $(UTIL_DIR)/utils.h $(UTIL_DIR)/utils.c
- cp $(UTIL_DIR)/utils.h .
- cp $(UTIL_DIR)/utils.c .
- $(CC) -c $(CFLAGS) utils.c -o $@
-
-md5.o: $(UTIL_DIR)/md5.h $(UTIL_DIR)/md5.c
- cp $(UTIL_DIR)/md5.h .
- cp $(UTIL_DIR)/md5.c .
- $(CC) -c $(CFLAGS) md5.c -o $@
-
-json2xml.o: json2xml.h json2xml.c
- $(CC) -c $(CFLAGS) json2xml.c -o $@
-
-
-clean:
- /bin/rm -f *.o *.so utils.c utils.h libobjson.so
-
+++ /dev/null
-
-#include "json2xml.h"
-
-static char* _escape_xml (char*);
-static int _recurse_jsonObjectToXML(jsonObject*, growing_buffer*);
-
-char* jsonObjectToXML(jsonObject* obj) {
-
- growing_buffer * res_xml;
- char * output;
-
- res_xml = buffer_init(1024);
-
- if (!obj)
- return strdup("<null/>");
-
- _recurse_jsonObjectToXML( obj, res_xml );
- output = buffer_data(res_xml);
-
- buffer_free(res_xml);
-
- return output;
-
-}
-
-int _recurse_jsonObjectToXML(jsonObject* obj, growing_buffer* res_xml) {
-
- char * hint = NULL;
- char * bool_val = NULL;
- int i = 0;
-
- if (obj->classname)
- hint = strdup(obj->classname);
-
- if(obj->type == JSON_NULL) {
-
- if (hint)
- buffer_fadd(res_xml, "<null class_hint=\"%s\"/>",hint);
- else
- buffer_add(res_xml, "<null/>");
-
- } else if(obj->type == JSON_BOOL) {
-
- if (obj->value.b)
- bool_val = strdup("true");
- else
- bool_val = strdup("false");
-
- if (hint)
- buffer_fadd(res_xml, "<boolean value=\"%s\" class_hint=\"%s\"/>", bool_val, hint);
- else
- buffer_fadd(res_xml, "<boolean value=\"%s\"/>", bool_val);
-
- free(bool_val);
-
- } else if (obj->type == JSON_STRING) {
- if (hint) {
- char * t = _escape_xml(jsonObjectGetString(obj));
- buffer_fadd(res_xml,"<string class_hint=\"%s\">%s</string>", hint, t);
- free(t);
- } else {
- char * t = _escape_xml(jsonObjectGetString(obj));
- buffer_fadd(res_xml,"<string>%s</string>", t);
- free(t);
- }
-
- } else if(obj->type == JSON_NUMBER) {
- double x = jsonObjectGetNumber(obj);
- if (hint) {
- if (x == (int)x)
- buffer_fadd(res_xml,"<number class_hint=\"%s\">%d</number>", hint, (int)x);
- else
- buffer_fadd(res_xml,"<number class_hint=\"%s\">%f</number>", hint, x);
- } else {
- if (x == (int)x)
- buffer_fadd(res_xml,"<number>%d</number>", (int)x);
- else
- buffer_fadd(res_xml,"<number>%f</number>", x);
- }
-
- } else if (obj->type == JSON_ARRAY) {
-
- if (hint)
- buffer_fadd(res_xml,"<array class_hint=\"%s\">", hint);
- else
- buffer_add(res_xml,"<array>");
-
- for ( i = 0; i!= obj->size; i++ )
- _recurse_jsonObjectToXML(jsonObjectGetIndex(obj,i), res_xml);
-
- buffer_add(res_xml,"</array>");
-
- } else if (obj->type == JSON_HASH) {
-
- if (hint)
- buffer_fadd(res_xml,"<object class_hint=\"%s\">", hint);
- else
- buffer_add(res_xml,"<object>");
-
- jsonObjectIterator* itr = jsonNewObjectIterator(obj);
- jsonObjectNode* tmp;
- while( (tmp = jsonObjectIteratorNext(itr)) ) {
-
- buffer_fadd(res_xml,"<element key=\"%s\">",tmp->key);
-
- _recurse_jsonObjectToXML(tmp->item, res_xml);
-
- buffer_add(res_xml,"</element>");
- }
- jsonObjectIteratorFree(itr);
-
- buffer_add(res_xml,"</object>");
- }
-
- if (hint)
- free(hint);
-
- return 1;
-}
-
-char* _escape_xml (char* text) {
- char* out;
- growing_buffer* b = buffer_init(256);
- int len = strlen(text);
- int i;
- for (i = 0; i < len; i++) {
- if (text[i] == '&')
- buffer_add(b,"&");
- else if (text[i] == '<')
- buffer_add(b,"<");
- else if (text[i] == '>')
- buffer_add(b,">");
- else
- buffer_add_char(b,text[i]);
- }
- out = buffer_data(b);
- buffer_free(b);
- return out;
-}
-
-
+++ /dev/null
-
-#include <string.h>
-#include <stdio.h>
-
-/* the JSON parser, so we can read the response we're XMLizing */
-#include "object.h"
-#include "json_parser.h"
-#include "utils.h"
-
-char* jsonObjectToXML(jsonObject*);
-
+++ /dev/null
-/*
-Copyright (C) 2005 Georgia Public Library Service
-Bill Erickson <highfalutin@gmail.com>
-
-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; either version 2
-of the License, or (at your option) any later version.
-
-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.
-*/
-
-
-#include "json_parser.h"
-
-/* keep a copy of the length of the current json string so we don't
- * have to calculate it in each function
- */
-int current_strlen; /* XXX need to move this into the function params for thread support */
-
-
-jsonObject* jsonParseString( char* string) {
- return json_parse_string( string );
-}
-
-jsonObject* jsonParseStringFmt( char* string, ... ) {
- VA_LIST_TO_STRING(string);
- return json_parse_string( VA_BUF );
-}
-
-
-
-//jsonObject* (*jsonParseString) (char* str) = &_jsonParseString;
-
-jsonObject* json_parse_string(char* string) {
-
- if(string == NULL) return NULL;
-
- current_strlen = strlen(string);
-
- if(current_strlen == 0)
- return NULL;
-
- unsigned long index = 0;
-
- json_eat_ws(string, &index, 1, current_strlen); /* remove leading whitespace */
- if(index == current_strlen) return NULL;
-
- jsonObject* obj = jsonNewObject(NULL);
-
- int status = _json_parse_string(string, &index, obj, current_strlen);
- if(!status) return obj;
-
- if(status == -2) {
- jsonObjectFree(obj);
- return NULL;
- }
-
- return NULL;
-}
-
-
-int _json_parse_string(char* string, unsigned long* index, jsonObject* obj, int current_strlen) {
- if( !string || !index || *index >= current_strlen) return -2;
-
- int status = 0; /* return code from parsing routines */
- char* classname = NULL; /* object class hint */
- json_eat_ws(string, index, 1, current_strlen); /* remove leading whitespace */
-
- char c = string[*index];
-
- /* remove any leading comments */
- if( c == '/' ) {
-
- while(1) {
- (*index)++; /* move to second comment char */
- status = json_eat_comment(string, index, &classname, 1, current_strlen);
- if(status) return status;
-
- json_eat_ws(string, index, 1, current_strlen);
- c = string[*index];
- if(c != '/')
- break;
- }
- }
-
- json_eat_ws(string, index, 1, current_strlen); /* remove leading whitespace */
-
- if(*index >= current_strlen)
- return -2;
-
- switch(c) {
-
- /* json string */
- case '"':
- (*index)++;
- status = json_parse_json_string(string, index, obj, current_strlen); break;
-
- /* json array */
- case '[':
- (*index)++;
- status = json_parse_json_array(string, index, obj, current_strlen);
- break;
-
- /* json object */
- case '{':
- (*index)++;
- status = json_parse_json_object(string, index, obj, current_strlen);
- break;
-
- /* NULL */
- case 'n':
- case 'N':
- status = json_parse_json_null(string, index, obj, current_strlen);
- break;
-
-
- /* true, false */
- case 'f':
- case 'F':
- case 't':
- case 'T':
- status = json_parse_json_bool(string, index, obj, current_strlen);
- break;
-
- default:
- if(is_number(c) || c == '.' || c == '-') { /* are we a number? */
- status = json_parse_json_number(string, index, obj, current_strlen);
- if(status) return status;
- break;
- }
-
- (*index)--;
- /* we should never get here */
- return json_handle_error(string, index, "_json_parse_string() final switch clause");
- }
-
- if(status) return status;
-
- json_eat_ws(string, index, 1, current_strlen);
-
- if( *index < current_strlen ) {
- /* remove any trailing comments */
- c = string[*index];
- if( c == '/' ) {
- (*index)++;
- status = json_eat_comment(string, index, NULL, 0, current_strlen);
- if(status) return status;
- }
- }
-
- if(classname){
- jsonObjectSetClass(obj, classname);
- free(classname);
- }
-
- return 0;
-}
-
-
-int json_parse_json_null(char* string, unsigned long* index, jsonObject* obj, int current_strlen) {
-
- if(*index >= (current_strlen - 3)) {
- return json_handle_error(string, index,
- "_parse_json_null(): invalid null" );
- }
-
- if(!strncasecmp(string + (*index), "null", 4)) {
- (*index) += 4;
- obj->type = JSON_NULL;
- return 0;
- } else {
- return json_handle_error(string, index,
- "_parse_json_null(): invalid null" );
- }
-}
-
-/* should be at the first character of the bool at this point */
-int json_parse_json_bool(char* string, unsigned long* index, jsonObject* obj, int current_strlen) {
- if( ! string || ! obj || *index >= current_strlen ) return -1;
-
- char* ret = "json_parse_json_bool(): truncated bool";
-
- if( *index > (current_strlen - 4))
- return json_handle_error(string, index, ret);
-
- if(!strncasecmp( string + (*index), "true", 4)) {
- (*index) += 4;
- obj->value.b = 1;
- obj->type = JSON_BOOL;
- return 0;
- }
-
- if( *index > (current_strlen - 5))
- return json_handle_error(string, index, ret);
-
- if(!strncasecmp( string + (*index), "false", 5)) {
- (*index) += 5;
- obj->value.b = 0;
- obj->type = JSON_BOOL;
- return 0;
- }
-
- return json_handle_error(string, index, ret);
-}
-
-
-/* expecting the first character of the number */
-int json_parse_json_number(char* string, unsigned long* index, jsonObject* obj, int current_strlen) {
- if( ! string || ! obj || *index >= current_strlen ) return -1;
-
- growing_buffer* buf = buffer_init(64);
- char c = string[*index];
-
- int done = 0;
- int dot_seen = 0;
-
- /* negative number? */
- if(c == '-') { buffer_add(buf, "-"); (*index)++; }
-
- c = string[*index];
-
- while(*index < current_strlen) {
-
- if(is_number(c)) {
- buffer_add_char(buf, c);
- }
-
- else if( c == '.' ) {
- if(dot_seen) {
- buffer_free(buf);
- return json_handle_error(string, index,
- "json_parse_json_number(): malformed json number");
- }
- dot_seen = 1;
- buffer_add_char(buf, c);
- } else {
- done = 1; break;
- }
-
- (*index)++;
- c = string[*index];
- if(done) break;
- }
-
- obj->type = JSON_NUMBER;
- obj->value.n = strtod(buf->buf, NULL);
- buffer_free(buf);
- return 0;
-}
-
-/* index should point to the character directly following the '['. when done
- * index will point to the character directly following the ']' character
- */
-int json_parse_json_array(char* string, unsigned long* index, jsonObject* obj, int current_strlen) {
-
- if( ! string || ! obj || ! index || *index >= current_strlen ) return -1;
-
- int status = 0;
- int in_parse = 0; /* true if this array already contains one item */
- obj->type = JSON_ARRAY;
- int set = 0;
- int done = 0;
-
- while(*index < current_strlen) {
-
- json_eat_ws(string, index, 1, current_strlen);
-
- if(string[*index] == ']') {
- (*index)++;
- done = 1;
- break;
- }
-
- if(in_parse) {
- json_eat_ws(string, index, 1, current_strlen);
- if(string[*index] != ',') {
- return json_handle_error(string, index,
- "json_parse_json_array(): array item not followed by a ','");
- }
- (*index)++;
- json_eat_ws(string, index, 1, current_strlen);
- }
-
- jsonObject* item = jsonNewObject(NULL);
-
- #ifndef STRICT_JSON_READ
- if(*index < current_strlen) {
- if(string[*index] == ',' || string[*index] == ']') {
- status = 0;
- set = 1;
- }
- }
- if(!set) status = _json_parse_string(string, index, item, current_strlen);
-
- #else
- status = _json_parse_string(string, index, item, current_strlen);
- #endif
-
- if(status) { jsonObjectFree(item); return status; }
- jsonObjectPush(obj, item);
- in_parse = 1;
- set = 0;
- }
-
- if(!done)
- return json_handle_error(string, index,
- "json_parse_json_array(): array not closed");
-
- return 0;
-}
-
-
-/* index should point to the character directly following the '{'. when done
- * index will point to the character directly following the '}'
- */
-int json_parse_json_object(char* string, unsigned long* index, jsonObject* obj, int current_strlen) {
- if( ! string || !obj || ! index || *index >= current_strlen ) return -1;
-
- obj->type = JSON_HASH;
- int status;
- int in_parse = 0; /* true if we've already added one item to this object */
- int set = 0;
- int done = 0;
-
- while(*index < current_strlen) {
-
- json_eat_ws(string, index, 1, current_strlen);
-
- if(string[*index] == '}') {
- (*index)++;
- done = 1;
- break;
- }
-
- if(in_parse) {
- if(string[*index] != ',') {
- return json_handle_error(string, index,
- "json_parse_json_object(): object missing ',' between elements" );
- }
- (*index)++;
- json_eat_ws(string, index, 1, current_strlen);
- }
-
- /* first we grab the hash key */
- jsonObject* key_obj = jsonNewObject(NULL);
- status = _json_parse_string(string, index, key_obj, current_strlen);
- if(status) return status;
-
- if(key_obj->type != JSON_STRING) {
- return json_handle_error(string, index,
- "_json_parse_json_object(): hash key not a string");
- }
-
- char* key = key_obj->value.s;
-
- json_eat_ws(string, index, 1, current_strlen);
-
- if(string[*index] != ':') {
- return json_handle_error(string, index,
- "json_parse_json_object(): hash key not followed by ':' character");
- }
-
- (*index)++;
-
- /* now grab the value object */
- json_eat_ws(string, index, 1, current_strlen);
- jsonObject* value_obj = jsonNewObject(NULL);
-
-#ifndef STRICT_JSON_READ
- if(*index < current_strlen) {
- if(string[*index] == ',' || string[*index] == '}') {
- status = 0;
- set = 1;
- }
- }
- if(!set)
- status = _json_parse_string(string, index, value_obj, current_strlen);
-
-#else
- status = _json_parse_string(string, index, value_obj, current_strlen);
-#endif
-
- if(status) return status;
-
- /* put the data into the object and continue */
- jsonObjectSetKey(obj, key, value_obj);
- jsonObjectFree(key_obj);
- in_parse = 1;
- set = 0;
- }
-
- if(!done)
- return json_handle_error(string, index,
- "json_parse_json_object(): object not closed");
-
- return 0;
-}
-
-
-
-/* when done, index will point to the character after the closing quote */
-int json_parse_json_string(char* string, unsigned long* index, jsonObject* obj, int current_strlen) {
- if( ! string || ! index || *index >= current_strlen ) return -1;
-
- int in_escape = 0;
- int done = 0;
- growing_buffer* buf = buffer_init(64);
-
- while(*index < current_strlen) {
-
- char c = string[*index];
-
- switch(c) {
-
- case '\\':
- if(in_escape) {
- buffer_add(buf, "\\");
- in_escape = 0;
- } else
- in_escape = 1;
- break;
-
- case '"':
- if(in_escape) {
- buffer_add(buf, "\"");
- in_escape = 0;
- } else
- done = 1;
- break;
-
- case 't':
- if(in_escape) {
- buffer_add(buf,"\t");
- in_escape = 0;
- } else
- buffer_add_char(buf, c);
- break;
-
- case 'b':
- if(in_escape) {
- buffer_add(buf,"\b");
- in_escape = 0;
- } else
- buffer_add_char(buf, c);
- break;
-
- case 'f':
- if(in_escape) {
- buffer_add(buf,"\f");
- in_escape = 0;
- } else
- buffer_add_char(buf, c);
- break;
-
- case 'r':
- if(in_escape) {
- buffer_add(buf,"\r");
- in_escape = 0;
- } else
- buffer_add_char(buf, c);
- break;
-
- case 'n':
- if(in_escape) {
- buffer_add(buf,"\n");
- in_escape = 0;
- } else
- buffer_add_char(buf, c);
- break;
-
- case 'u':
- if(in_escape) {
- (*index)++;
-
- if(*index >= (current_strlen - 4)) {
- buffer_free(buf);
- return json_handle_error(string, index,
- "json_parse_json_string(): truncated escaped unicode"); }
-
- char buff[5];
- memset(buff,0,5);
- memcpy(buff, string + (*index), 4);
-
-
- /* ----------------------------------------------------------------------- */
- /* ----------------------------------------------------------------------- */
- /* The following chunk was borrowed with permission from
- json-c http://oss.metaparadigm.com/json-c/ */
- unsigned char utf_out[4];
- memset(utf_out,0,4);
-
- #define hexdigit(x) ( ((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
-
- unsigned int ucs_char =
- (hexdigit(string[*index] ) << 12) +
- (hexdigit(string[*index + 1]) << 8) +
- (hexdigit(string[*index + 2]) << 4) +
- hexdigit(string[*index + 3]);
-
- if (ucs_char < 0x80) {
- utf_out[0] = ucs_char;
- buffer_add(buf, utf_out);
-
- } else if (ucs_char < 0x800) {
- utf_out[0] = 0xc0 | (ucs_char >> 6);
- utf_out[1] = 0x80 | (ucs_char & 0x3f);
- buffer_add(buf, utf_out);
-
- } else {
- utf_out[0] = 0xe0 | (ucs_char >> 12);
- utf_out[1] = 0x80 | ((ucs_char >> 6) & 0x3f);
- utf_out[2] = 0x80 | (ucs_char & 0x3f);
- buffer_add(buf, utf_out);
- }
- /* ----------------------------------------------------------------------- */
- /* ----------------------------------------------------------------------- */
-
- (*index) += 3;
- in_escape = 0;
-
- } else {
-
- buffer_add_char(buf, c);
- }
-
- break;
-
- default:
- buffer_add_char(buf, c);
- }
-
- (*index)++;
- if(done) break;
- }
-
- jsonObjectSetString(obj, buf->buf);
- buffer_free(buf);
- return 0;
-}
-
-
-void json_eat_ws(char* string, unsigned long* index, int eat_all, int current_strlen) {
- if( ! string || ! index ) return;
- if(*index >= current_strlen)
- return;
-
- if( eat_all ) { /* removes newlines, etc */
- while(string[*index] == ' ' ||
- string[*index] == '\n' ||
- string[*index] == '\t')
- (*index)++;
- }
-
- else
- while(string[*index] == ' ') (*index)++;
-}
-
-
-/* index should be at the '*' character at the beginning of the comment.
- * when done, index will point to the first character after the final /
- */
-int json_eat_comment(char* string, unsigned long* index, char** buffer, int parse_class, int current_strlen) {
- if( ! string || ! index || *index >= current_strlen ) return -1;
-
-
- if(string[*index] != '*' && string[*index] != '/' )
- return json_handle_error(string, index,
- "json_eat_comment(): invalid character after /");
-
- /* chop out any // style comments */
- if(string[*index] == '/') {
- (*index)++;
- char c = string[*index];
- while(*index < current_strlen) {
- (*index)++;
- if(c == '\n')
- return 0;
- c = string[*index];
- }
- return 0;
- }
-
- (*index)++;
-
- int on_star = 0; /* true if we just saw a '*' character */
-
- /* we're just past the '*' */
- if(!parse_class) { /* we're not concerned with class hints */
- while(*index < current_strlen) {
- if(string[*index] == '/') {
- if(on_star) {
- (*index)++;
- return 0;
- }
- }
-
- if(string[*index] == '*') on_star = 1;
- else on_star = 0;
-
- (*index)++;
- }
- return 0;
- }
-
-
-
- growing_buffer* buf = buffer_init(64);
-
- int first_dash = 0;
- int second_dash = 0;
- int third_dash = 0;
- int fourth_dash = 0;
-
- int in_hint = 0;
- int done = 0;
-
- /*--S hint--*/ /* <-- Hints look like this */
- /*--E hint--*/
-
- while(*index < current_strlen) {
- char c = string[*index];
-
- switch(c) {
-
- case '-':
- on_star = 0;
- if(third_dash) fourth_dash = 1;
- else if(in_hint) third_dash = 1;
- else if(first_dash) second_dash = 1;
- else first_dash = 1;
- break;
-
- case 'S':
- on_star = 0;
- if(second_dash && !in_hint) {
- (*index)++;
- json_eat_ws(string, index, 1, current_strlen);
- (*index)--; /* this will get incremented at the bottom of the loop */
- in_hint = 1;
- break;
- }
-
- if(second_dash && in_hint) {
- buffer_add_char(buf, c);
- break;
- }
-
- case 'E':
- on_star = 0;
- if(second_dash && !in_hint) {
- (*index)++;
- json_eat_ws(string, index, 1, current_strlen);
- (*index)--; /* this will get incremented at the bottom of the loop */
- in_hint = 1;
- break;
- }
-
- if(second_dash && in_hint) {
- buffer_add_char(buf, c);
- break;
- }
-
- case '*':
- on_star = 1;
- break;
-
- case '/':
- if(on_star)
- done = 1;
- else
- on_star = 0;
- break;
-
- default:
- on_star = 0;
- if(in_hint)
- buffer_add_char(buf, c);
- }
-
- (*index)++;
- if(done) break;
- }
-
- if( buf->n_used > 0 && buffer)
- *buffer = buffer_data(buf);
-
- buffer_free(buf);
- return 0;
-}
-
-int is_number(char c) {
- switch(c) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- return 1;
- }
- return 0;
-}
-
-int json_handle_error(char* string, unsigned long* index, char* err_msg) {
-
- char buf[60];
- memset(buf, 0, 60);
-
- if(*index > 30)
- strncpy( buf, string + (*index - 30), 59 );
- else
- strncpy( buf, string, 59 );
-
- fprintf(stderr,
- "\nError parsing json string at charracter %c "
- "(code %d) and index %ld\nString length: %d\nMsg:\t%s\nNear:\t%s\nFull String:\t%s\n",
- string[*index], string[*index], *index, current_strlen, err_msg, buf, string );
-
- return -1;
-}
-
-
-jsonObject* jsonParseFile( const char* filename ) {
- return json_parse_file( filename );
-}
-
-jsonObject* json_parse_file(const char* filename) {
- if(!filename) return NULL;
- char* data = file_to_string(filename);
- jsonObject* o = json_parse_string(data);
- free(data);
- return o;
-}
-
-
-
-
+++ /dev/null
-/*
-Copyright (C) 2005 Georgia Public Library Service
-Bill Erickson <highfalutin@gmail.com>
-
-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; either version 2
-of the License, or (at your option) any later version.
-
-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.
-*/
-
-
-
-
-/* ---------------------------------------------------------------------------------------
- JSON parser.
- * --------------------------------------------------------------------------------------- */
-#ifndef JSON_PARSER_H
-#define JSON_PARSER_H
-
-#include <stdio.h>
-#include "object.h"
-#include "utils.h"
-
-
-
-/* Parses the given JSON string and returns the built object.
- * returns NULL (and prints parser error to stderr) on error.
- */
-
-jsonObject* json_parse_string(char* string);
-
-jsonObject* jsonParseString(char* string);
-jsonObject* jsonParseStringFmt( char* string, ... );
-
-jsonObject* json_parse_file( const char* filename );
-
-jsonObject* jsonParseFile( const char* string );
-
-
-
-/* does the actual parsing work. returns 0 on success. -1 on error and
- * -2 if there was no object to build (string was all comments)
- */
-int _json_parse_string(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
-
-/* returns 0 on success and turns obj into a string object */
-int json_parse_json_string(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
-
-/* returns 0 on success and turns obj into a number or double object */
-int json_parse_json_number(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
-
-/* returns 0 on success and turns obj into an 'object' object */
-int json_parse_json_object(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
-
-/* returns 0 on success and turns object into an array object */
-int json_parse_json_array(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
-
-/* churns through whitespace and increments index as it goes.
- * eat_all == true means we should eat newlines, tabs
- */
-void json_eat_ws(char* string, unsigned long* index, int eat_all, int current_strlen);
-
-int json_parse_json_bool(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
-
-/* removes comments from a json string. if the comment contains a class hint
- * and class_hint isn't NULL, an allocated char* with the class name will be
- * shoved into *class_hint. returns 0 on success, -1 on parse error.
- * 'index' is assumed to be at the second character (*) of the comment
- */
-int json_eat_comment(char* string, unsigned long* index, char** class_hint, int parse_class, int current_strlen);
-
-/* prints a useful error message to stderr. always returns -1 */
-int json_handle_error(char* string, unsigned long* index, char* err_msg);
-
-/* returns true if c is 0-9 */
-int is_number(char c);
-
-int json_parse_json_null(char* string, unsigned long* index, jsonObject* obj, int current_strlen);
-
-
-#endif
+++ /dev/null
-/*
-Copyright (C) 2005 Georgia Public Library Service
-Bill Erickson <highfalutin@gmail.com>
-
-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; either version 2
-of the License, or (at your option) any later version.
-
-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.
-*/
-
-#include "object.h"
-#include "json_parser.h"
-
-
-/* ---------------------------------------------------------------------- */
-/* See object.h for function info */
-/* ---------------------------------------------------------------------- */
-
-
-char* __tabs(int count);
-
-jsonObject* jsonNewObject( const char* stringValue ) {
-
- jsonObject* obj = (jsonObject*) safe_malloc(sizeof(jsonObject));
- obj->size = 0;
- obj->type = JSON_NULL;
-
- if(stringValue) {
- obj->type = JSON_STRING;
- obj->value.s = strdup(stringValue);
- }
-
- return obj;
-}
-
-jsonObject* jsonNewObjectFmt( const char* stringValue, ... ) {
-
- jsonObject* obj = (jsonObject*) safe_malloc(sizeof(jsonObject));
- obj->size = 0;
- obj->type = JSON_NULL;
-
- if(stringValue) {
- VA_LIST_TO_STRING(stringValue);
- obj->type = JSON_STRING;
- obj->value.s = strdup(VA_BUF);
- }
-
- return obj;
-}
-
-
-
-
-jsonObject* jsonNewNumberObject( double num ) {
- jsonObject* o = jsonNewObject(NULL);
- o->type = JSON_NUMBER;
- o->value.n = num;
- return o;
-
-}
-
-
-jsonObjectNode* jsonNewObjectNode( jsonObject* obj ) {
- jsonObjectNode* node = (jsonObjectNode*) safe_malloc(sizeof(jsonObjectNode));
- node->item = obj;
- node->next = NULL;
- node->index = -1;
- return node;
-}
-
-unsigned long jsonObjectPush( jsonObject* obj, jsonObject* new_obj) {
- if(!obj) return -1;
-
- obj->type = JSON_ARRAY;
-
- if(new_obj == NULL) {
- new_obj = jsonNewObject(NULL);
- new_obj->type = JSON_NULL;
- }
-
- jsonObjectNode* node = jsonNewObjectNode(new_obj);
- node->index = obj->size++;
-
- if(obj->value.c == NULL) {
- obj->value.c = node;
-
- } else {
- /* append the node onto the end */
- jsonObjectNode* tmp = obj->value.c;
- while(tmp) {
- if(tmp->next == NULL) break;
- tmp = tmp->next;
- }
- tmp->next = node;
- }
- return obj->size;
-}
-
-unsigned long jsonObjectSetIndex( jsonObject* obj, unsigned long index, jsonObject* new_obj) {
- if( obj == NULL ) return -1;
- obj->type = JSON_ARRAY;
-
- if(obj->size <= index)
- obj->size = index + 1;
-
- if(new_obj == NULL) {
- new_obj = jsonNewObject(NULL);
- new_obj->type = JSON_NULL;
- }
-
- jsonObjectNode* node = jsonNewObjectNode(new_obj);
- node->index = index;
-
- if( obj->value.c == NULL ) {
- obj->value.c = node;
-
- } else {
-
- if(obj->value.c->index == index) {
- jsonObjectNode* tmp = obj->value.c->next;
- jsonObjectNodeFree(obj->value.c);
- obj->value.c = node;
- node->next = tmp;
-
- } else {
-
- jsonObjectNode* prev = obj->value.c;
- jsonObjectNode* cur = prev->next;
- int inserted = 0;
-
- while(cur != NULL) {
-
- /* replace an existing node */
- if( cur->index == index ) {
- jsonObjectNode* tmp = cur->next;
- jsonObjectNodeFree(cur);
- node->next = tmp;
- prev->next = node;
- inserted = 1;
- break;
-
- /* instert between two nodes */
- } else if( prev->index < index && cur->index > index ) {
- prev->next = node;
- node->next = cur;
- inserted = 1;
- break;
- }
- prev = cur;
- cur = cur->next;
- }
-
- /* shove on to the end */
- if(!inserted)
- prev->next = node;
- }
- }
-
- return obj->size;
-}
-
-
-void _jsonObjectShifIndex( jsonObject* obj, unsigned long index) {
- if( obj == NULL || index < 0 ) return;
-
- if(obj->value.c == NULL) {
- obj->size = 0;
- return;
- }
-
- jsonObjectNode* data = obj->value.c;
- while(data) {
- if(data->index >= index)
- data->index--;
- data = data->next;
- }
- obj->size--;
-}
-
-unsigned long jsonObjectRemoveIndex( jsonObject* obj, unsigned long index) {
- if( obj == NULL || index < 0 ) return -1;
-
- if(obj->value.c == NULL) return 0;
-
- /* removing the first item in the list */
- if(obj->value.c->index == index) {
- jsonObjectNode* tmp = obj->value.c->next;
- jsonObjectNodeFree(obj->value.c);
- obj->value.c = tmp;
- _jsonObjectShiftIndex(obj,index);
- return obj->size;
- }
-
-
- jsonObjectNode* prev = obj->value.c;
- jsonObjectNode* cur = prev->next;
-
- while(cur) {
- if(cur->index == index) {
- jsonObjectNode* tmp = cur->next;
- jsonObjectNodeFree(cur);
- prev->next = tmp;
- _jsonObjectShiftIndex(obj, index);
- break;
- }
- prev = cur;
- cur = cur->next;
- }
-
- return obj->size;
-}
-
-
-void _jsonObjectShiftIndex(jsonObject* obj, unsigned long index) {
-
- if( ! obj ) return;
-
- if(obj->value.c == NULL) {
- obj->size = 0;
- return;
- }
-
- jsonObjectNode* data = obj->value.c;
- while(data) {
- if(data->index >= index)
- data->index--;
- data = data->next;
- }
- obj->size--;
-}
-
-
-unsigned long jsonObjectRemoveKey( jsonObject* obj, const char* key) {
- if( obj == NULL || key == NULL ) return -1;
-
- if(obj->value.c == NULL) return 0;
-
- /* removing the first item in the list */
- if(!strcmp(obj->value.c->key, key)) {
-
- jsonObjectNode* tmp = obj->value.c->next;
- jsonObjectNodeFree(obj->value.c);
-
- obj->value.c = tmp;
- if(!obj->value.c) obj->size = 0;
- return obj->size;
- }
-
- jsonObjectNode* prev = obj->value.c;
- jsonObjectNode* cur = prev->next;
-
- while(cur) {
- if(!strcmp(cur->key,key)) {
-
- jsonObjectNode* tmp = cur->next;
- jsonObjectNodeFree(cur);
- prev->next = tmp;
- obj->size--;
- break;
- }
- prev = cur;
- cur = cur->next;
- }
-
- return obj->size;
-}
-
-
-unsigned long jsonObjectSetKey( jsonObject* obj, const char* key, jsonObject* new_obj ) {
- if( obj == NULL || key == NULL ) return -1;
- obj->type = JSON_HASH;
-
- if(new_obj == NULL) {
- new_obj = jsonNewObject(NULL);
- new_obj->type = JSON_NULL;
- }
-
- jsonObjectNode* node = jsonNewObjectNode(new_obj);
- node->key = strdup(key);
-
- if( obj->value.c == NULL ) {
- obj->value.c = node;
- obj->size++;
-
- } else {
-
- /* replace the first node */
- if(!strcmp(obj->value.c->key, key)) {
- jsonObjectNode* tmp = obj->value.c->next;
- jsonObjectNodeFree(obj->value.c);
- obj->value.c = node;
- node->next = tmp;
-
- } else {
-
- jsonObjectNode* prev = obj->value.c;
- jsonObjectNode* cur = prev->next;
- int inserted = 0;
-
- while(cur != NULL) {
-
- /* replace an existing node */
- if( !strcmp(cur->key, key) ) {
- jsonObjectNode* tmp = cur->next;
- jsonObjectNodeFree(cur);
- node->next = tmp;
- prev->next = node;
- inserted = 1;
- break;
- }
-
- prev = cur;
- cur = cur->next;
- }
-
- /* shove on to the end */
- if(!inserted) {
- prev->next = node;
- obj->size++;
- }
- }
- }
-
- return obj->size;
-}
-
-
-void jsonObjectFree( jsonObject* obj) {
- if(obj == NULL) return;
-
- free(obj->classname);
- free(obj->comment);
-
- if( obj->type == JSON_ARRAY || obj->type == JSON_HASH ) {
- while(obj->value.c) {
- jsonObjectNode* tmp = obj->value.c->next;
- jsonObjectNodeFree(obj->value.c);
- obj->value.c = tmp;
- }
- }
-
- if(obj->type == JSON_STRING)
- free(obj->value.s);
-
- free(obj);
-}
-
-void jsonObjectNodeFree( jsonObjectNode* node ) {
- if(node == NULL) return;
- free(node->key);
- jsonObjectFree(node->item);
- free(node);
-}
-
-jsonObject* jsonObjectGetIndex( const jsonObject* obj, unsigned long index ) {
-
- if( obj && index >= 0 &&
- index < obj->size && obj->type == JSON_ARRAY ) {
-
- jsonObjectNode* node = obj->value.c;
- while(node) {
- if(node->index == index)
- return node->item;
- node = node->next;
- }
- }
-
- return NULL;
-}
-
-jsonObject* jsonObjectGetKey( const jsonObject* obj, const char* key ) {
-
- if( obj && key && obj->type == JSON_HASH ) {
-
- jsonObjectNode* node = obj->value.c;
-
- while(node) {
- if(node->key && !strcmp(node->key, key))
- return node->item;
- node = node->next;
- }
- }
-
- return NULL;
-}
-
-char* jsonObjectGetString( const jsonObject* obj ) {
- if( obj && obj->type == JSON_STRING ) return obj->value.s;
- return NULL;
-}
-
-double jsonObjectGetNumber( const jsonObject* obj ) {
- if( obj && obj->type == JSON_NUMBER ) return obj->value.n;
- return 0;
-}
-
-void jsonObjectSetString( jsonObject* obj, const char* string) {
- if( obj ) {
- obj->type = JSON_STRING;
- if(string) obj->value.s = strdup(string);
- else obj->value.s = NULL;
- }
-}
-
-
-void jsonObjectSetNumber( jsonObject* obj, double num) {
- if(obj) {
- obj->type = JSON_NUMBER;
- obj->value.n = num;
- }
-}
-
-
-void jsonObjectSetClass( jsonObject* obj, const char* classname) {
- if( obj == NULL || classname == NULL ) return;
- obj->classname = strdup(classname);
-}
-
-
-
-char* jsonObjectToJSON( const jsonObject* obj ) {
-
- if(obj == NULL) return strdup("null");
-
- growing_buffer* buf = buffer_init(64);
-
- /* add class hints if we have a class name */
- if(obj->classname) {
- buffer_add(buf,"/*--S ");
- buffer_add(buf,obj->classname);
- buffer_add(buf, "--*/");
- }
-
- switch( obj->type ) {
-
- case JSON_BOOL:
- if(obj->value.b) buffer_add(buf, "true");
- else buffer_add(buf, "false");
- break;
-
- case JSON_NUMBER: {
- double x = obj->value.n;
-
- /* if the number does not need to be a double,
- turn it into an int on the way out */
- if( x == (int) x ) {
- INT_TO_STRING((int)x);
- buffer_add(buf, INTSTR);
-
- } else {
- DOUBLE_TO_STRING(x);
- buffer_add(buf, DOUBLESTR);
- }
- break;
- }
-
- case JSON_NULL:
- buffer_add(buf, "null");
- break;
-
- case JSON_STRING:
- buffer_add(buf, "\"");
- char* data = obj->value.s;
- int len = strlen(data);
-
- char* output = uescape(data, len, 1);
- buffer_add(buf, output);
- free(output);
- buffer_add(buf, "\"");
- break;
-
- case JSON_ARRAY:
- buffer_add(buf, "[");
- int i;
- for( i = 0; i!= obj->size; i++ ) {
- const jsonObject* x = jsonObjectGetIndex(obj,i);
- char* data = jsonObjectToJSON(x);
-
-#ifdef STRICT_JSON_WRITE
- buffer_add(buf, data);
-#else
- if(strcmp(data,"null")) /* only add the string if it isn't null */
- buffer_add(buf, data);
-#endif
-
- free(data);
- if(i != obj->size - 1)
- buffer_add(buf, ",");
- }
- buffer_add(buf, "]");
- break;
-
- case JSON_HASH:
-
- buffer_add(buf, "{");
- jsonObjectIterator* itr = jsonNewObjectIterator(obj);
- jsonObjectNode* tmp;
-
- while( (tmp = jsonObjectIteratorNext(itr)) ) {
-
- buffer_add(buf, "\"");
-
- char* key = tmp->key;
- int len = strlen(key);
- char* output = uescape(key, len, 1);
- buffer_add(buf, output);
- free(output);
-
- buffer_add(buf, "\":");
- char* data = jsonObjectToJSON(tmp->item);
-
-#ifdef STRICT_JSON_WRITE
- buffer_add(buf, data);
-#else
- if(strcmp(data,"null")) /* only add the string if it isn't null */
- buffer_add(buf, data);
-#endif
-
- if(jsonObjectIteratorHasNext(itr))
- buffer_add(buf, ",");
- free(data);
- }
-
- jsonObjectIteratorFree(itr);
- buffer_add(buf, "}");
- break;
-
- default:
- fprintf(stderr, "Unknown object type %d\n", obj->type);
- break;
-
- }
-
- /* close out the object hint */
- if(obj->classname) {
- buffer_add(buf, "/*--E ");
- buffer_add(buf, obj->classname);
- buffer_add(buf, "--*/");
- }
-
- if(obj->comment) {
- buffer_add(buf, " /*");
- buffer_add(buf, obj->comment);
- buffer_add(buf, "*/");
- }
-
- char* data = buffer_data(buf);
- buffer_free(buf);
- return data;
-
-}
-
-
-void jsonObjectSetComment( jsonObject* obj, const char* com) {
- if( obj == NULL || com == NULL ) return;
- obj->comment = strdup(com);
-}
-
-
-char* __tabs(int count) {
- growing_buffer* buf = buffer_init(24);
- int i;
- for(i=0;i!=count;i++) buffer_add(buf, " ");
- char* final = buffer_data( buf );
- buffer_free( buf );
- return final;
-}
-
-char* jsonFormatString( const char* string ) {
-
- if(!string) return strdup("");
-
- growing_buffer* buf = buffer_init(64);
- int i;
- int depth = 0;
- char* tab = NULL;
-
- for(i=0; i!= strlen(string); i++) {
-
- if( string[i] == '{' || string[i] == '[' ) {
-
- tab = __tabs(++depth);
- buffer_fadd( buf, "%c\n%s", string[i], tab);
- free(tab);
-
- } else if( string[i] == '}' || string[i] == ']' ) {
-
- tab = __tabs(--depth);
- buffer_fadd( buf, "\n%s%c", tab, string[i]);
- free(tab);
-
- if(string[i+1] != ',') {
- tab = __tabs(depth);
- buffer_fadd( buf, "\n%s", tab );
- free(tab);
- }
-
- } else if( string[i] == ',' ) {
-
- tab = __tabs(depth);
- buffer_fadd(buf, ",\n%s", tab);
- free(tab);
-
- } else { buffer_add_char(buf, string[i]); }
-
- }
-
- char* result = buffer_data(buf);
- buffer_free(buf);
- return result;
-
-}
-
-
-jsonObject* jsonObjectClone(const jsonObject* o) {
- if(!o) return NULL;
- char* json = jsonObjectToJSON(o);
- jsonObject* newo = jsonParseString(json);
- free(json);
- return newo;
-}
-
-
-
-/* ---------------------------------------------------------------------- */
-/* Iterator */
-
-jsonObjectIterator* jsonNewObjectIterator(const jsonObject* obj) {
-
- if(!obj) return NULL;
- jsonObjectIterator* iter = safe_malloc(sizeof(jsonObjectIterator));
- iter->obj = obj;
-
- if( obj->type == JSON_HASH || obj->type == JSON_ARRAY )
- iter->current = obj->value.c;
- else iter->current = NULL;
- return iter;
-}
-
-jsonObjectNode* jsonObjectIteratorNext( jsonObjectIterator* itr ) {
- if( itr == NULL ) return NULL;
-
- jsonObjectNode* tmp = itr->current;
- if(tmp == NULL) return NULL;
- itr->current = itr->current->next;
-
- return tmp;
-}
-
-void jsonObjectIteratorFree(jsonObjectIterator* iter) {
- free(iter);
-}
-
-int jsonObjectIteratorHasNext(const jsonObjectIterator* itr) {
- return (itr && itr->current);
-}
-
-
-jsonObject* jsonObjectFindPath( const jsonObject* obj, char* format, ...) {
- if(!obj || !format || strlen(format) < 1) return NULL;
-
- VA_LIST_TO_STRING(format);
- char* buf = VA_BUF;
-
- /* tmp storage for strtok_r */
- //char tokbuf[len];
- //bzero(tokbuf, len);
-
- char* token = NULL;
- char* t = buf;
- //char* tt = tokbuf;
- char* tt; /* strtok storage */
-
- /* copy the path before strtok_r destroys it */
- char* pathcopy = strdup(buf);
-
- /* grab the root of the path */
- token = strtok_r(t, "/", &tt);
- if(!token) return NULL;
-
- /* special case where path starts with // (start anywhere) */
- if(strlen(pathcopy) > 2 && pathcopy[0] == '/' && pathcopy[1] == '/') {
- jsonObject* it = _jsonObjectFindPathRecurse(obj, token, pathcopy + 1);
- free(pathcopy);
- return it;
- }
-
- free(pathcopy);
-
- t = NULL;
- do {
- obj = jsonObjectGetKey(obj, token);
- } while( (token = strtok_r(NULL, "/", &tt)) && obj);
-
- return jsonObjectClone(obj);
-}
-
-/* --------------------------------------------------------------- */
-
-
-
-jsonObject* _jsonObjectFindPathRecurse(const jsonObject* obj, char* root, char* path) {
-
- if(!obj || ! root || !path) return NULL;
-
- /* collect all of the potential objects */
- jsonObject* arr = __jsonObjectFindPathRecurse(obj, root);
-
- /* container for fully matching objects */
- jsonObject* newarr = jsonParseString("[]");
- int i;
-
- /* path is just /root or /root/ */
- if( strlen(root) + 2 >= strlen(path) ) {
- return arr;
-
- } else {
-
- /* gather all of the sub-objects that match the full path */
- for( i = 0; i < arr->size; i++ ) {
- jsonObject* a = jsonObjectGetIndex(arr, i);
- jsonObject* thing = jsonObjectFindPath(a , path + strlen(root) + 1);
-
- if(thing) { //jsonObjectPush(newarr, thing);
- if(thing->type == JSON_ARRAY) {
- int i;
- for( i = 0; i != thing->size; i++ )
- jsonObjectPush(newarr, jsonObjectClone(jsonObjectGetIndex(thing,i)));
- jsonObjectFree(thing);
-
- } else {
- jsonObjectPush(newarr, thing);
- }
- }
- }
- }
-
- jsonObjectFree(arr);
- return newarr;
-}
-
-jsonObject* __jsonObjectFindPathRecurse(const jsonObject* obj, char* root) {
-
- jsonObject* arr = jsonParseString("[]");
- if(!obj) return arr;
-
- int i;
-
- /* if the current object has a node that matches, add it */
-
- jsonObject* o = jsonObjectGetKey(obj, root);
- if(o) jsonObjectPush( arr, jsonObjectClone(o) );
-
- jsonObjectNode* tmp = NULL;
- jsonObject* childarr;
- jsonObjectIterator* itr = jsonNewObjectIterator(obj);
-
- /* recurse through the children and find all potential nodes */
- while( (tmp = jsonObjectIteratorNext(itr)) ) {
- childarr = __jsonObjectFindPathRecurse(tmp->item, root);
- if(childarr && childarr->size > 0) {
- for( i = 0; i!= childarr->size; i++ ) {
- jsonObjectPush( arr, jsonObjectClone(jsonObjectGetIndex(childarr, i)) );
- }
- }
- jsonObjectFree(childarr);
- }
-
- jsonObjectIteratorFree(itr);
-
- return arr;
-}
-
-
-char* jsonObjectToSimpleString( const jsonObject* o ) {
- char* value = NULL;
-
- if(o) {
- switch( o->type ) {
-
- case JSON_NUMBER: {
-
- if( o->value.n == (int) o->value.n ) {
- INT_TO_STRING((int) o->value.n);
- value = strdup(INTSTR);
-
- } else {
- DOUBLE_TO_STRING(o->value.n);
- value = strdup(DOUBLESTR);
- }
-
- break;
- }
-
- case JSON_STRING:
- value = strdup(o->value.s);
- }
- }
- return value;
-}
-
-
-int jsonBoolIsTrue( const jsonObject* o ) {
- return (o && o->type == JSON_BOOL && o->value.b);
-}
-
-
+++ /dev/null
-/*
-Copyright (C) 2005 Georgia Public Library Service
-Bill Erickson <highfalutin@gmail.com>
-
-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; either version 2
-of the License, or (at your option) any later version.
-
-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.
-*/
-
-
-/* ---------------------------------------------------------------------------------------
- libjson
- * --------------------------------------------------------------------------------------- */
-
-#ifndef _JSON_OBJECT_H
-#define _JSON_OBJECT_H
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "utils.h"
-
-/* json object types */
-#define JSON_HASH 0
-#define JSON_ARRAY 1
-#define JSON_STRING 2
-#define JSON_NUMBER 3
-#define JSON_NULL 4
-#define JSON_BOOL 5
-
-
-/* top level generic object structure */
-struct _jsonObjectStruct {
-
- /* how many sub-objects do we contain if we're an array or an object.
- Note that this includes null array elements in sparse arrays */
- unsigned long size;
-
- /* optional class hint */
- char* classname;
-
- /* see JSON types above */
- int type;
-
-
- /* our cargo */
- union _jsonObjectValue {
- struct _jsonObjectNodeStruct* c; /* our list of sub-objects if we're an array or a hash */
- char* s; /* string */
- int b; /* bool */
- double n; /* number */
- } value;
-
-
- /* client may provide a comment string which will be
- * added to the object when stringified */
- char* comment;
-
-};
-typedef struct _jsonObjectStruct jsonObject;
-
-
-/**
- String parsing function. This is assigned by the json_parser code.
- to avoid circular dependency, declare the parse function here,
- and have the json parse code set the variable to a real function
-*/
-//jsonObject* (*jsonParseString) (char* str);
-
-
-/* this contains a single element of the object along with the elements
- * index (if this object is an array) and key (if this object is a hash)
- */
-struct _jsonObjectNodeStruct {
-
- unsigned long index; /* our array position */
- char* key; /* our hash key */
-
- jsonObject* item; /* our object */
- struct _jsonObjectNodeStruct* next; /* pointer to the next object node */
-};
-typedef struct _jsonObjectNodeStruct jsonObjectNode;
-
-
-
-/* utility object for iterating over hash objects */
-struct _jsonObjectIteratorStruct {
- const jsonObject* obj; /* the topic object */
- jsonObjectNode* current; /* the current node within the object */
-};
-typedef struct _jsonObjectIteratorStruct jsonObjectIterator;
-
-
-/** Allocates a new iterator
- @param obj The object over which to iterate.
-*/
-jsonObjectIterator* jsonNewObjectIterator(const jsonObject* obj);
-
-/**
- De-allocates an iterator
- @param iter The iterator object to free
-*/
-void jsonObjectIteratorFree(jsonObjectIterator* iter);
-
-/**
- Returns the object_node currently pointed to by the iterator
- and increments the pointer to the next node
- @param iter The iterator in question.
- */
-jsonObjectNode* jsonObjectIteratorNext(jsonObjectIterator* iter);
-
-/**
- @param iter The iterator.
- @return True if there is another node after the current node.
- */
-int jsonObjectIteratorHasNext(const jsonObjectIterator* iter);
-
-
-/**
- Allocates a new object.
- @param string The string data if this object is to be a string.
- if not, string should be NULL
- @return The newly allocated object or NULL on memory error.
-*/
-jsonObject* jsonNewObjectFmt(const char* string, ...);
-jsonObject* jsonNewObject(const char* string);
-
-/**
- Allocates a new JSON number object.
- @param num The number this object is to hold
- @return The newly allocated object.
-*/
-jsonObject* jsonNewNumberObject( double num );
-
-
-/**
- Returns a pointer to the object at the given index. This call is
- only valid if the object has a type of JSON_ARRAY.
- @param obj The object
- @param index The position within the object
- @return The object at the given index.
-*/
-jsonObject* jsonObjectGetIndex( const jsonObject* obj, unsigned long index );
-
-
-/**
- Returns a pointer to the object with the given key
- @param obj The object
- @param key The key
- @return The object with the given key.
-*/
-jsonObject* jsonObjectGetKey( const jsonObject* obj, const char* key );
-
-/**
- De-allocates an object. Note that this function should only be called
- on objects that are _not_ children of other objects or there will be
- double-free's
- @param obj The object to free.
-*/
-void jsonObjectFree(jsonObject* obj);
-
-
-/**
- Allocates a new object node.
- @param obj The object to which the node will be appended.
- @return The new object node.
-*/
-jsonObjectNode* jsonNewObjectNode(jsonObject* obj);
-
-/**
- De-allocates an object node
- @param obj The object node to de-allocate.
-*/
-void jsonObjectNodeFree(jsonObjectNode* obj);
-
-
-/**
- Pushes the given object onto the end of the list. This coerces an object
- into becoming an array. _Only_ use this function on objects that you
- want to become an array.
- If obj is NULL, inserts a new NULL object into the list.
- @return array size on success, -1 on error
- */
-unsigned long jsonObjectPush(jsonObject* dest, jsonObject* newObj);
-
-/* removes (and deallocates) the object at the given index (if one exists) and inserts
- * the new one. returns the size on success, -1 on error
- * If obj is NULL, inserts a new object into the list with is_null set to true
- */
-unsigned long jsonObjectSetIndex(jsonObject* dest, unsigned long index, jsonObject* newObj);
-
-/* inserts the new object, overwriting (removing, deallocating) any
- * previous object with the given key.
- * returns the size on success, -1 on error
- * if 'obj' is NULL, a new object is inserted at key 'key' with 'is_null'
- * set to true
- */
-unsigned long jsonObjectSetKey(jsonObject* dest, const char* key, jsonObject* newObj);
-
-/* removes the object at the given index and, if more items exist,
- * re-indexes (shifts down by 1) the rest of the objects in the array
- */
-unsigned long jsonObjectRemoveIndex(jsonObject* dest, unsigned long index);
-
-/* removes (and deallocates) the object with key 'key' if it exists */
-unsigned long jsonObjectRemoveKey( jsonObject* dest, const char* key);
-
-/* returns a pointer to the string data held by this object if this object
- is a string. Otherwise returns NULL*/
-char* jsonObjectGetString(const jsonObject*);
-
-double jsonObjectGetNumber( const jsonObject* obj );
-
-/* sets the string data */
-void jsonObjectSetString(jsonObject* dest, const char* string);
-
-/* sets the number value for the object */
-void jsonObjectSetNumber(jsonObject* dest, double num);
-
-/* sets the class hint for this object */
-void jsonObjectSetClass(jsonObject* dest, const char* classname );
-
-/* converts an object to a json string. client is responsible for freeing the return string */
-char* jsonObjectToJSON( const jsonObject* obj );
-
-/* set this object's comment string */
-void jsonObjectSetComment(jsonObject* dest, const char* classname);
-
-/* utility method. starting at index 'index', shifts all indices down by one and
- * decrements the objects size by 1
- */
-void _jsonObjectShiftIndex(jsonObject* dest, unsigned long index);
-
-/* formats a JSON string from printing. User must free returned string */
-char* jsonFormatString( const char* jsonString );
-
-jsonObject* jsonObjectClone( const jsonObject* o );
-
-/* tries to extract the string data from an object.
- if object -> NULL (the C NULL)
- if array -> NULL (the C NULL)
- if null -> NULL (the C NULL)
- if true/false -> true/false
- if string/number/double the string version of either of those
- The caller is responsible for freeing the returned string
- */
-char* jsonObjectToSimpleString( const jsonObject* o );
-
-int jsonBoolIsTrue( const jsonObject* o );
-
-
-/* ------------------------------------------------------------------------ */
-/* XPATH */
-
-/* provides an XPATH style search interface (e.g. /some/node/here) and
- return the object at that location if one exists. Naturally,
- every element in the path must be a proper object ("hash" / {}).
- Returns NULL if the specified node is not found
- Note also that the object returned is a clone and
- must be freed by the caller
-*/
-jsonObject* jsonObjectFindPath( const jsonObject* obj, char* path, ... );
-
-
-/* Utility method. finds any object in the tree that matches the path.
- Use this for finding paths that start with '//' */
-jsonObject* _jsonObjectFindPathRecurse( const jsonObject* o, char* root, char* path );
-
-/* returns a list of object whose key is 'root'. These are used as
- potential objects when doing a // search */
-jsonObject* __jsonObjectFindPathRecurse( const jsonObject* o, char* root );
-
-/* ------------------------------------------------------------------------ */
-
-
-#endif
-
-
+++ /dev/null
-/*
-Copyright (C) 2005 Georgia Public Library Service
-Bill Erickson <highfalutin@gmail.com>
-
-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; either version 2
-of the License, or (at your option) any later version.
-
-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.
-*/
-
-//#include "utils.h"
-#include "object.h"
-#include "json_parser.h"
-
-#include <stdio.h>
-#include <fcntl.h>
-
-/* ---------------------------------------------------------------------- */
-/* See object.h for function info */
-/* ---------------------------------------------------------------------- */
-int main() {
-
-
-
- jsonObject* o;
-
-
- o = jsonParseString("[ 1, 4, 6, 9 ]");
- jsonObjectIterator* itr = jsonNewObjectIterator(o);
- jsonObjectNode* tmp = NULL;
- while( (tmp = jsonObjectIteratorNext(itr)) ) {
- char* q = jsonObjectToJSON(tmp->item);
- printf("Iterator thing => %s\n", q);
- free(q);
- }
- jsonObjectIteratorFree(itr);
- jsonObjectFree(o);
-
-
-
- printf("------------------------------------------------------------------\n");
- o = jsonParseString("{\"key\":-1}");
- char* h = jsonObjectToJSON(o);
- printf("\nParsed number: %s\n", h);
- free(h);
- jsonObjectFree(o);
-
-
- /* number, double, and 'null' parsing... */
- printf("------------------------------------------------------------------\n");
- o = jsonParseString("1");
- printf("\nParsed number: %f\n", jsonObjectGetNumber(o));
- jsonObjectFree(o);
-
-
- printf("------------------------------------------------------------------\n");
- o = jsonParseString("nUlL");
- char* s = jsonObjectToJSON(o);
- printf("\nJSON Null: %s\n", s);
- free(s);
- jsonObjectFree(o);
-
- printf("------------------------------------------------------------------\n");
- o = jsonParseString("[1, .5, null]");
- s = jsonObjectToJSON(o);
- printf("\nJSON MIX: %s\n", s );
- free(s);
- jsonObjectFree(o);
-
- printf("------------------------------------------------------------------\n");
- /* simulate an error.. */
- printf("\nShould print error msg: \n");
- o = jsonParseString("[1, .5. null]");
- if( o == NULL ) printf("\n");
- jsonObjectFree(o);
-
- printf("------------------------------------------------------------------\n");
- o = jsonParseString("[ Null, trUe, falSE, 1, 12.9, \"true\" ]");
- s = jsonObjectToJSON(o);
- printf("More JSON: %s\n", s);
- free(s);
- jsonObjectFree(o);
-
- printf("------------------------------------------------------------------\n");
- o = jsonParseString("[ Null, trUe, falSE, 1, 12.9, \"true\", "
- "{\"key\":[0,0.0,1],\"key2\":null},NULL, { }, [] ]");
- s = jsonObjectToJSON(o);
- printf("More JSON: %s\n", s);
- free(s);
- jsonObjectFree(o);
-
-
- printf("------------------------------------------------------------------\n");
- o = jsonParseString("{ Null: trUe }");
-
-
-
- printf("------------------------------------------------------------------\n");
- o = jsonParseString("\"Pin\\u0303ata\"");
- s = jsonObjectToJSON(o);
- printf("UNICODE:: %s\n", o->value.s);
- printf("Back to JSON: %s\n", s);
- jsonObjectFree(o);
- free(s);
-
-
- /* sample JSON string with some encoded UTF8 */
- char* jsons = "/*--S mvr--*/[null,null,null,\"Griswold del Castillo, Richard\",[],null,\"1405676\",null,null,\"1558853243 (alk. paper) :\",\"c2002\",\"Pin\\u0303ata Books\",null,[],[[\"Chavez, Cesar 1927-\",\"Juvenile literature\"],[\"Labor leaders\",\"United States\",\"Biography\",\"Juvenile literature\"],[\"Mexican Americans\",\"Biography\",\"Juvenile literature\"],[\"Agricultural laborers\",\"Labor unions\",\"United States\",\"History\",\"Juvenile literature\"],[\"United Farm Workers\",\"History\",\"Juvenile literature\"],[\"Chavez, Cesar 1927-\"],[\"Labor leaders\"],[\"Mexican Americans\",\"Biography\"],[\"United Farm Workers.\"],[\"Spanish language materials\",\"Bilingual\"],[\"Chavez, Cesar 1927-\",\"Literatura juvenil\"],[\"Li\\u0301deres obreros\",\"Estados Unidos\",\"Biografi\\u0301a\",\"Literatura juvenil\"],[\"Mexicano-americanos\",\"Biografi\\u0301a\",\"Literatura juvenil\"],[\"Sindicatos\",\"Trabajadores agri\\u0301colas\",\"Estados Unidos\",\"Historia\",\"Literatura juvenil\"],[\"Unio\\u0301n de Trabajadores Agri\\u0301colas\",\"Historia\",\"Literatura juvenil\"]],\"ocm48083852 \",\"Ce\\u0301sar Cha\\u0301vez : the struggle for justice = Ce\\u0301sar Cha\\u0301vez : la lucha por la justicia\",[\"text\"], { \"hi\":\"you\"} ]/*--E mvr--*/";
-
-
- printf("------------------------------------------------------------------\n");
- printf("\nOriginal JSON\n%s\n", jsons);
-
- /* parse the JSON string */
- jsonObject* yuk = jsonParseString(jsons);
-
- /* grab the class name from the object */
- printf("------------------------------------------------------------------\n");
- printf("\nParsed object with class %s\n", yuk->classname );
-
- /* turn the resulting object back into JSON */
- char* ccc = jsonObjectToJSON(yuk);
-
- /* extract a sub-object from the object and print its data*/
- o = jsonObjectGetIndex(yuk, 11);
- printf("\nRandom unicode string => %s\n", jsonObjectGetString(o));
-
- /* parse the new JSON string to build yet another object */
- jsonObject* yuk2 = jsonParseString(ccc);
-
- printf("------------------------------------------------------------------\n");
- /* turn that one back into JSON and print*/
- char* cccc = jsonObjectToJSON(yuk2);
- printf("\nFinal JSON: \n%s\n", cccc);
-
- char* string2 = strdup(jsons);
-
- printf("------------------------------------------------------------------\n");
- int x = 0;
- int count = 30;
- printf("\nParsing %d round trips at %f...\n", count, get_timestamp_millis());
-
- /* parse and stringify many times in a loop to check speed */
- while(x++ < count) {
-
- jsonObject* o = jsonParseString(string2);
- free(string2);
- string2 = jsonObjectToJSON(o);
- jsonObjectFree(o);
-
- if(!(x % 500))
- fprintf(stderr, "Round trip at %d\n", x);
- }
-
- printf("After Loop: %f\n", get_timestamp_millis());
-
-
- free(string2);
- free(ccc);
- free(cccc);
-
- /* only free the top level objects. objects that are 'children'
- of other objects should not be freed */
- jsonObjectFree(yuk);
- jsonObjectFree(yuk2);
-
-
-
- /* ------------------------------------------------------------------------ */
-
- /* parse a big JSON file */
- FILE* F = fopen("test.json", "r");
- if(!F) {
- perror("unable to open test.json for testing");
- exit(99);
- }
- fclose(F);
-
- char buf[10240];
- char smallbuf[512];
- bzero(buf, 10240);
- bzero(smallbuf, 512);
-
- while(fgets(smallbuf, 512, F))
- strcat(buf, smallbuf);
-
- /* dig our way into the JSON object we parsed, see test.json to get
- an idea of the object structure */
- printf("------------------------------------------------------------------\n");
- jsonObject* big = jsonParseString(buf);
- jsonObject* k = jsonObjectGetKey(big,"web-app");
- jsonObject* k2 = jsonObjectGetKey(k,"servlet");
- jsonObject* k3 = jsonObjectGetIndex(k2, 0);
- jsonObject* k4 = jsonObjectGetKey(k3,"servlet-class");
-
- jsonObjectFree(big);
-
- printf("\nValue for object with key 'servlet-class' in the JSON file => %s\n", jsonObjectGetString(k4));
-
-
- return 0;
-}
-
-
+++ /dev/null
-Note: Copy the source files found in this directory to the location
-specified in the 'Location' column within the source tree specified
-
-
-Patch Source Location Purpose
-------------------------------------------------------------------------------------------------------
-
-mod_offline.c jabberd-2.0s4 jabberd-2.0s4/sm/mod_offline.c Disables offline storage
-------------------------------------------------------------------------------------------------------
-
-nad.c jabberd-2.0s4 jabberd-2.0s4/util/nad.c Fixes segfault in a branch of code that we don't use
-
+++ /dev/null
-/*
- * jabberd - Jabber Open Source Server
- * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
- * Ryan Eatmon, Robert Norris
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
- */
-
-
-/** ! ! ! Patched version to disable offline storage for jabberd-2.0s4 ! ! ! */
-
-#include "sm.h"
-
-/** @file sm/mod_offline.c
- * @brief offline storage
- * @author Robert Norris
- * $Date$
- * $Revision$
- */
-
-typedef struct _mod_offline_st {
- int dropmessages;
- int dropsubscriptions;
-} *mod_offline_t;
-
-static mod_ret_t _offline_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) {
- st_ret_t ret;
- os_t os;
- os_object_t o;
- os_type_t ot;
- nad_t nad;
- pkt_t queued;
- int ns, elem, attr;
- char cttl[15], cstamp[18];
- time_t ttl, stamp;
-
- /* if they're becoming available for the first time */
- if(pkt->type == pkt_PRESENCE && pkt->to == NULL && sess->user->top == NULL) {
-
- ret = storage_get(pkt->sm->st, "queue", jid_user(sess->jid), NULL, &os);
- if(ret != st_SUCCESS) {
- log_debug(ZONE, "storage_get returned %d", ret);
- return mod_PASS;
- }
-
- if(os_iter_first(os))
- do {
- o = os_iter_object(os);
-
- if(os_object_get(o, "xml", (void **) &nad, &ot)) {
- queued = pkt_new(pkt->sm, nad_copy(nad));
- if(queued == NULL) {
- log_debug(ZONE, "invalid queued packet, not delivering");
- } else {
- /* check expiry as necessary */
- if((ns = nad_find_scoped_namespace(queued->nad, uri_EXPIRE, NULL)) >= 0 &&
- (elem = nad_find_elem(queued->nad, 1, ns, "x", 1)) >= 0 &&
- (attr = nad_find_attr(queued->nad, elem, -1, "seconds", NULL)) >= 0) {
- snprintf(cttl, 15, "%.*s", NAD_AVAL_L(queued->nad, attr), NAD_AVAL(queued->nad, attr));
- ttl = atoi(cttl);
-
- /* it should have a x:delay stamp, because we stamp everything we store */
- if((ns = nad_find_scoped_namespace(queued->nad, uri_DELAY, NULL)) >= 0 &&
- (elem = nad_find_elem(queued->nad, 1, ns, "x", 1)) >= 0 &&
- (attr = nad_find_attr(queued->nad, elem, -1, "stamp", NULL)) >= 0) {
- snprintf(cstamp, 18, "%.*s", NAD_AVAL_L(queued->nad, attr), NAD_AVAL(queued->nad, attr));
- stamp = datetime_in(cstamp);
-
- if(stamp + ttl <= time(NULL)) {
- log_debug(ZONE, "queued packet has expired, dropping");
- pkt_free(queued);
- continue;
- }
- }
- }
-
- log_debug(ZONE, "delivering queued packet to %s", jid_full(sess->jid));
- pkt_sess(queued, sess);
- }
- }
- } while(os_iter_next(os));
-
- os_free(os);
-
- /* drop the spool */
- storage_delete(pkt->sm->st, "queue", jid_user(sess->jid), NULL);
- }
-
- /* pass it so that other modules and mod_presence can get it */
- return mod_PASS;
-}
-
-static mod_ret_t _offline_pkt_user(mod_instance_t mi, user_t user, pkt_t pkt) {
- mod_offline_t offline = (mod_offline_t) mi->mod->private;
- int ns, elem, attr;
- os_t os;
- os_object_t o;
- pkt_t event;
-
- /* send messages and s10ns to the top session */
- if(user->top != NULL && (pkt->type & pkt_MESSAGE || pkt->type & pkt_S10N)) {
- pkt_sess(pkt, user->top);
- return mod_HANDLED;
- }
-
- /* save messages and s10ns for later */
- if((pkt->type & pkt_MESSAGE && !offline->dropmessages) ||
- (pkt->type & pkt_S10N && !offline->dropsubscriptions)) {
- log_debug(ZONE, "saving message for later");
-
- pkt_delay(pkt, time(NULL), user->sm->id);
-
- /* new object */
- os = os_new();
- o = os_object_new(os);
-
- os_object_put(o, "xml", pkt->nad, os_type_NAD);
-
- /* store it */
- switch(storage_put(user->sm->st, "queue", jid_user(user->jid), os)) {
- case st_FAILED:
- os_free(os);
- return -stanza_err_INTERNAL_SERVER_ERROR;
-
- case st_NOTIMPL:
- os_free(os);
- return -stanza_err_SERVICE_UNAVAILABLE; /* xmpp-im 9.5#4 */
-
- default:
- os_free(os);
-
- /* send offline events if they asked for it */
- if((ns = nad_find_scoped_namespace(pkt->nad, uri_EVENT, NULL)) >= 0 &&
- (elem = nad_find_elem(pkt->nad, 1, ns, "x", 1)) >= 0 &&
- nad_find_elem(pkt->nad, elem, ns, "offline", 1) >= 0) {
-
- event = pkt_create(user->sm, "message", NULL, jid_full(pkt->from), jid_full(pkt->to));
-
- attr = nad_find_attr(pkt->nad, 1, -1, "type", NULL);
- if(attr >= 0)
- nad_set_attr(event->nad, 1, -1, "type", NAD_AVAL(pkt->nad, attr), NAD_AVAL_L(pkt->nad, attr));
-
- ns = nad_add_namespace(event->nad, uri_EVENT, NULL);
- nad_append_elem(event->nad, ns, "x", 2);
- nad_append_elem(event->nad, ns, "offline", 3);
-
- nad_append_elem(event->nad, ns, "id", 3);
- attr = nad_find_attr(pkt->nad, 1, -1, "id", NULL);
- if(attr >= 0)
- nad_append_cdata(event->nad, NAD_AVAL(pkt->nad, attr), NAD_AVAL_L(pkt->nad, attr), 4);
-
- pkt_router(event);
- }
-
- pkt_free(pkt);
- return mod_HANDLED;
- }
- }
-
- return mod_PASS;
-}
-
-static void _offline_user_delete(mod_instance_t mi, jid_t jid) {
- os_t os;
- os_object_t o;
- os_type_t ot;
- nad_t nad;
- pkt_t queued;
- int ns, elem, attr;
- char cttl[15], cstamp[18];
- time_t ttl, stamp;
-
- log_debug(ZONE, "deleting queue for %s", jid_user(jid));
-
- /* bounce the queue */
- if(storage_get(mi->mod->mm->sm->st, "queue", jid_user(jid), NULL, &os) == st_SUCCESS) {
- if(os_iter_first(os))
- do {
- o = os_iter_object(os);
-
- if(os_object_get(o, "xml", (void **) &nad, &ot)) {
- queued = pkt_new(mi->mod->mm->sm, nad);
- if(queued == NULL) {
- log_debug(ZONE, "invalid queued packet, not delivering");
- } else {
- /* check expiry as necessary */
- if((ns = nad_find_scoped_namespace(queued->nad, uri_EXPIRE, NULL)) >= 0 &&
- (elem = nad_find_elem(queued->nad, 1, ns, "x", 1)) >= 0 &&
- (attr = nad_find_attr(queued->nad, elem, -1, "seconds", NULL)) >= 0) {
- snprintf(cttl, 15, "%.*s", NAD_AVAL_L(queued->nad, attr), NAD_AVAL(queued->nad, attr));
- ttl = atoi(cttl);
-
- /* it should have a x:delay stamp, because we stamp everything we store */
- if((ns = nad_find_scoped_namespace(queued->nad, uri_DELAY, NULL)) >= 0 &&
- (elem = nad_find_elem(queued->nad, 1, ns, "x", 1)) >= 0 &&
- (attr = nad_find_attr(queued->nad, elem, -1, "stamp", NULL)) >= 0) {
- snprintf(cstamp, 18, "%.*s", NAD_AVAL_L(queued->nad, attr), NAD_AVAL(queued->nad, attr));
- stamp = datetime_in(cstamp);
-
- if(stamp + ttl <= time(NULL)) {
- log_debug(ZONE, "queued packet has expired, dropping");
- pkt_free(queued);
- continue;
- }
- }
- }
-
- log_debug(ZONE, "bouncing queued packet from %s", jid_full(queued->from));
- pkt_router(pkt_error(queued, stanza_err_ITEM_NOT_FOUND));
- }
- }
- } while(os_iter_next(os));
-
- os_free(os);
- }
-
- storage_delete(mi->sm->st, "queue", jid_user(jid), NULL);
-}
-
-static void _offline_free(module_t mod) {
- mod_offline_t offline = (mod_offline_t) mod->private;
-
- free(offline);
-}
-
-int offline_init(mod_instance_t mi, char *arg) {
- module_t mod = mi->mod;
- char *configval;
- mod_offline_t offline;
- int dropmessages = 0;
- int dropsubscriptions = 0;
-
- if(mod->init) return 0;
-
- configval = config_get_one(mod->mm->sm->config, "offline.dropmessages", 0);
- if (configval != NULL)
- dropmessages = 1;
- configval = config_get_one(mod->mm->sm->config, "offline.dropsubscriptions", 0);
- if (configval != NULL)
- dropsubscriptions = 1;
-
- offline = (mod_offline_t) malloc(sizeof(struct _mod_offline_st));
- offline->dropmessages = dropmessages;
- offline->dropsubscriptions = dropsubscriptions;
-
- mod->private = offline;
-
- mod->in_sess = _offline_in_sess;
- mod->pkt_user = _offline_pkt_user;
- mod->user_delete = _offline_user_delete;
- mod->free = _offline_free;
-
- return 0;
-}
+++ /dev/null
-/*
- * jabberd - Jabber Open Source Server
- * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
- * Ryan Eatmon, Robert Norris
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
- */
-
-
-/** ! ! ! Patched version to fix segfault issue for jabberd-2.0s4 ! ! ! */
-
-/**
- * !!! Things to do (after 2.0)
- *
- * - make nad_find_scoped_namespace() take an element index, and only search
- * the scope on that element (currently, it searchs all elements from
- * end to start, which isn't really correct, though it works in most cases
- *
- * - new functions:
- * * insert one nad (or part thereof) into another nad
- * * clear a part of a nad (like xmlnode_hide)
- *
- * - audit use of depth array and parent (see j2 bug #792)
- */
-
-#include "util.h"
-
-#ifdef HAVE_EXPAT
-#include "expat/expat.h"
-#endif
-
-/* define NAD_DEBUG to get pointer tracking - great for weird bugs that you can't reproduce */
-#ifdef NAD_DEBUG
-
-static xht _nad_alloc_tracked = NULL;
-static xht _nad_free_tracked = NULL;
-
-static void _nad_ptr_check(const char *func, nad_t nad) {
- char loc[24];
- snprintf(loc, sizeof(loc), "%x", (int) nad);
-
- if(xhash_get(_nad_alloc_tracked, loc) == NULL) {
- fprintf(stderr, ">>> NAD OP %s: 0x%x not allocated!\n", func, (int) nad);
- abort();
- }
-
- if(xhash_get(_nad_free_tracked, loc) != NULL) {
- fprintf(stderr, ">>> NAD OP %s: 0x%x previously freed!\n", func, (int) nad);
- abort();
- }
-
- fprintf(stderr, ">>> NAD OP %s: 0x%x\n", func, (int) nad);
-}
-#else
-#define _nad_ptr_check(func,nad)
-#endif
-
-#define BLOCKSIZE 1024
-
-/** internal: do and return the math and ensure it gets realloc'd */
-int _nad_realloc(void **oblocks, int len)
-{
- void *nblocks;
- int nlen;
-
- /* round up to standard block sizes */
- nlen = (((len-1)/BLOCKSIZE)+1)*BLOCKSIZE;
-
- /* keep trying till we get it */
- while((nblocks = realloc(*oblocks, nlen)) == NULL) sleep(1);
- *oblocks = nblocks;
- return nlen;
-}
-
-/** this is the safety check used to make sure there's always enough mem */
-#define NAD_SAFE(blocks, size, len) if((size) > len) len = _nad_realloc((void**)&(blocks),(size));
-
-/** internal: append some cdata and return the index to it */
-int _nad_cdata(nad_t nad, const char *cdata, int len)
-{
- NAD_SAFE(nad->cdata, nad->ccur + len, nad->clen);
-
- memcpy(nad->cdata + nad->ccur, cdata, len);
- nad->ccur += len;
- return nad->ccur - len;
-}
-
-/** internal: create a new attr on any given elem */
-int _nad_attr(nad_t nad, int elem, int ns, const char *name, const char *val, int vallen)
-{
- int attr;
-
- /* make sure there's mem for us */
- NAD_SAFE(nad->attrs, (nad->acur + 1) * sizeof(struct nad_attr_st), nad->alen);
-
- attr = nad->acur;
- nad->acur++;
- nad->attrs[attr].next = nad->elems[elem].attr;
- nad->elems[elem].attr = attr;
- nad->attrs[attr].lname = strlen(name);
- nad->attrs[attr].iname = _nad_cdata(nad,name,nad->attrs[attr].lname);
- if(vallen > 0)
- nad->attrs[attr].lval = vallen;
- else
- nad->attrs[attr].lval = strlen(val);
- nad->attrs[attr].ival = _nad_cdata(nad,val,nad->attrs[attr].lval);
- nad->attrs[attr].my_ns = ns;
-
- return attr;
-}
-
-/** create a new cache, simple pointer to a list of nads */
-nad_cache_t nad_cache_new(void)
-{
- nad_cache_t cache;
- while((cache = malloc(sizeof(nad_cache_t))) == NULL) sleep(1);
- *cache = NULL;
-
-#ifdef NAD_DEBUG
- if(_nad_alloc_tracked == NULL) _nad_alloc_tracked = xhash_new(501);
- if(_nad_free_tracked == NULL) _nad_free_tracked = xhash_new(501);
-#endif
-
- return cache;
-}
-
-
-/** free the cache and any nads in it */
-void nad_cache_free(nad_cache_t cache)
-{
- nad_t cur;
- while((cur = *cache) != NULL)
- {
- *cache = cur->next;
- free(cur->elems);
- free(cur->attrs);
- free(cur->nss);
- free(cur->cdata);
- free(cur->depths);
- free(cur);
- }
- free(cache);
-}
-
-/** get the next nad from the cache, or create some */
-nad_t nad_new(nad_cache_t cache)
-{
- nad_t nad;
-
-#ifndef NAD_DEBUG
- /* If cache==NULL, then this NAD is not in a cache */
-
- if ((cache!=NULL) && (*cache != NULL))
- {
- nad = *cache;
- *cache = nad->next;
- nad->ccur = nad->ecur = nad->acur = nad->ncur = 0;
- nad->scope = -1;
- nad->cache = cache;
- nad->next = NULL;
- return nad;
- }
-#endif
-
- while((nad = malloc(sizeof(struct nad_st))) == NULL) sleep(1);
- memset(nad,0,sizeof(struct nad_st));
-
- nad->scope = -1;
- nad->cache = cache;
-
-#ifdef NAD_DEBUG
- {
- char loc[24];
- snprintf(loc, sizeof(loc), "%x", (int) nad);
- xhash_put(_nad_alloc_tracked, pstrdup(xhash_pool(_nad_alloc_tracked), loc), (void *) 1);
- }
- _nad_ptr_check(__func__, nad);
-#endif
-
- return nad;
-}
-
-nad_t nad_copy(nad_t nad)
-{
- nad_t copy;
-
- _nad_ptr_check(__func__, nad);
-
- if(nad == NULL) return NULL;
-
- /* create a new nad not participating in a cache */
- copy = nad_new(NULL);
-
- /* if it's not large enough, make bigger */
- NAD_SAFE(copy->elems, nad->elen, copy->elen);
- NAD_SAFE(copy->attrs, nad->alen, copy->alen);
- NAD_SAFE(copy->nss, nad->nlen, copy->nlen);
- NAD_SAFE(copy->cdata, nad->clen, copy->clen);
-
- /* copy all data */
- memcpy(copy->elems, nad->elems, nad->elen);
- memcpy(copy->attrs, nad->attrs, nad->alen);
- memcpy(copy->nss, nad->nss, nad->nlen);
- memcpy(copy->cdata, nad->cdata, nad->clen);
-
- /* sync data */
- copy->ecur = nad->ecur;
- copy->acur = nad->acur;
- copy->ncur = nad->ncur;
- copy->ccur = nad->ccur;
-
- copy->scope = nad->scope;
-
- return copy;
-}
-
-/** free nad, or plug nad back in the cache */
-void nad_free(nad_t nad)
-{
- if(nad == NULL) return;
-
-#ifdef NAD_DEBUG
- _nad_ptr_check(__func__, nad);
- {
- char loc[24];
- snprintf(loc, sizeof(loc), "%x", (int) nad);
- xhash_zap(_nad_alloc_tracked, loc);
- xhash_put(_nad_free_tracked, pstrdup(xhash_pool(_nad_free_tracked), loc), (void *) nad);
- }
-#else
- /* If nad->cache != NULL, then put back into cache, otherwise this nad is not in a cache */
-
- if (nad->cache != NULL) {
- nad->next = *(nad->cache);
- *(nad->cache) = nad;
- return;
- }
-#endif
-
- /* Free nad */
- free(nad->elems);
- free(nad->attrs);
- free(nad->cdata);
- free(nad->nss);
- free(nad->depths);
-}
-
-/** locate the next elem at a given depth with an optional matching name */
-int nad_find_elem(nad_t nad, int elem, int ns, const char *name, int depth)
-{
- int my_ns;
- int lname = 0;
-
- _nad_ptr_check(__func__, nad);
-
- /* make sure there are valid args */
- if(elem >= nad->ecur || name == NULL) return -1;
-
- /* set up args for searching */
- depth = nad->elems[elem].depth + depth;
- if(name != NULL) lname = strlen(name);
-
- /* search */
- for(elem++;elem < nad->ecur;elem++)
- {
- /* if we hit one with a depth less than ours, then we don't have the
- * same parent anymore, bail */
- if(nad->elems[elem].depth < depth)
- return -1;
-
- if(nad->elems[elem].depth == depth && (lname <= 0 || (lname == nad->elems[elem].lname && strncmp(name,nad->cdata + nad->elems[elem].iname, lname) == 0)) &&
- (ns < 0 || ((my_ns = nad->elems[elem].my_ns) >= 0 && NAD_NURI_L(nad, ns) == NAD_NURI_L(nad, my_ns) && strncmp(NAD_NURI(nad, ns), NAD_NURI(nad, my_ns), NAD_NURI_L(nad, ns)) == 0)))
- return elem;
- }
-
- return -1;
-}
-
-/** get a matching attr on this elem, both name and optional val */
-int nad_find_attr(nad_t nad, int elem, int ns, const char *name, const char *val)
-{
- int attr, my_ns;
- int lname, lval = 0;
-
- _nad_ptr_check(__func__, nad);
-
- /* make sure there are valid args */
- if(elem >= nad->ecur || name == NULL) return -1;
-
- attr = nad->elems[elem].attr;
- lname = strlen(name);
- if(val != NULL) lval = strlen(val);
-
- while(attr >= 0)
- {
- /* hefty, match name and if a val, also match that */
- if(lname == nad->attrs[attr].lname && strncmp(name,nad->cdata + nad->attrs[attr].iname, lname) == 0 &&
- (lval <= 0 || (lval == nad->attrs[attr].lval && strncmp(val,nad->cdata + nad->attrs[attr].ival, lval) == 0)) &&
- (ns < 0 || ((my_ns = nad->attrs[attr].my_ns) >= 0 && NAD_NURI_L(nad, ns) == NAD_NURI_L(nad, my_ns) && strncmp(NAD_NURI(nad, ns), NAD_NURI(nad, my_ns), NAD_NURI_L(nad, ns)) == 0)))
- return attr;
- attr = nad->attrs[attr].next;
- }
- return -1;
-}
-
-/** get a matching ns on this elem, both uri and optional prefix */
-int nad_find_namespace(nad_t nad, int elem, const char *uri, const char *prefix)
-{
- int check, ns;
-
- _nad_ptr_check(__func__, nad);
-
- if(uri == NULL)
- return -1;
-
- /* work backwards through our parents, looking for our namespace on each one.
- * if we find it, link it. if not, the namespace is undeclared - for now, just drop it */
- check = elem;
- while(check >= 0)
- {
- ns = nad->elems[check].ns;
- while(ns >= 0)
- {
- if(strlen(uri) == NAD_NURI_L(nad, ns) && strncmp(uri, NAD_NURI(nad, ns), NAD_NURI_L(nad, ns)) == 0 && (prefix == NULL || (nad->nss[ns].iprefix >= 0 && strlen(prefix) == NAD_NPREFIX_L(nad, ns) && strncmp(prefix, NAD_NPREFIX(nad, ns), NAD_NPREFIX_L(nad, ns)) == 0)))
- return ns;
- ns = nad->nss[ns].next;
- }
- check = nad->elems[check].parent;
- }
-
- return -1;
-}
-
-/** find a namespace in scope */
-int nad_find_scoped_namespace(nad_t nad, const char *uri, const char *prefix)
-{
- int ns;
-
- _nad_ptr_check(__func__, nad);
-
- if(uri == NULL)
- return -1;
-
- for(ns = 0; ns < nad->ncur; ns++)
- {
- if(strlen(uri) == NAD_NURI_L(nad, ns) && strncmp(uri, NAD_NURI(nad, ns), NAD_NURI_L(nad, ns)) == 0 &&
- (prefix == NULL ||
- (nad->nss[ns].iprefix >= 0 &&
- strlen(prefix) == NAD_NPREFIX_L(nad, ns) && strncmp(prefix, NAD_NPREFIX(nad, ns), NAD_NPREFIX_L(nad, ns)) == 0)))
- return ns;
- }
-
- return -1;
-}
-
-/** create, update, or zap any matching attr on this elem */
-void nad_set_attr(nad_t nad, int elem, int ns, const char *name, const char *val, int vallen)
-{
- int attr;
-
- _nad_ptr_check(__func__, nad);
-
- /* find one to replace first */
- if((attr = nad_find_attr(nad, elem, ns, name, NULL)) < 0)
- {
- /* only create new if there's a value to store */
- if(val != NULL)
- _nad_attr(nad, elem, ns, name, val, vallen);
- return;
- }
-
- /* got matching, update value or zap */
- if(val == NULL)
- {
- nad->attrs[attr].lval = nad->attrs[attr].lname = 0;
- }else{
- if(vallen > 0)
- nad->attrs[attr].lval = vallen;
- else
- nad->attrs[attr].lval = strlen(val);
- nad->attrs[attr].ival = _nad_cdata(nad,val,nad->attrs[attr].lval);
- }
-
-}
-
-/** shove in a new child elem after the given one */
-int nad_insert_elem(nad_t nad, int parent, int ns, const char *name, const char *cdata)
-{
- int elem = parent + 1;
-
- _nad_ptr_check(__func__, nad);
-
- NAD_SAFE(nad->elems, (nad->ecur + 1) * sizeof(struct nad_elem_st), nad->elen);
-
- /* relocate all the rest of the elems (unless we're at the end already) */
- if(nad->ecur != elem)
- memmove(&nad->elems[elem + 1], &nad->elems[elem], (nad->ecur - elem) * sizeof(struct nad_elem_st));
- nad->ecur++;
-
- /* set up req'd parts of new elem */
- nad->elems[elem].parent = parent;
- nad->elems[elem].lname = strlen(name);
- nad->elems[elem].iname = _nad_cdata(nad,name,nad->elems[elem].lname);
- nad->elems[elem].attr = -1;
- nad->elems[elem].ns = nad->scope; nad->scope = -1;
- nad->elems[elem].itail = nad->elems[elem].ltail = 0;
- nad->elems[elem].my_ns = ns;
-
- /* add cdata if given */
- if(cdata != NULL)
- {
- nad->elems[elem].lcdata = strlen(cdata);
- nad->elems[elem].icdata = _nad_cdata(nad,cdata,nad->elems[elem].lcdata);
- }else{
- nad->elems[elem].icdata = nad->elems[elem].lcdata = 0;
- }
-
- /* parent/child */
- nad->elems[elem].depth = nad->elems[parent].depth + 1;
-
- return elem;
-}
-
-/** wrap an element with another element */
-void nad_wrap_elem(nad_t nad, int elem, int ns, const char *name)
-{
- int cur;
-
- _nad_ptr_check(__func__, nad);
-
- if(elem >= nad->ecur) return;
-
- NAD_SAFE(nad->elems, (nad->ecur + 1) * sizeof(struct nad_elem_st), nad->elen);
-
- /* relocate all the rest of the elems after us */
- memmove(&nad->elems[elem + 1], &nad->elems[elem], (nad->ecur - elem) * sizeof(struct nad_elem_st));
- nad->ecur++;
-
- /* set up req'd parts of new elem */
- nad->elems[elem].lname = strlen(name);
- nad->elems[elem].iname = _nad_cdata(nad,name,nad->elems[elem].lname);
- nad->elems[elem].attr = -1;
- nad->elems[elem].ns = nad->scope; nad->scope = -1;
- nad->elems[elem].itail = nad->elems[elem].ltail = 0;
- nad->elems[elem].icdata = nad->elems[elem].lcdata = 0;
- nad->elems[elem].my_ns = ns;
-
- /* raise the bar on all the children */
- nad->elems[elem+1].depth++;
- for(cur = elem + 2; cur < nad->ecur && nad->elems[cur].depth > nad->elems[elem].depth; cur++) nad->elems[cur].depth++;
-
- /* relink the parents */
- nad->elems[elem].parent = nad->elems[elem + 1].parent;
- nad->elems[elem + 1].parent = elem;
-}
-
-/** create a new elem on the list */
-int nad_append_elem(nad_t nad, int ns, const char *name, int depth)
-{
- int elem;
-
- _nad_ptr_check(__func__, nad);
-
- /* make sure there's mem for us */
- NAD_SAFE(nad->elems, (nad->ecur + 1) * sizeof(struct nad_elem_st), nad->elen);
-
- elem = nad->ecur;
- nad->ecur++;
- nad->elems[elem].lname = strlen(name);
- nad->elems[elem].iname = _nad_cdata(nad,name,nad->elems[elem].lname);
- nad->elems[elem].icdata = nad->elems[elem].lcdata = 0;
- nad->elems[elem].itail = nad->elems[elem].ltail = 0;
- nad->elems[elem].attr = -1;
- nad->elems[elem].ns = nad->scope; nad->scope = -1;
- nad->elems[elem].depth = depth;
- nad->elems[elem].my_ns = ns;
-
- /* make sure there's mem in the depth array, then track us */
- NAD_SAFE(nad->depths, (depth + 1) * sizeof(int), nad->dlen);
- nad->depths[depth] = elem;
-
- /* our parent is the previous guy in the depth array */
- if(depth <= 0)
- nad->elems[elem].parent = -1;
- else
- nad->elems[elem].parent = nad->depths[depth - 1];
-
- return elem;
-}
-
-/** attach new attr to the last elem */
-int nad_append_attr(nad_t nad, int ns, const char *name, const char *val)
-{
- _nad_ptr_check(__func__, nad);
-
- return _nad_attr(nad, nad->ecur - 1, ns, name, val, 0);
-}
-
-/** append new cdata to the last elem */
-void nad_append_cdata(nad_t nad, const char *cdata, int len, int depth)
-{
- int elem = nad->ecur - 1;
-
- _nad_ptr_check(__func__, nad);
-
- /* make sure this cdata is the child of the last elem to append */
- if(nad->elems[elem].depth == depth - 1)
- {
- if(nad->elems[elem].icdata == 0)
- nad->elems[elem].icdata = nad->ccur;
- _nad_cdata(nad,cdata,len);
- nad->elems[elem].lcdata += len;
- return;
- }
-
- /* otherwise, pin the cdata on the tail of the last element at this depth */
- elem = nad->depths[depth];
- if(nad->elems[elem].itail == 0)
- nad->elems[elem].itail = nad->ccur;
- _nad_cdata(nad,cdata,len);
- nad->elems[elem].ltail += len;
-}
-
-/** bring a new namespace into scope */
-int nad_add_namespace(nad_t nad, const char *uri, const char *prefix)
-{
- int ns;
-
- _nad_ptr_check(__func__, nad);
-
- /* only add it if its not already in scope */
- ns = nad_find_scoped_namespace(nad, uri, NULL);
- if(ns >= 0)
- return ns;
-
- /* make sure there's mem for us */
- NAD_SAFE(nad->nss, (nad->ncur + 1) * sizeof(struct nad_ns_st), nad->nlen);
-
- ns = nad->ncur;
- nad->ncur++;
- nad->nss[ns].next = nad->scope;
- nad->scope = ns;
-
- nad->nss[ns].luri = strlen(uri);
- nad->nss[ns].iuri = _nad_cdata(nad, uri, nad->nss[ns].luri);
- if(prefix != NULL)
- {
- nad->nss[ns].lprefix = strlen(prefix);
- nad->nss[ns].iprefix = _nad_cdata(nad, prefix, nad->nss[ns].lprefix);
- }
- else
- nad->nss[ns].iprefix = -1;
-
- return ns;
-}
-
-/** declare a namespace on an already-existing element */
-int nad_append_namespace(nad_t nad, int elem, const char *uri, const char *prefix) {
- int ns;
-
- _nad_ptr_check(__func__, nad);
-
- /* see if its already scoped on this element */
- ns = nad_find_namespace(nad, elem, uri, NULL);
- if(ns >= 0)
- return ns;
-
- /* make some room */
- NAD_SAFE(nad->nss, (nad->ncur + 1) * sizeof(struct nad_ns_st), nad->nlen);
-
- ns = nad->ncur;
- nad->ncur++;
- nad->nss[ns].next = nad->elems[elem].ns;
- nad->elems[elem].ns = ns;
-
- nad->nss[ns].luri = strlen(uri);
- nad->nss[ns].iuri = _nad_cdata(nad, uri, nad->nss[ns].luri);
- if(prefix != NULL)
- {
- nad->nss[ns].lprefix = strlen(prefix);
- nad->nss[ns].iprefix = _nad_cdata(nad, prefix, nad->nss[ns].lprefix);
- }
- else
- nad->nss[ns].iprefix = -1;
-
- return ns;
-}
-
-void _nad_escape(nad_t nad, int data, int len, int flag)
-{
- char *c;
- int ic;
-
- if(len <= 0) return;
-
- /* first, if told, find and escape ' */
- while(flag >= 3 && (c = memchr(nad->cdata + data,'\'',len)) != NULL)
- {
- /* get offset */
- ic = c - nad->cdata;
-
- /* cute, eh? handle other data before this normally */
- _nad_escape(nad, data, ic - data, 2);
-
- /* ensure enough space, and add our escaped ' */
- NAD_SAFE(nad->cdata, nad->ccur + 6, nad->clen);
- memcpy(nad->cdata + nad->ccur, "'", 6);
- nad->ccur += 6;
-
- /* just update and loop for more */
- len -= (ic+1) - data;
- data = ic+1;
- }
-
- /* next look for < */
- while(flag >= 2 && (c = memchr(nad->cdata + data,'<',len)) != NULL)
- {
- ic = c - nad->cdata;
- _nad_escape(nad, data, ic - data, 1);
-
- /* ensure enough space, and add our escaped < */
- NAD_SAFE(nad->cdata, nad->ccur + 4, nad->clen);
- memcpy(nad->cdata + nad->ccur, "<", 4);
- nad->ccur += 4;
-
- /* just update and loop for more */
- len -= (ic+1) - data;
- data = ic+1;
- }
-
- /* check for ]]>, we need to escape the > */
- /* WE DID THIS (add the '0' as the first test to the while loop
- because the loops dies 3 lines in... (and we don't reall
- need this)) ...
- */
- while( 0 && flag >= 1 && (c = memchr(nad->cdata + data, '>', len)) != NULL)
- {
- ic = c - nad->cdata;
-
- _nad_escape(nad, data, ic - data, 0);
-
- /* check for the sequence */
-
- if( c >= nad->cdata + 2 && c[-1] == ']' && c[-2] == ']')
- {
- /* ensure enough space, and add our escaped > */
- NAD_SAFE(nad->cdata, nad->ccur + 4, nad->clen);
- memcpy(nad->cdata + nad->ccur, ">", 4);
- nad->ccur += 4;
- }
-
- /* otherwise, just plug the > in as-is */
- else
- {
- NAD_SAFE(nad->cdata, nad->ccur + 1, nad->clen);
- *(nad->cdata + nad->ccur) = '>';
- nad->ccur++;
- }
-
- /* just update and loop for more */
- len -= (ic+1) - data;
- data = ic+1;
- }
-
- /* if & is found, escape it */
- while((c = memchr(nad->cdata + data,'&',len)) != NULL)
- {
- ic = c - nad->cdata;
-
- /* ensure enough space */
- NAD_SAFE(nad->cdata, nad->ccur + 5 + (ic - data), nad->clen);
-
- /* handle normal data */
- memcpy(nad->cdata + nad->ccur, nad->cdata + data, (ic - data));
- nad->ccur += (ic - data);
-
- /* append escaped < */
- memcpy(nad->cdata + nad->ccur, "&", 5);
- nad->ccur += 5;
-
- /* just update and loop for more */
- len -= (ic+1) - data;
- data = ic+1;
- }
-
- /* nothing exciting, just append normal cdata */
- NAD_SAFE(nad->cdata, nad->ccur + len, nad->clen);
- memcpy(nad->cdata + nad->ccur, nad->cdata + data, len);
- nad->ccur += len;
-}
-
-/** internal recursive printing function */
-int _nad_lp0(nad_t nad, int elem)
-{
- int attr;
- int ndepth;
- int ns;
-
- /* there's a lot of code in here, but don't let that scare you, it's just duplication in order to be a bit more efficient cpu-wise */
-
- /* this whole thing is in a big loop for processing siblings */
- while(elem != nad->ecur)
- {
-
- /* make enough space for the opening element */
- ns = nad->elems[elem].my_ns;
- if(ns >= 0 && nad->nss[ns].iprefix >= 0)
- {
- NAD_SAFE(nad->cdata, nad->ccur + nad->elems[elem].lname + nad->nss[ns].lprefix + 2, nad->clen);
- } else {
- NAD_SAFE(nad->cdata, nad->ccur + nad->elems[elem].lname + 1, nad->clen);
- }
-
- /* opening tag */
- *(nad->cdata + nad->ccur++) = '<';
-
- /* add the prefix if necessary */
- if(ns >= 0 && nad->nss[ns].iprefix >= 0)
- {
- memcpy(nad->cdata + nad->ccur, nad->cdata + nad->nss[ns].iprefix, nad->nss[ns].lprefix);
- nad->ccur += nad->nss[ns].lprefix;
- *(nad->cdata + nad->ccur++) = ':';
- }
-
- /* copy in the name */
- memcpy(nad->cdata + nad->ccur, nad->cdata + nad->elems[elem].iname, nad->elems[elem].lname);
- nad->ccur += nad->elems[elem].lname;
-
- /* add the namespaces */
- for(ns = nad->elems[elem].ns; ns >= 0; ns = nad->nss[ns].next)
- {
- /* never explicitly declare the implicit xml namespace */
- if(nad->nss[ns].luri == strlen(uri_XML) && strncmp(uri_XML, nad->cdata + nad->nss[ns].iuri, nad->nss[ns].luri) == 0)
- continue;
-
- /* make space */
- if(nad->nss[ns].iprefix >= 0)
- {
- NAD_SAFE(nad->cdata, nad->ccur + nad->nss[ns].luri + nad->nss[ns].lprefix + 10, nad->clen);
- } else {
- NAD_SAFE(nad->cdata, nad->ccur + nad->nss[ns].luri + 9, nad->clen);
- }
-
- /* start */
- memcpy(nad->cdata + nad->ccur, " xmlns", 6);
- nad->ccur += 6;
-
- /* prefix if necessary */
- if(nad->nss[ns].iprefix >= 0)
- {
- *(nad->cdata + nad->ccur++) = ':';
- memcpy(nad->cdata + nad->ccur, nad->cdata + nad->nss[ns].iprefix, nad->nss[ns].lprefix);
- nad->ccur += nad->nss[ns].lprefix;
- }
-
- *(nad->cdata + nad->ccur++) = '=';
- *(nad->cdata + nad->ccur++) = '\'';
-
- /* uri */
- memcpy(nad->cdata + nad->ccur, nad->cdata + nad->nss[ns].iuri, nad->nss[ns].luri);
- nad->ccur += nad->nss[ns].luri;
-
- *(nad->cdata + nad->ccur++) = '\'';
- }
-
- for(attr = nad->elems[elem].attr; attr >= 0; attr = nad->attrs[attr].next)
- {
- if(nad->attrs[attr].lname <= 0) continue;
-
- /* make enough space for the wrapper part */
- ns = nad->attrs[attr].my_ns;
- if(ns >= 0 && nad->nss[ns].iprefix >= 0)
- {
- NAD_SAFE(nad->cdata, nad->ccur + nad->attrs[attr].lname + nad->nss[ns].lprefix + 4, nad->clen);
- } else {
- NAD_SAFE(nad->cdata, nad->ccur + nad->attrs[attr].lname + 3, nad->clen);
- }
-
- *(nad->cdata + nad->ccur++) = ' ';
-
- /* add the prefix if necessary */
- if(ns >= 0 && nad->nss[ns].iprefix >= 0)
- {
- memcpy(nad->cdata + nad->ccur, nad->cdata + nad->nss[ns].iprefix, nad->nss[ns].lprefix);
- nad->ccur += nad->nss[ns].lprefix;
- *(nad->cdata + nad->ccur++) = ':';
- }
-
- /* copy in the name parts */
- memcpy(nad->cdata + nad->ccur, nad->cdata + nad->attrs[attr].iname, nad->attrs[attr].lname);
- nad->ccur += nad->attrs[attr].lname;
- *(nad->cdata + nad->ccur++) = '=';
- *(nad->cdata + nad->ccur++) = '\'';
-
- /* copy in the escaped value */
- _nad_escape(nad, nad->attrs[attr].ival, nad->attrs[attr].lval, 3);
-
- /* make enough space for the closing quote and add it */
- NAD_SAFE(nad->cdata, nad->ccur + 1, nad->clen);
- *(nad->cdata + nad->ccur++) = '\'';
- }
-
- /* figure out what's next */
- if(elem+1 == nad->ecur)
- ndepth = -1;
- else
- ndepth = nad->elems[elem+1].depth;
-
- /* handle based on if there are children, update nelem after done */
- if(ndepth <= nad->elems[elem].depth)
- {
- /* make sure there's enough for what we could need */
- NAD_SAFE(nad->cdata, nad->ccur + 2, nad->clen);
- if(nad->elems[elem].lcdata == 0)
- {
- memcpy(nad->cdata + nad->ccur, "/>", 2);
- nad->ccur += 2;
- }else{
- *(nad->cdata + nad->ccur++) = '>';
-
- /* copy in escaped cdata */
- _nad_escape(nad, nad->elems[elem].icdata, nad->elems[elem].lcdata,2);
-
- /* make room */
- ns = nad->elems[elem].my_ns;
- if(ns >= 0 && nad->nss[ns].iprefix >= 0)
- {
- NAD_SAFE(nad->cdata, nad->ccur + 4 + nad->elems[elem].lname + nad->nss[ns].lprefix, nad->clen);
- } else {
- NAD_SAFE(nad->cdata, nad->ccur + 3 + nad->elems[elem].lname, nad->clen);
- }
-
- /* close tag */
- memcpy(nad->cdata + nad->ccur, "</", 2);
- nad->ccur += 2;
-
- /* add the prefix if necessary */
- if(ns >= 0 && nad->nss[ns].iprefix >= 0)
- {
- memcpy(nad->cdata + nad->ccur, nad->cdata + nad->nss[ns].iprefix, nad->nss[ns].lprefix);
- nad->ccur += nad->nss[ns].lprefix;
- *(nad->cdata + nad->ccur++) = ':';
- }
-
- memcpy(nad->cdata + nad->ccur, nad->cdata + nad->elems[elem].iname, nad->elems[elem].lname);
- nad->ccur += nad->elems[elem].lname;
- *(nad->cdata + nad->ccur++) = '>';
- }
-
- /* always try to append the tail */
- _nad_escape(nad, nad->elems[elem].itail, nad->elems[elem].ltail,2);
-
- /* if no siblings either, bail */
- if(ndepth < nad->elems[elem].depth)
- return elem+1;
-
- /* next sibling */
- elem++;
- }else{
- int nelem;
- /* process any children */
-
- /* close ourself and append any cdata first */
- NAD_SAFE(nad->cdata, nad->ccur + 1, nad->clen);
- *(nad->cdata + nad->ccur++) = '>';
- _nad_escape(nad, nad->elems[elem].icdata, nad->elems[elem].lcdata,2);
-
- /* process children */
- nelem = _nad_lp0(nad,elem+1);
-
- /* close and tail up */
- ns = nad->elems[elem].my_ns;
- if(ns >= 0 && nad->nss[ns].iprefix >= 0)
- {
- NAD_SAFE(nad->cdata, nad->ccur + 4 + nad->elems[elem].lname + nad->nss[ns].lprefix, nad->clen);
- } else {
- NAD_SAFE(nad->cdata, nad->ccur + 3 + nad->elems[elem].lname, nad->clen);
- }
- memcpy(nad->cdata + nad->ccur, "</", 2);
- nad->ccur += 2;
- if(ns >= 0 && nad->nss[ns].iprefix >= 0)
- {
- memcpy(nad->cdata + nad->ccur, nad->cdata + nad->nss[ns].iprefix, nad->nss[ns].lprefix);
- nad->ccur += nad->nss[ns].lprefix;
- *(nad->cdata + nad->ccur++) = ':';
- }
- memcpy(nad->cdata + nad->ccur, nad->cdata + nad->elems[elem].iname, nad->elems[elem].lname);
- nad->ccur += nad->elems[elem].lname;
- *(nad->cdata + nad->ccur++) = '>';
- _nad_escape(nad, nad->elems[elem].itail, nad->elems[elem].ltail,2);
-
- /* if the next element is not our sibling, we're done */
- if(nelem < nad->ecur && nad->elems[nelem].depth < nad->elems[elem].depth)
- return nelem;
-
- /* for next sibling in while loop */
- elem = nelem;
- }
-
- /* here's the end of that big while loop */
- }
-
- return elem;
-}
-
-void nad_print(nad_t nad, int elem, char **xml, int *len)
-{
- int ixml = nad->ccur;
-
- _nad_ptr_check(__func__, nad);
-
- _nad_lp0(nad,elem);
- *len = nad->ccur - ixml;
- *xml = nad->cdata + ixml;
-}
-
-/**
- * nads serialize to a buffer of this form:
- *
- * [buflen][ecur][acur][ncur][ccur][elems][attrs][nss][cdata]
- *
- * nothing is done with endianness or word length, so the nad must be
- * serialized and deserialized on the same platform
- *
- * buflen is not actually used by deserialize(), but is provided as a
- * convenience to the application so it knows how many bytes to read before
- * passing them in to deserialize()
- *
- * the depths array is not stored, so after deserialization
- * nad_append_elem() and nad_append_cdata() will not work. this is rarely
- * a problem
- */
-
-void nad_serialize(nad_t nad, char **buf, int *len) {
- char *pos;
-
- _nad_ptr_check(__func__, nad);
-
- *len = sizeof(int) * 5 + /* 4 ints in nad_t, plus one for len */
- sizeof(struct nad_elem_st) * nad->ecur +
- sizeof(struct nad_attr_st) * nad->acur +
- sizeof(struct nad_ns_st) * nad->ncur +
- sizeof(char) * nad->ccur;
-
- *buf = (char *) malloc(*len);
- pos = *buf;
-
- * (int *) pos = *len; pos += sizeof(int);
- * (int *) pos = nad->ecur; pos += sizeof(int);
- * (int *) pos = nad->acur; pos += sizeof(int);
- * (int *) pos = nad->ncur; pos += sizeof(int);
- * (int *) pos = nad->ccur; pos += sizeof(int);
-
- memcpy(pos, nad->elems, sizeof(struct nad_elem_st) * nad->ecur); pos += sizeof(struct nad_elem_st) * nad->ecur;
- memcpy(pos, nad->attrs, sizeof(struct nad_attr_st) * nad->acur); pos += sizeof(struct nad_attr_st) * nad->acur;
- memcpy(pos, nad->nss, sizeof(struct nad_ns_st) * nad->ncur); pos += sizeof(struct nad_ns_st) * nad->ncur;
- memcpy(pos, nad->cdata, sizeof(char) * nad->ccur);
-}
-
-nad_t nad_deserialize(nad_cache_t cache, const char *buf) {
- nad_t nad = nad_new(cache);
- const char *pos = buf + sizeof(int); /* skip len */
-
- _nad_ptr_check(__func__, nad);
-
- nad->ecur = * (int *) pos; pos += sizeof(int);
- nad->acur = * (int *) pos; pos += sizeof(int);
- nad->ncur = * (int *) pos; pos += sizeof(int);
- nad->ccur = * (int *) pos; pos += sizeof(int);
- nad->elen = nad->ecur;
- nad->alen = nad->acur;
- nad->nlen = nad->ncur;
- nad->clen = nad->ccur;
-
- if(nad->ecur > 0)
- {
- nad->elems = (struct nad_elem_st *) malloc(sizeof(struct nad_elem_st) * nad->ecur);
- memcpy(nad->elems, pos, sizeof(struct nad_elem_st) * nad->ecur);
- pos += sizeof(struct nad_elem_st) * nad->ecur;
- }
-
- if(nad->acur > 0)
- {
- nad->attrs = (struct nad_attr_st *) malloc(sizeof(struct nad_attr_st) * nad->acur);
- memcpy(nad->attrs, pos, sizeof(struct nad_attr_st) * nad->acur);
- pos += sizeof(struct nad_attr_st) * nad->acur;
- }
-
- if(nad->ncur > 0)
- {
- nad->nss = (struct nad_ns_st *) malloc(sizeof(struct nad_ns_st) * nad->ncur);
- memcpy(nad->nss, pos, sizeof(struct nad_ns_st) * nad->ncur);
- pos += sizeof(struct nad_ns_st) * nad->ncur;
- }
-
- if(nad->ccur > 0)
- {
- nad->cdata = (char *) malloc(sizeof(char) * nad->ccur);
- memcpy(nad->cdata, pos, sizeof(char) * nad->ccur);
- }
-
- return nad;
-}
-
-#ifdef HAVE_EXPAT
-
-/** parse a buffer into a nad */
-
-struct build_data {
- nad_t nad;
- int depth;
-};
-
-static void _nad_parse_element_start(void *arg, const char *name, const char **atts) {
- struct build_data *bd = (struct build_data *) arg;
- char buf[1024];
- char *uri, *elem, *prefix;
- const char **attr;
- int ns;
-
- /* make a copy */
- strncpy(buf, name, 1024);
- buf[1023] = '\0';
-
- /* expat gives us:
- prefixed namespaced elem: uri|elem|prefix
- default namespaced elem: uri|elem
- un-namespaced elem: elem
- */
-
- /* extract all the bits */
- uri = buf;
- elem = strchr(uri, '|');
- if(elem != NULL) {
- *elem = '\0';
- elem++;
- prefix = strchr(elem, '|');
- if(prefix != NULL) {
- *prefix = '\0';
- prefix++;
- }
- ns = nad_add_namespace(bd->nad, uri, prefix);
- } else {
- /* un-namespaced, just take it as-is */
- uri = NULL;
- elem = buf;
- prefix = NULL;
- ns = -1;
- }
-
- /* add it */
- nad_append_elem(bd->nad, ns, elem, bd->depth);
-
- /* now the attributes, one at a time */
- attr = atts;
- while(attr[0] != NULL) {
-
- /* make a copy */
- strncpy(buf, attr[0], 1024);
- buf[1023] = '\0';
-
- /* extract all the bits */
- uri = buf;
- elem = strchr(uri, '|');
- if(elem != NULL) {
- *elem = '\0';
- elem++;
- prefix = strchr(elem, '|');
- if(prefix != NULL) {
- *prefix = '\0';
- prefix++;
- }
- ns = nad_add_namespace(bd->nad, uri, prefix);
- } else {
- /* un-namespaced, just take it as-is */
- uri = NULL;
- elem = buf;
- prefix = NULL;
- ns = -1;
- }
-
- /* add it */
- nad_append_attr(bd->nad, ns, elem, (char *) attr[1]);
-
- attr += 2;
- }
-
- bd->depth++;
-}
-
-static void _nad_parse_element_end(void *arg, const char *name) {
- struct build_data *bd = (struct build_data *) arg;
-
- bd->depth--;
-}
-
-static void _nad_parse_cdata(void *arg, const char *str, int len) {
- struct build_data *bd = (struct build_data *) arg;
-
- /* go */
- nad_append_cdata(bd->nad, (char *) str, len, bd->depth);
-}
-
-static void _nad_parse_namespace_start(void *arg, const char *prefix, const char *uri) {
- struct build_data *bd = (struct build_data *) arg;
-
- nad_add_namespace(bd->nad, (char *) uri, (char *) prefix);
-}
-
-nad_t nad_parse(nad_cache_t cache, const char *buf, int len) {
- struct build_data bd;
- XML_Parser p;
-
- if(len == 0)
- len = strlen(buf);
-
- p = XML_ParserCreateNS(NULL, '|');
- if(p == NULL)
- return NULL;
-
- bd.nad = nad_new(cache);
- bd.depth = 0;
-
- XML_SetUserData(p, (void *) &bd);
- XML_SetElementHandler(p, _nad_parse_element_start, _nad_parse_element_end);
- XML_SetCharacterDataHandler(p, _nad_parse_cdata);
- XML_SetStartNamespaceDeclHandler(p, _nad_parse_namespace_start);
-
- if(!XML_Parse(p, buf, len, 1)) {
- XML_ParserFree(p);
- nad_free(bd.nad);
- return NULL;
- }
-
- XML_ParserFree(p);
-
- if(bd.depth != 0)
- return NULL;
-
- return bd.nad;
-}
-
-#endif
+++ /dev/null
-
-package JSON::number;
-sub new {
- my $class = shift;
- my $x = shift || $class;
- return bless \$x => __PACKAGE__;
-}
-
-use overload ( '""' => \&toString );
-
-sub toString { defined($_[1]) ? ${$_[1]} : ${$_[0]} }
-
-package JSON::bool::true;
-sub new { return bless {} => __PACKAGE__ }
-use overload ( '""' => \&toString );
-use overload ( 'bool' => sub { 1 } );
-use overload ( '0+' => sub { 1 } );
-
-sub toString { 'true' }
-
-package JSON::bool::false;
-sub new { return bless {} => __PACKAGE__ }
-use overload ( '""' => \&toString );
-use overload ( 'bool' => sub { 0 } );
-use overload ( '0+' => sub { 0 } );
-
-sub toString { 'false' }
-
-package JSON;
-use Unicode::Normalize;
-use vars qw/%_class_map/;
-
-sub register_class_hint {
- my $class = shift;
- my %args = @_;
-
- $_class_map{hints}{$args{hint}} = \%args;
- $_class_map{classes}{$args{name}} = \%args;
-}
-
-sub _JSON_regex {
- my $string = shift;
-
- $string =~ s/^\s* (
- { | # start object
- \[ | # start array
- -?\d+\.?\d* | # number literal
- "(?:(?:\\[\"])|[^\"])*" | # string literal
- (?:\/\*.+?\*\/) | # C comment
- true | # bool true
- false | # bool false
- null | # undef()
- : | # object key-value sep
- , | # list sep
- \] | # array end
- } # object end
- )
- \s*//sox;
- return ($string,$1);
-}
-
-sub lookup_class {
- my $self = shift;
- my $hint = shift;
- return $_class_map{hints}{$hint}{name}
-}
-
-sub lookup_hint {
- my $self = shift;
- my $class = shift;
- return $_class_map{classes}{$class}{hint}
-}
-
-sub _json_hint_to_class {
- my $type = shift;
- my $hint = shift;
-
- return $_class_map{hints}{$hint}{name} if (exists $_class_map{hints}{$hint});
-
- $type = 'hash' if ($type eq '}');
- $type = 'array' if ($type eq ']');
-
- JSON->register_class_hint(name => $hint, hint => $hint, type => $type);
-
- return $hint;
-}
-
-sub JSON2perl {
- my $class = shift;
- local $_ = shift;
-
- s/(?<!\\)\$/\\\$/gmo; # fixup $ for later
- s/(?<!\\)\@/\\\@/gmo; # fixup @ for later
- s/(?<!\\)\%/\\\%/gmo; # fixup % for later
-
- # Convert JSON Unicode...
- s/\\u([0-9a-fA-F]{4})/chr(hex($1))/esog;
-
- # handle class blessings
- s/\/\*--\s*S\w*?\s+\S+\s*--\*\// bless(/sog;
- s/(\]|\}|")\s*\/\*--\s*E\w*?\s+(\S+)\s*--\*\//$1 => _json_hint_to_class("$1", "$2")) /sog;
-
- my $re = qr/((?<!\\)"(?>(?<=\\)"|[^"])*(?<!\\)")/;
- # Grab strings...
- my @strings = /$re/sog;
-
- # Replace with code...
- #s/"(?:(?:\\[\"])|[^\"])*"/ do{ \$t = '"'.shift(\@strings).'"'; eval \$t;} /sog;
- s/$re/ eval shift(\@strings) /sog;
-
- # Perlify hash notation
- s/:/ => /sog;
-
- # Do numbers...
- #s/\b(-?\d+\.?\d*)\b/ JSON::number::new($1) /sog;
-
- # Change javascript stuff to perl...
- s/null/ undef /sog;
- s/true/ bless( {}, "JSON::bool::true") /sog;
- s/false/ bless( {}, "JSON::bool::false") /sog;
-
- my $ret;
- return eval '$ret = '.$_;
-}
-
-my $_json_index;
-sub ___JSON2perl {
- my $class = shift;
- my $data = shift;
-
- $data = [ split //, $data ];
-
- $_json_index = 0;
-
- return _json_parse_data($data);
-}
-
-sub _eat_WS {
- my $data = shift;
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-}
-
-sub _json_parse_data {
- my $data = shift;
-
- my $out;
-
- #warn "parse_data";
-
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-
- my $class = '';
-
- my $c = $$data[$_json_index];
-
- if ($c eq '/') {
- $_json_index++;
- $class = _json_parse_comment($data);
-
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
- $c = $$data[$_json_index];
- }
-
- if ($c eq '"') {
- $_json_index++;
- my $val = '';
-
- my $seen_slash = 0;
- my $done = 0;
- while (!$done) {
- my $c = $$data[$_json_index];
- #warn "c is $c";
-
- if ($c eq '\\') {
- if ($seen_slash) {
- $val .= '\\';
- $seen_slash = 0;
- } else {
- $seen_slash = 1;
- }
- } elsif ($c eq '"') {
- if ($seen_slash) {
- $val .= '"';
- $seen_slash = 0;
- } else {
- $done = 1;
- }
- } elsif ($c eq 't') {
- if ($seen_slash) {
- $val .= "\t";
- $seen_slash = 0;
- } else {
- $val .= 't';
- }
- } elsif ($c eq 'b') {
- if ($seen_slash) {
- $val .= "\b";
- $seen_slash = 0;
- } else {
- $val .= 'b';
- }
- } elsif ($c eq 'f') {
- if ($seen_slash) {
- $val .= "\f";
- $seen_slash = 0;
- } else {
- $val .= 'f';
- }
- } elsif ($c eq 'r') {
- if ($seen_slash) {
- $val .= "\r";
- $seen_slash = 0;
- } else {
- $val .= 'r';
- }
- } elsif ($c eq 'n') {
- if ($seen_slash) {
- $val .= "\n";
- $seen_slash = 0;
- } else {
- $val .= 'n';
- }
- } elsif ($c eq 'u') {
- if ($seen_slash) {
- $_json_index++;
- $val .= chr(hex(join('',$$data[$_json_index .. $_json_index + 3])));
- $_json_index += 3;
- $seen_slash = 0;
- } else {
- $val .= 'u';
- }
- } else {
- $val .= $c;
- }
- $_json_index++;
-
- #warn "string is $val";
- }
-
- $out = $val;
-
- #$out = _json_parse_string($data);
- } elsif ($c eq '[') {
- $_json_index++;
- $out = [];
-
- my $in_parse = 0;
- my $done = 0;
- while(!$done) {
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-
- if ($$data[$_json_index] eq ']') {
- $done = 1;
- $_json_index++;
- last;
- }
-
- if ($in_parse) {
- if ($$data[$_json_index] ne ',') {
- #warn "_json_parse_array: bad data, leaving array parser";
- last;
- }
- $_json_index++;
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
- }
-
- my $item = _json_parse_data($data);
-
- push @$out, $item;
- $in_parse++;
- }
-
- #$out = _json_parse_array($data);
- } elsif ($c eq '{') {
- $_json_index++;
- $out = {};
-
- my $in_parse = 0;
- my $done = 0;
- while(!$done) {
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-
- if ($$data[$_json_index] eq '}') {
- $done = 1;
- $_json_index++;
- last;
- }
-
- if ($in_parse) {
- if ($$data[$_json_index] ne ',') {
- #warn "_json_parse_object: bad data, leaving object parser";
- last;
- }
- $_json_index++;
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
- }
-
- my ($key,$value);
- $key = _json_parse_data($data);
-
- #warn "object key is $key";
-
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-
- if ($$data[$_json_index] ne ':') {
- #warn "_json_parse_object: bad data, leaving object parser";
- last;
- }
- $_json_index++;
- $value = _json_parse_data($data);
-
- $out->{$key} = $value;
- $in_parse++;
- }
- #$out = _json_parse_object($data);
- } elsif (lc($c) eq 'n') {
- if (lc(join('',$$data[$_json_index .. $_json_index + 3])) eq 'null') {
- $_json_index += 4;
- } else {
- warn "CRAP! bad null parsing...";
- }
- $out = undef;
- #$out = _json_parse_null($data);
- } elsif (lc($c) eq 't' or lc($c) eq 'f') {
- if (lc(join('',$$data[$_json_index .. $_json_index + 3])) eq 'true') {
- $out = 1;
- $_json_index += 4;
- } elsif (lc(join('',$$data[$_json_index .. $_json_index + 4])) eq 'false') {
- $out = 0;
- $_json_index += 5;
- } else {
- #warn "CRAP! bad bool parsing...";
- $out = undef;
- }
- #$out = _json_parse_bool($data);
- } elsif ($c =~ /\d+/o or $c eq '.' or $c eq '-') {
- my $val;
- while ($$data[$_json_index] =~ /[-\.0-9]+/io) {
- $val .= $$data[$_json_index];
- $_json_index++;
- }
- $out = 0+$val;
- #$out = _json_parse_number($data);
- }
-
- if ($class) {
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
- my $c = $$data[$_json_index];
-
- if ($c eq '/') {
- $_json_index++;
- _json_parse_comment($data)
- }
-
- bless( $out => lookup_class($class) );
- }
-
- $out;
-}
-
-sub _json_parse_null {
- my $data = shift;
-
- #warn "parse_null";
-
- if (lc(join('',$$data[$_json_index .. $_json_index + 3])) eq 'null') {
- $_json_index += 4;
- } else {
- #warn "CRAP! bad null parsing...";
- }
- return undef;
-}
-
-sub _json_parse_bool {
- my $data = shift;
-
- my $out;
-
- #warn "parse_bool";
-
- if (lc(join('',$$data[$_json_index .. $_json_index + 3])) eq 'true') {
- $out = 1;
- $_json_index += 4;
- } elsif (lc(join('',$$data[$_json_index .. $_json_index + 4])) eq 'false') {
- $out = 0;
- $_json_index += 5;
- } else {
- #warn "CRAP! bad bool parsing...";
- $out = undef;
- }
- return $out;
-}
-
-sub _json_parse_number {
- my $data = shift;
-
- #warn "parse_number";
-
- my $val;
- while ($$data[$_json_index] =~ /[-\.0-9]+/io) {
- $val .= $$data[$_json_index];
- $_json_index++;
- }
-
- return 0+$val;
-}
-
-sub _json_parse_object {
- my $data = shift;
-
- #warn "parse_object";
-
- my $out = {};
-
- my $in_parse = 0;
- my $done = 0;
- while(!$done) {
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-
- if ($$data[$_json_index] eq '}') {
- $done = 1;
- $_json_index++;
- last;
- }
-
- if ($in_parse) {
- if ($$data[$_json_index] ne ',') {
- #warn "_json_parse_object: bad data, leaving object parser";
- last;
- }
- $_json_index++;
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
- }
-
- my ($key,$value);
- $key = _json_parse_data($data);
-
- #warn "object key is $key";
-
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-
- if ($$data[$_json_index] ne ':') {
- #warn "_json_parse_object: bad data, leaving object parser";
- last;
- }
- $_json_index++;
- $value = _json_parse_data($data);
-
- $out->{$key} = $value;
- $in_parse++;
- }
-
- return $out;
-}
-
-sub _json_parse_array {
- my $data = shift;
-
- #warn "parse_array";
-
- my $out = [];
-
- my $in_parse = 0;
- my $done = 0;
- while(!$done) {
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
-
- if ($$data[$_json_index] eq ']') {
- $done = 1;
- $_json_index++;
- last;
- }
-
- if ($in_parse) {
- if ($$data[$_json_index] ne ',') {
- #warn "_json_parse_array: bad data, leaving array parser";
- last;
- }
- $_json_index++;
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
- }
-
- my $item = _json_parse_data($data);
-
- push @$out, $item;
- $in_parse++;
- }
-
- return $out;
-}
-
-
-sub _json_parse_string {
- my $data = shift;
-
- #warn "parse_string";
-
- my $val = '';
-
- my $seen_slash = 0;
- my $done = 0;
- while (!$done) {
- my $c = $$data[$_json_index];
- #warn "c is $c";
-
- if ($c eq '\\') {
- if ($seen_slash) {
- $val .= '\\';
- $seen_slash = 0;
- } else {
- $seen_slash = 1;
- }
- } elsif ($c eq '"') {
- if ($seen_slash) {
- $val .= '"';
- $seen_slash = 0;
- } else {
- $done = 1;
- }
- } elsif ($c eq 't') {
- if ($seen_slash) {
- $val .= "\t";
- $seen_slash = 0;
- } else {
- $val .= 't';
- }
- } elsif ($c eq 'b') {
- if ($seen_slash) {
- $val .= "\b";
- $seen_slash = 0;
- } else {
- $val .= 'b';
- }
- } elsif ($c eq 'f') {
- if ($seen_slash) {
- $val .= "\f";
- $seen_slash = 0;
- } else {
- $val .= 'f';
- }
- } elsif ($c eq 'r') {
- if ($seen_slash) {
- $val .= "\r";
- $seen_slash = 0;
- } else {
- $val .= 'r';
- }
- } elsif ($c eq 'n') {
- if ($seen_slash) {
- $val .= "\n";
- $seen_slash = 0;
- } else {
- $val .= 'n';
- }
- } elsif ($c eq 'u') {
- if ($seen_slash) {
- $_json_index++;
- $val .= chr(hex(join('',$$data[$_json_index .. $_json_index + 3])));
- $_json_index += 3;
- $seen_slash = 0;
- } else {
- $val .= 'u';
- }
- } else {
- $val .= $c;
- }
- $_json_index++;
-
- #warn "string is $val";
- }
-
- return $val;
-}
-
-sub _json_parse_comment {
- my $data = shift;
-
- #warn "parse_comment";
-
- if ($$data[$_json_index] eq '/') {
- $_json_index++;
- while (!($$data[$_json_index] eq "\n")) { $_json_index++ }
- $_json_index++;
- return undef;
- }
-
- my $class = '';
-
- if (join('',$$data[$_json_index .. $_json_index + 2]) eq '*--') {
- $_json_index += 3;
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
- if ($$data[$_json_index] eq 'S') {
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
- while ($$data[$_json_index] !~ /[-\s]+/o) {
- $class .= $$data[$_json_index];
- $_json_index++;
- }
- while ($$data[$_json_index] =~ /\s+/o) { $_json_index++ }
- }
- }
-
- while ($$data[$_json_index] ne '/') { $_json_index++ };
- $_json_index++;
-
- return $class;
-}
-
-sub old_JSON2perl {
- my ($class, $json) = @_;
-
- if (!defined($json)) {
- return undef;
- }
-
- $json =~ s/(?<!\\)\$/\\\$/gmo; # fixup $ for later
- $json =~ s/(?<!\\)\@/\\\@/gmo; # fixup @ for later
- $json =~ s/(?<!\\)\%/\\\%/gmo; # fixup % for later
-
- my @casts;
- my $casting_depth = 0;
- my $current_cast;
- my $element;
- my $output = '';
- while (($json,$element) = _JSON_regex($json)) {
-
- last unless ($element);
-
- if ($element eq 'null') {
- $output .= ' undef() ';
- next;
- } elsif ($element =~ /^\/\*--\s*S\w*?\s+(\w+)\s*--\*\/$/) {
- my $hint = $1;
- if (exists $_class_map{hints}{$hint}) {
- $casts[$casting_depth] = $hint;
- $output .= ' bless(';
- }
- next;
- } elsif ($element =~ /^\/\*/) {
- next;
- } elsif ($element =~ /^\d/) {
- $output .= "do { JSON::number::new($element) }";
- next;
- } elsif ($element eq '{' or $element eq '[') {
- $casting_depth++;
- } elsif ($element eq '}' or $element eq ']') {
- $casting_depth--;
- my $hint = $casts[$casting_depth];
- $casts[$casting_depth] = undef;
- if (defined $hint and exists $_class_map{hints}{$hint}) {
- $output .= $element . ',"'. $_class_map{hints}{$hint}{name} . '")';
- next;
- }
- } elsif ($element eq ':') {
- $output .= ' => ';
- next;
- } elsif ($element eq 'true') {
- $output .= 'bless( {}, "JSON::bool::true")';
- next;
- } elsif ($element eq 'false') {
- $output .= 'bless( {}, "JSON::bool::false")';
- next;
- }
-
- $output .= $element;
- }
-
- return eval $output;
-}
-
-sub perl2JSON {
- my ($class, $perl, $strict) = @_;
-
- my $output = '';
- if (!defined($perl)) {
- $output = '' if $strict;
- $output = 'null' unless $strict;
- } elsif (ref($perl) and ref($perl) =~ /^JSON/) {
- $output .= $perl;
- } elsif ( ref($perl) && exists($_class_map{classes}{ref($perl)}) ) {
- $output .= '/*--S '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
- if (lc($_class_map{classes}{ref($perl)}{type}) eq 'hash') {
- my %hash = %$perl;
- $output .= perl2JSON(undef,\%hash, $strict);
- } elsif (lc($_class_map{classes}{ref($perl)}{type}) eq 'array') {
- my @array = @$perl;
- $output .= perl2JSON(undef,\@array, $strict);
- }
- $output .= '/*--E '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
- } elsif (ref($perl) and ref($perl) =~ /HASH/) {
- $output .= '{';
- my $c = 0;
- for my $key (sort keys %$perl) {
- my $outkey = NFC($key);
- $output .= ',' if ($c);
-
- $outkey =~ s{\\}{\\\\}sgo;
- $outkey =~ s/"/\\"/sgo;
- $outkey =~ s/\t/\\t/sgo;
- $outkey =~ s/\f/\\f/sgo;
- $outkey =~ s/\r/\\r/sgo;
- $outkey =~ s/\n/\\n/sgo;
- $outkey =~ s/([\x{0080}-\x{fffd}])/sprintf('\u%0.4x',ord($1))/sgoe;
-
- $output .= '"'.$outkey.'":'. perl2JSON(undef,$$perl{$key}, $strict);
- $c++;
- }
- $output .= '}';
- } elsif (ref($perl) and ref($perl) =~ /ARRAY/) {
- $output .= '[';
- my $c = 0;
- for my $part (@$perl) {
- $output .= ',' if ($c);
-
- $output .= perl2JSON(undef,$part, $strict);
- $c++;
- }
- $output .= ']';
- } elsif (ref($perl) and ref($perl) =~ /CODE/) {
- $output .= perl2JSON(undef,$perl->(), $strict);
- } elsif (ref($perl) and ("$perl" =~ /^([^=]+)=(\w+)/o)) {
- my $type = $2;
- my $name = $1;
- JSON->register_class_hint(name => $name, hint => $name, type => lc($type));
- $output .= perl2JSON(undef,$perl, $strict);
- } else {
- $perl = NFC($perl);
- $perl =~ s{\\}{\\\\}sgo;
- $perl =~ s/"/\\"/sgo;
- $perl =~ s/\t/\\t/sgo;
- $perl =~ s/\f/\\f/sgo;
- $perl =~ s/\r/\\r/sgo;
- $perl =~ s/\n/\\n/sgo;
- $perl =~ s/([\x{0080}-\x{fffd}])/sprintf('\u%0.4x',ord($1))/sgoe;
- if (length($perl) < 10 and $perl =~ /^(?:\+|-)?\d*\.?\d+$/o and $perl !~ /^(?:\+|-)?0\d+/o ) {
- $output = $perl;
- } else {
- $output = '"'.$perl.'"';
- }
- }
-
- return $output;
-}
-
-my $depth = 0;
-sub perl2prettyJSON {
- my ($class, $perl, $nospace) = @_;
- $perl ||= $class;
-
- my $output = '';
- if (!defined($perl)) {
- $output = " "x$depth unless($nospace);
- $output .= 'null';
- } elsif (ref($perl) and ref($perl) =~ /^JSON/) {
- $output = " "x$depth unless($nospace);
- $output .= $perl;
- } elsif ( ref($perl) && exists($_class_map{classes}{ref($perl)}) ) {
- $depth++;
- $output .= "\n";
- $output .= " "x$depth;
- $output .= '/*--S '.$_class_map{classes}{ref($perl)}{hint}."--*/ ";
- if (lc($_class_map{classes}{ref($perl)}{type}) eq 'hash') {
- my %hash = %$perl;
- $output .= perl2prettyJSON(\%hash,undef,1);
- } elsif (lc($_class_map{classes}{ref($perl)}{type}) eq 'array') {
- my @array = @$perl;
- $output .= perl2prettyJSON(\@array,undef,1);
- }
- $output .= ' /*--E '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
- $depth--;
- } elsif (ref($perl) and ref($perl) =~ /HASH/) {
- $output .= " "x$depth unless ($nospace);
- $output .= "{\n";
- my $c = 0;
- $depth++;
- for my $key (sort keys %$perl) {
- $output .= ",\n" if ($c);
- $output .= " "x$depth;
- $output .= perl2prettyJSON($key)." : ".perl2prettyJSON($$perl{$key}, undef, 1);
- $c++;
- }
- $depth--;
- $output .= "\n";
- $output .= " "x$depth;
- $output .= '}';
- } elsif (ref($perl) and ref($perl) =~ /ARRAY/) {
- $output .= " "x$depth unless ($nospace);
- $output .= "[\n";
- my $c = 0;
- $depth++;
- for my $part (@$perl) {
- $output .= ",\n" if ($c);
- $output .= " "x$depth;
- $output .= perl2prettyJSON($part);
- $c++;
- }
- $depth--;
- $output .= "\n";
- $output .= " "x$depth;
- $output .= "]";
- } elsif (ref($perl) and ref($perl) =~ /CODE/) {
- $output .= perl2prettyJSON(undef,$perl->(), $nospace);
- } elsif (ref($perl) and "$perl" =~ /^([^=]+)=(\w{4,5})\(0x/) {
- my $type = $2;
- my $name = $1;
- register_class_hint(undef, name => $name, hint => $name, type => lc($type));
- $output .= perl2prettyJSON(undef,$perl);
- } else {
- $perl = NFC($perl);
- $perl =~ s/\\/\\\\/sgo;
- $perl =~ s/"/\\"/sgo;
- $perl =~ s/\t/\\t/sgo;
- $perl =~ s/\f/\\f/sgo;
- $perl =~ s/\r/\\r/sgo;
- $perl =~ s/\n/\\n/sgo;
- $perl =~ s/([\x{0080}-\x{fffd}])/sprintf('\u%0.4x',ord($1))/sgoe;
- $output .= " "x$depth unless($nospace);
- if (length($perl) < 10 and $perl =~ /^(?:\+|-)?\d*\.?\d+$/o and $perl !~ /^(?:\+|-)?0\d+/o ) {
- $output = $perl;
- } else {
- $output = '"'.$perl.'"';
- }
- }
-
- return $output;
-}
-
-1;
+++ /dev/null
-package OpenSRF;
-use strict;
-use Error;
-require UNIVERSAL::require;
-use vars qw/$VERSION $AUTOLOAD/;
-$VERSION = do { my @r=(q$Revision$=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
-
-=head1 OpenSRF
-
-=cut
-
-=head2 Overview
-
- Top level class for OpenSRF perl modules.
-
-=cut
-
-# Exception base classes
-#use Exception::Class
-# ( OpenSRFException => { fields => [ 'errno' ] });
-#push @Exception::Class::ISA, 'Error';
-
-=head3 AUTOLOAD()
-
- Traps methods calls for methods that have not been defined so they
- don't propogate up the class hierarchy.
-
-=cut
-sub AUTOLOAD {
- my $self = shift;
- my $type = ref($self) || $self;
- my $name = $AUTOLOAD;
- my $otype = ref $self;
-
- my ($package, $filename, $line) = caller;
- my ($package1, $filename1, $line1) = caller(1);
- my ($package2, $filename2, $line2) = caller(2);
- my ($package3, $filename3, $line3) = caller(3);
- my ($package4, $filename4, $line4) = caller(4);
- my ($package5, $filename5, $line5) = caller(5);
- $name =~ s/.*://; # strip fully-qualified portion
- warn <<" WARN";
-****
-** ${name}() isn't there. Please create me somewhere (like in $type)!
-** Error at $package ($filename), line $line
-** Call Stack (5 deep):
-** $package1 ($filename1), line $line1
-** $package2 ($filename2), line $line2
-** $package3 ($filename3), line $line3
-** $package4 ($filename4), line $line4
-** $package5 ($filename5), line $line5
-** Object type was $otype
-****
- WARN
-}
-
-
-
-=head3 alert_abstract()
-
- This method is called by abstract methods to ensure that
- the process dies when an undefined abstract method is called
-
-=cut
-sub alert_abstract() {
- my $c = shift;
- my $class = ref( $c ) || $c;
- my ($file, $line, $method) = (caller(1))[1..3];
- die " * Call to abstract method $method at $file, line $line";
-}
-
-sub class { return scalar(caller); }
-
-1;
+++ /dev/null
-package OpenSRF::AppSession;
-use OpenSRF::DOM;
-#use OpenSRF::DOM::Element::userAuth;
-use OpenSRF::DomainObject::oilsMessage;
-use OpenSRF::DomainObject::oilsMethod;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use OpenSRF::Transport::PeerHandle;
-use OpenSRF::Utils::Logger qw(:level);
-use OpenSRF::Utils::SettingsClient;
-use OpenSRF::Utils::Config;
-use OpenSRF::EX;
-use OpenSRF;
-use Exporter;
-use base qw/Exporter OpenSRF/;
-use Time::HiRes qw( time usleep );
-use warnings;
-use strict;
-
-our @EXPORT_OK = qw/CONNECTING INIT_CONNECTED CONNECTED DISCONNECTED CLIENT SERVER/;
-our %EXPORT_TAGS = ( state => [ qw/CONNECTING INIT_CONNECTED CONNECTED DISCONNECTED/ ],
- endpoint => [ qw/CLIENT SERVER/ ],
-);
-
-my $logger = "OpenSRF::Utils::Logger";
-
-our %_CACHE;
-our @_RESEND_QUEUE;
-
-sub CONNECTING { return 3 };
-sub INIT_CONNECTED { return 4 };
-sub CONNECTED { return 1 };
-sub DISCONNECTED { return 2 };
-
-sub CLIENT { return 2 };
-sub SERVER { return 1 };
-
-sub find {
- return undef unless (defined $_[1]);
- return $_CACHE{$_[1]} if (exists($_CACHE{$_[1]}));
-}
-
-sub transport_connected {
- my $self = shift;
- if( ! exists $self->{peer_handle} || ! $self->{peer_handle} ) {
- return 0;
- }
- return $self->{peer_handle}->tcp_connected();
-}
-
-sub connected {
- my $self = shift;
- return $self->state == CONNECTED;
-}
-# ----------------------------------------------------------------------------
-# Clears the transport buffers
-# call this if you are not through with the sesssion, but you want
-# to have a clean slate. You shouldn't have to call this if
-# you are correctly 'recv'ing all of the data from a request.
-# however, if you don't want all of the data, this will
-# slough off any excess
-# * * Note: This will delete data for all sessions using this transport
-# handle. For example, all client sessions use the same handle.
-# ----------------------------------------------------------------------------
-sub buffer_reset {
-
- my $self = shift;
- if( ! exists $self->{peer_handle} || ! $self->{peer_handle} ) {
- return 0;
- }
- $self->{peer_handle}->buffer_reset();
-}
-
-
-# when any incoming data is received, this method is called.
-sub server_build {
- my $class = shift;
- $class = ref($class) || $class;
-
- my $sess_id = shift;
- my $remote_id = shift;
- my $service = shift;
-
- warn "Missing args to server_build():\n" .
- "sess_id: $sess_id, remote_id: $remote_id, service: $service\n"
- unless ($sess_id and $remote_id and $service);
-
- return undef unless ($sess_id and $remote_id and $service);
-
- if ( my $thingy = $class->find($sess_id) ) {
- $thingy->remote_id( $remote_id );
- return $thingy;
- }
-
- if( $service eq "client" ) {
- #throw OpenSRF::EX::PANIC ("Attempting to build a client session as a server" .
- # " Session ID [$sess_id], remote_id [$remote_id]");
-
- warn "Attempting to build a client session as ".
- "a server Session ID [$sess_id], remote_id [$remote_id]";
-
- $logger->debug("Attempting to build a client session as ".
- "a server Session ID [$sess_id], remote_id [$remote_id]", ERROR );
-
- return undef;
- }
-
- my $config_client = OpenSRF::Utils::SettingsClient->new();
- my $stateless = $config_client->config_value("apps", $service, "stateless");
-
- #my $max_requests = $conf->$service->max_requests;
- my $max_requests = $config_client->config_value("apps",$service,"max_requests");
- $logger->debug( "Max Requests for $service is $max_requests", INTERNAL ) if (defined $max_requests);
-
- $logger->transport( "AppSession creating new session: $sess_id", INTERNAL );
-
- my $self = bless { recv_queue => [],
- request_queue => [],
- requests => 0,
- session_data => {},
- callbacks => {},
- endpoint => SERVER,
- state => CONNECTING,
- session_id => $sess_id,
- remote_id => $remote_id,
- peer_handle => OpenSRF::Transport::PeerHandle->retrieve($service),
- max_requests => $max_requests,
- session_threadTrace => 0,
- service => $service,
- stateless => $stateless,
- } => $class;
-
- return $_CACHE{$sess_id} = $self;
-}
-
-sub session_data {
- my $self = shift;
- my ($name, $datum) = @_;
-
- $self->{session_data}->{$name} = $datum if (defined $datum);
- return $self->{session_data}->{$name};
-}
-
-sub service { return shift()->{service}; }
-
-sub continue_request {
- my $self = shift;
- $self->{'requests'}++;
- return 1 if (!$self->{'max_requests'});
- return $self->{'requests'} <= $self->{'max_requests'} ? 1 : 0;
-}
-
-sub last_sent_payload {
- my( $self, $payload ) = @_;
- if( $payload ) {
- return $self->{'last_sent_payload'} = $payload;
- }
- return $self->{'last_sent_payload'};
-}
-
-sub last_sent_type {
- my( $self, $type ) = @_;
- if( $type ) {
- return $self->{'last_sent_type'} = $type;
- }
- return $self->{'last_sent_type'};
-}
-
-sub get_app_targets {
- my $app = shift;
-
- my $conf = OpenSRF::Utils::Config->current;
- my $router_name = $conf->bootstrap->router_name || 'router';
- my $routers = $conf->bootstrap->domains;
-
- unless($router_name and $routers) {
- throw OpenSRF::EX::Config
- ("Missing router config information 'router_name' and 'routers'");
- }
-
- my @targets;
- for my $router (@$routers) {
- push @targets, "$router_name\@$router/$app";
- }
-
- return @targets;
-}
-
-sub stateless {
- my $self = shift;
- my $state = shift;
- $self->{stateless} = $state if (defined $state);
- return $self->{stateless};
-}
-
-# When we're a client and we want to connect to a remote service
-# create( $app, username => $user, secret => $passwd );
-# OR
-# create( $app, sysname => $user, secret => $shared_secret );
-sub create {
- my $class = shift;
- $class = ref($class) || $class;
-
- my $app = shift;
- my $api_level = shift;
- my $quiet = shift;
-
- $api_level = 1 if (!defined($api_level));
-
- $logger->debug( "AppSession creating new client session for $app", DEBUG );
-
- my $stateless = 0;
- my $c = OpenSRF::Utils::SettingsClient->new();
- # we can get an infinite loop if we're grabbing the settings and we
- # need the settings to grab the settings...
- if($app ne "opensrf.settings" || $c->has_config()) {
- $stateless = $c->config_value("apps", $app, "stateless");
- }
-
- my $sess_id = time . rand( $$ );
- while ( $class->find($sess_id) ) {
- $sess_id = time . rand( $$ );
- }
-
-
- my ($r_id) = get_app_targets($app);
-
- my $peer_handle = OpenSRF::Transport::PeerHandle->retrieve("client");
- if( ! $peer_handle ) {
- $peer_handle = OpenSRF::Transport::PeerHandle->retrieve("system_client");
- }
-
- my $self = bless { app_name => $app,
- #client_auth => $auth,
- #recv_queue => [],
- request_queue => [],
- endpoint => CLIENT,
- state => DISCONNECTED,#since we're init'ing
- session_id => $sess_id,
- remote_id => $r_id,
- raise_error => $quiet ? 0 : 1,
- api_level => $api_level,
- orig_remote_id => $r_id,
- peer_handle => $peer_handle,
- session_threadTrace => 0,
- stateless => $stateless,
- } => $class;
-
- $logger->debug( "Created new client session $app : $sess_id" );
-
- return $_CACHE{$sess_id} = $self;
-}
-
-sub raise_remote_errors {
- my $self = shift;
- my $err = shift;
- $self->{raise_error} = $err if (defined $err);
- return $self->{raise_error};
-}
-
-sub api_level {
- return shift()->{api_level};
-}
-
-sub app {
- return shift()->{app_name};
-}
-
-sub reset {
- my $self = shift;
- $self->remote_id($$self{orig_remote_id});
-}
-
-# 'connect' can be used as a constructor if called as a class method,
-# or used to connect a session that has disconnectd if called against
-# an existing session that seems to be disconnected, or was just built
-# using 'create' above.
-
-# connect( $app, username => $user, secret => $passwd );
-# OR
-# connect( $app, sysname => $user, secret => $shared_secret );
-
-# --- Returns undef if the connect attempt times out.
-# --- Returns the OpenSRF::EX object if one is returned by the server
-# --- Returns self if connected
-sub connect {
- my $self = shift;
- my $class = ref($self) || $self;
-
-
- if ( ref( $self ) and $self->state && $self->state == CONNECTED ) {
- $logger->transport("AppSession already connected", DEBUG );
- } else {
- $logger->transport("AppSession not connected, connecting..", DEBUG );
- }
- return $self if ( ref( $self ) and $self->state && $self->state == CONNECTED );
-
-
- my $app = shift;
- my $api_level = shift;
- $api_level = 1 unless (defined $api_level);
-
- $self = $class->create($app, @_) if (!ref($self));
-
- return undef unless ($self);
-
- $self->{api_level} = $api_level;
-
- $self->reset;
- $self->state(CONNECTING);
- $self->send('CONNECT', "");
-
-
- # if we want to connect to settings, we may not have
- # any data for the settings client to work with...
- # just using a default for now XXX
-
- my $time_remaining = 5;
-
-=head blah
- my $client = OpenSRF::Utils::SettingsClient->new();
- my $trans = $client->config_value("client_connection","transport_host");
-
- if(!ref($trans)) {
- $time_remaining = $trans->{connect_timeout};
- } else {
- # XXX for now, just use the first
- $time_remaining = $trans->[0]->{connect_timeout};
- }
-=cut
-
- while ( $self->state != CONNECTED and $time_remaining > 0 ) {
- my $starttime = time;
- $self->queue_wait($time_remaining);
- my $endtime = time;
- $time_remaining -= ($endtime - $starttime);
- }
-
- return undef unless($self->state == CONNECTED);
-
- $self->stateless(0);
-
- return $self;
-}
-
-sub finish {
- my $self = shift;
- if( ! $self->session_id ) {
- return 0;
- }
-}
-
-sub unregister_callback {
- my $self = shift;
- my $type = shift;
- my $cb = shift;
- if (exists $self->{callbacks}{$type}) {
- delete $self->{callbacks}{$type}{$cb};
- return $cb;
- }
- return undef;
-}
-
-sub register_callback {
- my $self = shift;
- my $type = shift;
- my $cb = shift;
- my $cb_key = "$cb";
- $self->{callbacks}{$type}{$cb_key} = $cb;
- return $cb_key;
-}
-
-sub kill_me {
- my $self = shift;
- if( ! $self->session_id ) { return 0; }
-
- # run each 'death' callback;
- if (exists $self->{callbacks}{death}) {
- for my $sub (values %{$self->{callbacks}{death}}) {
- $sub->($self);
- }
- }
-
- $self->disconnect;
- $logger->transport( "AppSession killing self: " . $self->session_id(), DEBUG );
- delete $_CACHE{$self->session_id};
- delete($$self{$_}) for (keys %$self);
-}
-
-sub disconnect {
- my $self = shift;
-
- # run each 'disconnect' callback;
- if (exists $self->{callbacks}{disconnect}) {
- for my $sub (values %{$self->{callbacks}{disconnect}}) {
- $sub->($self);
- }
- }
-
- if ( !$self->stateless and $self->state != DISCONNECTED ) {
- $self->send('DISCONNECT', "") if ($self->endpoint == CLIENT);
- $self->state( DISCONNECTED );
- }
-
- $self->reset;
-}
-
-sub request {
- my $self = shift;
- my $meth = shift;
- return unless $self;
-
- # tell the logger to create a new xid - the logger will decide if it's really necessary
- $logger->mk_osrf_xid;
-
- my $method;
- if (!ref $meth) {
- $method = new OpenSRF::DomainObject::oilsMethod ( method => $meth );
- } else {
- $method = $meth;
- }
-
- $method->params( @_ );
-
- $self->send('REQUEST',$method);
-}
-
-sub full_request {
- my $self = shift;
- my $meth = shift;
-
- my $method;
- if (!ref $meth) {
- $method = new OpenSRF::DomainObject::oilsMethod ( method => $meth );
- } else {
- $method = $meth;
- }
-
- $method->params( @_ );
-
- $self->send(CONNECT => '', REQUEST => $method, DISCONNECT => '');
-}
-
-sub send {
- my $self = shift;
- my @payload_list = @_; # this is a Domain Object
-
- return unless ($self and $self->{peer_handle});
-
- $logger->debug( "In send", INTERNAL );
-
- my $tT;
-
- if( @payload_list % 2 ) { $tT = pop @payload_list; }
-
- if( ! @payload_list ) {
- $logger->debug( "payload_list param is incomplete in AppSession::send()", ERROR );
- return undef;
- }
-
- my @doc = ();
-
- my $disconnect = 0;
- my $connecting = 0;
-
- while( @payload_list ) {
-
- my ($msg_type, $payload) = ( shift(@payload_list), shift(@payload_list) );
-
- if ($msg_type eq 'DISCONNECT' ) {
- $disconnect++;
- if( $self->state == DISCONNECTED && !$connecting) {
- next;
- }
- }
-
- if( $msg_type eq "CONNECT" ) {
- $connecting++;
- }
-
- my $msg = OpenSRF::DomainObject::oilsMessage->new();
- $msg->type($msg_type);
-
- no warnings;
- $msg->threadTrace( $tT || int($self->session_threadTrace) || int($self->last_threadTrace) );
- use warnings;
-
- if ($msg->type eq 'REQUEST') {
- if ( !defined($tT) || $self->last_threadTrace != $tT ) {
- $msg->update_threadTrace;
- $self->session_threadTrace( $msg->threadTrace );
- $tT = $self->session_threadTrace;
- OpenSRF::AppRequest->new($self, $payload);
- }
- }
-
- $msg->api_level($self->api_level);
- $msg->payload($payload) if $payload;
-
- push @doc, $msg;
-
-
- $logger->info( "AppSession sending ".$msg->type." to ".$self->remote_id.
- " with threadTrace [".$msg->threadTrace."]" );
-
- }
-
- if ($self->endpoint == CLIENT and ! $disconnect) {
- $self->queue_wait(0);
-
-
- if($self->stateless && $self->state != CONNECTED) {
- $self->reset;
- $logger->debug("AppSession is stateless in send", INTERNAL );
- }
-
- if( !$self->stateless and $self->state != CONNECTED ) {
-
- $logger->debug( "Sending connect before request 1", INTERNAL );
-
- unless (($self->state == CONNECTING && $connecting )) {
- $logger->debug( "Sending connect before request 2", INTERNAL );
- my $v = $self->connect();
- if( ! $v ) {
- $logger->debug( "Unable to connect to remote service in AppSession::send()", ERROR );
- return undef;
- }
- if( ref($v) and $v->can("class") and $v->class->isa( "OpenSRF::EX" ) ) {
- return $v;
- }
- }
- }
-
- }
- my $json = JSON->perl2JSON(\@doc);
- $logger->internal("AppSession sending doc: $json");
-
- $self->{peer_handle}->send(
- to => $self->remote_id,
- thread => $self->session_id,
- body => $json );
-
- if( $disconnect) {
- $self->state( DISCONNECTED );
- }
-
- my $req = $self->app_request( $tT );
- $req->{_start} = time;
- return $req
-}
-
-sub app_request {
- my $self = shift;
- my $tT = shift;
-
- return undef unless (defined $tT);
- my ($req) = grep { $_->threadTrace == $tT } @{ $self->{request_queue} };
-
- return $req;
-}
-
-sub remove_app_request {
- my $self = shift;
- my $req = shift;
-
- my @list = grep { $_->threadTrace != $req->threadTrace } @{ $self->{request_queue} };
-
- $self->{request_queue} = \@list;
-}
-
-sub endpoint {
- return $_[0]->{endpoint};
-}
-
-
-sub session_id {
- my $self = shift;
- return $self->{session_id};
-}
-
-sub push_queue {
- my $self = shift;
- my $resp = shift;
- my $req = $self->app_request($resp->[1]);
- return $req->push_queue( $resp->[0] ) if ($req);
- push @{ $self->{recv_queue} }, $resp->[0];
-}
-
-sub last_threadTrace {
- my $self = shift;
- my $new_last_threadTrace = shift;
-
- my $old_last_threadTrace = $self->{last_threadTrace};
- if (defined $new_last_threadTrace) {
- $self->{last_threadTrace} = $new_last_threadTrace;
- return $new_last_threadTrace unless ($old_last_threadTrace);
- }
-
- return $old_last_threadTrace;
-}
-
-sub session_threadTrace {
- my $self = shift;
- my $new_last_threadTrace = shift;
-
- my $old_last_threadTrace = $self->{session_threadTrace};
- if (defined $new_last_threadTrace) {
- $self->{session_threadTrace} = $new_last_threadTrace;
- return $new_last_threadTrace unless ($old_last_threadTrace);
- }
-
- return $old_last_threadTrace;
-}
-
-sub last_message_type {
- my $self = shift;
- my $new_last_message_type = shift;
-
- my $old_last_message_type = $self->{last_message_type};
- if (defined $new_last_message_type) {
- $self->{last_message_type} = $new_last_message_type;
- return $new_last_message_type unless ($old_last_message_type);
- }
-
- return $old_last_message_type;
-}
-
-sub last_message_api_level {
- my $self = shift;
- my $new_last_message_api_level = shift;
-
- my $old_last_message_api_level = $self->{last_message_api_level};
- if (defined $new_last_message_api_level) {
- $self->{last_message_api_level} = $new_last_message_api_level;
- return $new_last_message_api_level unless ($old_last_message_api_level);
- }
-
- return $old_last_message_api_level;
-}
-
-sub remote_id {
- my $self = shift;
- my $new_remote_id = shift;
-
- my $old_remote_id = $self->{remote_id};
- if (defined $new_remote_id) {
- $self->{remote_id} = $new_remote_id;
- return $new_remote_id unless ($old_remote_id);
- }
-
- return $old_remote_id;
-}
-
-sub client_auth {
- return undef;
- my $self = shift;
- my $new_ua = shift;
-
- my $old_ua = $self->{client_auth};
- if (defined $new_ua) {
- $self->{client_auth} = $new_ua;
- return $new_ua unless ($old_ua);
- }
-
- return $old_ua->cloneNode(1);
-}
-
-sub state {
- my $self = shift;
- my $new_state = shift;
-
- my $old_state = $self->{state};
- if (defined $new_state) {
- $self->{state} = $new_state;
- return $new_state unless ($old_state);
- }
-
- return $old_state;
-}
-
-sub DESTROY {
- my $self = shift;
- delete $$self{$_} for keys %$self;
- return undef;
-}
-
-sub recv {
- my $self = shift;
- my @proto_args = @_;
- my %args;
-
- if ( @proto_args ) {
- if ( !(@proto_args % 2) ) {
- %args = @proto_args;
- } elsif (@proto_args == 1) {
- %args = ( timeout => @proto_args );
- }
- }
-
- #$logger->debug( ref($self). " recv_queue before wait: " . $self->_print_queue(), INTERNAL );
-
- if( exists( $args{timeout} ) ) {
- $args{timeout} = int($args{timeout});
- $self->{recv_timeout} = $args{timeout};
- }
-
- #$args{timeout} = 0 if ($self->complete);
-
- if(defined($args{timeout})) {
- $logger->debug( ref($self) ."->recv with timeout " . $args{timeout}, INTERNAL );
- }
-
- my $avail = @{ $self->{recv_queue} };
- $self->{remaining_recv_timeout} = $self->{recv_timeout};
-
- if (!$args{count}) {
- if (wantarray) {
- $args{count} = $avail;
- } else {
- $args{count} = 1;
- }
- }
-
- while ( $self->{remaining_recv_timeout} > 0 and $avail < $args{count} ) {
- last if $self->complete;
- my $starttime = time;
- $self->queue_wait($self->{remaining_recv_timeout});
- my $endtime = time;
- if ($self->{timeout_reset}) {
- $self->{timeout_reset} = 0;
- } else {
- $self->{remaining_recv_timeout} -= ($endtime - $starttime)
- }
- $avail = @{ $self->{recv_queue} };
- }
-
-
- my @list;
- while ( my $msg = shift @{ $self->{recv_queue} } ) {
- push @list, $msg;
- last if (scalar(@list) >= $args{count});
- }
-
- $logger->debug( "Number of matched responses: " . @list, DEBUG );
- $self->queue_wait(0); # check for statuses
-
- return $list[0] unless (wantarray);
- return @list;
-}
-
-sub push_resend {
- my $self = shift;
- push @OpenSRF::AppSession::_RESEND_QUEUE, @_;
-}
-
-sub flush_resend {
- my $self = shift;
- $logger->debug( "Resending..." . @_RESEND_QUEUE, INTERNAL );
- while ( my $req = shift @OpenSRF::AppSession::_RESEND_QUEUE ) {
- $req->resend unless $req->complete;
- }
-}
-
-
-sub queue_wait {
- my $self = shift;
- if( ! $self->{peer_handle} ) { return 0; }
- my $timeout = shift || 0;
- $logger->debug( "Calling queue_wait($timeout)" , INTERNAL );
- my $o = $self->{peer_handle}->process($timeout);
- $self->flush_resend;
- return $o;
-}
-
-sub _print_queue {
- my( $self ) = @_;
- my $string = "";
- foreach my $msg ( @{$self->{recv_queue}} ) {
- $string = $string . $msg->toString(1) . "\n";
- }
- return $string;
-}
-
-sub status {
- my $self = shift;
- return unless $self;
- $self->send( 'STATUS', @_ );
-}
-
-sub reset_request_timeout {
- my $self = shift;
- my $tt = shift;
- my $req = $self->app_request($tt);
- $req->{remaining_recv_timeout} = $req->{recv_timeout};
- $req->{timout_reset} = 1;
-}
-
-#-------------------------------------------------------------------------------
-
-package OpenSRF::AppRequest;
-use base qw/OpenSRF::AppSession/;
-use OpenSRF::Utils::Logger qw/:level/;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use Time::HiRes qw/time usleep/;
-
-sub new {
- my $class = shift;
- $class = ref($class) || $class;
-
- my $session = shift;
- my $threadTrace = $session->session_threadTrace || $session->last_threadTrace;
- my $payload = shift;
-
- my $self = { session => $session,
- threadTrace => $threadTrace,
- payload => $payload,
- complete => 0,
- timeout_reset => 0,
- recv_timeout => 30,
- remaining_recv_timeout => 30,
- recv_queue => [],
- };
-
- bless $self => $class;
-
- push @{ $self->session->{request_queue} }, $self;
-
- return $self;
-}
-
-sub recv_timeout {
- my $self = shift;
- my $timeout = shift;
- if (defined $timeout) {
- $self->{recv_timeout} = $timeout;
- $self->{remaining_recv_timeout} = $timeout;
- }
- return $self->{recv_timeout};
-}
-
-sub queue_size {
- my $size = @{$_[0]->{recv_queue}};
- return $size;
-}
-
-sub send {
- my $self = shift;
- return unless ($self and $self->session and !$self->complete);
- $self->session->send(@_);
-}
-
-sub finish {
- my $self = shift;
- return unless $self->session;
- $self->session->remove_app_request($self);
- delete($$self{$_}) for (keys %$self);
-}
-
-sub session {
- return shift()->{session};
-}
-
-sub complete {
- my $self = shift;
- my $complete = shift;
- return $self->{complete} if ($self->{complete});
- if (defined $complete) {
- $self->{complete} = $complete;
- $self->{_duration} = time - $self->{_start} if ($self->{complete});
- } else {
- $self->session->queue_wait(0);
- }
- return $self->{complete};
-}
-
-sub duration {
- my $self = shift;
- $self->wait_complete;
- return $self->{_duration};
-}
-
-sub wait_complete {
- my $self = shift;
- my $timeout = shift || 10;
- my $time_remaining = $timeout;
-
- while ( ! $self->complete and $time_remaining > 0 ) {
- my $starttime = time;
- $self->queue_wait($time_remaining);
- my $endtime = time;
- $time_remaining -= ($endtime - $starttime);
- }
-
- return $self->complete;
-}
-
-sub threadTrace {
- return shift()->{threadTrace};
-}
-
-sub push_queue {
- my $self = shift;
- my $resp = shift;
- if( !$resp ) { return 0; }
- if( UNIVERSAL::isa($resp, "Error")) {
- $self->{failed} = $resp;
- $self->complete(1);
- #return; eventually...
- }
- push @{ $self->{recv_queue} }, $resp;
-}
-
-sub failed {
- my $self = shift;
- return $self->{failed};
-}
-
-sub queue_wait {
- my $self = shift;
- return $self->session->queue_wait(@_)
-}
-
-sub payload { return shift()->{payload}; }
-
-sub resend {
- my $self = shift;
- return unless ($self and $self->session and !$self->complete);
- OpenSRF::Utils::Logger->debug( "I'm resending the request for threadTrace ". $self->threadTrace, DEBUG);
- return $self->session->send('REQUEST', $self->payload, $self->threadTrace );
-}
-
-sub status {
- my $self = shift;
- my $msg = shift;
- return unless ($self and $self->session and !$self->complete);
- $self->session->send( 'STATUS',$msg, $self->threadTrace );
-}
-
-sub stream_push {
- my $self = shift;
- my $msg = shift;
- $self->respond( $msg );
-}
-
-sub respond {
- my $self = shift;
- my $msg = shift;
- return unless ($self and $self->session and !$self->complete);
-
- my $response;
- if (ref($msg) && UNIVERSAL::isa($msg, 'OpenSRF::DomainObject::oilsResult')) {
- $response = $msg;
- } else {
- $response = new OpenSRF::DomainObject::oilsResult;
- $response->content($msg);
- }
-
- $self->session->send('RESULT', $response, $self->threadTrace);
-}
-
-sub respond_complete {
- my $self = shift;
- my $msg = shift;
- return unless ($self and $self->session and !$self->complete);
-
- my $response;
- if (ref($msg) && UNIVERSAL::isa($msg, 'OpenSRF::DomainObject::oilsResult')) {
- $response = $msg;
- } else {
- $response = new OpenSRF::DomainObject::oilsResult;
- $response->content($msg);
- }
-
- my $stat = OpenSRF::DomainObject::oilsConnectStatus->new(
- statusCode => STATUS_COMPLETE(),
- status => 'Request Complete' );
-
-
- $self->session->send( 'RESULT' => $response, 'STATUS' => $stat, $self->threadTrace);
- $self->complete(1);
-}
-
-sub register_death_callback {
- my $self = shift;
- my $cb = shift;
- $self->session->register_callback( death => $cb );
-}
-
-
-# utility method. checks to see of the request failed.
-# if so, throws an OpenSRF::EX::ERROR. if everything is
-# ok, it returns the content of the request
-sub gather {
- my $self = shift;
- my $finish = shift;
- $self->wait_complete;
- my $resp = $self->recv( timeout => 60 );
- if( $self->failed() ) {
- throw OpenSRF::EX::ERROR
- ($self->failed()->stringify());
- }
- if(!$resp) { return undef; }
- my $content = $resp->content;
- if($finish) { $self->finish();}
- return $content;
-}
-
-
-package OpenSRF::AppSubrequest;
-
-sub respond {
- my $self = shift;
- my $resp = shift;
- push @{$$self{resp}}, $resp if (defined $resp);
-}
-sub respond_complete { respond(@_); }
-
-sub new {
- my $class = shift;
- $class = ref($class) || $class;
- return bless({resp => [], @_}, $class);
-}
-
-sub responses { @{$_[0]->{resp}} }
-
-sub status {}
-
-
-1;
-
+++ /dev/null
-package OpenSRF::Application;
-use vars qw/$_app $log @_METHODS $thunk $server_class/;
-
-use base qw/OpenSRF/;
-use OpenSRF::AppSession;
-use OpenSRF::DomainObject::oilsMethod;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use OpenSRF::Utils::Logger qw/:level $logger/;
-use Data::Dumper;
-use Time::HiRes qw/time/;
-use OpenSRF::EX qw/:try/;
-use Carp;
-use JSON;
-#use OpenSRF::UnixServer; # to get the server class from UnixServer::App
-
-sub DESTROY{};
-
-use strict;
-use warnings;
-
-$log = 'OpenSRF::Utils::Logger';
-
-our $in_request = 0;
-our @pending_requests;
-
-sub package {
- my $self = shift;
- return 1 unless ref($self);
- return $self->{package};
-}
-
-sub signature {
- my $self = shift;
- return 0 unless ref($self);
- return $self->{signature};
-}
-
-sub argc {
- my $self = shift;
- return 0 unless ref($self);
- return $self->{argc};
-}
-
-sub api_name {
- my $self = shift;
- return 1 unless ref($self);
- return $self->{api_name};
-}
-
-sub api_level {
- my $self = shift;
- return 1 unless ref($self);
- return $self->{api_level};
-}
-
-sub server_class {
- my $class = shift;
- if($class) {
- $server_class = $class;
- }
- return $server_class;
-}
-
-sub thunk {
- my $self = shift;
- my $flag = shift;
- $thunk = $flag if (defined $flag);
- return $thunk;
-}
-
-sub application_implementation {
- my $self = shift;
- my $app = shift;
-
- if (defined $app) {
- $_app = $app;
- $_app->use;
- if( $@ ) {
- $log->error( "Error loading application_implementation: $app -> $@", ERROR);
- }
-
- }
-
- return $_app;
-}
-
-sub handler {
- my ($self, $session, $app_msg) = @_;
-
- if( ! $app_msg ) {
- return 1; # error?
- }
-
- my $app = $self->application_implementation;
-
- if ($session->last_message_type eq 'REQUEST') {
-
- my @p = $app_msg->params;
- my $method_name = $app_msg->method;
- my $method_proto = $session->last_message_api_level;
- $logger->info("CALL: $method_name [".join(', ',@p)."]");
-
- my $coderef = $app->method_lookup( $method_name, $method_proto, 1, 1 );
-
- unless ($coderef) {
- $session->status( OpenSRF::DomainObject::oilsMethodException->new(
- statusCode => STATUS_NOTFOUND(),
- status => "Method [$method_name] not found for $app"));
- return 1;
- }
-
- unless ($session->continue_request) {
- $session->status(
- OpenSRF::DomainObject::oilsConnectStatus->new(
- statusCode => STATUS_REDIRECTED(),
- status => 'Disconnect on max requests' ) );
- $session->kill_me;
- return 1;
- }
-
- if (ref $coderef) {
- my @args = $app_msg->params;
- my $appreq = OpenSRF::AppRequest->new( $session );
-
- $log->debug( "in_request = $in_request : [" . $appreq->threadTrace."]", INTERNAL );
- if( $in_request ) {
- $log->debug( "Pushing onto pending requests: " . $appreq->threadTrace, DEBUG );
- push @pending_requests, [ $appreq, \@args, $coderef ];
- return 1;
- }
-
-
- $in_request++;
-
- $log->debug( "Executing coderef for {$method_name}", INTERNAL );
-
- my $resp;
- try {
- # un-if(0) this block to enable param checking based on signature and argc
- if (0) {
- if (@args < $coderef->argc) {
- die "Not enough params passed to ".
- $coderef->api_name." : requires ". $coderef->argc
- }
- if (@args) {
- my $sig = $coderef->signature;
- if ($sig && exists $sig->{params}) {
- for my $p (0 .. scalar(@{ $sig->{params} }) - 1 ) {
- my $s = $sig->{params}->[$p];
- my $a = $args[$p];
- if ($s->{class} && JSON->lookup_hint(ref $a) ne $s->{class}) {
- die "Incorrect param class at position $p : should be a '$$s{class}'";
- } elsif ($s->{type}) {
- if (lc($s->{type}) eq 'object' && $a !~ /HASH/o) {
- die "Incorrect param type at position $p : should be an 'object'";
- } elsif (lc($s->{type}) eq 'array' && $a !~ /ARRAY/o) {
- die "Incorrect param type at position $p : should be an 'array'";
- } elsif (lc($s->{type}) eq 'number' && (ref($a) || $a !~ /^-?\d+(?:\.\d+)?$/o)) {
- die "Incorrect param type at position $p : should be a 'number'";
- } elsif (lc($s->{type}) eq 'string' && ref($a)) {
- die "Incorrect param type at position $p : should be a 'string'";
- }
- }
- }
- }
- }
- }
-
- my $start = time();
- $resp = $coderef->run( $appreq, @args);
- my $time = sprintf '%.3f', time() - $start;
-
- $log->debug( "Method duration for [$method_name]: ". $time );
- if( defined( $resp ) ) {
- $appreq->respond_complete( $resp );
- } else {
- $appreq->status( OpenSRF::DomainObject::oilsConnectStatus->new(
- statusCode => STATUS_COMPLETE(),
- status => 'Request Complete' ) );
- }
- } catch Error with {
- my $e = shift;
- warn "Caught error from 'run' method: $e\n";
-
- if(UNIVERSAL::isa($e,"Error")) {
- $e = $e->stringify();
- }
- my $sess_id = $session->session_id;
- $session->status(
- OpenSRF::DomainObject::oilsMethodException->new(
- statusCode => STATUS_INTERNALSERVERERROR(),
- status => " *** Call to [$method_name] failed for session ".
- "[$sess_id], thread trace ".
- "[".$appreq->threadTrace."]:\n$e\n"
- )
- );
- };
-
-
-
- # ----------------------------------------------
-
-
- # XXX may need this later
- # $_->[1] = 1 for (@OpenSRF::AppSession::_CLIENT_CACHE);
-
- $in_request--;
-
- $log->debug( "Pending Requests: " . scalar(@pending_requests), INTERNAL );
-
- # cycle through queued requests
- while( my $aref = shift @pending_requests ) {
- $in_request++;
- my $resp;
- try {
- # un-if(0) this block to enable param checking based on signature and argc
- if (0) {
- if (@args < $aref->[2]->argc) {
- die "Not enough params passed to ".
- $aref->[2]->api_name." : requires ". $aref->[2]->argc
- }
- if (@args) {
- my $sig = $aref->[2]->signature;
- if ($sig && exists $sig->{params}) {
- for my $p (0 .. scalar(@{ $sig->{params} }) - 1 ) {
- my $s = $sig->{params}->[$p];
- my $a = $args[$p];
- if ($s->{class} && JSON->lookup_hint(ref $a) ne $s->{class}) {
- die "Incorrect param class at position $p : should be a '$$s{class}'";
- } elsif ($s->{type}) {
- if (lc($s->{type}) eq 'object' && $a !~ /HASH/o) {
- die "Incorrect param type at position $p : should be an 'object'";
- } elsif (lc($s->{type}) eq 'array' && $a !~ /ARRAY/o) {
- die "Incorrect param type at position $p : should be an 'array'";
- } elsif (lc($s->{type}) eq 'number' && (ref($a) || $a !~ /^-?\d+(?:\.\d+)?$/o)) {
- die "Incorrect param type at position $p : should be a 'number'";
- } elsif (lc($s->{type}) eq 'string' && ref($a)) {
- die "Incorrect param type at position $p : should be a 'string'";
- }
- }
- }
- }
- }
- }
-
- my $start = time;
- my $response = $aref->[2]->run( $aref->[0], @{$aref->[1]} );
- my $time = sprintf '%.3f', time - $start;
- $log->debug( "Method duration for [".$aref->[2]->api_name." -> ".join(', ',@{$aref->[1]}).']: '.$time, DEBUG );
-
- $appreq = $aref->[0];
- if( ref( $response ) ) {
- $appreq->respond_complete( $response );
- } else {
- $appreq->status( OpenSRF::DomainObject::oilsConnectStatus->new(
- statusCode => STATUS_COMPLETE(),
- status => 'Request Complete' ) );
- }
- $log->debug( "Executed: " . $appreq->threadTrace, INTERNAL );
- } catch Error with {
- my $e = shift;
- if(UNIVERSAL::isa($e,"Error")) {
- $e = $e->stringify();
- }
- $session->status(
- OpenSRF::DomainObject::oilsMethodException->new(
- statusCode => STATUS_INTERNALSERVERERROR(),
- status => "Call to [".$aref->[2]->api_name."] faild: $e"
- )
- );
- };
- $in_request--;
- }
-
- return 1;
- }
-
- $log->info("Received non-REQUEST message in Application handler");
-
- my $res = OpenSRF::DomainObject::oilsMethodException->new(
- status => "Received non-REQUEST message in Application handler");
- $session->send('ERROR', $res);
- $session->kill_me;
- return 1;
-
- } else {
- $session->push_queue([ $app_msg, $session->last_threadTrace ]);
- }
-
- $session->last_message_type('');
- $session->last_message_api_level('');
-
- return 1;
-}
-
-sub is_registered {
- my $self = shift;
- my $api_name = shift;
- my $api_level = shift || 1;
- return exists($_METHODS[$api_level]{$api_name});
-}
-
-
-sub normalize_whitespace {
- my $txt = shift;
-
- $txt =~ s/^\s+//gso;
- $txt =~ s/\s+$//gso;
- $txt =~ s/\s+/ /gso;
- $txt =~ s/\n//gso;
- $txt =~ s/\. /\. /gso;
-
- return $txt;
-}
-
-sub parse_string_signature {
- my $string = shift;
- return [] unless $string;
- my @chunks = split(/\@/so, $string);
-
- my @params;
- my $ret;
- my $desc = '';
- for (@chunks) {
- if (/^return (.+)$/so) {
- $ret = [normalize_whitespace($1)];
- } elsif (/^param (\w+) \b(.+)$/so) {
- push @params, [ $1, normalize_whitespace($2) ];
- } else {
- $desc .= '@' if $desc;
- $desc .= $_;
- }
- }
-
- return [normalize_whitespace($desc),\@params, $ret];
-}
-
-sub parse_array_signature {
- my $array = shift;
- my ($d,$p,$r) = @$array;
- return {} unless ($d or $p or $r);
-
- return {
- desc => $d,
- params => [
- map {
- { name => $$_[0],
- desc => $$_[1],
- type => $$_[2],
- class => $$_[3],
- }
- } @$p
- ],
- 'return'=>
- { desc => $$r[0],
- type => $$r[1],
- class => $$r[2],
- }
- };
-}
-
-sub register_method {
- my $self = shift;
- my $app = ref($self) || $self;
- my %args = @_;
-
-
- throw OpenSRF::DomainObject::oilsMethodException unless ($args{method});
-
- $args{api_level} = 1 unless(defined($args{api_level}));
- $args{stream} ||= 0;
- $args{remote} ||= 0;
- $args{argc} ||= 0;
- $args{package} ||= $app;
- $args{server_class} = server_class();
- $args{api_name} ||= $args{server_class} . '.' . $args{method};
-
- # un-if(0) this block to enable signature parsing
- if (!$args{signature}) {
- if ($args{notes} && !ref($args{notes})) {
- $args{signature} =
- parse_array_signature( parse_string_signature( $args{notes} ) );
- }
- } elsif( !ref($args{signature}) ) {
- $args{signature} =
- parse_array_signature( parse_string_signature( $args{signature} ) );
- } elsif( ref($args{signature}) eq 'ARRAY') {
- $args{signature} =
- parse_array_signature( $args{signature} );
- }
-
- unless ($args{object_hint}) {
- ($args{object_hint} = $args{package}) =~ s/::/_/go;
- }
-
- JSON->register_class_hint( name => $args{package}, hint => $args{object_hint}, type => "hash" );
-
- $_METHODS[$args{api_level}]{$args{api_name}} = bless \%args => $app;
-
- __PACKAGE__->register_method(
- stream => 0,
- argc => $args{argc},
- api_name => $args{api_name}.'.atomic',
- method => 'make_stream_atomic',
- notes => "This is a system generated method. Please see the definition for $args{api_name}",
- ) if ($args{stream});
-}
-
-sub retrieve_remote_apis {
- my $method = shift;
- my $session = OpenSRF::AppSession->create('router');
- try {
- $session->connect or OpenSRF::EX::WARN->throw("Connection to router timed out");
- } catch Error with {
- my $e = shift;
- $log->debug( "Remote subrequest returned an error:\n". $e );
- return undef;
- } finally {
- return undef unless ($session->state == $session->CONNECTED);
- };
-
- my $req = $session->request( 'opensrf.router.info.class.list' );
- my $list = $req->recv;
-
- if( UNIVERSAL::isa($list,"Error") ) {
- throw $list;
- }
-
- my $content = $list->content;
-
- $req->finish;
- $session->finish;
- $session->disconnect;
-
- my %u_list = map { ($_ => 1) } @$content;
-
- for my $class ( keys %u_list ) {
- next if($class eq $server_class);
- populate_remote_method_cache($class, $method);
- }
-}
-
-sub populate_remote_method_cache {
- my $class = shift;
- my $meth = shift;
-
- my $session = OpenSRF::AppSession->create($class);
- try {
- $session->connect or OpenSRF::EX::WARN->throw("Connection to $class timed out");
-
- my $call = 'opensrf.system.method.all' unless (defined $meth);
- $call = 'opensrf.system.method' if (defined $meth);
-
- my $req = $session->request( $call, $meth );
-
- while (my $method = $req->recv) {
- next if (UNIVERSAL::isa($method, 'Error'));
-
- $method = $method->content;
- next if ( exists($_METHODS[$$method{api_level}]) &&
- exists($_METHODS[$$method{api_level}]{$$method{api_name}}) );
- $method->{remote} = 1;
- bless($method, __PACKAGE__ );
- $_METHODS[$$method{api_level}]{$$method{api_name}} = $method;
- }
-
- $req->finish;
- $session->finish;
- $session->disconnect;
-
- } catch Error with {
- my $e = shift;
- $log->debug( "Remote subrequest returned an error:\n". $e );
- return undef;
- };
-}
-
-sub method_lookup {
- my $self = shift;
- my $method = shift;
- my $proto = shift;
- my $no_recurse = shift || 0;
- my $no_remote = shift || 0;
-
- # this instead of " || 1;" above to allow api_level 0
- $proto = $self->api_level unless (defined $proto);
-
- my $class = ref($self) || $self;
-
- $log->debug("Lookup of [$method] by [$class] in api_level [$proto]", DEBUG);
- $log->debug("Available methods\n\t".join("\n\t", keys %{ $_METHODS[$proto] }), INTERNAL);
-
- my $meth;
- if (__PACKAGE__->thunk) {
- for my $p ( reverse(1 .. $proto) ) {
- if (exists $_METHODS[$p]{$method}) {
- $meth = $_METHODS[$p]{$method};
- }
- }
- } else {
- if (exists $_METHODS[$proto]{$method}) {
- $meth = $_METHODS[$proto]{$method};
- }
- }
-
- if (defined $meth) {
- if($no_remote and $meth->{remote}) {
- $log->debug("OH CRAP We're not supposed to return remote methods", WARN);
- return undef;
- }
-
- } elsif (!$no_recurse) {
- $log->debug("We didn't find [$method], asking everyone else.", DEBUG);
- retrieve_remote_apis($method);
- $meth = $self->method_lookup($method,$proto,1);
- }
-
- return $meth;
-}
-
-sub run {
- my $self = shift;
- my $req = shift;
-
- my $resp;
- my @params = @_;
-
- if ( !UNIVERSAL::isa($req, 'OpenSRF::AppRequest') ) {
- $log->debug("Creating a SubRequest object", DEBUG);
- unshift @params, $req;
- $req = OpenSRF::AppSubrequest->new;
- } else {
- $log->debug("This is a top level request", DEBUG);
- }
-
- if (!$self->{remote}) {
- my $code = \&{$self->{package} . '::' . $self->{method}};
- my $err = undef;
-
- try {
- $resp = $code->($self, $req, @params);
-
- } catch Error with {
- $err = shift;
-
- if( ref($self) eq 'HASH') {
- $log->error("Sub $$self{package}::$$self{method} DIED!!!\n\t$err\n", ERROR);
- }
- };
-
- if($err) {
- if(UNIVERSAL::isa($err,"Error")) {
- throw $err;
- } else {
- die $err->stringify;
- }
- }
-
-
- $log->debug("Coderef for [$$self{package}::$$self{method}] has been run", DEBUG);
-
- if ( ref($req) and UNIVERSAL::isa($req, 'OpenSRF::AppSubrequest') ) {
- $req->respond($resp) if (defined $resp);
- $log->debug("SubRequest object is responding with : " . join(" ",$req->responses), DEBUG);
- return $req->responses;
- } else {
- $log->debug("A top level Request object is responding $resp", DEBUG) if (defined $resp);
- return $resp;
- }
- } else {
- my $session = OpenSRF::AppSession->create($self->{server_class});
- try {
- #$session->connect or OpenSRF::EX::WARN->throw("Connection to [$$self{server_class}] timed out");
- my $remote_req = $session->request( $self->{api_name}, @params );
- while (my $remote_resp = $remote_req->recv) {
- OpenSRF::Utils::Logger->debug("Remote Subrequest Received " . $remote_resp, INTERNAL );
- if( UNIVERSAL::isa($remote_resp,"Error") ) {
- throw $remote_resp;
- }
- $req->respond( $remote_resp->content );
- }
- $remote_req->finish();
-
- } catch Error with {
- my $e = shift;
- $log->debug( "Remote subrequest returned an error:\n". $e );
- return undef;
- };
-
- if ($session) {
- $session->disconnect();
- $session->finish();
- }
-
- $log->debug( "Remote Subrequest Responses " . join(" ", $req->responses), INTERNAL );
-
- return $req->responses;
- }
- # huh? how'd we get here...
- return undef;
-}
-
-sub introspect {
- my $self = shift;
- my $client = shift;
- my $method = shift;
- my $limit = shift;
- my $offset = shift;
-
- if ($self->api_name =~ /all$/o) {
- $offset = $limit;
- $limit = $method;
- $method = undef;
- }
-
- my ($seen,$returned) = (0,0);
- for my $api_level ( reverse(1 .. $#_METHODS) ) {
- for my $api_name ( sort keys %{$_METHODS[$api_level]} ) {
- if (!$offset || $offset <= $seen) {
- if (!$_METHODS[$api_level]{$api_name}{remote}) {
- if (defined($method)) {
- if ($api_name =~ $method) {
- if (!$limit || $returned < $limit) {
- $client->respond( $_METHODS[$api_level]{$api_name} );
- $returned++;
- }
- }
- } else {
- if (!$limit || $returned < $limit) {
- $client->respond( $_METHODS[$api_level]{$api_name} );
- $returned++;
- }
- }
- }
- }
- $seen++;
- }
- }
-
- return undef;
-}
-__PACKAGE__->register_method(
- stream => 1,
- method => 'introspect',
- api_name => 'opensrf.system.method.all',
- argc => 0,
- signature => {
- desc => q/This method is used to introspect an entire OpenSRF Application/,
- return => {
- desc => q/A stream of objects describing the methods available via this OpenSRF Application/,
- type => 'object'
- }
- },
-);
-__PACKAGE__->register_method(
- stream => 1,
- method => 'introspect',
- argc => 1,
- api_name => 'opensrf.system.method',
- argc => 1,
- signature => {
- desc => q/Use this method to get the definition of a single OpenSRF Method/,
- params => [
- { desc => q/The method to introspect/,
- type => 'string' },
- ],
- return => { desc => q/An object describing the method requested, or an error if it can't be found/,
- type => 'object' }
- },
-);
-
-sub echo_method {
- my $self = shift;
- my $client = shift;
- my @args = @_;
-
- $client->respond( $_ ) for (@args);
- return undef;
-}
-__PACKAGE__->register_method(
- stream => 1,
- method => 'echo_method',
- argc => 1,
- api_name => 'opensrf.system.echo',
- signature => {
- desc => q/A test method that will echo back it's arguments in a streaming response/,
- params => [
- { desc => q/One or more arguments to echo back/ }
- ],
- return => { desc => q/A stream of the arguments passed/ }
- },
-);
-
-sub time_method {
- my( $self, $conn ) = @_;
- return CORE::time;
-}
-__PACKAGE__->register_method(
- method => 'time_method',
- argc => 0,
- api_name => 'opensrf.system.time',
- signature => {
- desc => q/Returns the current system time as epoch seconds/,
- return => { desc => q/epoch seconds/ }
- }
-);
-
-sub make_stream_atomic {
- my $self = shift;
- my $req = shift;
- my @args = @_;
-
- (my $m_name = $self->api_name) =~ s/\.atomic$//o;
- my @results = $self->method_lookup($m_name)->run(@args);
-
- return \@results;
-}
-
-
-1;
-
-
+++ /dev/null
-package OpenSRF::App::Client;
-use base 'OpenSRF::Application';
-use OpenSRF::Utils::Logger qw/:level/;
-
-
-1;
+++ /dev/null
-package OpenSRF::Application::Demo::Math;
-use base qw/OpenSRF::Application/;
-use OpenSRF::Application;
-use OpenSRF::Utils::Logger qw/:level/;
-use OpenSRF::DomainObject::oilsResponse;
-#use OpenSRF::DomainObject::oilsPrimitive;
-use OpenSRF::EX qw/:try/;
-use strict;
-use warnings;
-
-
-sub DESTROY{}
-
-our $log = 'OpenSRF::Utils::Logger';
-
-sub send_request {
- my $self = shift;
- my $client = shift;
-
- my $method_name = shift;
- my @params = @_;
-
- my $session = OpenSRF::AppSession->create( "opensrf.dbmath" );
- my $request = $session->request( "dbmath.$method_name", @params );
- my $response = $request->recv();
- if(!$response) { return undef; }
- if($response->isa("Error")) {throw $response ($response->stringify);}
- $session->finish();
-
- return $response->content;
-
-}
-__PACKAGE__->register_method( method => 'send_request', api_name => '_send_request' );
-
-__PACKAGE__->register_method( method => 'add_1', api_name => 'add' );
-sub add_1 {
- my $self = shift;
- my $client = shift;
- my @args = @_;
-
- my $meth = $self->method_lookup('_send_request');
- my ($result) = $meth->run('add',@args);
-
- return $result;
-
- return send_request( "add", @args );
-}
-
-__PACKAGE__->register_method( method => 'sub_1', api_name => 'sub' );
-sub sub_1 {
- my $self = shift;
- my $client = shift;
- my @args = @_;
-
- my $meth = $self->method_lookup('_send_request');
- my ($result) = $meth->run('sub',@args);
-
- return $result;
-
- return send_request( "sub", @args );
-}
-
-__PACKAGE__->register_method( method => 'mult_1', api_name => 'mult' );
-sub mult_1 {
- my $self = shift;
- my $client = shift;
- my @args = @_;
-
- my $meth = $self->method_lookup('_send_request');
- my ($result) = $meth->run('mult',@args);
-
- return $result;
-
- return send_request( "mult", @args );
-}
-
-__PACKAGE__->register_method( method => 'div_1', api_name => 'div' );
-sub div_1 {
- my $self = shift;
- my $client = shift;
- my @args = @_;
-
- my $meth = $self->method_lookup('_send_request');
- my ($result) = $meth->run('div',@args);
-
- return $result;
-
- return send_request( "div", @args );
-}
-
-
-1;
+++ /dev/null
-package OpenSRF::Application::Demo::MathDB;
-use JSON;
-use base qw/OpenSRF::Application/;
-use OpenSRF::Application;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-#use OpenSRF::DomainObject::oilsPrimitive;
-use OpenSRF::Utils::Logger qw/:level/;
-use strict;
-use warnings;
-
-sub DESTROY{}
-our $log = 'OpenSRF::Utils::Logger';
-sub initialize {}
-
-__PACKAGE__->register_method( method => 'add_1', api_name => 'dbmath.add' );
-sub add_1 {
- my $self = shift;
- my $client = shift;
-
- my $n1 = shift;
- my $n2 = shift;
- my $a = $n1 + $n2;
- return JSON::number->new($a);
-}
-
-__PACKAGE__->register_method( method => 'sub_1', api_name => 'dbmath.sub' );
-sub sub_1 {
- my $self = shift;
- my $client = shift;
-
- my $n1 = shift;
- my $n2 = shift;
- my $a = $n1 - $n2;
- return JSON::number->new($a);
-}
-
-__PACKAGE__->register_method( method => 'mult_1', api_name => 'dbmath.mult' );
-sub mult_1 {
- my $self = shift;
- my $client = shift;
-
- my $n1 = shift;
- my $n2 = shift;
- my $a = $n1 * $n2;
- return JSON::number->new($a);
-}
-
-__PACKAGE__->register_method( method => 'div_1', api_name => 'dbmath.div' );
-sub div_1 {
- my $self = shift;
- my $client = shift;
-
- my $n1 = shift;
- my $n2 = shift;
- my $a = $n1 / $n2;
- return JSON::number->new($a);
-}
-
-1;
+++ /dev/null
-package OpenSRF::Application::Persist;
-use base qw/OpenSRF::Application/;
-use OpenSRF::Application;
-
-use OpenSRF::Utils::SettingsClient;
-use OpenSRF::EX qw/:try/;
-use OpenSRF::Utils qw/:common/;
-use OpenSRF::Utils::Logger;
-use JSON;
-use DBI;
-
-use vars qw/$dbh $log $default_expire_time/;
-
-sub initialize {
- $log = 'OpenSRF::Utils::Logger';
-
- $sc = OpenSRF::Utils::SettingsClient->new;
-
- my $dbfile = $sc->config_value( apps => 'opensrf.persist' => app_settings => 'dbfile');
- unless ($dbfile) {
- throw OpenSRF::EX::PANIC ("Can't find my dbfile for SQLite!");
- }
-
- my $init_dbh = DBI->connect("dbi:SQLite:dbname=$dbfile","","");
- $init_dbh->{AutoCommit} = 1;
- $init_dbh->{RaiseError} = 0;
-
- $init_dbh->do( <<" SQL" );
- CREATE TABLE storage (
- id INTEGER PRIMARY KEY,
- name_id INTEGER,
- value TEXT
- );
- SQL
-
- $init_dbh->do( <<" SQL" );
- CREATE TABLE store_name (
- id INTEGER PRIMARY KEY,
- name TEXT UNIQUE
- );
- SQL
-
- $init_dbh->do( <<" SQL" );
- CREATE TABLE store_expire (
- id INTEGER PRIMARY KEY,
- atime INTEGER,
- expire_interval INTEGER
- );
- SQL
-
-}
-
-sub child_init {
- my $sc = OpenSRF::Utils::SettingsClient->new;
-
- $default_expire_time = $sc->config_value( apps => 'opensrf.persist' => app_settings => 'default_expire_time' );
- $default_expire_time ||= 300;
-
- my $dbfile = $sc->config_value( apps => 'opensrf.persist' => app_settings => 'dbfile');
- unless ($dbfile) {
- throw OpenSRF::EX::PANIC ("Can't find my dbfile for SQLite!");
- }
-
- $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile","","");
- $dbh->{AutoCommit} = 1;
- $dbh->{RaiseError} = 0;
-
-}
-
-sub create_store {
- my $self = shift;
- my $client = shift;
-
- my $name = shift || '';
-
- try {
-
- my $continue = 0;
- try {
- _get_name_id($name);
-
- } catch Error with {
- $continue++;
- };
-
- throw OpenSRF::EX::WARN ("Duplicate key: object name [$name] already exists! " . $dbh->errstr)
- unless ($continue);
-
- my $sth = $dbh->prepare("INSERT INTO store_name (name) VALUES (?);");
- $sth->execute($name);
- $sth->finish;
-
- unless ($name) {
- my $last_id = $dbh->last_insert_id(undef, undef, 'store_name', 'id');
- $name = 'AUTOGENERATED!!'.$last_id;
- $dbh->do("UPDATE store_name SET name = '$name' WHERE id = '$last_id';");
- }
-
- _flush_by_name($name);
- return $name;
- } catch Error with {
- return undef;
- };
-}
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.slot.create',
- method => 'create_store',
- argc => 1,
-);
-
-
-sub create_expirable_store {
- my $self = shift;
- my $client = shift;
- my $name = shift || do { throw OpenSRF::EX::InvalidArg ("Expirable slots must be given a name!") };
- my $time = shift || $default_expire_time;
-
- try {
- ($name) = $self->method_lookup( 'opensrf.persist.slot.create' )->run( $name );
- return undef unless $name;
-
- $self->method_lookup('opensrf.persist.slot.set_expire')->run($name, $time);
- return $name;
- } catch Error with {
- return undef;
- };
-
-}
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.slot.create_expirable',
- method => 'create_expirable_store',
- argc => 2,
-);
-
-sub _update_expire_atime {
- my $id = shift;
- $dbh->do('UPDATE store_expire SET atime = ? WHERE id = ?', {}, time(), $id);
-}
-
-sub set_expire_interval {
- my $self = shift;
- my $client = shift;
- my $slot = shift;
- my $new_interval = shift;
-
- try {
- my $etime = interval_to_seconds($new_interval);
- my $sid = _get_name_id($slot);
-
- $dbh->do('DELETE FROM store_expire where id = ?', {}, $sid);
- return 0 if ($etime == 0);
-
- $dbh->do('INSERT INTO store_expire (id, atime, expire_interval) VALUES (?,?,?);',{},$sid,time(),$etime);
- return $etime;
- }
-}
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.slot.set_expire',
- method => 'set_expire_interval',
- argc => 2,
-);
-
-sub find_slot {
- my $self = shift;
- my $client = shift;
- my $slot = shift;
-
- my $sid = _get_name_id($slot);
- return $slot if ($sid);
- return undef;
-}
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.slot.find',
- method => 'find_slot',
- argc => 2,
-);
-
-sub get_expire_interval {
- my $self = shift;
- my $client = shift;
- my $slot = shift;
-
- my $sid = _get_name_id($slot);
- my ($int) = $dbh->selectrow_array('SELECT expire_interval FROM store_expire WHERE id = ?;',{},$sid);
- return undef unless ($int);
-
- my ($future) = $dbh->selectrow_array('SELECT atime + expire_interval FROM store_expire WHERE id = ?;',{},$sid);
- return $future - time();
-}
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.slot.get_expire',
- method => 'get_expire_interval',
- argc => 2,
-);
-
-
-sub _sweep_expired_slots {
- return if (shift());
-
- my $expired_slots = $dbh->selectcol_arrayref(<<" SQL", {}, time() );
- SELECT id FROM store_expire WHERE (atime + expire_interval) <= ?;
- SQL
-
- return unless ($expired_slots);
-
- $dbh->do('DELETE FROM storage WHERE name_id IN ('.join(',', map { '?' } @$expired_slots).');', {}, @$expired_slots);
- $dbh->do('DELETE FROM store_expire WHERE id IN ('.join(',', map { '?' } @$expired_slots).');', {}, @$expired_slots);
- for my $id (@$expired_slots) {
- _flush_by_name(_get_id_name($id), 1);
- }
-}
-
-sub add_item {
- my $self = shift;
- my $client = shift;
-
- my $name = shift or do {
- throw OpenSRF::EX::WARN ("No name specified!");
- };
-
- my $value = shift || '';
-
- try {
- my $name_id = _get_name_id($name);
-
- if ($self->api_name =~ /object/) {
- $dbh->do('DELETE FROM storage WHERE name_id = ?;', {}, $name_id);
- }
-
- $dbh->do('INSERT INTO storage (name_id,value) VALUES (?,?);', {}, $name_id, JSON->perl2JSON($value));
-
- _flush_by_name($name);
-
- return $name;
- } catch Error with {
- return undef;
- };
-}
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.object.set',
- method => 'add_item',
- argc => 2,
-);
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.queue.push',
- method => 'add_item',
- argc => 2,
-);
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.stack.push',
- method => 'add_item',
- argc => 2,
-);
-
-sub _get_id_name {
- my $name = shift or do {
- throw OpenSRF::EX::WARN ("No slot id specified!");
- };
-
-
- my $name_id = $dbh->selectcol_arrayref("SELECT name FROM store_name WHERE id = ?;", {}, $name);
-
- if (!ref($name_id) || !defined($name_id->[0])) {
- throw OpenSRF::EX::WARN ("Slot id [$name] does not exist!");
- }
-
- return $name_id->[0];
-}
-
-sub _get_name_id {
- my $name = shift or do {
- throw OpenSRF::EX::WARN ("No slot name specified!");
- };
-
-
- my $name_id = $dbh->selectrow_arrayref("SELECT id FROM store_name WHERE name = ?;", {}, $name);
-
- if (!ref($name_id) || !defined($name_id->[0])) {
- throw OpenSRF::EX::WARN ("Slot name [$name] does not exist!");
- }
-
- return $name_id->[0];
-}
-
-sub destroy_store {
- my $self = shift;
- my $client = shift;
-
- my $name = shift;
-
- my $problem = 0;
- try {
- my $name_id = _get_name_id($name);
-
- $dbh->do("DELETE FROM storage WHERE name_id = ?;", {}, $name_id);
- $dbh->do("DELETE FROM store_name WHERE id = ?;", {}, $name_id);
- $dbh->do("DELETE FROM store_expire WHERE id = ?;", {}, $name_id);
-
- _sweep_expired_slots();
- return $name;
- } catch Error with {
- return undef;
- };
-
-}
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.slot.destroy',
- method => 'destroy_store',
- argc => 1,
-);
-
-sub _flush_by_name {
- my $name = shift;
- my $no_sweep = shift;
-
- my $name_id = _get_name_id($name);
-
- unless ($no_sweep) {
- _update_expire_atime($name);
- _sweep_expired_slots();
- }
-
- if ($name =~ /^AUTOGENERATED!!/) {
- my $count = $dbh->selectcol_arrayref("SELECT COUNT(*) FROM storage WHERE name_id = ?;", {}, $name_id);
- if (!ref($count) || $$count[0] == 0) {
- $dbh->do("DELETE FROM store_name WHERE name = ?;", {}, $name);
- }
- }
-}
-
-sub pop_queue {
- my $self = shift;
- my $client = shift;
-
- my $name = shift or do {
- throw OpenSRF::EX::WARN ("No queue name specified!");
- };
-
- try {
- my $name_id = _get_name_id($name);
-
- my $value = $dbh->selectrow_arrayref('SELECT id, value FROM storage WHERE name_id = ? ORDER BY id ASC LIMIT 1;', {}, $name_id);
- $dbh->do('DELETE FROM storage WHERE id = ?;',{}, $value->[0]) unless ($self->api_name =~ /peek$/);
-
- _flush_by_name($name);
-
- return JSON->JSON2perl( $value->[1] );
- } catch Error with {
- #my $e = shift;
- #return $e;
- return undef;
- };
-}
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.queue.peek',
- method => 'pop_queue',
- argc => 1,
-);
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.queue.pop',
- method => 'pop_queue',
- argc => 1,
-);
-
-
-sub peek_slot {
- my $self = shift;
- my $client = shift;
-
- my $name = shift or do {
- throw OpenSRF::EX::WARN ("No slot name specified!");
- };
- my $name_id = _get_name_id($name);
-
- my $order = 'ASC';
- $order = 'DESC' if ($self->api_name =~ /stack/o);
-
- my $values = $dbh->selectall_arrayref("SELECT value FROM storage WHERE name_id = ? ORDER BY id $order;", {}, $name_id);
-
- $client->respond( JSON->JSON2perl( $_->[0] ) ) for (@$values);
-
- _flush_by_name($name);
- return undef;
-}
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.queue.peek.all',
- method => 'peek_slot',
- argc => 1,
- stream => 1,
-);
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.stack.peek.all',
- method => 'peek_slot',
- argc => 1,
- stream => 1,
-);
-
-
-sub store_size {
- my $self = shift;
- my $client = shift;
-
- my $name = shift or do {
- throw OpenSRF::EX::WARN ("No queue name specified!");
- };
- my $name_id = _get_name_id($name);
-
- my $value = $dbh->selectcol_arrayref('SELECT SUM(LENGTH(value)) FROM storage WHERE name_id = ?;', {}, $name_id);
-
- return JSON->JSON2perl( $value->[0] );
-}
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.queue.size',
- method => 'shift_stack',
- argc => 1,
-);
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.stack.size',
- method => 'shift_stack',
- argc => 1,
-);
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.object.size',
- method => 'shift_stack',
- argc => 1,
-);
-
-sub store_depth {
- my $self = shift;
- my $client = shift;
-
- my $name = shift or do {
- throw OpenSRF::EX::WARN ("No queue name specified!");
- };
- my $name_id = _get_name_id($name);
-
- my $value = $dbh->selectcol_arrayref('SELECT COUNT(*) FROM storage WHERE name_id = ?;', {}, $name_id);
-
- return JSON->JSON2perl( $value->[0] );
-}
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.queue.length',
- method => 'shift_stack',
- argc => 1,
-);
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.stack.depth',
- method => 'shift_stack',
- argc => 1,
-);
-
-sub shift_stack {
- my $self = shift;
- my $client = shift;
-
- my $name = shift or do {
- throw OpenSRF::EX::WARN ("No slot name specified!");
- };
-
- try {
- my $name_id = _get_name_id($name);
-
- my $value = $dbh->selectrow_arrayref('SELECT id, value FROM storage WHERE name_id = ? ORDER BY id DESC LIMIT 1;', {}, $name_id);
- $dbh->do('DELETE FROM storage WHERE id = ?;',{}, $value->[0]) unless ($self->api_name =~ /peek$/);
-
- _flush_by_name($name);
-
- return JSON->JSON2perl( $value->[1] );
- } catch Error with {
- my $e = shift;
- return undef;
- };
-}
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.stack.peek',
- method => 'shift_stack',
- argc => 1,
-);
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.stack.pop',
- method => 'shift_stack',
- argc => 1,
-);
-
-sub get_object {
- my $self = shift;
- my $client = shift;
-
- my $name = shift or do {
- throw OpenSRF::EX::WARN ("No object name specified!");
- };
-
- try {
- my $name_id = _get_name_id($name);
-
- my $value = $dbh->selectrow_arrayref('SELECT name_id, value FROM storage WHERE name_id = ? ORDER BY id DESC LIMIT 1;', {}, $name_id);
- $dbh->do('DELETE FROM storage WHERE name_id = ?',{}, $value->[0]) unless ($self->api_name =~ /peek$/);
-
- _flush_by_name($name);
-
- return JSON->JSON2perl( $value->[1] );
- } catch Error with {
- return undef;
- };
-}
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.object.peek',
- method => 'shift_stack',
- argc => 1,
-);
-__PACKAGE__->register_method(
- api_name => 'opensrf.persist.object.get',
- method => 'shift_stack',
- argc => 1,
-);
-
-1;
+++ /dev/null
-package OpenSRF::Application::Settings;
-use OpenSRF::Application;
-use OpenSRF::Utils::SettingsParser;
-use OpenSRF::Utils::Logger qw/$logger/;
-use base 'OpenSRF::Application';
-
-sub child_exit {
- $logger->debug("settings server child exiting...$$");
-}
-
-
-__PACKAGE__->register_method( method => 'get_host_config', api_name => 'opensrf.settings.host_config.get' );
-sub get_host_config {
- my( $self, $client, $host ) = @_;
- my $parser = OpenSRF::Utils::SettingsParser->new();
- return $parser->get_server_config($host);
-}
-
-__PACKAGE__->register_method( method => 'get_default_config', api_name => 'opensrf.settings.default_config.get' );
-sub get_default_config {
- my( $self, $client ) = @_;
- my $parser = OpenSRF::Utils::SettingsParser->new();
- return $parser->get_default_config();
-}
-
-
-
-
-__PACKAGE__->register_method( method => 'xpath_get', api_name => 'opensrf.settings.xpath.get' );
-
-__PACKAGE__->register_method(
- method => 'xpath_get',
- api_name => 'opensrf.settings.xpath.get.raw' );
-
-sub xpath_get {
- my($self, $client, $xpath) = @_;
- warn "*************** Received XPATH $xpath\n";
- return OpenSRF::Utils::SettingsParser->new()->_get_all( $xpath );
-}
-
-
-1;
+++ /dev/null
-use XML::LibXML;
-use OpenSRF::Utils::Logger qw(:level);
-
-package XML::LibXML::Element;
-use OpenSRF::EX;
-
-sub AUTOLOAD {
- my $self = shift;
- (my $name = $AUTOLOAD) =~ s/.*://; # strip fully-qualified portion
-
- ### Check for recursion
- my $calling_method = (caller(1))[3];
- my @info = caller(1);
-
- if( @info ) {
- if ($info[0] =~ /AUTOLOAD/) { @info = caller(2); }
- }
- unless( @info ) { @info = caller(); }
- if( $calling_method and $calling_method eq "XML::LibXML::Element::AUTOLOAD" ) {
- throw OpenSRF::EX::PANIC ( "RECURSION! Caller [ @info ] | Object [ ".ref($self)." ]\n ** Trying to call $name", ERROR );
- }
- ### Check for recursion
-
- #OpenSRF::Utils::Logger->debug( "Autoloading method for DOM: $AUTOLOAD on ".$self->toString, INTERNAL );
-
- my $new_node = OpenSRF::DOM::upcast($self);
- OpenSRF::Utils::Logger->debug( "Autoloaded to: ".ref($new_node), INTERNAL );
-
- return $new_node->$name(@_);
-}
-
-
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM;
-use base qw/XML::LibXML OpenSRF/;
-
-our %_NAMESPACE_MAP = (
- 'http://open-ils.org/xml/namespaces/oils_v1' => 'oils',
-);
-
-our $_one_true_parser;
-
-sub new {
- my $self = shift;
- return $_one_true_parser if (defined $_one_true_parser);
- $_one_true_parser = $self->SUPER::new(@_);
- $_one_true_parser->keep_blanks(0);
- $XML::LibXML::skipXMLDeclaration = 0;
- return $_one_true_parser = $self->SUPER::new(@_);
-}
-
-sub createDocument {
- my $self = shift;
-
- # DOM API: createDocument(namespaceURI, qualifiedName, doctype?)
- my $doc = XML::LibXML::Document->new("1.0", "UTF-8");
- my $el = $doc->createElement('root');
-
- $el->setNamespace('http://open-ils.org/xml/namespaces/oils_v1', 'oils', 1);
- $doc->setDocumentElement($el);
-
- return $doc;
-}
-
-my %_loaded_classes;
-sub upcast {
- my $node = shift;
- return undef unless $node;
-
- my ($ns,$tag) = split ':' => $node->nodeName;
-
- return $node unless ($ns eq 'oils');
-
- my $class = "OpenSRF::DOM::Element::$tag";
- unless (exists $_loaded_classes{$class}) {
- $class->use;
- $_loaded_classes{$class} = 1;
- }
- if ($@) {
- OpenSRF::Utils::Logger->error("Couldn't use $class! $@");
- }
-
- #OpenSRF::Utils::Logger->debug("Upcasting ".$node->toString." to $class", INTERNAL);
-
- return bless $node => $class;
-}
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Node;
-use base 'XML::LibXML::Node';
-
-sub new {
- my $class = shift;
- return bless $class->SUPER::new(@_) => $class;
-}
-
-sub childNodes {
- my $self = shift;
- my @children = $self->_childNodes();
- return wantarray ? @children : OpenSRF::DOM::NodeList->new( @children );
-}
-
-sub attributes {
- my $self = shift;
- my @attr = $self->_attributes();
- return wantarray ? @attr : OpenSRF::DOM::NamedNodeMap->new( @attr );
-}
-
-sub findnodes {
- my ($node, $xpath) = @_;
- my @nodes = $node->_findnodes($xpath);
- if (wantarray) {
- return @nodes;
- } else {
- return OpenSRF::DOM::NodeList->new(@nodes);
- }
-}
-
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::NamedNodeMap;
-use base 'XML::LibXML::NamedNodeMap';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::NodeList;
-use base 'XML::LibXML::NodeList';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Element;
-use base 'XML::LibXML::Element';
-
-sub new {
- my $class = shift;
-
- # magically create the element (tag) name, or build a blank element
- (my $name = $class) =~ s/^OpenSRF::DOM::Element:://;
- if ($name) {
- $name = "oils:$name";
- } else {
- undef $name;
- }
-
- my $self = $class->SUPER::new($name);
-
- my %attrs = @_;
- for my $aname (keys %attrs) {
- $self->setAttribute($aname, $attrs{$aname});
- }
-
- return $self;
-}
-
-sub getElementsByTagName {
- my ( $node , $name ) = @_;
- my $xpath = "descendant::$name";
- my @nodes = $node->_findnodes($xpath);
- return wantarray ? @nodes : OpenSRF::DOM::NodeList->new(@nodes);
-}
-
-sub getElementsByTagNameNS {
- my ( $node, $nsURI, $name ) = @_;
- my $xpath = "descendant::*[local-name()='$name' and namespace-uri()='$nsURI']";
- my @nodes = $node->_findnodes($xpath);
- return wantarray ? @nodes : OpenSRF::DOM::NodeList->new(@nodes);
-}
-
-sub getElementsByLocalName {
- my ( $node,$name ) = @_;
- my $xpath = "descendant::*[local-name()='$name']";
- my @nodes = $node->_findnodes($xpath);
- return wantarray ? @nodes : OpenSRF::DOM::NodeList->new(@nodes);
-}
-
-sub getChildrenByLocalName {
- my ( $node,$name ) = @_;
- my $xpath = "./*[local-name()='$name']";
- my @nodes = $node->_findnodes($xpath);
- return @nodes;
-}
-
-sub getChildrenByTagName {
- my ( $node, $name ) = @_;
- my @nodes = grep { $_->nodeName eq $name } $node->childNodes();
- return @nodes;
-}
-
-sub getChildrenByTagNameNS {
- my ( $node, $nsURI, $name ) = @_;
- my $xpath = "*[local-name()='$name' and namespace-uri()='$nsURI']";
- my @nodes = $node->_findnodes($xpath);
- return @nodes;
-}
-
-sub appendWellBalancedChunk {
- my ( $self, $chunk ) = @_;
-
- my $local_parser = OpenSRF::DOM->new();
- my $frag = $local_parser->parse_xml_chunk( $chunk );
-
- $self->appendChild( $frag );
-}
-
-package OpenSRF::DOM::Element::root;
-use base 'OpenSRF::DOM::Element';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Text;
-use base 'XML::LibXML::Text';
-
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Comment;
-use base 'XML::LibXML::Comment';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::CDATASection;
-use base 'XML::LibXML::CDATASection';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Document;
-use base 'XML::LibXML::Document';
-
-sub empty {
- my $self = shift;
- return undef unless (ref($self));
- $self->documentElement->removeChild($_) for $self->documentElement->childNodes;
- return $self;
-}
-
-sub new {
- my $class = shift;
- return bless $class->SUPER::new(@_) => $class;
-}
-
-sub getElementsByTagName {
- my ( $doc , $name ) = @_;
- my $xpath = "descendant-or-self::node()/$name";
- my @nodes = $doc->_findnodes($xpath);
- return wantarray ? @nodes : OpenSRF::DOM::NodeList->new(@nodes);
-}
-
-sub getElementsByTagNameNS {
- my ( $doc, $nsURI, $name ) = @_;
- my $xpath = "descendant-or-self::*[local-name()='$name' and namespace-uri()='$nsURI']";
- my @nodes = $doc->_findnodes($xpath);
- return wantarray ? @nodes : OpenSRF::DOM::NodeList->new(@nodes);
-}
-
-sub getElementsByLocalName {
- my ( $doc,$name ) = @_;
- my $xpath = "descendant-or-self::*[local-name()='$name']";
- my @nodes = $doc->_findnodes($xpath);
- return wantarray ? @nodes : OpenSRF::DOM::NodeList->new(@nodes);
-}
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::DocumentFragment;
-use base 'XML::LibXML::DocumentFragment';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Attr;
-use base 'XML::LibXML::Attr';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Dtd;
-use base 'XML::LibXML::Dtd';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::PI;
-use base 'XML::LibXML::PI';
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Namespace;
-use base 'XML::LibXML::Namespace';
-
-sub isEqualNode {
- my ( $self, $ref ) = @_;
- if ( $ref->isa("XML::LibXML::Namespace") ) {
- return $self->_isEqual($ref);
- }
- return 0;
-}
-
-#--------------------------------------------------------------------------------
-package OpenSRF::DOM::Schema;
-use base 'XML::LibXML::Schema';
-
-1;
+++ /dev/null
-package OpenSRF::DOM::Element::domainObject;
-use strict; use warnings;
-use base 'OpenSRF::DOM::Element';
-use OpenSRF::DOM;
-use OpenSRF::DOM::Element::domainObjectAttr;
-use OpenSRF::Utils::Logger qw(:level);
-use OpenSRF::EX qw(:try);
-use Carp;
-#use OpenSRF::DomainObject::oilsPrimitive;
-#use OpenSRF::DomainObject::oilsResponse;
-use vars qw($AUTOLOAD);
-
-sub AUTOLOAD {
- my $self = shift;
- (my $name = $AUTOLOAD) =~ s/.*://; # strip fully-qualified portion
-
- return class($self) if ($name eq 'class');
- if ($self->can($name)) {
- return $self->$name(@_);
- }
-
- if (1) {
- ### Check for recursion
- my $calling_method = (caller(1))[3];
- my @info = caller(1);
-
- if( @info ) {
- if ($info[0] =~ /AUTOLOAD/) { @info = caller(2); }
- }
- unless( @info ) { @info = caller(); }
-
- if( $calling_method and $calling_method eq "OpenSRF::DOM::Element::domainObject::AUTOLOAD" ) {
- warn Carp::cluck;
- throw OpenSRF::EX::PANIC ( "RECURSION! Caller [ @info[0..2] ] | Object [ ".ref($self)." ]\n ** Trying to call $name", ERROR );
- }
- ### Check for recursion
- }
-
- my @args = @_;
- my $meth = class($self).'::'.$name;
-
- try {
- return $self->$meth(@args);
- } catch Error with {
- my $e = shift;
- if( $e ) {
- OpenSRF::Utils::Logger->error( $@ . $e);
- } else {
- OpenSRF::Utils::Logger->error( $@ );
- }
- die $@;
- };
-
-
- my $node = OpenSRF::DOM::Element::domainObject::upcast($self);
- OpenSRF::Utils::Logger->debug( "Autoloaded to: ".ref($node), INTERNAL );
-
- return $node->$name(@_);
-}
-
-sub downcast {
- my $obj = shift;
- return bless $obj => 'XML::LibXML::Element';
-}
-
-sub upcast {
- my $self = shift;
- return bless $self => class($self);
-}
-
-sub new {
- my $class = shift;
- my $type = shift;
- my $obj = $class->SUPER::new( name => $type );
- while (@_) {
- my ($attr,$val) = (shift,shift);
- last unless ($attr and $val);
- $obj->addAttr( $attr, $val );
- #$obj->appendChild( OpenSRF::DOM::Element::domainObjectAttr->new($attr, $val) );
- }
- return $obj;
-}
-
-sub class {
- my $self = shift;
- return 'OpenSRF::DomainObject::'.$self->getAttribute('name');
-}
-
-sub base_type {
- my $self = shift;
- return $self->getAttribute('name');
-}
-
-sub addAttr {
- my $self = shift;
- $self->appendChild( $_ ) for OpenSRF::DOM::Element::domainObjectAttr->new(@_);
- return $self;
-}
-
-sub attrNode {
- my $self = shift;
- my $type = shift;
- return (grep { $_->getAttribute('name') eq $type } $self->getChildrenByTagName("oils:domainObjectAttr"))[0];
-}
-
-sub attrHash {
- my $self = shift;
- my %attrs = map { ( $_->getAttribute('name') => $_->getAttribute('value') ) } $self->getChildrenByTagName('oils:domainObjectAttr');
-
- return \%attrs;
-}
-
-sub attrValue {
- my $self = shift;
- return $self->attrHash->{shift};
-}
-
-1;
+++ /dev/null
-package OpenSRF::DOM::Element::domainObjectAttr;
-use base 'OpenSRF::DOM::Element';
-
-sub new {
- my $class = shift;
- my @nodes;
- while (@_) {
- my ($name,$val) = (shift,shift);
- push @nodes, $class->SUPER::new(name => $name, value => $val);
- }
- return @nodes if (wantarray);
- return $nodes[0];
-}
-
-1;
+++ /dev/null
-package OpenSRF::DOM::Element::domainObjectCollection;
-use base 'OpenSRF::DOM::Element';
-use OpenSRF::DOM::Element::domainObjectAttr;
-use OpenSRF::EX;
-
-sub AUTOLOAD {
- my $self = CORE::shift;
- (my $name = $AUTOLOAD) =~ s/.*://; # strip fully-qualified portion
-
- return class($self) if ($name eq 'class');
-
- my @args = @_;
- my $meth = class($self).'::'.$name;
-
- ### Check for recursion
- my $calling_method = (caller(1))[3];
- my @info = caller(1);
-
- if( @info ) {
- if ($info[0] =~ /AUTOLOAD/) { @info = caller(2); }
- }
- unless( @info ) { @info = caller(); }
- if( $calling_method and $calling_method eq "OpenSRF::DOM::Element::domainObjectCollection::AUTOLOAD" ) {
- throw OpenSRF::EX::PANIC ( "RECURSION! Caller [ @info ] | Object [ ".ref($self)." ]\n ** Trying to call $name", ERROR );
- }
- ### Check for recursion
-
- try {
- return $self->$meth(@args);;
- } catch Error with {
- my $e = shift;
- OpenSRF::Utils::Logger->error( $@ . $e);
- die $@;
- };
-
- return upcast($self)->$name(@_);
-}
-
-sub downcast {
- my $obj = CORE::shift;
- return bless $obj => 'XML::LibXML::Element';
-}
-
-sub upcast {
- my $self = CORE::shift;
- return bless $self => class($self);
-}
-
-sub new {
- my $class = CORE::shift;
- my $type = CORE::shift;
- my $obj = $class->SUPER::new( name => $type );
- while ( my $val = shift) {
- throw OpenSRF::EX::NotADomainObject
- if (ref $val and $val->nodeName !~ /^oils:domainObject/o);
- $obj->appendChild( $val );
- }
- return $obj;
-}
-
-sub class {
- my $self = shift;
- return 'OpenSRF::DomainObjectCollection::'.$self->getAttribute('name');
-}
-
-sub base_type {
- my $self = shift;
- return $self->getAttribute('name');
-}
-
-sub pop {
- my $self = CORE::shift;
- return $self->removeChild( $self->lastChild )->upcast;
-}
-
-sub push {
- my $self = CORE::shift;
- my @args = @_;
- for my $node (@args) {
- #throw OpenSRF::EX::NotADomainObject ( "$_ must be a oils:domainOjbect*, it's a ".$_->nodeName )
- # unless ($_->nodeName =~ /^oils:domainObject/o);
-
- unless ($node->nodeName =~ /^oils:domainObject/o) {
- $node = OpenSRF::DomainObject::oilsScalar->new($node);
- }
-
- $self->appendChild( $node );
- }
-}
-
-sub shift {
- my $self = CORE::shift;
- return $self->removeChild( $self->firstChild )->upcast;
-}
-
-sub unshift {
- my $self = CORE::shift;
- my @args = @_;
- for (reverse @args) {
- throw OpenSRF::EX::NotADomainObject
- unless ($_->nodeName =~ /^oils:domainObject/o);
- $self->insertBefore( $_, $self->firstChild );
- }
-}
-
-sub first {
- my $self = CORE::shift;
- return $self->firstChild->upcast;
-}
-
-sub list {
- my $self = CORE::shift;
- return map {(bless($_ => 'OpenSRF::DomainObject::'.$_->getAttribute('name')))} $self->childNodes;
-}
-
-1;
+++ /dev/null
-package OpenSRF::DOM::Element::params;
-use base 'OpenSRF::DOM::Element';
-
-1;
+++ /dev/null
-package OpenSRF::DomainObject;
-use base 'OpenSRF::DOM::Element::domainObject';
-use OpenSRF::DOM;
-use OpenSRF::Utils::Logger qw(:level);
-use OpenSRF::DomainObject::oilsPrimitive;
-my $logger = "OpenSRF::Utils::Logger";
-
-=head1 NAME
-
-OpenSRF::DomainObject
-
-=head1 SYNOPSIS
-
-OpenSRF::DomainObject is an abstract base class. It
-should not be used directly. See C<OpenSRF::DomainObject::*>
-for details.
-
-=cut
-
-my $tmp_doc;
-
-sub object_castor {
- my $self = shift;
- my $node = shift;
-
- return unless (defined $node);
-
- if (ref($node) eq 'HASH') {
- return new OpenSRF::DomainObject::oilsHash (%$node);
- } elsif (ref($node) eq 'ARRAY') {
- return new OpenSRF::DomainObject::oilsArray (@$node);
- }
-
- return $node;
-}
-
-sub native_castor {
- my $self = shift;
- my $node = shift;
-
- return unless (defined $node);
-
- if ($node->nodeType == 3) {
- return $node->nodeValue;
- } elsif ($node->nodeName =~ /domainObject/o) {
- return $node->tie_me if ($node->class->can('tie_me'));
- }
- return $node;
-}
-
-sub new {
- my $class = shift;
- $class = ref($class) || $class;
-
- (my $type = $class) =~ s/^.+://o;
-
- $tmp_doc ||= OpenSRF::DOM->createDocument;
- my $dO = OpenSRF::DOM::Element::domainObject->new( $type, @_ );
-
- $tmp_doc->documentElement->appendChild($dO);
-
- return $dO;
-}
-
-sub _attr_get_set {
- my $self = shift;
- my $part = shift;
-
- my $node = $self->attrNode($part);
-
- if (defined(my $new_value = shift)) {
- if (defined $node) {
- my $old_val = $node->getAttribute( "value" );
- $node->setAttribute(value => $new_value);
- return $old_val;
- } else {
- $self->addAttr( $part => $new_value );
- return $new_value;
- }
- } elsif ( $node ) {
- return $node->getAttribute( "value" );
- }
-}
-
-1;
+++ /dev/null
-package OpenSRF::DomainObject::oilsMessage;
-use JSON;
-use OpenSRF::AppSession;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use OpenSRF::Utils::Logger qw/:level/;
-use warnings; use strict;
-use OpenSRF::EX qw/:try/;
-
-JSON->register_class_hint(hint => 'osrfMessage', name => 'OpenSRF::DomainObject::oilsMessage', type => 'hash');
-
-sub toString {
- my $self = shift;
- my $pretty = shift;
- return JSON->perl2prettyJSON($self) if ($pretty);
- return JSON->perl2JSON($self);
-}
-
-sub new {
- my $self = shift;
- my $class = ref($self) || $self;
- my %args = @_;
- return bless \%args => $class;
-}
-
-
-=head1 NAME
-
-OpenSRF::DomainObject::oilsMessage
-
-=head1
-
-use OpenSRF::DomainObject::oilsMessage;
-
-my $msg = OpenSRF::DomainObject::oilsMessage->new( type => 'CONNECT' );
-
-$msg->payload( $domain_object );
-
-=head1 ABSTRACT
-
-OpenSRF::DomainObject::oilsMessage is used internally to wrap data sent
-between client and server. It provides the structure needed to authenticate
-session data, and also provides the logic needed to unwrap session data and
-pass this information along to the Application Layer.
-
-=cut
-
-my $log = 'OpenSRF::Utils::Logger';
-
-=head1 METHODS
-
-=head2 OpenSRF::DomainObject::oilsMessage->type( [$new_type] )
-
-=over 4
-
-Used to specify the type of message. One of
-B<CONNECT, REQUEST, RESULT, STATUS, ERROR, or DISCONNECT>.
-
-=back
-
-=cut
-
-sub type {
- my $self = shift;
- my $val = shift;
- $self->{type} = $val if (defined $val);
- return $self->{type};
-}
-
-=head2 OpenSRF::DomainObject::oilsMessage->api_level( [$new_api_level] )
-
-=over 4
-
-Used to specify the api_level of message. Currently, only api_level C<1> is
-supported. This will be used to check that messages are well-formed, and as
-a hint to the Application as to which version of a method should fulfill a
-REQUEST message.
-
-=back
-
-=cut
-
-sub api_level {
- my $self = shift;
- my $val = shift;
- $self->{api_level} = $val if (defined $val);
- return $self->{api_level};
-}
-
-=head2 OpenSRF::DomainObject::oilsMessage->threadTrace( [$new_threadTrace] );
-
-=over 4
-
-Sets or gets the current message sequence identifier, or thread trace number,
-for a message. Useful as a debugging aid, but that's about it.
-
-=back
-
-=cut
-
-sub threadTrace {
- my $self = shift;
- my $val = shift;
- $self->{threadTrace} = $val if (defined $val);
- return $self->{threadTrace};
-}
-
-=head2 OpenSRF::DomainObject::oilsMessage->update_threadTrace
-
-=over 4
-
-Increments the threadTrace component of a message. This is automatic when
-using the normal session processing stack.
-
-=back
-
-=cut
-
-sub update_threadTrace {
- my $self = shift;
- my $tT = $self->threadTrace;
-
- $tT ||= 0;
- $tT++;
-
- $log->debug("Setting threadTrace to $tT",DEBUG);
-
- $self->threadTrace($tT);
-
- return $tT;
-}
-
-=head2 OpenSRF::DomainObject::oilsMessage->payload( [$new_payload] )
-
-=over 4
-
-Sets or gets the payload of a message. This should be exactly one object
-of (sub)type domainObject or domainObjectCollection.
-
-=back
-
-=cut
-
-sub payload {
- my $self = shift;
- my $val = shift;
- $self->{payload} = $val if (defined $val);
- return $self->{payload};
-}
-
-=head2 OpenSRF::DomainObject::oilsMessage->handler( $session_id )
-
-=over 4
-
-Used by the message processing stack to set session state information from the current
-message, and then sends control (via the payload) to the Application layer.
-
-=back
-
-=cut
-
-sub handler {
- my $self = shift;
- my $session = shift;
-
- my $mtype = $self->type;
- my $api_level = $self->api_level || 1;;
- my $tT = $self->threadTrace;
-
- $session->last_message_type($mtype);
- $session->last_message_api_level($api_level);
- $session->last_threadTrace($tT);
-
- $log->debug(" Received api_level => [$api_level], MType => [$mtype], ".
- "from [".$session->remote_id."], threadTrace[".$self->threadTrace."]");
-
- my $val;
- if ( $session->endpoint == $session->SERVER() ) {
- $val = $self->do_server( $session, $mtype, $api_level, $tT );
-
- } elsif ($session->endpoint == $session->CLIENT()) {
- $val = $self->do_client( $session, $mtype, $api_level, $tT );
- }
-
- if( $val ) {
- return OpenSRF::Application->handler($session, $self->payload);
- } else {
- $log->debug("Request was handled internally", DEBUG);
- }
-
- return 1;
-
-}
-
-
-
-# handle server side message processing
-
-# !!! Returning 0 means that we don't want to pass ourselves up to the message layer !!!
-sub do_server {
- my( $self, $session, $mtype, $api_level, $tT ) = @_;
-
- # A Server should never receive STATUS messages. If so, we drop them.
- # This is to keep STATUS's from dead client sessions from creating new server
- # sessions which send mangled session exceptions to backends for messages
- # that they are not aware of any more.
- if( $mtype eq 'STATUS' ) { return 0; }
-
-
- if ($mtype eq 'DISCONNECT') {
- $session->disconnect;
- $session->kill_me;
- return 0;
- }
-
- if ($session->state == $session->CONNECTING()) {
-
- if($mtype ne "CONNECT" and $session->stateless) {
- return 1; #pass the message up the stack
- }
-
- # the transport layer thinks this is a new connection. is it?
- unless ($mtype eq 'CONNECT') {
- $log->error("Connection seems to be mangled: Got $mtype instead of CONNECT");
-
- my $res = OpenSRF::DomainObject::oilsBrokenSession->new(
- status => "Connection seems to be mangled: Got $mtype instead of CONNECT",
- );
-
- $session->status($res);
- $session->kill_me;
- return 0;
-
- }
-
- my $res = OpenSRF::DomainObject::oilsConnectStatus->new;
- $session->status($res);
- $session->state( $session->CONNECTED );
-
- return 0;
- }
-
-
- return 1;
-
-}
-
-
-# Handle client side message processing. Return 1 when the the message should be pushed
-# up to the application layer. return 0 otherwise.
-sub do_client {
-
- my( $self, $session , $mtype, $api_level, $tT) = @_;
-
-
- if ($mtype eq 'STATUS') {
-
- if ($self->payload->statusCode == STATUS_OK) {
- $session->state($session->CONNECTED);
- $log->debug("We connected successfully to ".$session->app);
- return 0;
- }
-
- if ($self->payload->statusCode == STATUS_TIMEOUT) {
- $session->state( $session->DISCONNECTED );
- $session->reset;
- $session->connect;
- $session->push_resend( $session->app_request($self->threadTrace) );
- $log->debug("Disconnected because of timeout");
- return 0;
-
- } elsif ($self->payload->statusCode == STATUS_REDIRECTED) {
- $session->state( $session->DISCONNECTED );
- $session->reset;
- $session->connect;
- $session->push_resend( $session->app_request($self->threadTrace) );
- $log->debug("Disconnected because of redirect", WARN);
- return 0;
-
- } elsif ($self->payload->statusCode == STATUS_EXPFAILED) {
- $session->state( $session->DISCONNECTED );
- $log->debug("Disconnected because of mangled session", WARN);
- $session->reset;
- $session->push_resend( $session->app_request($self->threadTrace) );
- return 0;
-
- } elsif ($self->payload->statusCode == STATUS_CONTINUE) {
- $session->reset_request_timeout($self->threadTrace);
- return 0;
-
- } elsif ($self->payload->statusCode == STATUS_COMPLETE) {
- my $req = $session->app_request($self->threadTrace);
- $req->complete(1) if ($req);
- return 0;
- }
-
- # add more STATUS handling code here (as 'elsif's), for Message layer status stuff
-
- #$session->state( $session->DISCONNECTED() );
- #$session->reset;
-
- } elsif ($session->state == $session->CONNECTING()) {
- # This should be changed to check the type of response (is it a connectException?, etc.)
- }
-
- if( $self->payload and $self->payload->isa( "ERROR" ) ) {
- if ($session->raise_remote_errors) {
- $self->payload->throw();
- }
- }
-
- $log->debug("oilsMessage passing to Application: " . $self->type." : ".$session->remote_id );
-
- return 1;
-
-}
-
-1;
+++ /dev/null
-package OpenSRF::DomainObject::oilsMethod;
-
-use JSON;
-JSON->register_class_hint(hint => 'osrfMethod', name => 'OpenSRF::DomainObject::oilsMethod', type => 'hash');
-
-sub toString {
- my $self = shift;
- my $pretty = shift;
- return JSON->perl2prettyJSON($self) if ($pretty);
- return JSON->perl2JSON($self);
-}
-
-sub new {
- my $self = shift;
- my $class = ref($self) || $self;
- my %args = @_;
- return bless \%args => $class;
-}
-
-
-=head1 NAME
-
-OpenSRF::DomainObject::oilsMethod
-
-=head1 SYNOPSIS
-
-use OpenSRF::DomainObject::oilsMethod;
-
-my $method = OpenSRF::DomainObject::oilsMethod->new( method => 'search' );
-
-$method->return_type( 'mods' );
-
-$method->params( 'title:harry potter' );
-
-$client->send( 'REQUEST', $method );
-
-=head1 METHODS
-
-=head2 OpenSRF::DomainObject::oilsMethod->method( [$new_method_name] )
-
-=over 4
-
-Sets or gets the method name that will be called on the server. As above,
-this can be specified as a build attribute as well as added to a prebuilt
-oilsMethod object.
-
-=back
-
-=cut
-
-sub method {
- my $self = shift;
- my $val = shift;
- $self->{method} = $val if (defined $val);
- return $self->{method};
-}
-
-=head2 OpenSRF::DomainObject::oilsMethod->return_type( [$new_return_type] )
-
-=over 4
-
-Sets or gets the return type for this method call. This can also be supplied as
-a build attribute.
-
-This option does not require that the server return the type you request. It is
-used as a suggestion when more than one return type or format is possible.
-
-=back
-
-=cut
-
-
-sub return_type {
- my $self = shift;
- my $val = shift;
- $self->{return_type} = $val if (defined $val);
- return $self->{return_type};
-}
-
-=head2 OpenSRF::DomainObject::oilsMethod->params( @new_params )
-
-=over 4
-
-Sets or gets the parameters for this method call. Just pass in either text
-parameters, or DOM nodes of any type.
-
-=back
-
-=cut
-
-
-sub params {
- my $self = shift;
- my @args = @_;
- $self->{params} = \@args if (@args);
- return @{ $self->{params} };
-}
-
-1;
+++ /dev/null
-package OpenSRF::DomainObjectCollection::oilsMultiSearch;
-use OpenSRF::DomainObjectCollection;
-use OpenSRF::DomainObject::oilsPrimitive;
-use OpenSRF::DomainObject::oilsSearch;
-use OpenSRF::DOM::Element::searchCriteria;
-use OpenSRF::DOM::Element::searchCriterium;
-use base 'OpenSRF::DomainObjectCollection::oilsHash';
-
-sub new {
- my $class = shift;
- my %args = @_;
-
- $class = ref($class) || $class;
-
- my $self = $class->SUPER::new;
-
- tie my %hash, 'OpenSRF::DomainObjectCollection::oilsHash', $self;
-
- $self->set( bind_count => 1 );
- $self->set( searches => new OpenSRF::DomainObjectCollection::oilsHash );
- $self->set( relators => new OpenSRF::DomainObjectCollection::oilsArray );
- $self->set( fields => new OpenSRF::DomainObjectCollection::oilsArray );
- $self->set( group_by => new OpenSRF::DomainObjectCollection::oilsArray );
- $self->set( order_by => new OpenSRF::DomainObjectCollection::oilsArray );
-
- return $self;
-}
-
-sub add_subsearch {
- my $self = shift;
- my $alias = shift;
- my $search = shift;
- my $relator = shift;
-
- $search = OpenSRF::DomainObject::oilsSearch->new($search) if (ref($search) eq 'ARRAY');
-
- $self->searches->set( $alias => $search );
-
- if ($self->searches->size > 1) {
- throw OpenSRF::EX::InvalidArg ('You need to pass a relator searchCriterium')
- unless (defined $relator);
- }
-
- $relator = OpenSRF::DOM::Element::searchCriterium->new( @$relator )
- if (ref($relator) eq 'ARRAY');
-
- $self->relators->push( $relator ) if (defined $relator);
-
- return $self;
-}
-
-sub relators {
- return $_[0]->_accessor('relators');
-}
-
-sub searches {
- return $_[0]->_accessor('searches');
-}
-
-sub fields {
- my $self = shift;
- my @parts = @_;
- if (@parts) {
- $self->set( fields => OpenSRF::DomainObjectCollection::oilsArray->new(@_) );
- }
- return $self->_accessor('fields')->list;
-}
-
-sub format {
- $_[0]->set( format => $_[1] ) if (defined $_[1]);
- return $_[0]->_accessor('format');
-}
-
-sub limit {
- $_[0]->set( limit => $_[1] ) if (defined $_[1]);
- return $_[0]->_accessor('limit');
-}
-
-sub offset {
- $_[0]->set( offset => $_[1] ) if (defined $_[1]);
- return $_[0]->_accessor('offset');
-}
-
-sub chunk_key {
- $_[0]->set( chunk_key => $_[1] ) if (defined $_[1]);
- return $_[0]->_accessor('chunk_key');
-}
-
-sub order_by {
- my $self = shift;
- my @parts = @_;
- if (@parts) {
- $self->set( order_by => OpenSRF::DomainObjectCollection::oilsArray->new(@_) );
- }
- return $self->_accessor('order_by')->list;
-}
-
-sub group_by {
- my $self = shift;
- my @parts = @_;
- if (@parts) {
- $self->set( group_by => OpenSRF::DomainObjectCollection::oilsArray->new(@_) );
- }
- return $self->_accessor('group_by')->list;
-}
-
-sub SQL_select_list {
- my $self = shift;
-
- if (my $sql = $self->_accessor('sql_select_list')) {
- return $sql;
- }
-
- $self->set( sql_select_list => 'SELECT '.join(', ', $self->fields) ) if defined($self->fields);
- return $self->_accessor('sql_select_list');
-}
-
-sub SQL_group_by {
- my $self = shift;
-
- if (my $sql = $self->_accessor('sql_group_by')) {
- return $sql;
- }
-
- $self->set( sql_group_by => 'GROUP BY '.join(', ', $self->group_by) ) if defined($self->group_by);
- return $self->_accessor('sql_group_by');
-}
-
-sub SQL_order_by {
- my $self = shift;
-
- if (my $sql = $self->_accessor('sql_order_by')) {
- return $sql;
- }
-
- $self->set( sql_order_by => 'ORDER BY '.join(', ', $self->order_by) ) if defined($self->order_by);
- return $self->_accessor('sql_order_by');
-}
-
-sub SQL_offset {
- my $self = shift;
-
- if (my $sql = $self->_accessor('sql_offset')) {
- return $sql;
- }
-
- $self->set( sql_offset => 'OFFSET '.$self->offset ) if defined($self->offset);
- return $self->_accessor('sql_offset');
-}
-
-sub SQL_limit {
- my $self = shift;
-
- if (my $sql = $self->_accessor('sql_limit')) {
- return $sql;
- }
-
- $self->set( sql_limit => 'LIMIT '.$self->limit ) if defined($self->limit);
- return $self->_accessor('sql_limit');
-}
-
-sub toSQL {
- my $self = shift;
-
- my $SQL = $self->SQL_select_list.' FROM ';
-
- my @subselects;
- for my $search ( $self->searches->keys ) {
- push @subselects, '('.$self->searches->_accessor($search)->toSQL.') '.$search;
- }
- $SQL .= join(', ', @subselects).' WHERE ';
-
- my @relators;
- for my $rel ( $self->relators->list ) {
- push @relators, $rel->value->toSQL( no_quote => 1 );
- }
- $SQL .= join(' AND ', @relators).' ';
- $SQL .= join ' ', ($self->SQL_group_by, $self->SQL_order_by, $self->SQL_limit, $self->SQL_offset);
-
- return $SQL;
-}
-
-#this is just to allow DomainObject to "upcast" nicely
-package OpenSRF::DomainObject::oilsMultiSearch;
-use base OpenSRF::DomainObjectCollection::oilsMultiSearch;
-1;
+++ /dev/null
-package OpenSRF::DomainObject::oilsScalar;
-use base 'OpenSRF::DomainObject';
-use OpenSRF::DomainObject;
-
-=head1 NAME
-
-OpenSRF::DomainObject::oilsScalar
-
-=head1 SYNOPSIS
-
- use OpenSRF::DomainObject::oilsScalar;
-
- my $text = OpenSRF::DomainObject::oilsScalar->new( 'a string or number' );
- $text->value( 'replacement value' );
- print "$text"; # stringify
-
- ...
-
- $text->value( 1 );
- if( $text ) { # boolify
-
- ...
-
- $text->value( rand() * 1000 );
- print 10 + $text; # numify
-
- Or, using the TIE interface:
-
- my $scalar;
- my $real_object = tie($scalar, 'OpenSRF::DomainObject::oilsScalar', "a string to store...");
-
- $scalar = "a new string";
- print $scalar . "\n";
- print $real_object->toString . "\n";
-
-=head1 METHODS
-
-=head2 OpenSRF::DomainObject::oilsScalar->value( [$new_value] )
-
-=over 4
-
-Sets or gets the value of the scalar. As above, this can be specified
-as a build attribute as well as added to a prebuilt oilsScalar object.
-
-=back
-
-=cut
-
-use overload '""' => sub { return ''.$_[0]->value };
-use overload '0+' => sub { return int($_[0]->value) };
-use overload '<=>' => sub { return int($_[0]->value) <=> $_[1] };
-use overload 'bool' => sub { return 1 if ($_[0]->value); return 0 };
-
-sub new {
- my $class = shift;
- $class = ref($class) || $class;
-
- my $value = shift;
-
- return $value
- if ( defined $value and
- ref $value and $value->can('base_type') and
- UNIVERSAL::isa($value->class, __PACKAGE__) and
- !scalar(@_)
- );
-
- my $self = $class->SUPER::new;
-
- if (ref($value) and ref($value) eq 'SCALAR') {
- $self->value($$value);
- tie( $$value, ref($self->upcast), $self);
- } else {
- $self->value($value) if (defined $value);
- }
-
- return $self;
-}
-
-sub TIESCALAR {
- return CORE::shift()->new(@_);
-}
-
-sub value {
- my $self = shift;
- my $value = shift;
-
- if ( defined $value ) {
- $self->removeChild($_) for ($self->childNodes);
- if (ref($value) && $value->isa('XML::LibXML::Node')) {
- #throw OpenSRF::EX::NotADomainObject
- # unless ($value->nodeName =~ /^oils:domainObject/o);
- $self->appendChild($value);
- } elsif (defined $value) {
- $self->appendText( ''.$value );
- }
-
- return $value
- } else {
- $value = $self->firstChild;
- if ($value) {
- if ($value->nodeType == 3) {
- return $value->textContent;
- } else {
- return $value;
- }
- }
- return undef;
- }
-}
-
-sub FETCH { $_[0]->value }
-sub STORE { $_[0]->value($_[1]) }
-
-package OpenSRF::DomainObject::oilsPair;
-use base 'OpenSRF::DomainObject::oilsScalar';
-
-=head1 NAME
-
-OpenSRF::DomainObject::oilsPair
-
-=head1 SYNOPSIS
-
- use OpenSRF::DomainObject::oilsPair;
-
- my $pair = OpenSRF::DomainObject::oilsPair->new( 'key_for_pair' => 'a string or number' );
-
- $pair->key( 'replacement key' );
- $pair->value( 'replacement value' );
-
- print "$pair"; # stringify 'value'
-
- ...
-
- $pair->value( 1 );
-
- if( $pair ) { # boolify
-
- ...
-
- $pair->value( rand() * 1000 );
-
- print 10 + $pair; # numify 'value'
-
-=head1 ABSTRACT
-
-This class impliments a "named pair" object. This is the basis for
-hash-type domain objects.
-
-=head1 METHODS
-
-=head2 OpenSRF::DomainObject::oilsPair->value( [$new_value] )
-
-=over 4
-
-Sets or gets the value of the pair. As above, this can be specified
-as a build attribute as well as added to a prebuilt oilsPair object.
-
-=back
-
-=head2 OpenSRF::DomainObject::oilsPair->key( [$new_key] )
-
-=over 4
-
-Sets or gets the key of the pair. As above, this can be specified
-as a build attribute as well as added to a prebuilt oilsPair object.
-This must be a perlish scalar; any string or number that is valid as the
-attribute on an XML node will work.
-
-=back
-
-=cut
-
-use overload '""' => sub { return ''.$_[0]->value };
-use overload '0+' => sub { return int($_[0]->value) };
-use overload 'bool' => sub { return 1 if ($_[0]->value); return 0 };
-
-sub new {
- my $class = shift;
- my ($key, $value) = @_;
-
- my $self = $class->SUPER::new($value);
- $self->setAttribute( key => $key);
-
- return $self;
-}
-
-sub key {
- my $self = shift;
- my $key = shift;
-
- $self->setAttribute( key => $key) if ($key);
- return $self->getAttribute( 'key' );
-}
-
-package OpenSRF::DomainObjectCollection::oilsArray;
-use base qw/OpenSRF::DomainObjectCollection Tie::Array/;
-use OpenSRF::DomainObjectCollection;
-
-=head1 NAME
-
-OpenSRF::DomainObjectCollection::oilsArray
-
-=head1 SYNOPSIS
-
- use OpenSRF::DomainObject::oilsPrimitive;
-
- my $collection = OpenSRF::DomainObjectCollection::oilsArray->new( $domain_object, $another_domain_object, ...);
-
- $collection->push( 'appended value' );
- $collection->unshift( 'prepended vaule' );
- my $first = $collection->shift;
- my $last = $collection->pop;
-
- ...
-
- my @values = $collection->list;
-
- Or, using the TIE interface:
-
- my @array;
- my $real_object = tie(@array, 'OpenSRF::DomainObjectCollection::oilsArray', $domain, $objects, 'to', $store);
-
- or to tie an existing $collection object
-
- my @array;
- tie(@array, 'OpenSRF::DomainObjectCollection::oilsArray', $collection);
-
- or even....
-
- my @array;
- tie(@array, ref($collection), $collection);
-
-
- $array[2] = $DomainObject; # replaces 'to' (which is now an OpenSRF::DomainObject::oilsScalar) above
- delete( $array[3] ); # removes '$store' above.
- my $size = scalar( @array );
-
- print $real_object->toString;
-
-=head1 ABSTRACT
-
-This package impliments array-like domain objects. A full tie interface
-is also provided. If elements are passed in as strings (or numbers) they
-are turned into oilsScalar objects. Any simple scalar or Domain Object may
-be stored in the array.
-
-=head1 METHODS
-
-=head2 OpenSRF::DomainObjectCollection::oilsArray->list()
-
-=over 4
-
-Returns the array of 'OpenSRF::DomainObject's that this collection contains.
-
-=back
-
-=cut
-
-sub tie_me {
- my $class = shift;
- $class = ref($class) || $class;
- my $node = shift;
- my @array;
- tie @array, $class, $node;
- return \@array;
-}
-
-# an existing DomainObjectCollection::oilsArray can now be tied
-sub TIEARRAY {
- return CORE::shift()->new(@_);
-}
-
-sub new {
- my $class = CORE::shift;
- $class = ref($class) || $class;
-
- my $first = CORE::shift;
-
- return $first
- if ( defined $first and
- ref $first and $first->can('base_type') and
- UNIVERSAL::isa($first->class, __PACKAGE__) and
- !scalar(@_)
- );
-
- my $self = $class->SUPER::new;
-
- my @args = @_;
- if (ref($first) and ref($first) eq 'ARRAY') {
- push @args, @$first;
- tie( @$first, ref($self->upcast), $self);
- } else {
- unshift @args, $first if (defined $first);
- }
-
- $self->STORE($self->FETCHSIZE, $_) for (@args);
- return $self;
-}
-
-sub STORE {
- my $self = CORE::shift;
- my ($index, $value) = @_;
-
- $value = OpenSRF::DomainObject::oilsScalar->new($value)
- unless ( ref $value and $value->nodeName =~ /^oils:domainObject/o );
-
- $self->_expand($index) unless ($self->EXISTS($index));
-
- ($self->childNodes)[$index]->replaceNode( $value );
-
- return $value->upcast;
-}
-
-sub push {
- my $self = CORE::shift;
- my @values = @_;
- $self->STORE($self->FETCHSIZE, $_) for (@values);
-}
-
-sub pop {
- my $self = CORE::shift;
- my $node = $self->SUPER::pop;
- if ($node) {
- if ($node->base_type eq 'oilsScalar') {
- return $node->value;
- }
- return $node->upcast;
- }
-}
-
-sub unshift {
- my $self = CORE::shift;
- my @values = @_;
- $self->insertBefore($self->firstChild, $_ ) for (reverse @values);
-}
-
-sub shift {
- my $self = CORE::shift;
- my $node = $self->SUPER::shift;
- if ($node) {
- if ($node->base_type eq 'oilsScalar') {
- return $node->value;
- }
- return $node->upcast;
- }
-}
-
-sub FETCH {
- my $self = CORE::shift;
- my $index = CORE::shift;
- my $node = ($self->childNodes)[$index]->upcast;
- if ($node) {
- if ($node->base_type eq 'oilsScalar') {
- return $node->value;
- }
- return $node->upcast;
- }
-}
-
-sub size {
- my $self = CORE::shift;
- scalar($self->FETCHSIZE)
-}
-
-sub FETCHSIZE {
- my $self = CORE::shift;
- my @a = $self->childNodes;
- return scalar(@a);
-}
-
-sub _expand {
- my $self = CORE::shift;
- my $count = CORE::shift;
- my $size = $self->FETCHSIZE;
- for ($size..$count) {
- $self->SUPER::push( new OpenSRF::DomainObject::oilsScalar );
- }
-}
-
-sub STORESIZE {
- my $self = CORE::shift;
- my $count = CORE::shift;
- my $size = $self->FETCHSIZE - 1;
-
- if (defined $count and $count != $size) {
- if ($size < $count) {
- $self->_expand($count);
- $size = $self->FETCHSIZE - 1;
- } else {
- while ($size > $count) {
- $self->SUPER::pop;
- $size = $self->FETCHSIZE - 1;
- }
- }
- }
-
- return $size
-}
-
-sub EXISTS {
- my $self = CORE::shift;
- my $index = CORE::shift;
- return $self->FETCHSIZE > abs($index) ? 1 : 0;
-}
-
-sub CLEAR {
- my $self = CORE::shift;
- $self->STORESIZE(0);
- return $self;
-}
-
-sub DELETE {
- my $self = CORE::shift;
- my $index = CORE::shift;
- return $self->removeChild( ($self->childNodes)[$index] );
-}
-
-package OpenSRF::DomainObjectCollection::oilsHash;
-use base qw/OpenSRF::DomainObjectCollection Tie::Hash/;
-
-=head1 NAME
-
-OpenSRF::DomainObjectCollection::oilsHash
-
-=head1 SYNOPSIS
-
- use OpenSRF::DomainObject::oilsPrimitive;
-
- my $collection = OpenSRF::DomainObjectCollection::oilsHash->new( key1 => $domain_object, key2 => $another_domain_object, ...);
-
- $collection->set( key =>'value' );
- my $value = $collection->find( $key );
- my $dead_value = $collection->remove( $key );
- my @keys = $collection->keys;
- my @values = $collection->values;
-
- Or, using the TIE interface:
-
- my %hash;
- my $real_object = tie(%hash, 'OpenSRF::DomainObjectCollection::oilsHash', domain => $objects, to => $store);
-
- or to tie an existing $collection object
-
- my %hash;
- tie(%hash, 'OpenSRF::DomainObjectCollection::oilsHash', $collection);
-
- or even....
-
- my %hash;
- tie(%hash, ref($collection), $collection);
-
- or perhaps ...
-
- my $content = $session->recv->content; # eh? EH?!?!
- tie(my %hash, ref($content), $content);
-
- $hash{domain} = $DomainObject; # replaces value for key 'domain' above
- delete( $hash{to} ); # removes 'to => $store' above.
- for my $key ( keys %hash ) {
- ... do stuff ...
- }
-
- print $real_object->toString;
-
-=head1 ABSTRACT
-
-This package impliments hash-like domain objects. A full tie interface
-is also provided. If elements are passed in as strings (or numbers) they
-are turned into oilsScalar objects. Any simple scalar or Domain Object may
-be stored in the hash.
-
-=back
-
-=cut
-
-sub tie_me {
- my $class = shift;
- $class = ref($class) || $class;
- my $node = shift;
- my %hash;
- tie %hash, $class, $node;
- return %hash;
-}
-
-
-sub keys {
- my $self = shift;
- return map { $_->key } $self->childNodes;
-}
-
-sub values {
- my $self = shift;
- return map { $_->value } $self->childNodes;
-}
-
-# an existing DomainObjectCollection::oilsHash can now be tied
-sub TIEHASH {
- return shift()->new(@_);
-}
-
-sub new {
- my $class = shift;
- $class = ref($class) || $class;
- my $first = shift;
-
- return $first
- if ( defined $first and
- ref $first and $first->can('base_type') and
- UNIVERSAL::isa($first->class, __PACKAGE__) and
- !scalar(@_)
- );
-
- my $self = $class->SUPER::new;
-
- my @args = @_;
- if (ref($first) and ref($first) eq 'HASH') {
- push @args, %$first;
- tie( %$first, ref($self->upcast), $self);
- } else {
- unshift @args, $first if (defined $first);
- }
-
- my %arg_hash = @args;
- while ( my ($key, $value) = each(%arg_hash) ) {
- $self->STORE($key => $value);
- }
- return $self;
-}
-
-sub STORE {
- shift()->set(@_);
-}
-
-sub set {
- my $self = shift;
- my ($key, $value) = @_;
-
- my $node = $self->find_node($key);
-
- return $node->value( $value ) if (defined $node);
- return $self->appendChild( OpenSRF::DomainObject::oilsPair->new($key => $value) );
-}
-
-sub _accessor {
- my $self = shift;
- my $key = shift;
- my $node = find_node($self, $key);
- return $node->value if ($node);
-}
-
-sub find_node {
- my $self = shift;
- my $key = shift;
- return ($self->findnodes("oils:domainObject[\@name=\"oilsPair\" and \@key=\"$key\"]", $self))[0];
-}
-
-sub find {
- my $self = shift;
- my $key = shift;
- my $node = $self->find_node($key);
- my $value = $node->value if (defined $node);
- return $value;
-}
-
-sub size {
- my $self = CORE::shift;
- my @a = $self->childNodes;
- return scalar(@a);
-}
-
-sub FETCH {
- my $self = shift;
- my $key = shift;
- return $self->find($key);
-}
-
-sub EXISTS {
- my $self = shift;
- my $key = shift;
- return $self->find_node($key);
-}
-
-sub CLEAR {
- my $self = shift;
- $self->removeChild for ($self->childNodes);
- return $self;
-}
-
-sub DELETE {
- shift()->remove(@_);
-}
-
-sub remove {
- my $self = shift;
- my $key = shift;
- return $self->removeChild( $self->find_node($key) );
-}
-
-sub FIRSTKEY {
- my $self = shift;
- return $self->firstChild->key;
-}
-
-sub NEXTKEY {
- my $self = shift;
- my $key = shift;
- my ($prev_node) = $self->find_node($key);
- my $last_node = $self->lastChild;
-
- if ($last_node and $last_node->key eq $prev_node->key) {
- return undef;
- } else {
- return $prev_node->nextSibling->key;
- }
-}
-
-package OpenSRF::DomainObject::oilsHash;
-use base qw/OpenSRF::DomainObjectCollection::oilsHash/;
-
-package OpenSRF::DomainObject::oilsArray;
-use base qw/OpenSRF::DomainObjectCollection::oilsArray/;
-
-1;
+++ /dev/null
-package OpenSRF::DomainObject::oilsResponse;
-use vars qw/@EXPORT_OK %EXPORT_TAGS/;
-use Exporter;
-use JSON;
-use base qw/Exporter/;
-use OpenSRF::Utils::Logger qw/:level/;
-
-JSON->register_class_hint( hint => 'osrfResponse', name => 'OpenSRF::DomainObject::oilsResponse', type => 'hash' );
-
-BEGIN {
-@EXPORT_OK = qw/STATUS_CONTINUE STATUS_OK STATUS_ACCEPTED
- STATUS_BADREQUEST STATUS_UNAUTHORIZED STATUS_FORBIDDEN
- STATUS_NOTFOUND STATUS_NOTALLOWED STATUS_TIMEOUT
- STATUS_INTERNALSERVERERROR STATUS_NOTIMPLEMENTED
- STATUS_VERSIONNOTSUPPORTED STATUS_REDIRECTED
- STATUS_EXPFAILED STATUS_COMPLETE/;
-
-%EXPORT_TAGS = (
- status => [ qw/STATUS_CONTINUE STATUS_OK STATUS_ACCEPTED
- STATUS_BADREQUEST STATUS_UNAUTHORIZED STATUS_FORBIDDEN
- STATUS_NOTFOUND STATUS_NOTALLOWED STATUS_TIMEOUT
- STATUS_INTERNALSERVERERROR STATUS_NOTIMPLEMENTED
- STATUS_VERSIONNOTSUPPORTED STATUS_REDIRECTED
- STATUS_EXPFAILED STATUS_COMPLETE/ ],
-);
-
-}
-
-=head1 NAME
-
-OpenSRF::DomainObject::oilsResponse
-
-=head1 SYNOPSIS
-
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-
-my $resp = OpenSRF::DomainObject::oilsResponse->new;
-
-$resp->status( 'a status message' );
-
-$resp->statusCode( STATUS_CONTINUE );
-
-$client->respond( $resp );
-
-=head1 ABSTRACT
-
-OpenSRF::DomainObject::oilsResponse implements the base class for all Application
-layer messages send between the client and server.
-
-=cut
-
-sub STATUS_CONTINUE { return 100 }
-
-sub STATUS_OK { return 200 }
-sub STATUS_ACCEPTED { return 202 }
-sub STATUS_COMPLETE { return 205 }
-
-sub STATUS_REDIRECTED { return 307 }
-
-sub STATUS_BADREQUEST { return 400 }
-sub STATUS_UNAUTHORIZED { return 401 }
-sub STATUS_FORBIDDEN { return 403 }
-sub STATUS_NOTFOUND { return 404 }
-sub STATUS_NOTALLOWED { return 405 }
-sub STATUS_TIMEOUT { return 408 }
-sub STATUS_EXPFAILED { return 417 }
-
-sub STATUS_INTERNALSERVERERROR { return 500 }
-sub STATUS_NOTIMPLEMENTED { return 501 }
-sub STATUS_VERSIONNOTSUPPORTED { return 505 }
-
-my $log = 'OpenSRF::Utils::Logger';
-
-sub toString {
- my $self = shift;
- my $pretty = shift;
- return JSON->perl2prettyJSON($self) if ($pretty);
- return JSON->perl2JSON($self);
-}
-
-sub new {
- my $class = shift;
- $class = ref($class) || $class;
-
- my $default_status = eval "\$${class}::status";
- my $default_statusCode = eval "\$${class}::statusCode";
-
- my %args = ( status => $default_status,
- statusCode => $default_statusCode,
- @_ );
-
- return bless( \%args => $class );
-}
-
-sub status {
- my $self = shift;
- my $val = shift;
- $self->{status} = $val if (defined $val);
- return $self->{status};
-}
-
-sub statusCode {
- my $self = shift;
- my $val = shift;
- $self->{statusCode} = $val if (defined $val);
- return $self->{statusCode};
-}
-
-
-#-------------------------------------------------------------------------------
-
-
-
-package OpenSRF::DomainObject::oilsStatus;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use base 'OpenSRF::DomainObject::oilsResponse';
-use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfStatus', name => 'OpenSRF::DomainObject::oilsStatus', type => 'hash' );
-
-=head1 NAME
-
-OpenSRF::DomainObject::oilsException
-
-=head1 SYNOPSIS
-
-use OpenSRF::DomainObject::oilsResponse;
-
-...
-
-# something happens.
-
-$client->status( OpenSRF::DomainObject::oilsStatus->new );
-
-=head1 ABSTRACT
-
-The base class for Status messages sent between client and server. This
-is implemented on top of the C<OpenSRF::DomainObject::oilsResponse> class, and
-sets the default B<status> to C<Status> and B<statusCode> to C<STATUS_OK>.
-
-=cut
-
-$status = 'Status';
-$statusCode = STATUS_OK;
-
-package OpenSRF::DomainObject::oilsConnectStatus;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use base 'OpenSRF::DomainObject::oilsStatus';
-use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfConnectStatus', name => 'OpenSRF::DomainObject::oilsConnectStatus', type => 'hash' );
-
-=head1 NAME
-
-OpenSRF::DomainObject::oilsConnectStatus
-
-=head1 SYNOPSIS
-
-use OpenSRF::DomainObject::oilsResponse;
-
-...
-
-# something happens.
-
-$client->status( new OpenSRF::DomainObject::oilsConnectStatus );
-
-=head1 ABSTRACT
-
-The class for Stati relating to the connection status of a session. This
-is implemented on top of the C<OpenSRF::DomainObject::oilsStatus> class, and
-sets the default B<status> to C<Connection Successful> and B<statusCode> to C<STATUS_OK>.
-
-=head1 SEE ALSO
-
-B<OpenSRF::DomainObject::oilsStatus>
-
-=cut
-
-$status = 'Connection Successful';
-$statusCode = STATUS_OK;
-
-
-
-
-package OpenSRF::DomainObject::oilsContinueStatus;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use base 'OpenSRF::DomainObject::oilsStatus';
-use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfContinueStatus', name => 'OpenSRF::DomainObject::oilsContinueStatus', type => 'hash' );
-
-=head1 NAME
-
-OpenSRF::DomainObject::oilsContinueStatus
-
-=head1 SYNOPSIS
-
-use OpenSRF::DomainObject::oilsResponse;
-
-...
-
-# something happens.
-
-$client->status( new OpenSRF::DomainObject::oilsContinueStatus );
-
-=head1 ABSTRACT
-
-Implements the STATUS_CONTINUE message, informing the client that it should
-continue to wait for a response to it's request.
-
-=head1 SEE ALSO
-
-B<OpenSRF::DomainObject::oilsStatus>
-
-=cut
-
-$status = 'Please hold. Creating response...';
-$statusCode = STATUS_CONTINUE;
-
-1;
-
-
-
-#-------------------------------------------------------------------------------
-
-
-
-package OpenSRF::DomainObject::oilsResult;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use OpenSRF::DomainObject::oilsPrimitive;
-use base 'OpenSRF::DomainObject::oilsResponse';
-use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfResult', name => 'OpenSRF::DomainObject::oilsResult', type => 'hash' );
-
-
-$status = 'OK';
-$statusCode = STATUS_OK;
-
-=head1 NAME
-
-OpenSRF::DomainObject::oilsResult
-
-=head1 SYNOPSIS
-
-use OpenSRF::DomainObject::oilsResponse;
-
- .... do stuff, create $object ...
-
-my $res = OpenSRF::DomainObject::oilsResult->new;
-
-$res->content($object)
-
-$session->respond( $res );
-
-=head1 ABSTRACT
-
-This is the base class for encapuslating RESULT messages send from the server
-to a client. It is a subclass of B<OpenSRF::DomainObject::oilsResponse>, and
-sets B<status> to C<OK> and B<statusCode> to C<STATUS_OK>.
-
-=head1 METHODS
-
-=head2 OpenSRF::DomainObject::oilsMessage->content( [$new_content] )
-
-=over 4
-
-Sets or gets the content of the response. This should be exactly one object
-of (sub)type domainObject or domainObjectCollection.
-
-=back
-
-=cut
-
-sub content {
- my $self = shift;
- my $val = shift;
-
- $self->{content} = $val if (defined $val);
- return $self->{content};
-}
-
-=head1 SEE ALSO
-
-B<OpenSRF::DomainObject::oilsResponse>
-
-=cut
-
-1;
-
-
-
-#-------------------------------------------------------------------------------
-
-
-
-package OpenSRF::DomainObject::oilsException;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use OpenSRF::EX;
-use base qw/OpenSRF::EX OpenSRF::DomainObject::oilsResponse/;
-use vars qw/$status $statusCode/;
-use Error;
-JSON->register_class_hint( hint => 'osrfException', name => 'OpenSRF::DomainObject::oilsException', type => 'hash' );
-
-sub message {
- my $self = shift;
- return '<' . $self->statusCode . '> ' . $self->status;
-}
-
-sub new {
- my $class = shift;
- return $class->OpenSRF::DomainObject::oilsResponse::new( @_ );
-}
-
-
-=head1 NAME
-
-OpenSRF::DomainObject::oilsException
-
-=head1 SYNOPSIS
-
-use OpenSRF::DomainObject::oilsResponse;
-
-...
-
-# something breaks.
-
-$client->send( 'ERROR', OpenSRF::DomainObject::oilsException->new( status => "ARRRRRRG!" ) );
-
-=head1 ABSTRACT
-
-The base class for Exception messages sent between client and server. This
-is implemented on top of the C<OpenSRF::DomainObject::oilsResponse> class, and
-sets the default B<status> to C<Exception occured> and B<statusCode> to C<STATUS_BADREQUEST>.
-
-=cut
-
-$status = 'Exception occured';
-$statusCode = STATUS_INTERNALSERVERERROR;
-
-package OpenSRF::DomainObject::oilsConnectException;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use OpenSRF::EX;
-use base qw/OpenSRF::DomainObject::oilsException OpenSRF::EX::ERROR/;
-use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfConnectException', name => 'OpenSRF::DomainObject::oilsConnectException', type => 'hash' );
-
-=head1 NAME
-
-OpenSRF::DomainObject::oilsConnectException
-
-=head1 SYNOPSIS
-
-use OpenSRF::DomainObject::oilsResponse;
-
-...
-
-# something breaks while connecting.
-
-$client->send( 'ERROR', new OpenSRF::DomainObject::oilsConnectException );
-
-=head1 ABSTRACT
-
-The class for Exceptions that occur durring the B<CONNECT> phase of a session. This
-is implemented on top of the C<OpenSRF::DomainObject::oilsException> class, and
-sets the default B<status> to C<Connect Request Failed> and B<statusCode> to C<STATUS_FORBIDDEN>.
-
-=head1 SEE ALSO
-
-B<OpenSRF::DomainObject::oilsException>
-
-=cut
-
-
-$status = 'Connect Request Failed';
-$statusCode = STATUS_FORBIDDEN;
-
-package OpenSRF::DomainObject::oilsMethodException;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use base 'OpenSRF::DomainObject::oilsException';
-use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfMethodException', name => 'OpenSRF::DomainObject::oilsMethodException', type => 'hash' );
-
-=head1 NAME
-
-OpenSRF::DomainObject::oilsMehtodException
-
-=head1 SYNOPSIS
-
-use OpenSRF::DomainObject::oilsResponse;
-
-...
-
-# something breaks while looking up or starting
-# a method call.
-
-$client->send( 'ERROR', new OpenSRF::DomainObject::oilsMethodException );
-
-=head1 ABSTRACT
-
-The class for Exceptions that occur durring the B<CONNECT> phase of a session. This
-is implemented on top of the C<OpenSRF::DomainObject::oilsException> class, and
-sets the default B<status> to C<Connect Request Failed> and B<statusCode> to C<STATUS_NOTFOUND>.
-
-=head1 SEE ALSO
-
-B<OpenSRF::DomainObject::oilsException>
-
-=cut
-
-
-$status = 'A server error occured during method execution';
-$statusCode = STATUS_INTERNALSERVERERROR;
-
-# -------------------------------------------
-
-package OpenSRF::DomainObject::oilsServerError;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use base 'OpenSRF::DomainObject::oilsException';
-use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfServerError', name => 'OpenSRF::DomainObject::oilsServerError', type => 'hash' );
-
-$status = 'Internal Server Error';
-$statusCode = STATUS_INTERNALSERVERERROR;
-
-# -------------------------------------------
-
-
-
-
-
-package OpenSRF::DomainObject::oilsBrokenSession;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use OpenSRF::EX;
-use base qw/OpenSRF::DomainObject::oilsException OpenSRF::EX::ERROR/;
-use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfBrokenSession', name => 'OpenSRF::DomainObject::oilsBrokenSession', type => 'hash' );
-$status = "Request on Disconnected Session";
-$statusCode = STATUS_EXPFAILED;
-
-package OpenSRF::DomainObject::oilsXMLParseError;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use OpenSRF::EX;
-use base qw/OpenSRF::DomainObject::oilsException OpenSRF::EX::ERROR/;
-use vars qw/$status $statusCode/;
-JSON->register_class_hint( hint => 'osrfXMLParseError', name => 'OpenSRF::DomainObject::oilsXMLParseError', type => 'hash' );
-$status = "XML Parse Error";
-$statusCode = STATUS_EXPFAILED;
-
-package OpenSRF::DomainObject::oilsAuthException;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use OpenSRF::EX;
-use base qw/OpenSRF::DomainObject::oilsException OpenSRF::EX::ERROR/;
-JSON->register_class_hint( hint => 'osrfAuthException', name => 'OpenSRF::DomainObject::oilsAuthException', type => 'hash' );
-use vars qw/$status $statusCode/;
-$status = "Authentication Failure";
-$statusCode = STATUS_FORBIDDEN;
-
-1;
+++ /dev/null
-package OpenSRF::DomainObject::oilsSearch;
-use OpenSRF::DomainObject;
-use OpenSRF::DomainObject::oilsPrimitive;
-use OpenSRF::DOM::Element::searchCriteria;
-use base 'OpenSRF::DomainObject';
-
-sub new {
- my $class = shift;
- $class = ref($class) || $class;
-
- unshift @_, 'table' if (@_ == 1);
- my %args = @_;
-
- my $self = $class->SUPER::new;
-
- for my $part ( keys %args ) {
- if ($part ne 'criteria') {
- $self->$part( $args{$part} );
- next;
- }
- $self->criteria( OpenSRF::DOM::Element::searchCriteria->new( @{$args{$part}} ) );
- }
- return $self;
-}
-
-sub format {
- my $self = shift;
- return $self->_attr_get_set( format => shift );
-}
-
-sub table {
- my $self = shift;
- return $self->_attr_get_set( table => shift );
-}
-
-sub fields {
- my $self = shift;
- my $new_fields_ref = shift;
-
- my ($old_fields) = $self->getChildrenByTagName("oils:domainObjectCollection");
-
- if ($new_fields_ref) {
- my $do = OpenSRF::DomainObjectCollection::oilsArray->new( @$new_fields_ref );
- if (defined $old_fields) {
- $old_fields->replaceNode($do);
- } else {
- $self->appendChild($do);
- return $do->list;
- }
- }
-
- return $old_fields->list if ($old_fields);
-}
-
-sub limit {
- my $self = shift;
- return $self->_attr_get_set( limit => shift );
-}
-
-sub offset {
- my $self = shift;
- return $self->_attr_get_set( offset => shift );
-}
-
-sub group_by {
- my $self = shift;
- return $self->_attr_get_set( group_by => shift );
-}
-
-sub criteria {
- my $self = shift;
- my $new_crit = shift;
-
- if (@_) {
- unshift @_, $new_crit;
- $new_crit = OpenSRF::DOM::Element::searchCriteria->new(@_);
- }
-
- my ($old_crit) = $self->getChildrenByTagName("oils:searchCriteria");
-
- if (defined $new_crit) {
- if (defined $old_crit) {
- $old_crit->replaceNode($new_crit);
- } else {
- $self->appendChild($new_crit);
- return $new_crit;
- }
- }
-
- return $old_crit;
-}
-
-sub toSQL {
- my $self = shift;
-
- my $SQL = 'SELECT ' . join(',', $self->fields);
- $SQL .= ' FROM ' . $self->table;
- $SQL .= ' WHERE ' . $self->criteria->toSQL if ($self->criteria);
- $SQL .= ' GROUP BY ' . $self->group_by if ($self->group_by);
- $SQL .= ' LIMIT ' . $self->limit if ($self->limit);
- $SQL .= ' OFFSET ' . $self->offset if ($self->offset);
-
- return $SQL;
-}
-
-1;
+++ /dev/null
-package OpenSRF::DomainObjectCollection;
-use base 'OpenSRF::DOM::Element::domainObjectCollection';
-use OpenSRF::DOM;
-use OpenSRF::Utils::Logger qw(:level);
-my $logger = "OpenSRF::Utils::Logger";
-
-=head1 NAME
-
-OpenSRF::DomainObjectCollection
-
-=head1 SYNOPSIS
-
-OpenSRF::DomainObjectCollection is an abstract base class. It
-should not be used directly. See C<OpenSRF::DomainObjectCollection::*>
-for details.
-
-=cut
-
-sub new {
- my $class = shift;
- $class = ref($class) || $class;
-
- my @args = shift;
-
- (my $type = $class) =~ s/^.+://o;
-
- my $doc = OpenSRF::DOM->createDocument;
- my $dO = OpenSRF::DOM::Element::domainObjectCollection->new( $type, @args );
-
- $doc->documentElement->appendChild($dO);
-
- return $dO;
-}
-
-1;
+++ /dev/null
-package OpenSRF::EX;
-use Error qw(:try);
-use base qw( OpenSRF Error );
-use OpenSRF::Utils::Logger;
-
-my $log = "OpenSRF::Utils::Logger";
-$Error::Debug = 1;
-
-sub new {
- my( $class, $message ) = @_;
- $class = ref( $class ) || $class;
- my $self = {};
- $self->{'msg'} = ${$class . '::ex_msg_header'} ." \n$message";
- return bless( $self, $class );
-}
-
-sub message() { return $_[0]->{'msg'}; }
-
-sub DESTROY{}
-
-
-=head1 OpenSRF::EX
-
-Top level exception. This class logs an exception when it is thrown. Exception subclasses
-should subclass one of OpenSRF::EX::INFO, NOTICE, WARN, ERROR, CRITICAL, and PANIC and provide
-a new() method that takes a message and a message() method that returns that message.
-
-=cut
-
-=head2 Synopsis
-
-
- throw OpenSRF::EX::Jabber ("I Am Dying");
-
- OpenSRF::EX::InvalidArg->throw( "Another way" );
-
- my $je = OpenSRF::EX::Jabber->new( "I Cannot Connect" );
- $je->throw();
-
-
- See OpenSRF/EX.pm for example subclasses.
-
-=cut
-
-# Log myself and throw myself
-
-#sub message() { shift->alert_abstract(); }
-
-#sub new() { shift->alert_abstract(); }
-
-sub throw() {
-
- my $self = shift;
-
- if( ! ref( $self ) || scalar( @_ ) ) {
- $self = $self->new( @_ );
- }
-
- if( $self->class->isa( "OpenSRF::EX::INFO" ) ||
- $self->class->isa( "OpenSRF::EX::NOTICE" ) ||
- $self->class->isa( "OpenSRF::EX::WARN" ) ) {
-
- $log->debug( $self->stringify(), $log->DEBUG );
- }
-
- else{ $log->debug( $self->stringify(), $log->ERROR ); }
-
- $self->SUPER::throw;
-}
-
-
-sub stringify() {
-
- my $self = shift;
- my $ctime = localtime();
- my( $package, $file, $line) = get_caller();
- my $name = ref( $self );
- my $msg = $self->message();
-
- $msg =~ s/^/Mess: /mg;
-
- return " * ! EXCEPTION ! * \nTYPE: $name\n$msg\n".
- "Loc.: $line $package \nLoc.: $file \nTime: $ctime\n";
-}
-
-
-# --- determine the originating caller of this exception
-sub get_caller() {
-
- $package = caller();
- my $x = 0;
- while( $package->isa( "Error" ) || $package =~ /^Error::/ ) {
- $package = caller( ++$x );
- }
- return (caller($x));
-}
-
-
-
-
-# -------------------------------------------------------------------
-# -------------------------------------------------------------------
-
-# Top level exception subclasses defining the different exception
-# levels.
-
-# -------------------------------------------------------------------
-
-package OpenSRF::EX::INFO;
-use base qw(OpenSRF::EX);
-our $ex_msg_header = "System INFO";
-
-# -------------------------------------------------------------------
-
-package OpenSRF::EX::NOTICE;
-use base qw(OpenSRF::EX);
-our $ex_msg_header = "System NOTICE";
-
-# -------------------------------------------------------------------
-
-package OpenSRF::EX::WARN;
-use base qw(OpenSRF::EX);
-our $ex_msg_header = "System WARNING";
-
-# -------------------------------------------------------------------
-
-package OpenSRF::EX::ERROR;
-use base qw(OpenSRF::EX);
-our $ex_msg_header = "System ERROR";
-
-# -------------------------------------------------------------------
-
-package OpenSRF::EX::CRITICAL;
-use base qw(OpenSRF::EX);
-our $ex_msg_header = "System CRITICAL";
-
-# -------------------------------------------------------------------
-
-package OpenSRF::EX::PANIC;
-use base qw(OpenSRF::EX);
-our $ex_msg_header = "System PANIC";
-
-# -------------------------------------------------------------------
-# -------------------------------------------------------------------
-
-# Some basic exceptions
-
-# -------------------------------------------------------------------
-package OpenSRF::EX::Jabber;
-use base 'OpenSRF::EX::ERROR';
-our $ex_msg_header = "Jabber Exception";
-
-package OpenSRF::EX::JabberDisconnected;
-use base 'OpenSRF::EX::ERROR';
-our $ex_msg_header = "JabberDisconnected Exception";
-
-=head2 OpenSRF::EX::Jabber
-
-Thrown when there is a problem using the Jabber service
-
-=cut
-
-package OpenSRF::EX::Transport;
-use base 'OpenSRF::EX::ERROR';
-our $ex_msg_header = "Transport Exception";
-
-
-
-# -------------------------------------------------------------------
-package OpenSRF::EX::InvalidArg;
-use base 'OpenSRF::EX::ERROR';
-our $ex_msg_header = "Invalid Arg Exception";
-
-=head2 OpenSRF::EX::InvalidArg
-
-Thrown where an argument to a method was invalid or not provided
-
-=cut
-
-
-# -------------------------------------------------------------------
-package OpenSRF::EX::NotADomainObject;
-use base 'OpenSRF::EX::ERROR';
-our $ex_msg_header = "Must be a Domain Object";
-
-=head2 OpenSRF::EX::NotADomainObject
-
-Thrown where a OpenSRF::DomainObject::oilsScalar or
-OpenSRF::DomainObject::oilsPair was passed a value that
-is not a perl scalar or a OpenSRF::DomainObject.
-
-=cut
-
-
-# -------------------------------------------------------------------
-package OpenSRF::EX::ArrayOutOfBounds;
-use base 'OpenSRF::EX::ERROR';
-our $ex_msg_header = "Tied array access on a nonexistant index";
-
-=head2 OpenSRF::EX::ArrayOutOfBounds
-
-Thrown where a TIEd array (OpenSRF::DomainObject::oilsArray) was accessed at
-a nonexistant index
-
-=cut
-
-
-
-# -------------------------------------------------------------------
-package OpenSRF::EX::Socket;
-use base 'OpenSRF::EX::ERROR';
-our $ex_msg_header = "Socket Exception";
-
-=head2 OpenSRF::EX::Socket
-
-Thrown when there is a network layer exception
-
-=cut
-
-
-
-# -------------------------------------------------------------------
-package OpenSRF::EX::Config;
-use base 'OpenSRF::EX::PANIC';
-our $ex_msg_header = "Config Exception";
-
-=head2 OpenSRF::EX::Config
-
-Thrown when a package requires a config option that it cannot retrieve
-or the config file itself cannot be loaded
-
-=cut
-
-
-# -------------------------------------------------------------------
-package OpenSRF::EX::User;
-use base 'OpenSRF::EX::ERROR';
-our $ex_msg_header = "User Exception";
-
-=head2 OpenSRF::EX::User
-
-Thrown when an error occurs due to user identification information
-
-=cut
-
-package OpenSRF::EX::Session;
-use base 'OpenSRF::EX::ERROR';
-our $ex_msg_header = "Session Error";
-
-
-1;
+++ /dev/null
-package OpenSRF::MultiSession;
-use OpenSRF::AppSession;
-use OpenSRF::Utils::Logger;
-use Time::HiRes qw/time usleep/;
-
-my $log = 'OpenSRF::Utils::Logger';
-
-sub new {
- my $class = shift;
- $class = ref($class) || $class;
-
- my $self = bless {@_} => $class;
-
- $self->{api_level} = 1 if (!defined($self->{api_level}));
- $self->{session_hash_function} = \&_dummy_session_hash_function
- if (!defined($self->{session_hash_function}));
-
- if ($self->{cap}) {
- $self->session_cap($self->{cap}) if (!$self->session_cap);
- $self->request_cap($self->{cap}) if (!$self->request_cap);
- }
-
- if (!$self->session_cap) {
- # XXX make adaptive the default once the logic is in place
- #$self->adaptive(1);
-
- $self->session_cap(10);
- }
- if (!$self->request_cap) {
- # XXX make adaptive the default once the logic is in place
- #$self->adaptive(1);
-
- $self->request_cap(10);
- }
-
- $self->{sessions} = [];
- $self->{running} = [];
- $self->{completed} = [];
- $self->{failed} = [];
-
- for ( 1 .. $self->session_cap) {
- push @{ $self->{sessions} },
- OpenSRF::AppSession->create(
- $self->{app},
- $self->{api_level},
- 1
- );
- #print "Creating connection ".$self->{sessions}->[-1]->session_id." ...\n";
- $log->debug("Creating connection ".$self->{sessions}->[-1]->session_id." ...");
- }
-
- return $self;
-}
-
-sub _dummy_session_hash_function {
- my $self = shift;
- $self->{_dummy_hash_counter} = 1 if (!exists($self->{_dummy_hash_counter}));
- return $self->{_dummy_hash_counter}++;
-}
-
-sub connect {
- my $self = shift;
- for my $ses (@{$self->{sessions}}) {
- $ses->connect unless ($ses->connected);
- }
-}
-
-sub finish {
- my $self = shift;
- $_->finish for (@{$self->{sessions}});
-}
-
-sub disconnect {
- my $self = shift;
- $_->disconnect for (@{$self->{sessions}});
-}
-
-sub session_hash_function {
- my $self = shift;
- my $session_hash_function = shift;
- return unless (ref $self);
-
- $self->{session_hash_function} = $session_hash_function if (defined $session_hash_function);
- return $self->{session_hash_function};
-}
-
-sub failure_handler {
- my $self = shift;
- my $failure_handler = shift;
- return unless (ref $self);
-
- $self->{failure_handler} = $failure_handler if (defined $failure_handler);
- return $self->{failure_handler};
-}
-
-sub success_handler {
- my $self = shift;
- my $success_handler = shift;
- return unless (ref $self);
-
- $self->{success_handler} = $success_handler if (defined $success_handler);
- return $self->{success_handler};
-}
-
-sub session_cap {
- my $self = shift;
- my $cap = shift;
- return unless (ref $self);
-
- $self->{session_cap} = $cap if (defined $cap);
- return $self->{session_cap};
-}
-
-sub request_cap {
- my $self = shift;
- my $cap = shift;
- return unless (ref $self);
-
- $self->{request_cap} = $cap if (defined $cap);
- return $self->{request_cap};
-}
-
-sub adaptive {
- my $self = shift;
- my $adapt = shift;
- return unless (ref $self);
-
- $self->{adaptive} = $adapt if (defined $adapt);
- return $self->{adaptive};
-}
-
-sub completed {
- my $self = shift;
- my $count = shift;
- return unless (ref $self);
-
-
- if (wantarray) {
- $count ||= scalar @{$self->{completed}};
- }
-
- if (defined $count) {
- return () unless (@{$self->{completed}});
- return splice @{$self->{completed}}, 0, $count;
- }
-
- return scalar @{$self->{completed}};
-}
-
-sub failed {
- my $self = shift;
- my $count = shift;
- return unless (ref $self);
-
-
- if (wantarray) {
- $count ||= scalar @{$self->{failed}};
- }
-
- if (defined $count) {
- return () unless (@{$self->{failed}});
- return splice @{$self->{failed}}, 0, $count;
- }
-
- return scalar @{$self->{failed}};
-}
-
-sub running {
- my $self = shift;
- return unless (ref $self);
- return scalar(@{ $self->{running} });
-}
-
-
-sub request {
- my $self = shift;
- my $hash_param;
-
- my $method = shift;
- if (ref $method) {
- $hash_param = $method;
- $method = shift;
- }
-
- my @params = @_;
-
- $self->session_reap;
- if ($self->running < $self->request_cap ) {
- my $index = $self->session_hash_function->($self, (defined $hash_param ? $hash_param : ()), $method, @params);
- my $ses = $self->{sessions}->[$index % $self->session_cap];
-
- #print "Running $method using session ".$ses->session_id."\n";
-
- my $req = $ses->request( $method, @params );
-
- push @{ $self->{running} },
- { req => $req,
- meth => $method,
- hash => $hash_param,
- params => [@params]
- };
-
- $log->debug("Making request [$method] ".$self->running."...");
-
- return $req;
- } elsif (!$self->adaptive) {
- #print "Oops. Too many running: ".$self->running."\n";
- $self->session_wait;
- return $self->request((defined $hash_param ? $hash_param : ()), $method => @params);
- } else {
- # XXX do addaptive stuff ...
- }
-}
-
-sub session_wait {
- my $self = shift;
- my $all = shift;
-
- my $count;
- if ($all) {
- $count = $self->running;
- while ($self->running) {
- $self->session_reap;
- }
- return $count;
- } else {
- while(($count = $self->session_reap) == 0 && $self->running) {
- usleep 100;
- }
- return $count;
- }
-}
-
-sub session_reap {
- my $self = shift;
-
- my @done;
- my @running;
- while ( my $req = shift @{ $self->{running} } ) {
- if ($req->{req}->complete) {
- #print "Currently running: ".$self->running."\n";
-
- $req->{response} = [ $req->{req}->recv ];
- $req->{duration} = $req->{req}->duration;
-
- #print "Completed ".$req->{meth}." in session ".$req->{req}->session->session_id." [$req->{duration}]\n";
-
- if ($req->{req}->failed) {
- #print "ARG!!!! Failed command $req->{meth} in session ".$req->{req}->session->session_id."\n";
- $req->{error} = $req->{req}->failed;
- push @{ $self->{failed} }, $req;
- } else {
- push @{ $self->{completed} }, $req;
- }
-
- push @done, $req;
-
- } else {
- #$log->debug("Still running ".$req->{meth}." in session ".$req->{req}->session->session_id);
- push @running, $req;
- }
- }
- push @{ $self->{running} }, @running;
-
- for my $req ( @done ) {
- my $handler = $req->{error} ? $self->failure_handler : $self->success_handler;
- $handler->($self, $req) if ($handler);
-
- $req->{req}->finish;
- delete $$req{$_} for (keys %$req);
-
- }
-
- my $complete = scalar @done;
- my $incomplete = scalar @running;
-
- #$log->debug("Still running $incomplete, completed $complete");
-
- return $complete;
-}
-
-1;
-
+++ /dev/null
-package OpenSRF::System;
-use strict; use warnings;
-use OpenSRF;
-use base 'OpenSRF';
-use OpenSRF::Utils::Logger qw(:level);
-use OpenSRF::Transport::Listener;
-use OpenSRF::Transport;
-use OpenSRF::UnixServer;
-use OpenSRF::Utils;
-use OpenSRF::Utils::LogServer;
-use OpenSRF::DOM;
-use OpenSRF::EX qw/:try/;
-use POSIX ":sys_wait_h";
-use OpenSRF::Utils::Config;
-use OpenSRF::Utils::SettingsParser;
-use OpenSRF::Utils::SettingsClient;
-use OpenSRF::Application;
-use Net::Server::PreFork;
-use strict;
-
-my $bootstrap_config_file;
-sub import {
- my( $self, $config ) = @_;
- $bootstrap_config_file = $config;
-}
-
-=head2 Name/Description
-
-OpenSRF::System
-
-To start the system: OpenSRF::System->bootstrap();
-
-Simple system process management and automation. After instantiating the class, simply call
-bootstrap() to launch the system. Each launched process is stored as a process-id/method-name
-pair in a local hash. When we receive a SIG{CHILD}, we loop through this hash and relaunch
-any child processes that may have terminated.
-
-Currently automated processes include launching the internal Unix Servers, launching the inbound
-connections for each application, and starting the system shell.
-
-
-Note: There should be only one instance of this class
-alive at any given time. It is designed as a globel process handler and, hence, will cause much
-oddness if you call the bootstrap() method twice or attempt to create two of these by trickery.
-There is a single instance of the class created on the first call to new(). This same instance is
-returned on subsequent calls to new().
-
-=cut
-
-$| = 1;
-
-sub DESTROY {}
-
-# ----------------------------------------------
-
-$SIG{INT} = sub { instance()->killall(); };
-
-$SIG{HUP} = sub{ instance()->hupall(); };
-
-#$SIG{CHLD} = \&process_automation;
-
-
-{
- # ---
- # put $instance in a closure and return it for requests to new()
- # since there should only be one System instance running
- # -----
- my $instance;
- sub instance { return __PACKAGE__->new(); }
- sub new {
- my( $class ) = @_;
-
- if( ! $instance ) {
- $class = ref( $class ) || $class;
- my $self = {};
- $self->{'pid_hash'} = {};
- bless( $self, $class );
- $instance = $self;
- }
- return $instance;
- }
-}
-
-# ----------------------------------------------
-# Commands to execute at system launch
-
-sub _unixserver {
- my( $app ) = @_;
- return "OpenSRF::UnixServer->new( '$app')->serve()";
-}
-
-sub _listener {
- my( $app ) = @_;
- return "OpenSRF::Transport::Listener->new( '$app' )->initialize()->listen()";
-}
-
-
-# ----------------------------------------------
-# Boot up the system
-
-sub load_bootstrap_config {
-
- if(OpenSRF::Utils::Config->current) {
- return;
- }
-
- if(!$bootstrap_config_file) {
- die "Please provide a bootstrap config file to OpenSRF::System!\n" .
- "use OpenSRF::System qw(/path/to/bootstrap_config);";
- }
-
- OpenSRF::Utils::Config->load( config_file => $bootstrap_config_file );
-
- JSON->register_class_hint( name => "OpenSRF::Application", hint => "method", type => "hash" );
-
- OpenSRF::Transport->message_envelope( "OpenSRF::Transport::SlimJabber::MessageWrapper" );
- OpenSRF::Transport::PeerHandle->set_peer_client( "OpenSRF::Transport::SlimJabber::PeerConnection" );
- OpenSRF::Transport::Listener->set_listener( "OpenSRF::Transport::SlimJabber::Inbound" );
- OpenSRF::Application->server_class('client');
-}
-
-sub bootstrap {
-
- my $self = __PACKAGE__->instance();
- load_bootstrap_config();
- OpenSRF::Utils::Logger::set_config();
- my $bsconfig = OpenSRF::Utils::Config->current;
-
- # Start a process group and make me the captain
- setpgrp( 0, 0 );
- $0 = "OpenSRF System";
-
- # -----------------------------------------------
- # Launch the settings sever if necessary...
- my $are_settings_server = 0;
- if( (my $cfile = $bsconfig->bootstrap->settings_config) ) {
- my $parser = OpenSRF::Utils::SettingsParser->new();
-
- # since we're (probably) the settings server, we can go ahead and load the real config file
- $parser->initialize( $cfile );
- $OpenSRF::Utils::SettingsClient::host_config =
- $parser->get_server_config($bsconfig->env->hostname);
-
- my $client = OpenSRF::Utils::SettingsClient->new();
- my $apps = $client->config_value("activeapps", "appname");
- if(ref($apps) ne "ARRAY") { $apps = [$apps]; }
-
- if(!defined($apps) || @$apps == 0) {
- print "No apps to load, exiting...";
- return;
- }
-
- for my $app (@$apps) {
- # verify we are a settings server and launch
- if( $app eq "opensrf.settings" and
- $client->config_value("apps","opensrf.settings", "language") =~ /perl/i ) {
-
- $are_settings_server = 1;
- $self->launch_settings();
- sleep 1;
- $self->launch_settings_listener();
- last;
- }
- }
- }
-
- # Launch everything else
- OpenSRF::System->bootstrap_client(client_name => "system_client");
- my $client = OpenSRF::Utils::SettingsClient->new();
- my $apps = $client->config_value("activeapps", "appname" );
- if(!ref($apps)) { $apps = [$apps]; }
-
- if(!defined($apps) || @$apps == 0) {
- print "No apps to load, exiting...";
- return;
- }
-
- my $server_type = $client->config_value("server_type");
- $server_type ||= "basic";
-
- my $con = OpenSRF::Transport::PeerHandle->retrieve;
- if($con) {
- $con->disconnect;
- }
-
-
-
- if( $server_type eq "prefork" ) {
- $server_type = "Net::Server::PreFork";
- } else {
- $server_type = "Net::Server::Single";
- }
-
- _log( " * Server type: $server_type", INTERNAL );
-
- $server_type->use;
-
- if( $@ ) {
- throw OpenSRF::EX::PANIC ("Cannot set $server_type: $@" );
- }
-
- push @OpenSRF::UnixServer::ISA, $server_type;
-
- _log( " * System bootstrap" );
-
- # --- Boot the Unix servers
- $self->launch_unix($apps);
-
- sleep 2;
-
- # --- Boot the listeners
- $self->launch_listener($apps);
-
- sleep 1;
-
- _log( " * System is ready..." );
-
-# sleep 1;
-# my $ps = `ps ax | grep " Open" | grep -v grep | sort -r -k5`;
-# print "\n --- PS --- \n$ps --- PS ---\n\n";
-
- while( 1 ) { sleep; }
- exit;
-}
-
-
-
-# ----------------------------------------------
-# Bootstraps a single client connection.
-
-# named params are 'config_file' and 'client_name'
-#
-sub bootstrap_client {
- my $self = shift;
-
- my $con = OpenSRF::Transport::PeerHandle->retrieve;
-
- if($con and $con->tcp_connected) {
- return;
- }
-
- my %params = @_;
-
- $bootstrap_config_file =
- $params{config_file} || $bootstrap_config_file;
-
- my $app = $params{client_name} || "client";
-
-
- load_bootstrap_config();
- OpenSRF::Utils::Logger::set_config();
- OpenSRF::Transport::PeerHandle->construct( $app );
-
-}
-
-sub connected {
- if (my $con = OpenSRF::Transport::PeerHandle->retrieve) {
- return 1 if ($con->tcp_connected);
- }
- return 0;
-}
-
-sub bootstrap_logger {
- $0 = "Log Server";
- OpenSRF::Utils::LogServer->serve();
-}
-
-
-# ----------------------------------------------
-# Cycle through the known processes, reap the dead child
-# and put a new child in its place. (MMWWAHAHHAHAAAA!)
-
-sub process_automation {
-
- my $self = __PACKAGE__->instance();
-
- foreach my $pid ( keys %{$self->pid_hash} ) {
-
- if( waitpid( $pid, WNOHANG ) == $pid ) {
-
- my $method = $self->pid_hash->{$pid};
- delete $self->pid_hash->{$pid};
-
- my $newpid = OpenSRF::Utils::safe_fork();
-
- OpenSRF::Utils::Logger->debug( "Relaunching $method", ERROR );
- _log( "Relaunching => $method" );
-
- if( $newpid ) {
- $self->pid_hash( $newpid, $method );
- }
- else { eval $method; exit; }
- }
- }
-
- $SIG{CHLD} = \&process_automation;
-}
-
-
-
-sub launch_settings {
-
- # XXX the $self like this and pid automation will not work with this setup....
- my($self) = @_;
- @OpenSRF::UnixServer::ISA = qw(OpenSRF Net::Server::PreFork);
-
- my $pid = OpenSRF::Utils::safe_fork();
- if( $pid ) {
- $self->pid_hash( $pid , "launch_settings()" );
- }
- else {
- my $apname = "opensrf.settings";
- #$0 = "OpenSRF App [$apname]";
- eval _unixserver( $apname );
- if($@) { die "$@\n"; }
- exit;
- }
-
- @OpenSRF::UnixServer::ISA = qw(OpenSRF);
-
-}
-
-
-sub launch_settings_listener {
-
- my $self = shift;
- my $app = "opensrf.settings";
- my $pid = OpenSRF::Utils::safe_fork();
- if ( $pid ) {
- $self->pid_hash( $pid , _listener( $app ) );
- }
- else {
- my $apname = $app;
- $0 = "OpenSRF listener [$apname]";
- eval _listener( $app );
- exit;
- }
-
-}
-
-# ----------------------------------------------
-# Launch the Unix Servers
-
-sub launch_unix {
- my( $self, $apps ) = @_;
-
- my $client = OpenSRF::Utils::SettingsClient->new();
-
- foreach my $app ( @$apps ) {
-
- next unless $app;
- my $lang = $client->config_value( "apps", $app, "language");
- next unless $lang =~ /perl/i;
- next if $app eq "opensrf.settings";
-
- _log( " * Starting UnixServer for $app..." );
-
- my $pid = OpenSRF::Utils::safe_fork();
- if( $pid ) {
- $self->pid_hash( $pid , _unixserver( $app ) );
- }
- else {
- my $apname = $app;
- $0 = "OpenSRF App ($apname)";
- eval _unixserver( $app );
- exit;
- }
- }
-}
-
-# ----------------------------------------------
-# Launch the inbound clients
-
-sub launch_listener {
-
- my( $self, $apps ) = @_;
- my $client = OpenSRF::Utils::SettingsClient->new();
-
- foreach my $app ( @$apps ) {
-
- next unless $app;
- my $lang = $client->config_value( "apps", $app, "language");
- next unless $lang =~ /perl/i;
- next if $app eq "opensrf.settings";
-
- _log( " * Starting Listener for $app..." );
-
- my $pid = OpenSRF::Utils::safe_fork();
- if ( $pid ) {
- $self->pid_hash( $pid , _listener( $app ) );
- }
- else {
- my $apname = $app;
- $0 = "OpenSRF listener [$apname]";
- eval _listener( $app );
- exit;
- }
- }
-}
-
-
-# ----------------------------------------------
-
-sub pid_hash {
- my( $self, $pid, $method ) = @_;
- $self->{'pid_hash'}->{$pid} = $method
- if( $pid and $method );
- return $self->{'pid_hash'};
-}
-
-# ----------------------------------------------
-# If requested, the System can shut down.
-
-sub killall {
-
- $SIG{CHLD} = 'IGNORE';
- $SIG{INT} = 'IGNORE';
- kill( 'INT', -$$ ); #kill all in process group
- exit;
-
-}
-
-# ----------------------------------------------
-# Handle $SIG{HUP}
-sub hupall {
-
- _log( "HUPping brood" );
- $SIG{CHLD} = 'IGNORE';
- $SIG{HUP} = 'IGNORE';
- kill( 'HUP', -$$ );
-# $SIG{CHLD} = \&process_automation;
- $SIG{HUP} = sub{ instance()->hupall(); };
-}
-
-
-# ----------------------------------------------
-# Log to debug, and stdout
-
-sub _log {
- my $string = shift;
- OpenSRF::Utils::Logger->debug( $string, INFO );
- print $string . "\n";
-}
-
-# ----------------------------------------------
-
-
-1;
-
-
+++ /dev/null
-package OpenSRF::Transport;
-use strict; use warnings;
-use base 'OpenSRF';
-use Time::HiRes qw/time/;
-use OpenSRF::AppSession;
-use OpenSRF::Utils::Logger qw(:level);
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use OpenSRF::EX qw/:try/;
-use OpenSRF::Transport::SlimJabber::MessageWrapper;
-
-#------------------
-# --- These must be implemented by all Transport subclasses
-# -------------------------------------------
-
-=head2 get_listener
-
-Returns the package name of the package the system will use to
-gather incoming requests
-
-=cut
-
-sub get_listener { shift()->alert_abstract(); }
-
-=head2 get_peer_client
-
-Returns the name of the package responsible for client communication
-
-=cut
-
-sub get_peer_client { shift()->alert_abstract(); }
-
-=head2 get_msg_envelope
-
-Returns the name of the package responsible for parsing incoming messages
-
-=cut
-
-sub get_msg_envelope { shift()->alert_abstract(); }
-
-# -------------------------------------------
-
-our $message_envelope;
-my $logger = "OpenSRF::Utils::Logger";
-
-
-
-=head2 message_envelope( [$envelope] );
-
-Sets the message envelope class that will allow us to extract
-information from the messages we receive from the low
-level transport
-
-=cut
-
-sub message_envelope {
- my( $class, $envelope ) = @_;
- if( $envelope ) {
- $message_envelope = $envelope;
- $envelope->use;
- if( $@ ) {
- $logger->error(
- "Error loading message_envelope: $envelope -> $@", ERROR);
- }
- }
- return $message_envelope;
-}
-
-=head2 handler( $data )
-
-Creates a new MessageWrapper, extracts the remote_id, session_id, and message body
-from the message. Then, creates or retrieves the AppSession object with the session_id and remote_id.
-Finally, creates the message document from the body of the message and calls
-the handler method on the message document.
-
-=cut
-
-sub handler {
- my $start_time = time();
- my( $class, $service, $data ) = @_;
-
- $logger->transport( "Transport handler() received $data", INTERNAL );
-
- # pass data to the message envelope
- my $helper = OpenSRF::Transport::SlimJabber::MessageWrapper->new( $data );
-
- # Extract message information
- my $remote_id = $helper->get_remote_id();
- my $sess_id = $helper->get_sess_id();
- my $body = $helper->get_body();
- my $type = $helper->get_msg_type();
-
- $logger->set_osrf_xid($helper->get_osrf_xid);
-
- if (defined($type) and $type eq 'error') {
- throw OpenSRF::EX::Session ("$remote_id IS NOT CONNECTED TO THE NETWORK!!!");
-
- }
-
- # See if the app_session already exists. If so, make
- # sure the sender hasn't changed if we're a server
- my $app_session = OpenSRF::AppSession->find( $sess_id );
- if( $app_session and $app_session->endpoint == $app_session->SERVER() and
- $app_session->remote_id ne $remote_id ) {
- $logger->transport( "Backend Gone or invalid sender", INTERNAL );
- my $res = OpenSRF::DomainObject::oilsBrokenSession->new();
- $res->status( "Backend Gone or invalid sender, Reconnect" );
- $app_session->status( $res );
- return 1;
- }
-
- # Retrieve or build the app_session as appropriate (server_build decides which to do)
- $logger->transport( "AppSession is valid or does not exist yet", INTERNAL );
- $app_session = OpenSRF::AppSession->server_build( $sess_id, $remote_id, $service );
-
- if( ! $app_session ) {
- throw OpenSRF::EX::Session ("Transport::handler(): No AppSession object returned from server_build()");
- }
-
- # Create a document from the JSON contained within the message
- my $doc;
- eval { $doc = JSON->JSON2perl($body); };
- if( $@ ) {
-
- $logger->transport( "Received bogus JSON: $@", INFO );
- $logger->transport( "Bogus JSON data: \n $body \n", INTERNAL );
- my $res = OpenSRF::DomainObject::oilsXMLParseError->new( status => "JSON Parse Error --- $body\n\n$@" );
-
- $app_session->status($res);
- #$app_session->kill_me;
- return 1;
- }
-
- $logger->transport( "Transport::handler() creating \n$body", INTERNAL );
-
- # We need to disconnect the session if we got a jabber error on the client side. For
- # server side, we'll just tear down the session and go away.
- if (defined($type) and $type eq 'error') {
- # If we're a server
- if( $app_session->endpoint == $app_session->SERVER() ) {
- $app_session->kill_me;
- return 1;
- } else {
- $app_session->reset;
- $app_session->state( $app_session->DISCONNECTED );
- # below will lead to infinite looping, should return an exception
- #$app_session->push_resend( $app_session->app_request(
- # $doc->documentElement->firstChild->threadTrace ) );
- $logger->debug(
- "Got Jabber error on client connection $remote_id, nothing we can do..", ERROR );
- return 1;
- }
- }
-
-
- # cycle through and pass each oilsMessage contained in the message
- # up to the message layer for processing.
- for my $msg (@$doc) {
-
- next unless ( $msg && UNIVERSAL::isa($msg => 'OpenSRF::DomainObject::oilsMessage'));
-
- if( $app_session->endpoint == $app_session->SERVER() ) {
-
- try {
-
- if( ! $msg->handler( $app_session ) ) { return 0; }
-
- $logger->debug("Successfully handled message", DEBUG);
-
- } catch Error with {
-
- my $e = shift;
- my $res = OpenSRF::DomainObject::oilsServerError->new();
- $res->status( $res->status . "\n$e");
- $app_session->status($res) if $res;
- $app_session->kill_me;
- return 0;
-
- };
-
- } else {
-
- if( ! $msg->handler( $app_session ) ) { return 0; }
- $logger->info("Successfully handled message", DEBUG);
-
- }
-
- }
-
- $logger->debug(sprintf("Message processing duration: %.3fs",(time() - $start_time)), DEBUG);
-
- return $app_session;
-}
-
-1;
+++ /dev/null
-package OpenSRF::Transport::Jabber;
-use base qw/OpenSRF::Transport/;
-
-
-sub get_listener { return "OpenSRF::Transport::Jabber::JInbound"; }
-
-sub get_peer_client { return "OpenSRF::Transport::Jabber::JPeerConnection"; }
-
-sub get_msg_envelope { return "OpenSRF::Transport::Jabber::JMessageWrapper"; }
-
-1;
+++ /dev/null
-package OpenSRF::Transport::Jabber::JInbound;
-use strict;use warnings;
-use base qw/OpenSRF::Transport::Jabber::JabberClient/;
-use OpenSRF::EX;
-use OpenSRF::Utils::Config;
-use OpenSRF::Utils::Logger qw(:level);
-
-my $logger = "OpenSRF::Utils::Logger";
-
-=head1 Description
-
-This is the jabber connection where all incoming client requests will be accepted.
-This connection takes the data, passes it off to the system then returns to take
-more data. Connection params are all taken from the config file and the values
-retreived are based on the $app name passed into new().
-
-This service should be loaded at system startup.
-
-=cut
-
-# XXX This will be overhauled to connect as a component instead of as
-# a user. all in good time, though.
-
-{
- my $unix_sock;
- sub unix_sock { return $unix_sock; }
- my $instance;
-
- sub new {
- my( $class, $app ) = @_;
- $class = ref( $class ) || $class;
- if( ! $instance ) {
- my $app_state = $app . "_inbound";
- my $config = OpenSRF::Utils::Config->current;
-
- if( ! $config ) {
- throw OpenSRF::EX::Jabber( "No suitable config found" );
- }
-
- my $host = $config->transport->server->primary;
- my $username = $config->transport->users->$app;
- my $password = $config->transport->auth->password;
- my $debug = $config->transport->llevel->$app_state;
- my $log = $config->transport->log->$app_state;
- my $resource = "system";
-
-
- my $self = __PACKAGE__->SUPER::new(
- username => $username,
- host => $host,
- resource => $resource,
- password => $password,
- log_file => $log,
- debug => $debug,
- );
-
-
- my $f = $config->dirs->sock_dir;
- $unix_sock = join( "/", $f, $config->unix_sock->$app );
- bless( $self, $class );
- $instance = $self;
- }
- $instance->SetCallBacks( message => \&handle_message );
- return $instance;
- }
-
-}
-
-# ---
-# All incoming messages are passed untouched to the Unix Server for processing. The
-# Unix socket is closed by the Unix Server as soon as it has received all of the
-# data. This means we can go back to accepting more incoming connection.
-# -----
-sub handle_message {
- my $sid = shift;
- my $message = shift;
-
- my $packet = $message->GetXML();
-
- $logger->transport( "JInbound $$ received $packet", INTERNAL );
-
- # Send the packet to the unix socket for processing.
- my $sock = unix_sock();
- my $socket;
- my $x = 0;
- for( ;$x != 5; $x++ ) { #try 5 times
- if( $socket = IO::Socket::UNIX->new( Peer => $sock ) ) {
- last;
- }
- }
- if( $x == 5 ) {
- throw OpenSRF::EX::Socket(
- "Unable to connect to UnixServer: socket-file: $sock \n :=> $! " );
- }
- print $socket $packet;
- close( $socket );
-}
-
-
-1;
-
+++ /dev/null
-package OpenSRF::Transport::Jabber::JMessageWrapper;
-use Jabber::NodeFactory;
-use Net::Jabber qw(Client);
-use Net::Jabber::Message;
-use base qw/ Net::Jabber::Message OpenSRF /;
-use OpenSRF::Utils::Logger qw(:level);
-use strict; use warnings;
-
-=head1 Description
-
-OpenSRF::Transport::Jabber::JMessageWrapper
-
-Provides a means to extract information about a Jabber
-message when all you have is the raw XML. The API
-implemented here should be implemented by any Transport
-helper/MessageWrapper class.
-
-=cut
-
-sub DESTROY{}
-
-my $logger = "OpenSRF::Utils::Logger";
-my $_node_factory = Jabber::NodeFactory->new( fromstr => 1 );
-
-
-=head2 new( Net::Jabber::Message/$raw_xml )
-
-Pass in the raw Jabber message as XML and create a new
-JMessageWrapper
-
-=cut
-
-sub new {
- my( $class, $xml ) = @_;
- $class = ref( $class ) || $class;
-
- return undef unless( $xml );
-
- my $self;
-
- if( ref( $xml ) ) {
- $self = $xml;
- } else {
- $logger->transport( "MWrapper got: " . $xml, INTERNAL );
- my $node = $_node_factory->newNodeFromStr( $xml );
- $self = $class->SUPER::new();
- $self->SetFrom( $node->attr('from') );
- $self->SetThread( $node->getTag('thread')->data );
- $self->SetBody( $node->getTag('body')->data );
- }
-
- bless( $self, $class );
-
- $logger->transport( "MessageWrapper $self after blessing", INTERNAL );
-
- return $self;
-
-}
-
-=head2 get_remote_id
-
-Returns the JID (user@host/resource) of the remote user
-
-=cut
-sub get_remote_id {
- my( $self ) = @_;
- return $self->GetFrom();
-}
-
-=head2 get_sess_id
-
-Returns the Jabber thread associated with this message
-
-=cut
-sub get_sess_id {
- my( $self ) = @_;
- return $self->GetThread();
-}
-
-=head2 get_body
-
-Returns the message body of the Jabber message
-
-=cut
-sub get_body {
- my( $self ) = @_;
- return $self->GetBody();
-}
-
-
-1;
+++ /dev/null
-package OpenSRF::Transport::Jabber::JPeerConnection;
-use strict;
-use base qw/OpenSRF::Transport::Jabber::JabberClient/;
-use OpenSRF::Utils::Config;
-use OpenSRF::Utils::Logger qw(:level);
-
-=head1 Description
-
-Represents a single connection to a remote peer. The
-Jabber values are loaded from the config file.
-
-Subclasses OpenSRF::Transport::JabberClient.
-
-=cut
-
-=head2 new()
-
- new( $appname );
-
- The $appname parameter tells this class how to find the correct
- Jabber username, password, etc to connect to the server.
-
-=cut
-
-our $main_instance;
-our %apps_hash;
-
-sub retrieve {
- my( $class, $app ) = @_;
- my @keys = keys %apps_hash;
- OpenSRF::Utils::Logger->transport(
- "Requesting peer for $app and we have @keys", INTERNAL );
- return $apps_hash{$app};
-}
-
-
-
-sub new {
- my( $class, $app ) = @_;
- my $config = OpenSRF::Utils::Config->current;
-
- if( ! $config ) {
- throw OpenSRF::EX::Config( "No suitable config found" );
- }
-
- my $app_stat = $app . "_peer";
- my $host = $config->transport->server->primary;
- my $username = $config->transport->users->$app;
- my $password = $config->transport->auth->password;
- my $debug = $config->transport->llevel->$app_stat;
- my $log = $config->transport->log->$app_stat;
- my $resource = $config->env->hostname . "_$$";
-
- OpenSRF::EX::Config->throw( "JPeer could not load all necesarry values from config" )
- unless ( $host and $username and $password and $resource );
-
-
- my $self = __PACKAGE__->SUPER::new(
- username => $username,
- host => $host,
- resource => $resource,
- password => $password,
- log_file => $log,
- debug => $debug,
- );
-
- bless( $self, $class );
-
- $self->SetCallBacks( message => sub {
- my $msg = $_[1];
- OpenSRF::Utils::Logger->transport(
- "JPeer passing \n$msg \n to Transport->handler for $app", INTERNAL );
- OpenSRF::Transport->handler( $app, $msg ); } );
-
- $apps_hash{$app} = $self;
- return $apps_hash{$app};
-}
-
-1;
-
+++ /dev/null
-package OpenSRF::Transport::Jabber::JabberClient;
-use strict; use warnings;
-use OpenSRF::EX;
-use Net::Jabber qw( Client );
-use base qw( OpenSRF Net::Jabber::Client );
-use OpenSRF::Utils::Logger qw(:level);
-
-=head1 Description
-
-OpenSRF::Transport::Jabber::JabberClient
-
-Subclasses Net::Jabber::Client and, hence, provides the same
-functionality. What it provides in addition is mainly some logging
-and exception throwing on the call to 'initialize()', which sets
-up the connection and authentication.
-
-=cut
-
-my $logger = "OpenSRF::Utils::Logger";
-
-sub DESTROY{};
-
-
-=head2 new()
-
-Creates a new JabberClient object. The parameters should be self explanatory.
-If not, see Net::Jabber::Client for more.
-
-debug and log_file are not required if you don't care to log the activity,
-however all other parameters are.
-
-%params:
-
- host
- username
- resource
- password
- debug
- log_file
-
-=cut
-
-sub new {
-
- my( $class, %params ) = @_;
-
- $class = ref( $class ) || $class;
-
- my $host = $params{'host'} || return undef;
- my $username = $params{'username'} || return undef;
- my $resource = $params{'resource'} || return undef;
- my $password = $params{'password'} || return undef;
- my $debug = $params{'debug'};
- my $log_file = $params{'log_file'};
-
- my $self;
-
- if( $debug and $log_file ) {
- $self = Net::Jabber::Client->new(
- debuglevel => $debug, debugfile => $log_file );
- }
- else { $self = Net::Jabber::Client->new(); }
-
- bless( $self, $class );
-
- $self->host( $host );
- $self->username( $username );
- $self->resource( $resource );
- $self->password( $password );
-
- $logger->transport( "Creating Jabber instance: $host, $username, $resource",
- $logger->INFO );
-
- $self->SetCallBacks( send =>
- sub { $logger->transport( "JabberClient in 'send' callback: @_", INTERNAL ); } );
-
-
- return $self;
-}
-
-# -------------------------------------------------
-
-=head2 gather()
-
-Gathers all Jabber messages sitting in the collection queue
-and hands them each to their respective callbacks. This call
-does not block (calls Process(0))
-
-=cut
-
-sub gather { my $self = shift; $self->Process( 0 ); }
-
-# -------------------------------------------------
-
-=head2 listen()
-
-Blocks and gathers incoming messages as they arrive. Does not return
-unless an error occurs.
-
-Throws an OpenSRF::EX::JabberException if the call to Process ever fails.
-
-=cut
-sub listen {
- my $self = shift;
- while(1) {
- my $o = $self->process( -1 );
- if( ! defined( $o ) ) {
- throw OpenSRF::EX::Jabber( "Listen Loop failed at 'Process()'" );
- }
- }
-}
-
-# -------------------------------------------------
-
-sub password {
- my( $self, $password ) = @_;
- $self->{'oils:password'} = $password if $password;
- return $self->{'oils:password'};
-}
-
-# -------------------------------------------------
-
-sub username {
- my( $self, $username ) = @_;
- $self->{'oils:username'} = $username if $username;
- return $self->{'oils:username'};
-}
-
-# -------------------------------------------------
-
-sub resource {
- my( $self, $resource ) = @_;
- $self->{'oils:resource'} = $resource if $resource;
- return $self->{'oils:resource'};
-}
-
-# -------------------------------------------------
-
-sub host {
- my( $self, $host ) = @_;
- $self->{'oils:host'} = $host if $host;
- return $self->{'oils:host'};
-}
-
-# -------------------------------------------------
-
-=head2 send()
-
- Sends a Jabber message.
-
- %params:
- to - The JID of the recipient
- thread - The Jabber thread
- body - The body of the message
-
-=cut
-
-sub send {
- my( $self, %params ) = @_;
-
- my $to = $params{'to'} || return undef;
- my $body = $params{'body'} || return undef;
- my $thread = $params{'thread'};
-
- my $msg = Net::Jabber::Message->new();
-
- $msg->SetTo( $to );
- $msg->SetThread( $thread ) if $thread;
- $msg->SetBody( $body );
-
- $logger->transport(
- "JabberClient Sending message to $to with thread $thread and body: \n$body", INTERNAL );
-
- $self->Send( $msg );
-}
-
-
-=head2 inintialize()
-
-Connect to the server and log in.
-
-Throws an OpenSRF::EX::JabberException if we cannot connect
-to the server or if the authentication fails.
-
-=cut
-
-# --- The logging lines have been commented out until we decide
-# on which log files we're using.
-
-sub initialize {
-
- my $self = shift;
-
- my $host = $self->host;
- my $username = $self->username;
- my $resource = $self->resource;
- my $password = $self->password;
-
- my $jid = "$username\@$host\/$resource";
-
- # --- 5 tries to connect to the jabber server
- my $x = 0;
- for( ; $x != 5; $x++ ) {
- $logger->transport( "$jid: Attempting to connecto to server...$x", WARN );
- if( $self->Connect( 'hostname' => $host ) ) {
- last;
- }
- else { sleep 3; }
- }
-
- if( $x == 5 ) {
- die "could not connect to server $!\n";
- throw OpenSRF::EX::Jabber( " Could not connect to Jabber server" );
- }
-
- $logger->transport( "Logging into jabber as $jid " .
- "from " . ref( $self ), DEBUG );
-
- # --- Log in
- my @a = $self->AuthSend( 'username' => $username,
- 'password' => $password, 'resource' => $resource );
-
- if( $a[0] eq "ok" ) {
- $logger->transport( " * $jid: Jabber authenticated and connected", DEBUG );
- }
- else {
- throw OpenSRF::EX::Jabber( " * $jid: Unable to authenticate: @a" );
- }
-
- return $self;
-}
-
-sub construct {
- my( $class, $app ) = @_;
- $logger->transport("Constructing new Jabber connection for $app", INTERNAL );
- $class->peer_handle(
- $class->new( $app )->initialize() );
-}
-
-sub process {
-
- my( $self, $timeout ) = @_;
- if( ! $timeout ) { $timeout = 0; }
-
- unless( $self->Connected() ) {
- OpenSRF::EX::Jabber->throw(
- "This JabberClient instance is no longer connected to the server", ERROR );
- }
-
- my $val;
-
- if( $timeout eq "-1" ) {
- $val = $self->Process();
- }
- else { $val = $self->Process( $timeout ); }
-
- if( $timeout eq "-1" ) { $timeout = " "; }
-
- if( ! defined( $val ) ) {
- OpenSRF::EX::Jabber->throw(
- "Call to Net::Jabber::Client->Process( $timeout ) failed", ERROR );
- }
- elsif( ! $val ) {
- $logger->transport(
- "Call to Net::Jabber::Client->Process( $timeout ) returned 0 bytes of data", DEBUG );
- }
- elsif( $val ) {
- $logger->transport(
- "Call to Net::Jabber::Client->Process( $timeout ) successfully returned data", INTERNAL );
- }
-
- return $val;
-
-}
-
-
-1;
+++ /dev/null
-package OpenSRF::Transport::Listener;
-use base 'OpenSRF';
-use OpenSRF::Utils::Logger qw(:level);
-use OpenSRF::Transport::SlimJabber::Inbound;
-use base 'OpenSRF::Transport::SlimJabber::Inbound';
-
-=head1 Description
-
-This is the empty class that acts as the subclass of the transport listener. My API
-includes
-
-new( $app )
- create a new Listener with appname $app
-
-initialize()
- Perform any transport layer connections/authentication.
-
-listen()
- Block, wait for, and process incoming messages
-
-=cut
-
-=head2 set_listener()
-
-Sets my superclass. Pass in a string representing the perl module
-(e.g. OpenSRF::Transport::Jabber::JInbound) to be used as the
-superclass and it will be pushed onto @ISA.
-
-=cut
-
-sub set_listener {
- my( $class, $listener ) = @_;
- OpenSRF::Utils::Logger->transport("Loading Listener $listener", INFO );
- if( $listener ) {
- $listener->use;
- if( $@ ) {
- OpenSRF::Utils::Logger->error(
- "Unable to set transport listener: $@", ERROR );
- }
- unshift @ISA, $listener;
- }
-}
-
-
-1;
+++ /dev/null
-package OpenSRF::Transport::PeerHandle;
-use OpenSRF::Utils::Logger qw(:level);
-use OpenSRF::EX;
-use base qw/OpenSRF::Transport::SlimJabber::PeerConnection/;
-use vars '@ISA';
-
-my $peer;
-
-=head2 peer_handle( $handle )
-
-Assigns the object that will act as the peer connection handle.
-
-=cut
-sub peer_handle {
- my( $class, $handle ) = @_;
- if( $handle ) { $peer = $handle; }
- return $peer;
-}
-
-
-=head2 set_peer_client( $peer )
-
-Sets the class that will act as the superclass of this class.
-Pass in a string representing the module to be used as the superclass,
-and that module is 'used' and unshifted into @ISA. We now have that
-classes capabilities.
-
-=cut
-sub set_peer_client {
- my( $class, $peer ) = @_;
- if( $peer ) {
- $peer->use;
- if( $@ ) {
- throw OpenSRF::EX::PANIC ( "Unable to set peer client: $@" );
- }
- unshift @ISA, $peer;
- }
-}
-
-1;
+++ /dev/null
-package OpenSRF::Transport::SlimJabber;
-use base qw/OpenSRF::Transport/;
-
-=head2 OpenSRF::Transport::SlimJabber
-
-Implements the Transport interface for providing the system with appropriate
-classes for handling transport layer messaging
-
-=cut
-
-
-sub get_listener { return "OpenSRF::Transport::SlimJabber::Inbound"; }
-
-sub get_peer_client { return "OpenSRF::Transport::SlimJabber::PeerConnection"; }
-
-sub get_msg_envelope { return "OpenSRF::Transport::SlimJabber::MessageWrapper"; }
-
-1;
+++ /dev/null
-package OpenSRF::Transport::SlimJabber::Client;
-use strict; use warnings;
-use OpenSRF::EX;
-use base qw( OpenSRF );
-use OpenSRF::Utils::Logger qw(:level);
-use OpenSRF::Utils::Config;
-use Time::HiRes qw(ualarm);
-use OpenSRF::Utils::Config;
-
-use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
-use IO::Socket::INET;
-use IO::Socket::UNIX;
-
-=head1 Description
-
-OpenSRF::Transport::SlimJabber::Client
-
-Home-brewed slimmed down jabber connection agent. Supports SSL connections
-with a config file options:
-
- transport->server->sslport # the ssl port
- transport->server->ssl # is this ssl?
-
-=cut
-
-my $logger = "OpenSRF::Utils::Logger";
-
-sub DESTROY{
- my $self = shift;
- $self->disconnect;
-}
-
-sub disconnect{
- my $self = shift;
- my $socket = $self->{_socket};
- if( $socket and $socket->connected() ) {
- print $socket "</stream:stream>";
- close( $socket );
- }
-}
-
-
-=head2 new()
-
-Creates a new Client object.
-
-debug and log_file are not required if you don't care to log the activity,
-however all other parameters are.
-
-%params:
-
- username
- resource
- password
- debug
- log_file
-
-=cut
-
-sub new {
-
- my( $class, %params ) = @_;
-
- $class = ref( $class ) || $class;
-
- my $port = $params{'port'} || return undef;
- my $username = $params{'username'} || return undef;
- my $resource = $params{'resource'} || return undef;
- my $password = $params{'password'} || return undef;
- my $host = $params{'host'} || return undef;
-
- my $jid = "$username\@$host\/$resource";
-
- my $self = bless {} => $class;
-
- $self->jid( $jid );
- $self->host( $host );
- $self->port( $port );
- $self->username( $username );
- $self->resource( $resource );
- $self->password( $password );
- $self->{temp_buffer} = "";
-
- $logger->transport( "Creating Client instance: $host:$port, $username, $resource",
- $logger->INFO );
-
- return $self;
-}
-
-# clears the tmp buffer as well as the TCP buffer
-sub buffer_reset {
-
- my $self = shift;
- $self->{temp_buffer} = "";
-
- my $fh = $self->{_socket};
- set_nonblock( $fh );
- my $t_buf = "";
- while( sysread( $fh, $t_buf, 4096 ) ) {}
- set_block( $fh );
-}
-# -------------------------------------------------
-
-=head2 gather()
-
-Gathers all Jabber messages sitting in the collection queue
-and hands them each to their respective callbacks. This call
-does not block (calls Process(0))
-
-=cut
-
-sub gather { my $self = shift; $self->process( 0 ); }
-
-# -------------------------------------------------
-
-=head2 listen()
-
-Blocks and gathers incoming messages as they arrive. Does not return
-unless an error occurs.
-
-Throws an OpenSRF::EX::JabberException if the call to Process ever fails.
-
-=cut
-sub listen {
- my $self = shift;
-
- my $sock = $self->unix_sock();
- my $socket = IO::Socket::UNIX->new( Peer => $sock );
- $logger->transport( "Unix Socket opened by Listener", INTERNAL );
-
- throw OpenSRF::EX::Socket( "Unable to connect to UnixServer: socket-file: $sock \n :=> $! " )
- unless ($socket->connected);
-
- while(1) {
- my $o = $self->process( -1 );
- $logger->transport( "Call to process() in listener returned:\n $o", INTERNAL );
- if( ! defined( $o ) ) {
- throw OpenSRF::EX::Jabber( "Listen Loop failed at 'process()'" );
- }
- print $socket $o;
-
- }
- throw OpenSRF::EX::Socket( "How did we get here?!?!" );
-}
-
-sub set_nonblock {
- my $fh = shift;
- my $flags = fcntl($fh, F_GETFL, 0)
- or die "Can't get flags for the socket: $!\n";
-
- $logger->transport( "Setting NONBLOCK: original flags: $flags", INTERNAL );
-
- fcntl($fh, F_SETFL, $flags | O_NONBLOCK)
- or die "Can't set flags for the socket: $!\n";
-
- return $flags;
-}
-
-sub reset_fl {
- my $fh = shift;
- my $flags = shift;
- $logger->transport( "Restoring BLOCK: to flags $flags", INTERNAL );
- fcntl($fh, F_SETFL, $flags) if defined $flags;
-}
-
-sub set_block {
- my $fh = shift;
-
- my $flags = fcntl($fh, F_GETFL, 0)
- or die "Can't get flags for the socket: $!\n";
-
- $flags &= ~O_NONBLOCK;
-
- fcntl($fh, F_SETFL, $flags)
- or die "Can't set flags for the socket: $!\n";
-}
-
-
-sub timed_read {
- my ($self, $timeout) = @_;
- $timeout = defined($timeout) ? int($timeout) : undef;
-
- $logger->transport( "Temp Buffer Contained: \n". $self->{temp_buffer}, INTERNAL) if $self->{temp_buffer};
- if( $self->can( "app" ) ) {
- $logger->transport( "timed_read called for ".$self->app.", I am: ".$self->jid, INTERNAL );
- }
-
- # See if there is a complete message in the temp_buffer
- # that we can return
- if( $self->{temp_buffer} ) {
- my $buffer = $self->{temp_buffer};
- my $complete = 0;
- $self->{temp_buffer} = '';
-
- my ($tag) = ($buffer =~ /<([^\s\?\>]+)/o);
- $self->{last_tag} = $tag;
- $logger->transport("Using tag: $tag ", INTERNAL);
-
- if ( $buffer =~ /^(.*?<\/$tag>){1}(.*)/s) {
- $buffer = $1;
- $self->{temp_buffer} = $2;
- $complete++;
- $logger->transport( "completed read with $buffer", INTERNAL );
- } elsif ( $buffer =~ /^<$tag[^>]*?\/>(.*)/) {
- $self->{temp_buffer} = $1;
- $complete++;
- $logger->transport( "completed read with $buffer", INTERNAL );
- } else {
- $self->{temp_buffer} = $buffer;
- }
-
- if( $buffer and $complete ) {
- return $buffer;
- }
-
- }
- ############
-
- my $fh = $self->{_socket};
-
- unless( $fh and $fh->connected ) {
- throw OpenSRF::EX::Socket ("Attempted read on closed socket", ERROR );
- }
-
- $logger->transport( "Temp Buffer After first attempt: \n ".$self->{temp_buffer}, INTERNAL) if $self->{temp_buffer};
-
- my $flags;
- if (defined($timeout) && !$timeout) {
- $flags = set_nonblock( $fh );
- }
-
- $timeout ||= 0;
- $logger->transport( "Calling timed_read with timetout $timeout", INTERNAL );
-
-
- my $complete = 0;
- my $first_read = 1;
- my $xml = '';
- eval {
- my $tag = '';
- eval {
- no warnings;
- local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
-
- # alarm needs a number greater => 1.
- my $alarm_timeout = $timeout;
- if( $alarm_timeout > 0 and $alarm_timeout < 1 ) {
- $alarm_timeout = 1;
- }
- alarm $alarm_timeout;
- do {
-
- my $buffer = $self->{temp_buffer};
- $self->{temp_buffer} = '';
- #####
-
- # This code is no longer in use
- #my $ff = fcntl($fh, F_GETFL, 0);
- #if ($ff == ($ff | O_NONBLOCK) and $timeout > 0 ) {
- #throw OpenSRF::EX::ERROR ("File flags are set to NONBLOCK but timeout is $timeout", ERROR );
- #}
-
- my $t_buf = "";
- my $read_size = 1024; my $f = 0;
- while( my $n = sysread( $fh, $t_buf, $read_size ) ) {
-
- unless( $fh->connected ) {
- OpenSRF::EX::JabberDisconnected->throw(
- "Lost jabber client in timed_read()");
- }
-
- # XXX Change me to debug/internal at some point, this is for testing...
- # XXX Found a race condition where reading >= $read_size bytes of data
- # will fail if the log line below is removed.
- $logger->info("timed_read() read $n bytes of data");
-
-
- $buffer .= $t_buf;
- if( $n < $read_size ) {
- #reset_fl( $fh, $f ) if $f;
- set_block( $fh );
- last;
- }
- # see if there is any more data to grab...
- $f = set_nonblock( $fh );
- }
-
- #sysread($fh, $buffer, 2048, length($buffer) );
- #sysread( $fh, $t_buf, 2048 );
- #$buffer .= $t_buf;
-
- #####
- $logger->transport(" Got [$buffer] from the socket", INTERNAL);
-
- if ($first_read) {
- $logger->transport(" First read Buffer\n [$buffer]", INTERNAL);
- ($tag) = ($buffer =~ /<([^\s\?\>\/]+){1}/o);
- $self->{last_tag} = $tag;
- $first_read--;
- $logger->transport("Using tag: $tag ", INTERNAL);
- }
-
- if (!$first_read && $buffer =~ /^(.*?<\/$tag>){1}(.*)/s) {
- $buffer = $1;
- $self->{temp_buffer} = $2;
- $complete++;
- $logger->transport( "completed read with $buffer", INTERNAL );
- } elsif (!$first_read && $buffer =~ /^<$tag[^>]*?\/>(.*)/) {
- $self->{temp_buffer} = $1;
- $complete++;
- $logger->transport( "completed read with $buffer", INTERNAL );
- }
-
- $xml .= $buffer;
-
- } while (!$complete && $xml);
- alarm(0);
- };
- alarm(0);
- };
-
- $logger->transport( "XML Read: $xml", INTERNAL );
- #reset_fl( $fh, $flags) if defined $flags;
- set_block( $fh ) if defined $flags;
-
- if ($complete) {
- return $xml;
- }
- if( $@ ) {
- return undef;
- }
- return "";
-}
-
-
-# -------------------------------------------------
-
-sub tcp_connected {
-
- my $self = shift;
- return 1 if ($self->{_socket} and $self->{_socket}->connected);
- return 0;
-}
-
-sub password {
- my( $self, $password ) = @_;
- $self->{'oils:password'} = $password if $password;
- return $self->{'oils:password'};
-}
-
-# -------------------------------------------------
-
-sub username {
- my( $self, $username ) = @_;
- $self->{'oils:username'} = $username if $username;
- return $self->{'oils:username'};
-}
-
-# -------------------------------------------------
-
-sub resource {
- my( $self, $resource ) = @_;
- $self->{'oils:resource'} = $resource if $resource;
- return $self->{'oils:resource'};
-}
-
-# -------------------------------------------------
-
-sub jid {
- my( $self, $jid ) = @_;
- $self->{'oils:jid'} = $jid if $jid;
- return $self->{'oils:jid'};
-}
-
-sub port {
- my( $self, $port ) = @_;
- $self->{'oils:port'} = $port if $port;
- return $self->{'oils:port'};
-}
-
-sub host {
- my( $self, $host ) = @_;
- $self->{'oils:host'} = $host if $host;
- return $self->{'oils:host'};
-}
-
-# -------------------------------------------------
-
-=head2 send()
-
- Sends a Jabber message.
-
- %params:
- to - The JID of the recipient
- thread - The Jabber thread
- body - The body of the message
-
-=cut
-
-sub send {
- my $self = shift;
- my %params = @_;
-
- my $to = $params{'to'} || return undef;
- my $body = $params{'body'} || return undef;
- my $thread = $params{'thread'} || "";
- my $router_command = $params{'router_command'} || "";
- my $router_class = $params{'router_class'} || "";
-
- my $msg = OpenSRF::Transport::SlimJabber::MessageWrapper->new;
-
- $msg->setTo( $to );
- $msg->setThread( $thread ) if $thread;
- $msg->setBody( $body );
- $msg->set_router_command( $router_command );
- $msg->set_router_class( $router_class );
- $msg->set_osrf_xid($logger->get_osrf_xid);
-
- $logger->transport(
- "JabberClient Sending message to $to with thread $thread and body: \n$body", INTERNAL );
-
- my $soc = $self->{_socket};
- unless( $soc and $soc->connected ) {
- throw OpenSRF::EX::Jabber ("No longer connected to jabber server");
- }
- print $soc $msg->toString;
-
- $logger->transport(
- "JabberClient Sent message to $to with thread $thread and body: \n$body", INTERNAL );
-}
-
-
-=head2 inintialize()
-
-Connect to the server and log in.
-
-Throws an OpenSRF::EX::JabberException if we cannot connect
-to the server or if the authentication fails.
-
-=cut
-
-# --- The logging lines have been commented out until we decide
-# on which log files we're using.
-
-sub initialize {
-
- my $self = shift;
-
- my $jid = $self->jid;
- my $host = $self->host;
- my $port = $self->port;
- my $username = $self->username;
- my $resource = $self->resource;
- my $password = $self->password;
-
- my $stream = <<" XML";
-<stream:stream to='$host' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>
- XML
-
- my $conf = OpenSRF::Utils::Config->current;
- my $tail = "_$$";
- if(!$conf->bootstrap->router_name && $username eq "router") {
- $tail = "";
- }
-
- my $auth = <<" XML";
-<iq id='123' type='set'>
-<query xmlns='jabber:iq:auth'>
-<username>$username</username>
-<password>$password</password>
-<resource>${resource}$tail</resource>
-</query>
-</iq>
- XML
-
- my $sock_type = 'IO::Socket::INET';
-
- # if port is a string, then we're connecting to a UNIX socket
- unless( $port =~ /^\d+$/ ) {
- $sock_type = 'IO::Socket::UNIX';
- }
-
- # --- 5 tries to connect to the jabber server
- my $socket;
- for(1..5) {
- $socket = $sock_type->new( PeerHost => $host,
- PeerPort => $port,
- Peer => $port,
- Proto => 'tcp' );
- $logger->debug( "$jid: $_ connect attempt to $host:$port");
- last if ( $socket and $socket->connected );
- $logger->warn( "$jid: Failed to connect to server...$host:$port (Try # $_)");
- sleep 3;
- }
-
- unless ( $socket and $socket->connected ) {
- throw OpenSRF::EX::Jabber( " Could not connect to Jabber server: $!" );
- }
-
- $logger->transport( "Logging into jabber as $jid " .
- "from " . ref( $self ), DEBUG );
-
- print $socket $stream;
-
- my $buffer;
- eval {
- eval {
- local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
- alarm 3;
- sysread($socket, $buffer, 4096);
- $logger->transport( "Login buffer 1: $buffer", INTERNAL );
- alarm(0);
- };
- alarm(0);
- };
-
- print $socket $auth;
-
- if( $socket and $socket->connected() ) {
- $self->{_socket} = $socket;
- } else {
- throw OpenSRF::EX::Jabber( " ** Unable to connect to Jabber server", ERROR );
- }
-
-
- $buffer = $self->timed_read(10);
-
- if( $buffer ) {$logger->transport( "Login buffer 2: $buffer", INTERNAL );}
-
- if( $buffer and $buffer =~ /type=["\']result["\']/ ) {
- $logger->transport( " * $jid: Jabber authenticated and connected", DEBUG );
- } else {
- if( !$buffer ) { $buffer = " "; }
- $socket->close;
- throw OpenSRF::EX::Jabber( " * $jid: Unable to authenticate: $buffer", ERROR );
- }
-
- return $self;
-}
-
-sub construct {
- my( $class, $app ) = @_;
- $logger->transport("Constructing new Jabber connection for $app, my class $class", INTERNAL );
- $class->peer_handle(
- $class->new( $app )->initialize() );
-}
-
-sub process {
-
- my( $self, $timeout ) = @_;
-
- $timeout ||= 0;
- $timeout = int($timeout);
- undef $timeout if ( $timeout < 0 );
-
- unless( $self->{_socket}->connected ) {
- OpenSRF::EX::JabberDisconnected->throw(
- "This JabberClient instance is no longer connected to the server " .
- $self->username . " : " . $self->resource, ERROR );
- }
-
- my $val = $self->timed_read( $timeout );
-
- $timeout = "FOREVER" unless ( defined $timeout );
-
- if ( ! defined( $val ) ) {
- OpenSRF::EX::Jabber->throw(
- "Call to Client->timed_read( $timeout ) failed", ERROR );
- } elsif ( ! $val ) {
- $logger->transport(
- "Call to Client->timed_read( $timeout ) returned 0 bytes of data", INTERNAL );
- } elsif ( $val ) {
- $logger->transport(
- "Call to Client->timed_read( $timeout ) successfully returned data", INTERNAL );
- }
-
- my $t = $self->{last_tag};
-
- if( $t and $val ) {
- my @msgs = $val =~ /(<$t[^>]*>.*?<\/$t>)/g;
- $val = shift(@msgs);
-
- if (@msgs) {
- my $tmp = $self->{temp_buffer};
-
- $self->{temp_buffer} = '';
- $self->{temp_buffer} .= $_ for (@msgs);
- $self->{temp_buffer} .= $tmp;
- }
- }
-
- return $val;
-}
-
-
-# --------------------------------------------------------------
-# Sets the socket to O_NONBLOCK, reads all of the data off of
-# the socket, the restores the sockets flags
-# Returns 1 on success, 0 if the socket isn't connected
-# --------------------------------------------------------------
-sub flush_socket {
-
- my $self = shift;
- my $socket = $self->{_socket};
-
- if( $socket ) {
-
- my $buf;
- my $flags = fcntl($socket, F_GETFL, 0);
-
- fcntl($socket, F_SETFL, $flags | O_NONBLOCK);
- while( my $n = sysread( $socket, $buf, 8192 ) ) {
- $logger->debug("flush_socket dropped $n bytes of data");
- if(!$socket->connected()) {
- $logger->error("flush_socket dropped data on disconnected socket: $buf");
- }
- }
- fcntl($socket, F_SETFL, $flags);
-
- return 0 unless $socket->connected();
-
- return 1;
-
- } else {
-
- return 0;
- }
-}
-
-
-
-1;
+++ /dev/null
-package OpenSRF::Transport::SlimJabber::Inbound;
-use strict;use warnings;
-use base qw/OpenSRF::Transport::SlimJabber::Client/;
-use OpenSRF::EX qw(:try);
-use OpenSRF::Utils::Logger qw(:level);
-use OpenSRF::Utils::SettingsClient;
-use OpenSRF::Utils::Config;
-use Time::HiRes qw/usleep/;
-
-my $logger = "OpenSRF::Utils::Logger";
-
-=head1 Description
-
-This is the jabber connection where all incoming client requests will be accepted.
-This connection takes the data, passes it off to the system then returns to take
-more data. Connection params are all taken from the config file and the values
-retreived are based on the $app name passed into new().
-
-This service should be loaded at system startup.
-
-=cut
-
-# XXX This will be overhauled to connect as a component instead of as
-# a user. all in good time, though.
-
-{
- my $unix_sock;
- sub unix_sock { return $unix_sock; }
- my $instance;
-
- sub new {
- my( $class, $app ) = @_;
- $class = ref( $class ) || $class;
- if( ! $instance ) {
-
- my $conf = OpenSRF::Utils::Config->current;
- my $domains = $conf->bootstrap->domains;
-
- my $username = $conf->bootstrap->username;
- my $password = $conf->bootstrap->passwd;
- my $port = $conf->bootstrap->port;
- my $host = $domains->[0]; # XXX for now...
- my $resource = $app . '_listener_at_' . $conf->env->hostname;
-
- my $router_name = $conf->bootstrap->router_name;
- # no router, only one listener running..
- if(!$router_name) {
- $username = "router";
- $resource = $app;
- }
-
- OpenSRF::Utils::Logger->transport("Inbound as $username, $password, $resource, $host, $port\n", INTERNAL );
-
- my $self = __PACKAGE__->SUPER::new(
- username => $username,
- resource => $resource,
- password => $password,
- host => $host,
- port => $port,
- );
-
- $self->{app} = $app;
-
- my $client = OpenSRF::Utils::SettingsClient->new();
- my $f = $client->config_value("dirs", "sock");
- $unix_sock = join( "/", $f,
- $client->config_value("apps", $app, "unix_config", "unix_sock" ));
- bless( $self, $class );
- $instance = $self;
- }
- return $instance;
- }
-
-}
-
-sub DESTROY {
- my $self = shift;
-
- my $routers = $self->{routers}; #store for destroy
- my $router_name = $self->{router_name};
-
- unless($router_name and $routers) {
- return;
- }
-
- my @targets;
- for my $router (@$routers) {
- push @targets, "$router_name\@$router/router";
- }
-
- for my $router (@targets) {
- if($self->tcp_connected()) {
- $self->send( to => $router, body => "registering",
- router_command => "unregister" , router_class => $self->{app} );
- }
- }
-}
-
-sub listen {
- my $self = shift;
-
- my $routers;
-
- try {
-
- my $conf = OpenSRF::Utils::Config->current;
- my $router_name = $conf->bootstrap->router_name;
- my $routers = $conf->bootstrap->domains;
-
- $self->{routers} = $routers; #store for destroy
- $self->{router_name} = $router_name;
-
- if($router_name and $routers) {
-
- my @targets;
- for my $router (@$routers) {
- push @targets, "$router_name\@$router/router";
- }
-
- for my $router (@targets) {
- $logger->transport( $self->{app} . " connecting to router $router", INFO );
- $self->send( to => $router,
- body => "registering", router_command => "register" , router_class => $self->{app} );
- }
- $logger->transport( $self->{app} . " :routers connected", INFO );
-
- } else {
-
- $logger->transport("Bypassing routers...", INFO);
- }
-
-
- } catch OpenSRF::EX::Config with {
- $logger->transport( $self->{app} . ": No routers defined" , WARN );
- # no routers defined
- };
-
-
-
-
- $logger->transport( $self->{app} . " going into listen loop", INFO );
-
- while(1) {
-
- my $sock = $self->unix_sock();
- my $o;
-
- $logger->debug("Inbound listener calling process()");
-
- try {
- $o = $self->process( -1 );
-
- $logger->debug("Inbound listener received ".length($o)." bytes of data");
-
- if(!$o){
- $logger->error(
- "Inbound received no data from the Jabber socket in process()");
- usleep(100000); # otherwise we loop and pound syslog logger with errors
- }
-
- } catch OpenSRF::EX::JabberDisconnected with {
-
- $logger->error("Inbound process lost its ".
- "jabber connection. Attempting to reconnect...");
- $self->initialize;
- $o = undef;
- };
-
-
- if($o) {
- my $socket = IO::Socket::UNIX->new( Peer => $sock );
- throw OpenSRF::EX::Socket(
- "Unable to connect to UnixServer: socket-file: $sock \n :=> $! " )
- unless ($socket->connected);
- print $socket $o;
- $socket->close;
- }
- }
-
- throw OpenSRF::EX::Socket( "How did we get here?!?!" );
-}
-
-1;
-
+++ /dev/null
-package OpenSRF::Transport::SlimJabber::MessageWrapper;
-use XML::LibXML;
-use OpenSRF::EX qw/:try/;
-use OpenSRF::Utils::Logger qw/$logger/;
-
-sub new {
- my $class = shift;
- $class = ref($class) || $class;
-
- my $xml = shift;
-
- my ($doc, $msg);
- if ($xml) {
- my $err;
-
- try {
- $doc = XML::LibXML->new->parse_string($xml);
- } catch Error with {
- $err = shift;
- warn "MessageWrapper received bad XML : error = $err\nXML = $xml\n";
- $logger->error("MessageWrapper received bad XML : error = $err : XML = $xml");
- };
- throw $err if $err;
-
- $msg = $doc->documentElement;
- } else {
- $doc = XML::LibXML::Document->createDocument;
- $msg = $doc->createElement( 'message' );
- $doc->setDocumentElement( $msg );
- }
-
-
- my $self = { msg_node => $msg };
-
- return bless $self => $class;
-}
-
-sub toString {
- my $self = shift;
- if( $self->{msg_node} ) {
- return $self->{msg_node}->toString(@_);
- }
- return "";
-}
-
-sub get_body {
- my $self = shift;
- my ($t_body) = grep {$_->nodeName eq 'body'} $self->{msg_node}->childNodes;
- if( $t_body ) {
- my $body = $t_body->textContent;
- return $body;
- }
- return "";
-}
-
-sub get_sess_id {
- my $self = shift;
- my ($t_node) = grep {$_->nodeName eq 'thread'} $self->{msg_node}->childNodes;
- if( $t_node ) {
- return $t_node->textContent;
- }
- return "";
-}
-
-sub get_msg_type {
- my $self = shift;
- $self->{msg_node}->getAttribute( 'type' );
-}
-
-sub get_remote_id {
- my $self = shift;
-
- #
- my $rid = $self->{msg_node}->getAttribute( 'router_from' );
- return $rid if $rid;
-
- return $self->{msg_node}->getAttribute( 'from' );
-}
-
-sub setType {
- my $self = shift;
- $self->{msg_node}->setAttribute( type => shift );
-}
-
-sub setTo {
- my $self = shift;
- $self->{msg_node}->setAttribute( to => shift );
-}
-
-sub setThread {
- my $self = shift;
- $self->{msg_node}->appendTextChild( thread => shift );
-}
-
-sub setBody {
- my $self = shift;
- my $body = shift;
- $self->{msg_node}->appendTextChild( body => $body );
-}
-
-sub set_router_command {
- my( $self, $router_command ) = @_;
- if( $router_command ) {
- $self->{msg_node}->setAttribute( router_command => $router_command );
- }
-}
-sub set_router_class {
- my( $self, $router_class ) = @_;
- if( $router_class ) {
- $self->{msg_node}->setAttribute( router_class => $router_class );
- }
-}
-
-sub set_osrf_xid {
- my( $self, $xid ) = @_;
- $self->{msg_node}->setAttribute( osrf_xid => $xid );
-}
-
-
-sub get_osrf_xid {
- my $self = shift;
- $self->{msg_node}->getAttribute('osrf_xid');
-}
-
-
-1;
+++ /dev/null
-package OpenSRF::Transport::SlimJabber::PeerConnection;
-use strict;
-use base qw/OpenSRF::Transport::SlimJabber::Client/;
-use OpenSRF::Utils::Config;
-use OpenSRF::Utils::Logger qw(:level);
-use OpenSRF::EX qw/:try/;
-
-=head1 Description
-
-Represents a single connection to a remote peer. The
-Jabber values are loaded from the config file.
-
-Subclasses OpenSRF::Transport::SlimJabber::Client.
-
-=cut
-
-=head2 new()
-
- new( $appname );
-
- The $appname parameter tells this class how to find the correct
- Jabber username, password, etc to connect to the server.
-
-=cut
-
-our %apps_hash;
-our $_singleton_connection;
-
-sub retrieve {
- my( $class, $app ) = @_;
- return $_singleton_connection;
-# my @keys = keys %apps_hash;
-# OpenSRF::Utils::Logger->transport(
-# "Requesting peer for $app and we have @keys", INFO );
-# return $apps_hash{$app};
-}
-
-
-
-# !! In here we use the bootstrap config ....
-sub new {
- my( $class, $app ) = @_;
-
- my $peer_con = $class->retrieve;
- return $peer_con if ($peer_con and $peer_con->tcp_connected);
-
- my $config = OpenSRF::Utils::Config->current;
-
- if( ! $config ) {
- throw OpenSRF::EX::Config( "No suitable config found for PeerConnection" );
- }
-
- my $conf = OpenSRF::Utils::Config->current;
- my $domains = $conf->bootstrap->domains;
- my $h = $conf->env->hostname;
-
- my $username = $conf->bootstrap->username;
- my $password = $conf->bootstrap->passwd;
- my $port = $conf->bootstrap->port;
- my $resource = "${app}_drone_at_$h";
- my $host = $domains->[0]; # XXX for now...
-
- if( $app eq "client" ) { $resource = "client_at_$h"; }
-
-# unless ( $conf->bootstrap->router_name ) {
-# $username = 'router';
-# $resource = $app;
-# }
-
-
- OpenSRF::EX::Config->throw( "JPeer could not load all necesarry values from config" )
- unless ( $username and $password and $resource and $host and $port );
-
- OpenSRF::Utils::Logger->transport( "Built Peer with", INTERNAL );
-
- my $self = __PACKAGE__->SUPER::new(
- username => $username,
- resource => $resource,
- password => $password,
- host => $host,
- port => $port,
- );
-
- bless( $self, $class );
-
- $self->app($app);
-
- $_singleton_connection = $self;
- $apps_hash{$app} = $self;
-
- return $_singleton_connection;
- return $apps_hash{$app};
-}
-
-sub process {
-
- my $self = shift;
- my $val = $self->SUPER::process(@_);
- return 0 unless $val;
-
- OpenSRF::Utils::Logger->transport( "Calling transport handler for ".$self->app." with: $val", INTERNAL );
- my $t;
- $t = OpenSRF::Transport->handler($self->app, $val);
-
- return $t;
-}
-
-sub app {
- my $self = shift;
- my $app = shift;
- if( $app ) {
- OpenSRF::Utils::Logger->transport( "PEER changing app to $app: ".$self->jid, INTERNAL );
- }
-
- $self->{app} = $app if ($app);
- return $self->{app};
-}
-
-1;
-
+++ /dev/null
-package OpenSRF::UnixServer;
-use strict; use warnings;
-use base qw/OpenSRF/;
-use OpenSRF::EX qw(:try);
-use OpenSRF::Utils::Logger qw(:level $logger);
-use OpenSRF::Transport::PeerHandle;
-use OpenSRF::Application;
-use OpenSRF::AppSession;
-use OpenSRF::DomainObject::oilsResponse qw/:status/;
-use OpenSRF::System;
-use OpenSRF::Utils::SettingsClient;
-use Time::HiRes qw(time);
-use JSON;
-use vars qw/@ISA $app/;
-use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
-use Carp;
-
-use IO::Socket::INET;
-use IO::Socket::UNIX;
-
-sub DESTROY { confess "Dying $$"; }
-
-=head1 What am I
-
-All inbound messages are passed on to the UnixServer for processing.
-We take the data, close the Unix socket, and pass the data on to our abstract
-'process()' method.
-
-Our purpose is to 'multiplex' a single TCP connection into multiple 'client' connections.
-So when you pass data down the Unix socket to us, we have been preforked and waiting
-to disperse new data among us.
-
-=cut
-
-sub app { return $app; }
-
-{
-
- sub new {
- my( $class, $app1 ) = @_;
- if( ! $app1 ) {
- throw OpenSRF::EX::InvalidArg( "UnixServer requires an app name to run" );
- }
- $app = $app1;
- my $self = bless( {}, $class );
-# my $client = OpenSRF::Utils::SettingsClient->new();
-# if( $client->config_value("server_type") !~ /fork/i ||
-# OpenSRF::Utils::Config->current->bootstrap->settings_config ) {
-# warn "Calling hooks for non-prefork\n";
-# $self->configure_hook();
-# $self->child_init_hook();
-# }
- return $self;
- }
-
-}
-
-=head2 process_request()
-
-Takes the incoming data, closes the Unix socket and hands the data untouched
-to the abstract process() method. This method is implemented in our subclasses.
-
-=cut
-
-sub process_request {
-
- my $self = shift;
- my $data; my $d;
- while( $d = <STDIN> ) { $data .= $d; }
-
- my $orig = $0;
- $0 = "$0*";
-
- if( ! $data or ! defined( $data ) or $data eq "" ) {
- close($self->{server}->{client});
- $logger->debug("Unix child received empty data from socket", ERROR);
- $0 = $orig;
- return;
- }
-
-
- if( ! close( $self->{server}->{client} ) ) {
- $logger->debug( "Error closing Unix socket: $!", ERROR );
- }
-
- my $app = $self->app();
- $logger->transport( "UnixServer for $app received $data", INTERNAL );
-
- # --------------------------------------------------------------
- # Drop all data from the socket before coninuting to process
- # --------------------------------------------------------------
- my $ph = OpenSRF::Transport::PeerHandle->retrieve;
- if(!$ph->flush_socket()) {
- $logger->error("We received a request ".
- "and we are no longer connected to the jabber network. ".
- "We will go away and drop this request: $data");
- exit;
- }
-
- my $app_session = OpenSRF::Transport->handler( $self->app(), $data );
-
- if(!ref($app_session)) {
- $logger->transport( "Did not receive AppSession from transport handler, returning...", WARN );
- $0 = $orig;
- return;
- }
-
- if($app_session->stateless and $app_session->state != $app_session->CONNECTED()){
- $logger->debug("Exiting keepalive for stateless session / orig = $orig");
- $app_session->kill_me;
- $0 = $orig;
- return;
- }
-
-
- my $client = OpenSRF::Utils::SettingsClient->new();
- my $keepalive = $client->config_value("apps", $self->app(), "keepalive");
-
- my $req_counter = 0;
- while( $app_session and
- $app_session->state and
- $app_session->state != $app_session->DISCONNECTED() and
- $app_session->find( $app_session->session_id ) ) {
-
-
- my $before = time;
- $logger->debug( "UnixServer calling queue_wait $keepalive", INTERNAL );
- $app_session->queue_wait( $keepalive );
- $logger->debug( "after queue wait $keepalive", INTERNAL );
- my $after = time;
-
- if( ($after - $before) >= $keepalive ) {
-
- my $res = OpenSRF::DomainObject::oilsConnectStatus->new(
- status => "Disconnected on timeout",
- statusCode => STATUS_TIMEOUT);
- $app_session->status($res);
- $app_session->state( $app_session->DISCONNECTED() );
- last;
- }
-
- }
-
- my $x = 0;
- while( $app_session && $app_session->queue_wait(0) ) {
- $logger->debug( "Looping on zombies " . $x++ , DEBUG);
- }
-
- $logger->debug( "Timed out, disconnected, or auth failed" );
- $app_session->kill_me if ($app_session);
-
- $0 = $orig;
-}
-
-
-sub serve {
- my( $self ) = @_;
-
- my $app = $self->app();
- $logger->set_service($app);
-
- $0 = "OpenSRF master [$app]";
-
- my $client = OpenSRF::Utils::SettingsClient->new();
- my @base = ('apps', $app, 'unix_config' );
-
- my $min_servers = $client->config_value(@base, 'min_children');
- my $max_servers = $client->config_value(@base, "max_children" );
- my $min_spare = $client->config_value(@base, "min_spare_children" );
- my $max_spare = $client->config_value(@base, "max_spare_children" );
- my $max_requests = $client->config_value(@base, "max_requests" );
- # fwiw, these file paths are (obviously) not portable
- my $log_file = join("/", $client->config_value("dirs", "log"), $client->config_value(@base, "unix_log" ));
- my $port = join("/", $client->config_value("dirs", "sock"), $client->config_value(@base, "unix_sock" ));
- my $pid_file = join("/", $client->config_value("dirs", "pid"), $client->config_value(@base, "unix_pid" ));
-
- $min_spare ||= $min_servers;
- $max_spare ||= $max_servers;
- $max_requests ||= 1000;
-
- $logger->info("UnixServer: min=$min_servers, max=$max_servers, min_spare=$min_spare ".
- "max_spare=$max_spare, max_req=$max_requests, log_file=$log_file, port=$port, pid_file=$pid_file");
-
- $self->run(
- min_servers => $min_servers,
- max_servers => $max_servers,
- min_spare_servers => $min_spare,
- max_spare_servers => $max_spare,
- max_requests => $max_requests,
- log_file => $log_file,
- port => $port,
- proto => 'unix',
- pid_file => $pid_file,
- );
-
-}
-
-
-sub configure_hook {
- my $self = shift;
- my $app = $self->app;
-
- # boot a client
- OpenSRF::System->bootstrap_client( client_name => "system_client" );
-
- $logger->debug( "Setting application implementaion for $app", DEBUG );
- my $client = OpenSRF::Utils::SettingsClient->new();
- my $imp = $client->config_value("apps", $app, "implementation");
- OpenSRF::Application::server_class($app);
- OpenSRF::Application->application_implementation( $imp );
- JSON->register_class_hint( name => $imp, hint => $app, type => "hash" );
- OpenSRF::Application->application_implementation->initialize()
- if (OpenSRF::Application->application_implementation->can('initialize'));
-
- if( $client->config_value("server_type") !~ /fork/i ) {
- $self->child_init_hook();
- }
-
- my $con = OpenSRF::Transport::PeerHandle->retrieve;
- if($con) {
- $con->disconnect;
- }
-
- return OpenSRF::Application->application_implementation;
-}
-
-sub child_init_hook {
-
- $0 =~ s/master/drone/g;
-
- if ($ENV{OPENSRF_PROFILE}) {
- my $file = $0;
- $file =~ s/\W/_/go;
- eval "use Devel::Profiler output_file => '/tmp/profiler_$file.out', buffer_size => 0;";
- if ($@) {
- $logger->debug("Could not load Devel::Profiler: $@",ERROR);
- } else {
- $0 .= ' [PROFILING]';
- $logger->debug("Running under Devel::Profiler", INFO);
- }
- }
-
- my $self = shift;
-
-# $logger->transport(
-# "Creating PeerHandle from UnixServer child_init_hook", INTERNAL );
- OpenSRF::Transport::PeerHandle->construct( $self->app() );
- $logger->transport( "PeerHandle Created from UnixServer child_init_hook", INTERNAL );
-
- OpenSRF::Application->application_implementation->child_init
- if (OpenSRF::Application->application_implementation->can('child_init'));
-
- return OpenSRF::Transport::PeerHandle->retrieve;
-}
-
-sub child_finish_hook {
- $logger->debug("attempting to call child exit handler...");
- OpenSRF::Application->application_implementation->child_exit
- if (OpenSRF::Application->application_implementation->can('child_exit'));
-}
-
-
-1;
-
+++ /dev/null
-package OpenSRF::Utils;
-
-=head1 NAME
-
-OpenSRF::Utils
-
-=head1 DESCRIPTION
-
-This is a container package for methods that are useful to derived modules.
-It has no constructor, and is generally not useful by itself... but this
-is where most of the generic methods live.
-
-
-=head1 METHODS
-
-
-=cut
-
-use vars qw/@ISA $AUTOLOAD %EXPORT_TAGS @EXPORT_OK @EXPORT $VERSION/;
-push @ISA, 'Exporter';
-
-$VERSION = do { my @r=(q$Revision$=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
-
-use Time::Local;
-use Errno;
-use POSIX;
-use FileHandle;
-#use Cache::FileCache;
-#use Storable qw(dclone);
-use Digest::MD5 qw(md5 md5_hex md5_base64);
-use Exporter;
-use DateTime;
-use DateTime::Format::ISO8601;
-use DateTime::TimeZone;
-
-our $date_parser = DateTime::Format::ISO8601->new;
-
-# This turns errors into warnings, so daemons don't die.
-#$Storable::forgive_me = 1;
-
-%EXPORT_TAGS = (
- common => [qw(interval_to_seconds seconds_to_interval sendmail tree_filter)],
- daemon => [qw(safe_fork set_psname daemonize)],
- datetime => [qw(clense_ISO8601 gmtime_ISO8601 interval_to_seconds seconds_to_interval)],
-);
-
-Exporter::export_ok_tags('common','daemon','datetime'); # add aa, cc and dd to @EXPORT_OK
-
-sub AUTOLOAD {
- my $self = shift;
- my $type = ref($self) or return undef;
-
- my $name = $AUTOLOAD;
- $name =~ s/.*://; # strip fully-qualified portion
-
- if (defined($_[0])) {
- return $self->{$name} = shift;
- }
- return $self->{$name};
-}
-
-
-sub _sub_builder {
- my $self = shift;
- my $class = ref($self) || $self;
- my $part = shift;
- unless ($class->can($part)) {
- *{$class.'::'.$part} =
- sub {
- my $self = shift;
- my $new_val = shift;
- if ($new_val) {
- $$self{$part} = $new_val;
- }
- return $$self{$part};
- };
- }
-}
-
-sub tree_filter {
- my $tree = shift;
- my $field = shift;
- my $filter = shift;
-
- my @things = $filter->($tree);
- for my $v ( @{$tree->$field} ){
- push @things, $filter->($v);
- push @things, tree_filter($v, $field, $filter);
- }
- return @things
-}
-
-#sub standalone_ipc_cache {
-# my $self = shift;
-# my $class = ref($self) || $self;
-# my $uniquifier = shift || return undef;
-# my $expires = shift || 3600;
-
-# return new Cache::FileCache ( { namespace => $class.'::'.$uniquifier, default_expires_in => $expires } );
-#}
-
-sub sendmail {
- my $self = shift;
- my $message = shift || $self;
-
- open SM, '|/usr/sbin/sendmail -U -t' or return 0;
- print SM $message;
- close SM or return 0;
- return 1;
-}
-
-sub __strip_comments {
- my $self = shift;
- my $config_file = shift;
- my ($line, @done);
- while (<$config_file>) {
- s/^\s*(.*)\s*$/$1/o if (lc($$self{keep_space}) ne 'true');
- /^(.*)$/o;
- $line .= $1;
- # keep new lines if keep_space is true
- if ($line =~ /^$/o && (lc($$self{keep_space}) ne 'true')) {
- $line = '';
- next;
- }
- if (/^([^<]+)\s*<<\s*(\w+)\s*$/o) {
- $line = "$1 = ";
- my $breaker = $2;
- while (<$config_file>) {
- chomp;
- last if (/^$breaker/);
- $line .= $_;
- }
- }
-
- if ($line =~ /^#/ && $line !~ /^#\s*include\s+/o) {
- $line = '';
- next;
- }
- if ($line =~ /\\$/o) {
- chomp $line;
- $line =~ s/^\s*(.*)\s*\\$/$1/o;
- next;
- }
- push @done, $line;
- $line = '';
- }
- return @done;
-}
-
-
-=head2 $thing->encrypt(@stuff)
-
-Returns a one way hash (MD5) of the values appended together.
-
-=cut
-
-sub encrypt {
- my $self = shift;
- return md5_hex(join('',@_));
-}
-
-=head2 $utils_obj->es_time('field') OR noo_es_time($timestamp)
-
-Returns the epoch-second style timestamp for the value stored in
-$utils_obj->{field}. Returns B<0> for an empty or invalid date stamp, and
-assumes a PostgreSQL style datestamp to be supplied.
-
-=cut
-
-sub es_time {
- my $self = shift;
- my $part = shift;
- my $es_part = $part.'_ES';
- return $$self{$es_part} if (exists($$self{$es_part}) && defined($$self{$es_part}) && $$self{$es_part});
- if (!$$self{$part} or $$self{$part} !~ /\d+/) {
- return 0;
-
- }
- my @tm = reverse($$self{$part} =~ /([\d\.]+)/og);
- if ($tm[5] > 0) {
- $tm[5] -= 1;
- }
-
- return $$self{$es_part} = noo_es_time($$self{$part});
-}
-
-=head2 noo_es_time($timestamp) (non-OO es_time)
-
-Returns the epoch-second style timestamp for the B<$timestamp> passed
-in. Returns B<0> for an empty or invalid date stamp, and
-assumes a PostgreSQL style datestamp to be supplied.
-
-=cut
-
-sub noo_es_time {
- my $timestamp = shift;
-
- my @tm = reverse($timestamp =~ /([\d\.]+)/og);
- if ($tm[5] > 0) {
- $tm[5] -= 1;
- }
- return timelocal(int($tm[1]), int($tm[2]), int($tm[3]), int($tm[4]) || 1, int($tm[5]), int($tm[6]) || 2002 );
-}
-
-
-=head2 $thing->interval_to_seconds('interval') OR interval_to_seconds('interval')
-
-=head2 $thing->seconds_to_interval($seconds) OR seconds_to_interval($seconds)
-
-Returns the number of seconds for any interval passed, or the interval for the seconds.
-This is the generic version of B<interval> listed below.
-
-The interval must match the regex I</\s*\+?\s*(\d+)\s*(\w{1})\w*\s*/g>, for example
-B<2 weeks, 3 d and 1hour + 17 Months> or
-B<1 year, 5 Months, 2 weeks, 3 days and 1 hour of seconds> meaning 46148400 seconds.
-
- my $expire_time = time() + $thing->interval_to_seconds('17h 9m');
-
-The time size indicator may be one of
-
-=over 2
-
-=item s[econd[s]]
-
-for seconds
-
-=item m[inute[s]]
-
-for minutes
-
-=item h[our[s]]
-
-for hours
-
-=item d[ay[s]]
-
-for days
-
-=item w[eek[s]]
-
-for weeks
-
-=item M[onth[s]]
-
-for months (really (365 * 1d)/12 ... that may get smarter, though)
-
-=item y[ear[s]]
-
-for years (this is 365 * 1d)
-
-=back
-
-=cut
-sub interval_to_seconds {
- my $self = shift;
- my $interval = shift || $self;
-
- $interval =~ s/and/,/g;
- $interval =~ s/,/ /g;
-
- my $amount = 0;
- while ($interval =~ /\s*\+?\s*(\d+)\s*(\w+)\s*/g) {
- my ($count, $type) = ($1, $2);
- $amount += $count if ($type eq 's');
- $amount += 60 * $count if ($type =~ /^m(?!o)/oi);
- $amount += 60 * 60 * $count if ($type =~ /^h/);
- $amount += 60 * 60 * 24 * $count if ($type =~ /^d/oi);
- $amount += 60 * 60 * 24 * 7 * $count if ($2 =~ /^w/oi);
- $amount += ((60 * 60 * 24 * 365)/12) * $count if ($type =~ /^mo/io);
- $amount += 60 * 60 * 24 * 365 * $count if ($type =~ /^y/oi);
- }
- return $amount;
-}
-
-sub seconds_to_interval {
- my $self = shift;
- my $interval = shift || $self;
-
- my $limit = shift || 's';
- $limit =~ s/^(.)/$1/o;
-
- my ($y,$ym,$M,$Mm,$w,$wm,$d,$dm,$h,$hm,$m,$mm,$s,$string);
- my ($year, $month, $week, $day, $hour, $minute, $second) =
- ('year','Month','week','day', 'hour', 'minute', 'second');
-
- if ($y = int($interval / (60 * 60 * 24 * 365))) {
- $string = "$y $year". ($y > 1 ? 's' : '');
- $ym = $interval % (60 * 60 * 24 * 365);
- } else {
- $ym = $interval;
- }
- return $string if ($limit eq 'y');
-
- if ($M = int($ym / ((60 * 60 * 24 * 365)/12))) {
- $string .= ($string ? ', ':'')."$M $month". ($M > 1 ? 's' : '');
- $Mm = $ym % ((60 * 60 * 24 * 365)/12);
- } else {
- $Mm = $ym;
- }
- return $string if ($limit eq 'M');
-
- if ($w = int($Mm / 604800)) {
- $string .= ($string ? ', ':'')."$w $week". ($w > 1 ? 's' : '');
- $wm = $Mm % 604800;
- } else {
- $wm = $Mm;
- }
- return $string if ($limit eq 'w');
-
- if ($d = int($wm / 86400)) {
- $string .= ($string ? ', ':'')."$d $day". ($d > 1 ? 's' : '');
- $dm = $wm % 86400;
- } else {
- $dm = $wm;
- }
- return $string if ($limit eq 'd');
-
- if ($h = int($dm / 3600)) {
- $string .= ($string ? ', ' : '')."$h $hour". ($h > 1 ? 's' : '');
- $hm = $dm % 3600;
- } else {
- $hm = $dm;
- }
- return $string if ($limit eq 'h');
-
- if ($m = int($hm / 60)) {
- $string .= ($string ? ', ':'')."$m $minute". ($m > 1 ? 's' : '');
- $mm = $hm % 60;
- } else {
- $mm = $hm;
- }
- return $string if ($limit eq 'm');
-
- if ($s = int($mm)) {
- $string .= ($string ? ', ':'')."$s $second". ($s > 1 ? 's' : '');
- } else {
- $string = "0s" unless ($string);
- }
- return $string;
-}
-
-sub full {
- my $self = shift;
- $$self{empty} = 0;
-}
-
-=head2 $utils_obj->set_psname('string') OR set_psname('string')
-
-Sets the name of this process in a B<ps> listing to B<string>.
-
-
-=cut
-
-sub set_psname {
- my $self = shift;
- my $PS_NAME = shift || $self;
- $0 = $PS_NAME if ($PS_NAME);
-}
-
-sub gmtime_ISO8601 {
- my $self = shift;
- my @date = gmtime;
-
- my $y = $date[5] + 1900;
- my $M = $date[4] + 1;
- my $d = $date[3];
- my $h = $date[2];
- my $m = $date[1];
- my $s = $date[0];
-
- return sprintf('%d-%0.2d-%0.2dT%0.2d:%0.2d:%0.2d+00:00', $y, $M, $d, $h, $m, $s);
-}
-
-sub clense_ISO8601 {
- my $self = shift;
- my $date = shift || $self;
- if ($date =~ /^\s*(\d{4})-?(\d{2})-?(\d{2})/o) {
- my $new_date = "$1-$2-$3";
-
- if ($date =~/(\d{2}):(\d{2}):(\d{2})/o) {
- $new_date .= "T$1:$2:$3";
-
- my $z;
- if ($date =~ /([-+]{1})([0-9]{1,2})(?::?([0-9]{1,2}))*\s*$/o) {
- $z = sprintf('%s%0.2d%0.2d',$1,$2,$3)
- } else {
- $z = DateTime::TimeZone::offset_as_string(
- DateTime::TimeZone
- ->new( name => 'local' )
- ->offset_for_datetime(
- $date_parser->parse_datetime($new_date)
- )
- );
- }
-
- if (length($z) > 3 && index($z, ':') == -1) {
- substr($z,3,0) = ':';
- substr($z,6,0) = ':' if (length($z) > 6);
- }
-
- $new_date .= $z;
- } else {
- $new_date .= "T00:00:00";
- }
-
- return $new_date;
- }
- return $date;
-}
-
-=head2 $utils_obj->daemonize('ps_name') OR daemonize('ps_name')
-
-Turns the current process into a daemon. B<ps_name> is optional, and is used
-as the argument to I<< set_psname() >> if passed.
-
-
-=cut
-
-sub daemonize {
- my $self = shift;
- my $PS_NAME = shift || $self;
- my $pid;
- if ($pid = safe_fork($self)) {
- exit 0;
- } elsif (defined($pid)) {
- set_psname($PS_NAME);
- chdir '/';
- setsid;
- return $$;
- }
-}
-
-=head2 $utils_obj->safe_fork('ps_name') OR safe_fork('ps_name');
-
-Forks the current process in a retry loop. B<ps_name> is optional, and is used
-as the argument to I<< set_psname() >> if passed.
-
-
-=cut
-
-sub safe_fork {
- my $self = shift;
- my $pid;
-
-FORK:
- {
- if (defined($pid = fork())) {
- srand(time ^ ($$ + ($$ << 15))) unless ($pid);
- return $pid;
- } elsif ($! == EAGAIN) {
- $self->error("Can't fork()! $!, taking 5 and trying again.") if (ref $self);
- sleep 5;
- redo FORK;
- } else {
- $self->error("Can't fork()! $!") if ($! && ref($self));
- exit $!;
- }
- }
-}
-
-#------------------------------------------------------------------------------------------------------------------------------------
-
-
-1;
+++ /dev/null
-package OpenSRF::Utils::Cache;
-use strict; use warnings;
-use base qw/OpenSRF/;
-use Cache::Memcached;
-use OpenSRF::Utils::Logger qw/:level/;
-use OpenSRF::Utils::Config;
-use OpenSRF::Utils::SettingsClient;
-use OpenSRF::EX qw(:try);
-use JSON;
-
-my $log = 'OpenSRF::Utils::Logger';
-
-=head OpenSRF::Utils::Cache
-
-This class just subclasses Cache::Memcached.
-see Cache::Memcached for more options.
-
-The value passed to the call to current is the cache type
-you wish to access. The below example sets/gets data
-from the 'user' cache.
-
-my $cache = OpenSRF::Utils::Cache->current("user");
-$cache->set( "key1", "value1" [, $expire_secs ] );
-my $val = $cache->get( "key1" );
-
-
-=cut
-
-sub DESTROY {}
-
-my %caches;
-
-# ------------------------------------------------------
-# Persist methods and method names
-# ------------------------------------------------------
-my $persist_add_slot;
-my $persist_push_stack;
-my $persist_peek_stack;
-my $persist_destroy_slot;
-my $persist_slot_get_expire;
-my $persist_slot_find;
-
-my $max_persist_time;
-my $persist_add_slot_name = "opensrf.persist.slot.create_expirable";
-my $persist_push_stack_name = "opensrf.persist.stack.push";
-my $persist_peek_stack_name = "opensrf.persist.stack.peek";
-my $persist_destroy_slot_name = "opensrf.persist.slot.destroy";
-my $persist_slot_get_expire_name = "opensrf.persist.slot.get_expire";
-my $persist_slot_find_name = "opensrf.persist.slot.find";;
-
-# ------------------------------------------------------
-
-
-# return a named cache if it exists
-sub current {
- my ( $class, $c_type ) = @_;
- return undef unless $c_type;
- return $caches{$c_type} if exists $caches{$c_type};
- return $caches{$c_type} = $class->new( $c_type );
-}
-
-
-# create a new named memcache object.
-sub new {
-
- my( $class, $cache_type, $persist ) = @_;
- $cache_type ||= 'global';
- $class = ref( $class ) || $class;
-
- return $caches{$cache_type}
- if (defined $caches{$cache_type});
-
- my $conf = OpenSRF::Utils::SettingsClient->new;
- my $servers = $conf->config_value( cache => $cache_type => servers => 'server' );
- $max_persist_time = $conf->config_value( cache => $cache_type => 'max_cache_time' );
-
- if(!ref($servers)){
- $servers = [ $servers ];
- }
-
- my $self = {};
- $self->{persist} = $persist || 0;
- $self->{memcache} = Cache::Memcached->new( { servers => $servers } );
- if(!$self->{memcache}) {
- throw OpenSRF::EX::PANIC ("Unable to create a new memcache object for $cache_type");
- }
-
- bless($self, $class);
- $caches{$cache_type} = $self;
- return $self;
-}
-
-
-
-sub put_cache {
- my($self, $key, $value, $expiretime ) = @_;
- return undef unless( defined $key and defined $value );
-
- $value = JSON->perl2JSON($value);
-
- if($self->{persist}){ _load_methods(); }
-
- $expiretime ||= $max_persist_time;
-
- unless( $self->{memcache}->set( $key, $value, $expiretime ) ) {
- $log->error("Unable to store $key => [".length($value)." bytes] in memcached server" );
- return undef;
- }
-
- $log->debug("Stored $key => $value in memcached server", INTERNAL);
-
- if($self->{"persist"}) {
-
- my ($slot) = $persist_add_slot->run("_CACHEVAL_$key", $expiretime . "s");
-
- if(!$slot) {
- # slot may already exist
- ($slot) = $persist_slot_find->run("_CACHEVAL_$key");
- if(!defined($slot)) {
- throw OpenSRF::EX::ERROR ("Unable to create cache slot $key in persist server" );
- } else {
- #XXX destroy the slot and rebuild it to prevent DOS
- }
- }
-
- ($slot) = $persist_push_stack->run("_CACHEVAL_$key", $value);
-
- if(!$slot) {
- throw OpenSRF::EX::ERROR ("Unable to push data onto stack in persist slot _CACHEVAL_$key" );
- }
- }
-
- return $key;
-}
-
-sub delete_cache {
- my( $self, $key ) = @_;
- if(!$key) { return undef; }
- if($self->{persist}){ _load_methods(); }
- $self->{memcache}->delete($key);
- if( $self->{persist} ) {
- $persist_destroy_slot->run("_CACHEVAL_$key");
- }
- return $key;
-}
-
-sub get_cache {
- my($self, $key ) = @_;
-
- my $val = $self->{memcache}->get( $key );
- return JSON->JSON2perl($val) if defined($val);
-
- if($self->{persist}){ _load_methods(); }
-
- # if not in memcache but we are persisting, the put it into memcache
- if( $self->{"persist"} ) {
- $val = $persist_peek_stack->( "_CACHEVAL_$key" );
- if(defined($val)) {
- my ($expire) = $persist_slot_get_expire->run("_CACHEVAL_$key");
- if($expire) {
- $self->{memcache}->set( $key, $val, $expire);
- } else {
- $self->{memcache}->set( $key, $val, $max_persist_time);
- }
- return JSON->JSON2perl($val);
- }
- }
- return undef;
-}
-
-
-
-
-sub _load_methods {
-
- if(!$persist_add_slot) {
- $persist_add_slot =
- OpenSRF::Application->method_lookup($persist_add_slot_name);
- if(!ref($persist_add_slot)) {
- throw OpenSRF::EX::PANIC ("Unable to retrieve method $persist_add_slot_name");
- }
- }
-
- if(!$persist_push_stack) {
- $persist_push_stack =
- OpenSRF::Application->method_lookup($persist_push_stack_name);
- if(!ref($persist_push_stack)) {
- throw OpenSRF::EX::PANIC ("Unable to retrieve method $persist_push_stack_name");
- }
- }
-
- if(!$persist_peek_stack) {
- $persist_peek_stack =
- OpenSRF::Application->method_lookup($persist_peek_stack_name);
- if(!ref($persist_peek_stack)) {
- throw OpenSRF::EX::PANIC ("Unable to retrieve method $persist_peek_stack_name");
- }
- }
-
- if(!$persist_destroy_slot) {
- $persist_destroy_slot =
- OpenSRF::Application->method_lookup($persist_destroy_slot_name);
- if(!ref($persist_destroy_slot)) {
- throw OpenSRF::EX::PANIC ("Unable to retrieve method $persist_destroy_slot_name");
- }
- }
- if(!$persist_slot_get_expire) {
- $persist_slot_get_expire =
- OpenSRF::Application->method_lookup($persist_slot_get_expire_name);
- if(!ref($persist_slot_get_expire)) {
- throw OpenSRF::EX::PANIC ("Unable to retrieve method $persist_slot_get_expire_name");
- }
- }
- if(!$persist_slot_find) {
- $persist_slot_find =
- OpenSRF::Application->method_lookup($persist_slot_find_name);
- if(!ref($persist_slot_find)) {
- throw OpenSRF::EX::PANIC ("Unable to retrieve method $persist_slot_find_name");
- }
- }
-}
-
-
-
-
-
-
-
-1;
-
+++ /dev/null
-package OpenSRF::Utils::Config::Section;
-
-no strict 'refs';
-
-use vars qw/@ISA $AUTOLOAD $VERSION/;
-push @ISA, qw/OpenSRF::Utils/;
-
-use OpenSRF::Utils (':common');
-use Net::Domain qw/hostfqdn/;
-
-$VERSION = do { my @r=(q$Revision$=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
-
-my %SECTIONCACHE;
-my %SUBSECTION_FIXUP;
-
-#use overload '""' => \&OpenSRF::Utils::Config::dump_ini;
-
-sub SECTION {
- my $sec = shift;
- return $sec->__id(@_);
-}
-
-sub new {
- my $self = shift;
- my $class = ref($self) || $self;
-
- $self = bless {}, $class;
-
- my $lines = shift;
-
- for my $line (@$lines) {
-
- #($line) = split(/\s+\/\//, $line);
- #($line) = split(/\s+#/, $line);
-
- if ($line =~ /^\s*\[([^\[\]]+)\]/) {
- $self->_sub_builder('__id');
- $self->__id( $1 );
- next;
- }
-
- my ($protokey,$value,$keytype,$key);
- if ($line =~ /^([^=\s]+)\s*=\s*(.*)\s*$/s) {
- ($protokey,$value) = ($1,$2);
- ($keytype,$key) = split(/:/,$protokey);
- }
-
- $key = $protokey unless ($key);
-
- if ($keytype ne $key) {
- $keytype = lc $keytype;
- if ($keytype eq 'list') {
- $value = [split /\s*,\s*/, $value];
- } elsif ($keytype eq 'bool') {
- $value = do{ $value =~ /^t|y|1/i ? 1 : 0; };
- } elsif ($keytype eq 'interval') {
- $value = interval_to_seconds($value);
- } elsif ($keytype eq 'subsection') {
- if (exists $SECTIONCACHE{$value}) {
- $value = $SECTIONCACHE{$value};
- } else {
- $SUBSECTION_FIXUP{$value}{$self->SECTION} = $key ;
- next;
- }
- }
- }
-
- $self->_sub_builder($key);
- $self->$key($value);
- }
-
- no warnings;
- if (my $parent_def = $SUBSECTION_FIXUP{$self->SECTION}) {
- my ($parent_section, $parent_key) = each %$parent_def;
- $SECTIONCACHE{$parent_section}->{$parent_key} = $self;
- delete $SUBSECTION_FIXUP{$self->SECTION};
- }
-
- $SECTIONCACHE{$self->SECTION} = $self;
-
- return $self;
-}
-
-package OpenSRF::Utils::Config;
-
-use vars qw/@ISA $AUTOLOAD $VERSION $OpenSRF::Utils::ConfigCache/;
-push @ISA, qw/OpenSRF::Utils/;
-
-use FileHandle;
-use OpenSRF::Utils (':common');
-use OpenSRF::Utils::Logger;
-use Net::Domain qw/hostfqdn/;
-
-#use overload '""' => \&OpenSRF::Utils::Config::dump_ini;
-
-sub import {
- my $class = shift;
- my $config_file = shift;
-
- return unless $config_file;
-
- $class->load( config_file => $config_file);
-}
-
-sub dump_ini {
- no warnings;
- my $self = shift;
- my $string;
- my $included = 0;
- if ($self->isa('OpenSRF::Utils::Config')) {
- if (UNIVERSAL::isa(scalar(caller()), 'OpenSRF::Utils::Config' )) {
- $included = 1;
- } else {
- $string = "# Main File: " . $self->FILE . "\n\n" . $string;
- }
- }
- for my $section ( ('__id', grep { $_ ne '__id' } sort keys %$self) ) {
- next if ($section eq 'env' && $self->isa('OpenSRF::Utils::Config'));
- if ($section eq '__id') {
- $string .= '['.$self->SECTION."]\n" if ($self->isa('OpenSRF::Utils::Config::Section'));
- } elsif (ref($self->$section)) {
- if (ref($self->$section) =~ /ARRAY/o) {
- $string .= "list:$section = ". join(', ', @{$self->$section}) . "\n";
- } elsif (UNIVERSAL::isa($self->$section,'OpenSRF::Utils::Config::Section')) {
- if ($self->isa('OpenSRF::Utils::Config::Section')) {
- $string .= "subsection:$section = " . $self->$section->SECTION . "\n";
- next;
- } else {
- next if ($self->$section->{__sub} && !$included);
- $string .= $self->$section . "\n";
- }
- } elsif (UNIVERSAL::isa($self->$section,'OpenSRF::Utils::Config')) {
- $string .= $self->$section . "\n";
- }
- } else {
- next if $section eq '__sub';
- $string .= "$section = " . $self->$section . "\n";
- }
- }
- if ($included) {
- $string =~ s/^/## /gm;
- $string = "# Subfile: " . $self->FILE . "\n#" . '-'x79 . "\n".'#include "'.$self->FILE."\"\n". $string;
- }
-
- return $string;
-}
-
-=head1 NAME
-
-OpenSRF::Utils::Config
-
-
-=head1 SYNOPSIS
-
-
- use OpenSRF::Utils::Config;
-
- my $config_obj = OpenSRF::Utils::Config->load( config_file => '/config/file.cnf' );
-
- my $attrs_href = $config_obj->attributes();
-
- $config_obj->attributes->no_db(0);
-
- open FH, '>'.$config_obj->FILE() . '.new';
- print FH $config_obj;
- close FH;
-
-
-
-=head1 DESCRIPTION
-
-
-This module is mainly used by other modules to load a configuration file.
-
-
-=head1 NOTES
-
-
-Hashrefs of sections can be returned by calling a method of the object of the same name as the section.
-They can be set by passing a hashref back to the same method. Sections will B<NOT> be autovivicated, though.
-
-Here be a config file example, HAR!:
-
- [datasource]
- # backend=XMLRPC
- backend=DBI
- subsection:definition=devel_db
-
- [devel_db]
- dsn=dbi:Pg(RaiseError => 0, AutoCommit => 1):dbname=dcl;host=nsite-dev
- user=postgres
- pw=postgres
- #readonly=1
-
- [live_db]
- dsn=dbi:Pg(RaiseError => 0, AutoCommit => 1):dbname=dcl
- user=n2dcl
- pw=dclserver
- #readonly=1
-
- [devel_xmlrpc]
- subsection:definition=devel_rpc
-
- [logs]
- base=/var/log/nsite
- debug=debug.log
- error=error.log
-
- [debug]
- enabled=1
- level=ALL
-
- [devel_rpc]
- url=https://localhost:9000/
- proto=SSL
- SSL_cipher_list=ALL
- SSL_verify_mode=5
- SSL_use_cert=1
- SSL_key_file=client-key.pem
- SSL_cert_file=client-cert.pem
- SSL_ca_file=cacert.pem
- log_level=4
-
- [dirs]
- base_dir=/home/miker/cvs/NOC/monitor_core/
- cert_dir=certs/
-
-
-=head1 METHODS
-
-
-=cut
-
-
-$VERSION = do { my @r=(q$Revision$=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
-
-
-=head2 OpenSRF::Utils::Config->load( config_file => '/some/config/file.cnf' )
-
-Returns a OpenSRF::Utils::Config object representing the config file that was loaded.
-The most recently loaded config file (hopefully the only one per app)
-is stored at $OpenSRF::Utils::ConfigCache. Use OpenSRF::Utils::Config::current() to get at it.
-
-
-=cut
-
-sub load {
- my $pkg = shift;
- $pkg = ref($pkg) || $pkg;
-
- my %args = @_;
-
- (my $new_pkg = $args{config_file}) =~ s/\W+/_/g;
- $new_pkg .= "::$pkg";
- $new_section_pkg .= "${new_pkg}::Section";
-
- { eval <<" PERL";
-
- package $new_pkg;
- use base $pkg;
- sub section_pkg { return '$new_section_pkg'; }
-
- package $new_section_pkg;
- use base "${pkg}::Section";
-
- PERL
- }
-
- return $new_pkg->_load( %args );
-}
-
-sub _load {
- my $pkg = shift;
- $pkg = ref($pkg) || $pkg;
- my $self = {@_};
- bless $self, $pkg;
-
- no warnings;
- if ((exists $$self{config_file} and OpenSRF::Utils::Config->current) and (OpenSRF::Utils::Config->current->FILE eq $$self{config_file}) and (!$self->{force})) {
- delete $$self{force};
- return OpenSRF::Utils::Config->current();
- }
-
- $self->_sub_builder('__id');
- $self->FILE($$self{config_file});
- delete $$self{config_file};
- return undef unless ($self->FILE);
-
- $self->load_config();
- $self->load_env();
- $self->mangle_dirs();
- $self->mangle_logs();
-
- $OpenSRF::Utils::ConfigCache = $self unless $self->nocache;
- delete $$self{nocache};
- delete $$self{force};
- return $self;
-}
-
-sub sections {
- my $self = shift;
- my %filters = @_;
-
- my @parts = (grep { UNIVERSAL::isa($_,'OpenSRF::Utils::Config::Section') } values %$self);
- if (keys %filters) {
- my $must_match = scalar(keys %filters);
- my @ok_parts;
- foreach my $part (@parts) {
- my $part_count = 0;
- for my $fkey (keys %filters) {
- $part_count++ if ($part->$key eq $filters{$key});
- }
- push @ok_parts, $part if ($part_count == $must_match);
- }
- return @ok_parts;
- }
- return @parts;
-}
-
-sub current {
- return $OpenSRF::Utils::ConfigCache;
-}
-
-sub FILE {
- return shift()->__id(@_);
-}
-
-sub load_env {
- my $self = shift;
- my $host = hostfqdn();
- chomp $host;
- $$self{env} = $self->section_pkg->new;
- $$self{env}{hostname} = $host;
-}
-
-sub mangle_logs {
- my $self = shift;
- return unless ($self->logs && $self->dirs && $self->dirs->log_dir);
- for my $i ( keys %{$self->logs} ) {
- next if ($self->logs->$i =~ /^\//);
- $self->logs->$i($self->dirs->log_dir."/".$self->logs->$i);
- }
-}
-
-sub mangle_dirs {
- my $self = shift;
- return unless ($self->dirs && $self->dirs->base_dir);
- for my $i ( keys %{$self->dirs} ) {
- if ( $i ne 'base_dir' ) {
- next if ($self->dirs->$i =~ /^\//);
- my $dir_tmp = $self->dirs->base_dir."/".$self->dirs->$i;
- $dir_tmp =~ s#//#/#go;
- $dir_tmp =~ s#/$##go;
- $self->dirs->$i($dir_tmp);
- }
- }
-}
-
-sub load_config {
- my $self = shift;
- my $config = new FileHandle $self->FILE, 'r';
- unless ($config) {
- OpenSRF::Utils::Logger->error("Could not open ".$self->FILE.": $!\n");
- die "Could not open ".$self->FILE.": $!\n";
- }
- my @stripped_config = $self->__strip_comments($config) if (defined $config);
-
- my $chunk = [];
- for my $line (@stripped_config) {
- no warnings;
- next unless ($line);
-
- if ($line =~ /^\s*\[/ and @$chunk) {
- my $section = $self->section_pkg->new($chunk);
-
- my $sub_name = $section->SECTION;
- $self->_sub_builder($sub_name);
- $self->$sub_name($section);
-
- #$self->{$section->SECTION} = $section;
-
- $chunk = [];
- push @$chunk,$line;
- next;
- }
- if ($line =~ /^#\s*include\s+"(\S+)"\s*$/o) {
- my $included_file = $1;
- my $section = OpenSRF::Utils::Config->load(config_file => $included_file, nocache => 1);
-
- my $sub_name = $section->FILE;
- $self->_sub_builder($sub_name);
- $self->$sub_name($section);
-
- for my $subsect (keys %$section) {
- next if ($subsect eq '__id');
-
- $self->_sub_builder($subsect);
- $self->$subsect($$section{$subsect});
-
- #$self->$subsect($section->$subsect);
- $self->$subsect->{__sub} = 1;
- }
- next;
- }
-
- push @$chunk,$line;
- }
- my $section = $self->section_pkg->new($chunk) if (@$chunk);
- my $sub_name = $section->SECTION;
- $self->_sub_builder($sub_name);
- $self->$sub_name($section);
-
-}
-
-
-#------------------------------------------------------------------------------------------------------------------------------------
-
-=head1 SEE ALSO
-
- OpenSRF::Utils
-
-=head1 BUGS
-
-No know bugs, but report any to mrylander@gmail.com.
-
-=head1 COPYRIGHT AND LICENSING
-
-Mike Rylander, Copyright 2000-2007
-
-The OpenSRF::Utils::Config module is free software. You may distribute under the terms
-of the GNU General Public License version 2 or greater.
-
-=cut
-
-
-1;
+++ /dev/null
-package OpenSRF::Utils::LogServer;
-use strict; use warnings;
-use base qw(OpenSRF);
-use IO::Socket::INET;
-use FileHandle;
-use OpenSRF::Utils::Config;
-use Fcntl;
-use Time::HiRes qw(gettimeofday);
-use OpenSRF::Utils::Logger;
-
-=head2 Name
-
-OpenSRF::Utils::LogServer
-
-=cut
-
-=head2 Synopsis
-
-Networ Logger
-
-=cut
-
-=head2 Description
-
-
-=cut
-
-
-
-our $config;
-our $port;
-our $bufsize = 4096;
-our $proto;
-our @file_info;
-
-
-sub DESTROY {
- for my $file (@file_info) {
- if( $file->handle ) {
- close( $file->handle );
- }
- }
-}
-
-
-sub serve {
-
- $config = OpenSRF::Utils::Config->current;
-
- unless ($config) { throw OpenSRF::EX::Config ("No suitable config found"); }
-
- $port = $config->system->log_port;
- $proto = $config->system->log_proto;
-
-
- my $server = IO::Socket::INET->new(
- LocalPort => $port,
- Proto => $proto )
- or die "Error creating server socket : $@\n";
-
-
-
- while ( 1 ) {
- my $client = <$server>;
- process( $client );
- }
-
- close( $server );
-}
-
-sub process {
- my $client = shift;
- my @params = split(/\|/,$client);
- my $log = shift @params;
-
- if( (!$log) || (!@params) ) {
- warn "Invalid logging params: $log\n";
- return;
- }
-
- # Put |'s back in since they are stripped
- # from the message by 'split'
- my $message;
- if( @params > 1 ) {
- foreach my $param (@params) {
- if( $param ne $params[0] ) {
- $message .= "|";
- }
- $message .= $param;
- }
- }
- else{ $message = "@params"; }
-
- my @lines = split( "\n", $message );
- my $time = format_time();
-
- my $fh;
-
- my ($f_obj) = grep { $_->name eq $log } @file_info;
-
- unless( $f_obj and ($fh=$f_obj->handle) ) {
- my $file = $config->logs->$log;
-
- sysopen( $fh, $file, O_WRONLY|O_APPEND|O_CREAT )
- or warn "Cannot sysopen $log: $!";
- $fh->autoflush(1);
-
- my $obj = new OpenSRF::Utils::NetLogFile( $log, $file, $fh );
- push @file_info, $obj;
- }
-
- foreach my $line (@lines) {
- print $fh "$time $line\n" || die "$!";
- }
-
-}
-
-sub format_time {
- my ($s, $ms) = gettimeofday();
- my @time = localtime( $s );
- $ms = substr( $ms, 0, 3 );
- my $year = $time[5] + 1900;
- my $mon = $time[4] + 1;
- my $day = $time[3];
- my $hour = $time[2];
- my $min = $time[1];
- my $sec = $time[0];
- $mon = "0" . "$mon" if ( length($mon) == 1 );
- $day = "0" . "$day" if ( length($day) == 1 );
- $hour = "0" . "$hour" if ( length($hour) == 1 );
- $min = "0" . "$min" if (length($min) == 1 );
- $sec = "0" . "$sec" if (length($sec) == 1 );
-
- my $proc = $$;
- while( length( $proc ) < 5 ) { $proc = "0" . "$proc"; }
- return "[$year-$mon-$day $hour:$min:$sec.$ms $proc]";
-}
-
-
-package OpenSRF::Utils::NetLogFile;
-
-sub new{ return bless( [ $_[1], $_[2], $_[3] ], $_[0] ); }
-
-sub name { return $_[0]->[0]; }
-sub file { return $_[0]->[1]; }
-sub handle { return $_[0]->[2]; }
-
-
-1;
+++ /dev/null
-package OpenSRF::Utils::Logger;
-use strict;
-use vars qw($AUTOLOAD @EXPORT_OK %EXPORT_TAGS);
-use Exporter;
-use Unix::Syslog qw(:macros :subs);
-use base qw/OpenSRF Exporter/;
-use FileHandle;
-use Time::HiRes qw(gettimeofday);
-use OpenSRF::Utils::Config;
-use Fcntl;
-
-=head1
-
-Logger code
-
-my $logger = OpenSRF::Utils::Logger;
-$logger->error( $msg );
-
-For backwards compability, a log level may also be provided to each log
-function thereby overriding the level defined by the function.
-
-i.e. $logger->error( $msg, WARN ); # logs at log level WARN
-
-=cut
-
-@EXPORT_OK = qw/ NONE ERROR WARN INFO DEBUG INTERNAL /;
-push @EXPORT_OK, '$logger';
-
-%EXPORT_TAGS = ( level => [ qw/ NONE ERROR WARN INFO DEBUG INTERNAL / ], logger => [ '$logger' ] );
-
-my $config; # config handle
-my $loglevel; # global log level
-my $logfile; # log file
-my $facility; # syslog facility
-my $actfac; # activity log syslog facility
-my $actfile; # activity log file
-my $service = $0; # default service name
-my $syslog_enabled = 0; # is syslog enabled?
-my $act_syslog_enabled = 0; # is syslog enabled?
-my $logfile_enabled = 1; # are we logging to a file?
-my $act_logfile_enabled = 1; # are we logging to a file?
-my $logdir; # log file directory
-
-our $logger = "OpenSRF::Utils::Logger";
-
-# log levels
-sub ACTIVITY { return -1; }
-sub NONE { return 0; }
-sub ERROR { return 1; }
-sub WARN { return 2; }
-sub INFO { return 3; }
-sub DEBUG { return 4; }
-sub INTERNAL { return 5; }
-sub ALL { return 100; }
-
-my $isclient; # true if we control the osrf_xid
-
-# load up our config options
-sub set_config {
-
- return if defined $config;
-
- $config = OpenSRF::Utils::Config->current;
- if( !defined($config) ) {
- $loglevel = INFO();
- warn "*** Logger found no config. Using STDERR ***\n";
- }
-
- $loglevel = $config->bootstrap->debug;
- if($loglevel =~ /error/i){ $loglevel = ERROR(); }
- elsif($loglevel =~ /warn/i){ $loglevel = WARN(); }
- elsif($loglevel =~ /info/i){ $loglevel = INFO(); }
- elsif($loglevel =~ /debug/i){ $loglevel = DEBUG(); }
- elsif($loglevel =~ /internal/i){ $loglevel = INTERNAL(); }
- else{$loglevel= INFO(); }
-
- my $logdir = $config->bootstrap->log_dir;
-
- $logfile = $config->bootstrap->logfile;
- if($logfile =~ /^syslog/) {
- $syslog_enabled = 1;
- $logfile_enabled = 0;
- $logfile =~ s/^syslog:?//;
- $facility = $logfile;
- $logfile = undef;
- $facility = _fac_to_const($facility);
- openlog($service, 0, $facility);
-
- } else { $logfile = "$logdir/$logfile"; }
-
- $actfile = $config->bootstrap->actlog;
- if($actfile =~ /^syslog/) {
- $act_syslog_enabled = 1;
- $act_logfile_enabled = 0;
- $actfile =~ s/^syslog:?//;
- $actfac = $actfile || "local1";
- $actfile = undef;
- $actfac = _fac_to_const($actfac);
-
- } else { $actfile = "$logdir/$actfile"; }
-
- $isclient = (OpenSRF::Utils::Config->current->bootstrap->client =~ /^true$/iog) ? 1 : 0;
-}
-
-sub _fac_to_const {
- my $name = shift;
- return LOG_LOCAL0 unless $name;
- return LOG_LOCAL0 if $name =~ /local0/i;
- return LOG_LOCAL1 if $name =~ /local1/i;
- return LOG_LOCAL2 if $name =~ /local2/i;
- return LOG_LOCAL3 if $name =~ /local3/i;
- return LOG_LOCAL4 if $name =~ /local4/i;
- return LOG_LOCAL5 if $name =~ /local5/i;
- return LOG_LOCAL6 if $name =~ /local6/i;
- return LOG_LOCAL7 if $name =~ /local7/i;
- return LOG_LOCAL0;
-}
-
-sub is_syslog {
- set_config();
- return $syslog_enabled;
-}
-
-sub is_act_syslog {
- set_config();
- return $act_syslog_enabled;
-}
-
-sub is_filelog {
- set_config();
- return $logfile_enabled;
-}
-
-sub is_act_filelog {
- set_config();
- return $act_logfile_enabled;
-}
-
-sub set_service {
- my( $self, $svc ) = @_;
- $service = $svc;
- if( is_syslog() ) {
- closelog();
- openlog($service, 0, $facility);
- }
-}
-
-sub error {
- my( $self, $msg, $level ) = @_;
- $level = ERROR() unless defined ($level);
- _log_message( $msg, $level );
-}
-
-sub warn {
- my( $self, $msg, $level ) = @_;
- $level = WARN() unless defined ($level);
- _log_message( $msg, $level );
-}
-
-sub info {
- my( $self, $msg, $level ) = @_;
- $level = INFO() unless defined ($level);
- _log_message( $msg, $level );
-}
-
-sub debug {
- my( $self, $msg, $level ) = @_;
- $level = DEBUG() unless defined ($level);
- _log_message( $msg, $level );
-}
-
-sub internal {
- my( $self, $msg, $level ) = @_;
- $level = INTERNAL() unless defined ($level);
- _log_message( $msg, $level );
-}
-
-sub activity {
- my( $self, $msg ) = @_;
- _log_message( $msg, ACTIVITY() );
-}
-
-# for backward compability
-sub transport {
- my( $self, $msg, $level ) = @_;
- $level = DEBUG() unless defined ($level);
- _log_message( $msg, $level );
-}
-
-
-# ----------------------------------------------------------------------
-# creates a new xid if necessary
-# ----------------------------------------------------------------------
-my $osrf_xid = '';
-my $osrf_xid_inc = 0;
-sub mk_osrf_xid {
- return unless $isclient;
- $osrf_xid_inc++;
- return $osrf_xid = "$^T${$}$osrf_xid_inc";
-}
-
-sub set_osrf_xid {
- return if $isclient; # if we're a client, we control our xid
- $osrf_xid = $_[1];
-}
-
-sub get_osrf_xid { return $osrf_xid; }
-# ----------------------------------------------------------------------
-
-
-sub _log_message {
- my( $msg, $level ) = @_;
- return if $level > $loglevel;
-
- my $l; my $n;
- my $fac = $facility;
-
- if ($level == ERROR()) {$l = LOG_ERR; $n = "ERR "; }
- elsif ($level == WARN()) {$l = LOG_WARNING; $n = "WARN"; }
- elsif ($level == INFO()) {$l = LOG_INFO; $n = "INFO"; }
- elsif ($level == DEBUG()) {$l = LOG_DEBUG; $n = "DEBG"; }
- elsif ($level == INTERNAL()) {$l = LOG_DEBUG; $n = "INTL"; }
- elsif ($level == ACTIVITY()) {$l = LOG_INFO; $n = "ACT"; $fac = $actfac; }
-
- my( undef, $file, $line_no ) = caller(1);
- $file =~ s#/.*/##og;
-
- # help syslog with the formatting
- $msg =~ s/\%/\%\%/gso if( is_act_syslog() or is_syslog() );
-
- $msg = "[$n:"."$$".":$file:$line_no:$osrf_xid] $msg";
-
- $msg = substr($msg, 0, 1536);
-
- if( $level == ACTIVITY() ) {
- if( is_act_syslog() ) { syslog( $fac | $l, $msg ); }
- elsif( is_act_filelog() ) { _write_file( $msg, 1 ); }
-
- } else {
- if( is_syslog() ) { syslog( $fac | $l, $msg ); }
- elsif( is_filelog() ) { _write_file($msg); }
- }
-}
-
-
-sub _write_file {
- my( $msg, $isact) = @_;
- my $file = $logfile;
- $file = $actfile if $isact;
- my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
- $year += 1900; $mon += 1;
- sysopen( SINK, $file, O_NONBLOCK|O_WRONLY|O_APPEND|O_CREAT )
- or die "Cannot sysopen $logfile: $!";
- binmode(SINK, ':utf8');
- print SINK "[$year-$mon-$mday $hour:$min:$sec] $service $msg\n";
- close( SINK );
-}
-
-
-
-1;
+++ /dev/null
-use strict; use warnings;
-package OpenSRF::Utils::SettingsClient;
-use OpenSRF::Utils::SettingsParser;
-use OpenSRF::System;
-use OpenSRF::AppSession;
-use OpenSRF::Utils::Config;
-use OpenSRF::EX qw(:try);
-
-use vars qw/$host_config/;
-
-
-sub new {return bless({},shift());}
-my $session;
-$host_config = undef;
-
-my $we_cache = 1;
-sub set_cache {
- my($self, $val) = @_;
- if(defined($val)) { $we_cache = $val; }
-}
-
-sub has_config {
- if($host_config) { return 1; }
- return 0;
-}
-
-
-# ------------------------------------
-# utility method for grabbing config info
-sub config_value {
- my($self,@keys) = @_;
-
-
- my $bsconfig = OpenSRF::Utils::Config->current;
- die "No bootstrap config exists. Have you bootstrapped?\n" unless $bsconfig;
- my $host = $bsconfig->env->hostname;
-
- if($we_cache) {
- if(!$host_config) { grab_host_config($host); }
- } else {
- grab_host_config($host);
- }
-
- if(!$host_config) {
- throw OpenSRF::EX::Config ("Unable to retrieve host config for $host" );
- }
-
- my $hash = $host_config;
-
- # XXX TO DO, check local config 'version',
- # call out to settings server when necessary....
- try {
- for my $key (@keys) {
- if(!ref($hash) eq 'HASH'){
- return undef;
- }
- $hash = $hash->{$key};
- }
-
- } catch Error with {
- my $e = shift;
- throw OpenSRF::EX::Config ("No Config information for @keys : $e : $@");
- };
-
- return $hash;
-
-}
-
-
-# XXX make smarter and more robust...
-sub grab_host_config {
-
- my $host = shift;
-
- $session = OpenSRF::AppSession->create( "opensrf.settings" ) unless $session;
- my $bsconfig = OpenSRF::Utils::Config->current;
-
- my $resp;
- my $req;
- try {
-
- if( ! ($session->connect()) ) {die "Settings Connect timed out\n";}
- $req = $session->request( "opensrf.settings.host_config.get", $host );
- $resp = $req->recv( timeout => 10 );
-
- } catch OpenSRF::EX with {
-
- if( ! ($session->connect()) ) {die "Settings Connect timed out\n";}
- $req = $session->request( "opensrf.settings.default_config.get" );
- $resp = $req->recv( timeout => 10 );
-
- } catch Error with {
-
- my $e = shift;
- warn "Connection to Settings Failed $e : $@ ***\n";
- die $e;
-
- } otherwise {
-
- my $e = shift;
- warn "Settings Retrieval Failed $e : $@ ***\n";
- die $e;
- };
-
- if(!$resp) {
- warn "No Response from settings server...going to sleep\n";
- sleep;
- }
-
- if( $resp && UNIVERSAL::isa( $resp, "OpenSRF::EX" ) ) {
- throw $resp;
- }
-
- $host_config = $resp->content();
- $req->finish();
- $session->disconnect();
- $session->finish;
- $session->kill_me();
-}
-
-
-
-1;
+++ /dev/null
-use strict; use warnings;
-package OpenSRF::Utils::SettingsParser;
-use OpenSRF::Utils::Config;
-use OpenSRF::EX qw(:try);
-
-
-
-use XML::LibXML;
-
-sub DESTROY{}
-our $log = 'OpenSRF::Utils::Logger';
-my $parser;
-my $doc;
-
-sub new { return bless({},shift()); }
-
-
-# returns 0 if the config file could not be found or if there is a parse error
-# returns 1 if successful
-sub initialize {
-
- my ($self,$bootstrap_config) = @_;
- return 0 unless($self and $bootstrap_config);
-
- $parser = XML::LibXML->new();
- $parser->keep_blanks(0);
- try {
- $doc = $parser->parse_file( $bootstrap_config );
- } catch Error with {
- return 0;
- };
- return 1;
-}
-
-sub _get { _get_overlay(@_) }
-
-sub _get_overlay {
- my( $self, $xpath ) = @_;
- my @nodes = $doc->documentElement->findnodes( $xpath );
-
- my $base = XML2perl(shift(@nodes));
- my @overlays;
- for my $node (@nodes) {
- push @overlays, XML2perl($node);
- }
-
- for my $ol ( @overlays ) {
- $base = merge_perl($base, $ol);
- }
-
- return $base;
-}
-
-sub _get_all {
- my( $self, $xpath ) = @_;
- my @nodes = $doc->documentElement->findnodes( $xpath );
-
- my @overlays;
- for my $node (@nodes) {
- push @overlays, XML2perl($node);
- }
-
- return \@overlays;
-}
-
-sub merge_perl {
- my $base = shift;
- my $ol = shift;
-
- if (ref($ol)) {
- if (ref($ol) eq 'HASH') {
- for my $key (keys %$ol) {
- if (ref($$ol{$key}) and ref($$ol{$key}) eq ref($$base{$key})) {
- merge_perl($$base{$key}, $$ol{$key});
- } else {
- $$base{$key} = $$ol{$key};
- }
- }
- } else {
- for my $key (0 .. scalar(@$ol) - 1) {
- if (ref($$ol[$key]) and ref($$ol[$key]) eq ref($$base[$key])) {
- merge_perl($$base[$key], $$ol[$key]);
- } else {
- $$base[$key] = $$ol[$key];
- }
- }
- }
- } else {
- $base = $ol;
- }
-
- return $base;
-}
-
-
-sub XML2perl {
- my $node = shift;
- my %output;
-
- return undef unless($node);
-
- for my $attr ( ($node->attributes()) ) {
- next unless($attr);
- $output{$attr->nodeName} = $attr->value;
- }
-
- my @kids = $node->childNodes;
- if (@kids == 1 && $kids[0]->nodeType == 3) {
- return $kids[0]->textContent;
- } else {
- for my $kid ( @kids ) {
- next if ($kid->nodeName eq 'comment');
- if (exists $output{$kid->nodeName}) {
- if (ref $output{$kid->nodeName} ne 'ARRAY') {
- $output{$kid->nodeName} = [$output{$kid->nodeName}, XML2perl($kid)];
- } else {
- push @{$output{$kid->nodeName}}, XML2perl($kid);
- }
- next;
- }
- $output{$kid->nodeName} = XML2perl($kid);
- }
- }
-
- return \%output;
-}
-
-
-# returns the full config hash for a given server
-sub get_server_config {
- my( $self, $server ) = @_;
- my $xpath = "/opensrf/default|/opensrf/hosts/$server";
- return $self->_get( $xpath );
-}
-
-sub get_default_config {
- my( $self, $server ) = @_;
- my $xpath = "/opensrf/default";
- return $self->_get( $xpath );
-}
-
-sub get_bootstrap_config {
- my( $self ) = @_;
- my $xpath = "/opensrf/bootstrap";
- return $self->_get( $xpath );
-}
-
-sub get_router_config {
- my( $self, $router ) = @_;
- my $xpath = "/opensrf/routers/$router";
- return $self->_get($xpath );
-}
-
-
-
-
-1;
+++ /dev/null
-# OSRF_LOG_PARAMS log all incoming method params at OSRF_INFO log level.
-# OSRF_STRICT_PARAMS instructs the app handler to return an error if the number of method arguments
-# provided to any method is not at least as large as the 'argc' setting for the method
-
-CFLAGS += -rdynamic -fno-strict-aliasing -fPIC
-
-TARGETS = strndup.o strnlen.o
-HEADERS = strndup.h strnlen.h
-
-all: libfreebsd_str_compat.so $(TARGETS)
-
-libfreebsd_str_compat.so: $(TARGETS)
- $(CC) -shared -W1 $(TARGETS) -o $@
-
-strndup.o: strndup.c strndup.h
-strnlen.o: strnlen.c strnlen.h
-
-clean:
- /bin/rm -f *o
-
+++ /dev/null
-/*
- * Copyright (c) 2007 Albert Lee <trisk at acm.jhu.edu>.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "strnlen.h"
-
-char *
-strndup(const char *s, size_t n)
-{
- char *ns;
-
- n = strnlen(s, n);
-
- if ((ns = (char *)malloc(n + 1))) {
- ns[n] = '\0';
- return memcpy(ns, s, n);
- }
-
- return NULL;
-}
+++ /dev/null
-/*
- * Copyright (c) 2007 Albert Lee <trisk at acm.jhu.edu>.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-char *strndup(const char *s, size_t n);
-
+++ /dev/null
-/*
- * Copyright (c) 2007 The Akuma Project
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * $Id$
- */
-
-/*
- * sys/types.h is a Single Unix Specification header and defines size_t.
- */
-
-#include <sys/types.h>
-
-/*
- * As per the Linux manual page:
- *
- * The strnlen() function returns the number of characters in the string
- * pointed to by s, not including the terminating '\0' character, but at most
- * maxlen. In doing this, strnlen() looks only at the first maxlen characters
- * at s and never beyond s+maxlen.
- *
- * The strnlen() function returns strlen(s), if that is less than maxlen, or
- * maxlen if there is no '\0' character among the first maxlen characters
- * pointed to by s.
- */
-
-size_t
-strnlen(const char *string, size_t maxlen)
-{
- int len = 0;
-
- if (maxlen == 0)
- return (0);
-
- while (*string++ && ++len < maxlen)
- ;
-
- return (len);
-}
+++ /dev/null
-/*
- * Copyright (c) 2007 The Akuma Project
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * $Id$
- */
-
-size_t strnlen(const char *, size_t);
-
+++ /dev/null
-# -----------------------------------------------------------------------
-# Copyright (C) 2007 Georgia Public Library Service
-# Bill Erickson <billserickson@gmail.com>
-#
-# 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; either version 2
-# of the License, or (at your option) any later version.
-#
-# 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.
-# -----------------------------------------------------------------------
-
-
-from osrf.utils import *
-from osrf.ex import *
-
-class osrfConfig(object):
- """Loads and parses the bootstrap config file"""
-
- config = None
-
- def __init__(self, file=None):
- self.file = file
- self.data = {}
-
- def parseConfig(self,file=None):
- self.data = osrfXMLFileToObject(file or self.file)
- osrfConfig.config = self
-
- def getValue(self, key, idx=None):
- val = osrfObjectFindPath(self.data, key, idx)
- if not val:
- raise osrfConfigException("Config value not found: " + key)
- return val
-
-
-def osrfConfigValue(key, idx=None):
- """Returns a bootstrap config value.
-
- key -- A string representing the path to the value in the config object
- e.g. "domains.domain", "username"
- idx -- Optional array index if the searched value is an array member
- """
- return osrfConfig.config.getValue(key, idx)
-
+++ /dev/null
-# -----------------------------------------------------------------------
-# Copyright (C) 2007 Georgia Public Library Service
-# Bill Erickson <billserickson@gmail.com>
-#
-# 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; either version 2
-# of the License, or (at your option) any later version.
-#
-# 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.
-#
-#
-# Collection of global constants
-# -----------------------------------------------------------------------
-
-# -----------------------------------------------------------------------
-# log levels
-# -----------------------------------------------------------------------
-OSRF_LOG_ERR = 1
-OSRF_LOG_WARN = 2
-OSRF_LOG_INFO = 3
-OSRF_LOG_DEBUG = 4
-OSRF_LOG_INTERNAL = 5
-
-# -----------------------------------------------------------------------
-# Session states
-# -----------------------------------------------------------------------
-OSRF_APP_SESSION_CONNECTED = 0
-OSRF_APP_SESSION_CONNECTING = 1
-OSRF_APP_SESSION_DISCONNECTED = 2
-
-# -----------------------------------------------------------------------
-# OpenSRF message types
-# -----------------------------------------------------------------------
-OSRF_MESSAGE_TYPE_REQUEST = 'REQUEST'
-OSRF_MESSAGE_TYPE_STATUS = 'STATUS'
-OSRF_MESSAGE_TYPE_RESULT = 'RESULT'
-OSRF_MESSAGE_TYPE_CONNECT = 'CONNECT'
-OSRF_MESSAGE_TYPE_DISCONNECT = 'DISCONNECT'
-
-# -----------------------------------------------------------------------
-# OpenSRF message statuses
-# -----------------------------------------------------------------------
-OSRF_STATUS_CONTINUE = 100
-OSRF_STATUS_OK = 200
-OSRF_STATUS_ACCEPTED = 202
-OSRF_STATUS_COMPLETE = 205
-OSRF_STATUS_REDIRECTED = 307
-OSRF_STATUS_BADREQUEST = 400
-OSRF_STATUS_UNAUTHORIZED = 401
-OSRF_STATUS_FORBIDDEN = 403
-OSRF_STATUS_NOTFOUND = 404
-OSRF_STATUS_NOTALLOWED = 405
-OSRF_STATUS_TIMEOUT = 408
-OSRF_STATUS_EXPFAILED = 417
-OSRF_STATUS_INTERNALSERVERERROR = 500
-OSRF_STATUS_NOTIMPLEMENTED = 501
-OSRF_STATUS_VERSIONNOTSUPPORTED = 505
-
-
-# -----------------------------------------------------------------------
-# Some well-known services
-# -----------------------------------------------------------------------
-OSRF_APP_SETTINGS = 'opensrf.settings'
-OSRF_APP_MATH = 'opensrf.math'
-
-
-# where do we find the settings config
-OSRF_METHOD_GET_HOST_CONFIG = 'opensrf.settings.host_config.get'
-
-
+++ /dev/null
-# -----------------------------------------------------------------------
-# Copyright (C) 2007 Georgia Public Library Service
-# Bill Erickson <billserickson@gmail.com>
-#
-# 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; either version 2
-# of the License, or (at your option) any later version.
-#
-# 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.
-#
-#
-# This modules define the exception classes. In general, an
-# exception is little more than a name.
-# -----------------------------------------------------------------------
-
-class osrfException(Exception):
- """Root class for exceptions."""
- def __init__(self, info=None):
- self.info = info;
- def __str__(self):
- return self.info
-
-
-class osrfNetworkException(osrfException):
- def __str__(self):
- str = "\nUnable to communicate with the OpenSRF network"
- if self.info:
- str = str + '\n' + repr(self.info)
- return str
-
-class osrfProtocolException(osrfException):
- """Raised when something happens during opensrf network stack processing."""
- pass
-
-class osrfServiceException(osrfException):
- """Raised when there was an error communicating with a remote service."""
- pass
-
-class osrfConfigException(osrfException):
- """Invalid config option requested."""
- pass
-
-class osrfNetworkObjectException(osrfException):
- pass
-
-class osrfJSONParseException(osrfException):
- """Raised when a JSON parsing error occurs."""
- pass
-
-
-
+++ /dev/null
-# -----------------------------------------------------------------------
-# Copyright (C) 2007 Georgia Public Library Service
-# Bill Erickson <billserickson@gmail.com>
-#
-# 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; either version 2
-# of the License, or (at your option) any later version.
-#
-# 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.
-# -----------------------------------------------------------------------
-
-
-import simplejson, types
-from osrf.net_obj import *
-
-JSON_PAYLOAD_KEY = '__p'
-JSON_CLASS_KEY = '__c'
-
-#class osrfNetworkObject(object):
-# """Base class for serializable network objects."""
-# def getData(self):
-# """Returns a dict of data contained by this object"""
-# return self.data
-#
-#
-#class __unknown(osrfNetworkObject):
-# """Default class for un-registered network objects."""
-# def __init__(self, data=None):
-# self.data = data
-#
-#setattr(__unknown,'__keys', [])
-#setattr(osrfNetworkObject,'__unknown', __unknown)
-#
-#
-#def osrfNetworkRegisterHint(hint, keys, type='hash'):
-# """Register a network hint.
-#
-# This creates a new class at osrfNetworkObject.<hint> with
-# methods for accessing/mutating the object's data.
-# Method names will match the names found in the keys array
-#
-# hint - The hint name to encode with the object
-# type - The data container type.
-# keys - An array of data keys. If type is an 'array', the order of
-# the keys will determine how the data is accessed
-# """
-#
-# estr = "class %s(osrfNetworkObject):\n" % hint
-# estr += "\tdef __init__(self, data=None):\n"
-# estr += "\t\tself.data = data\n"
-# estr += "\t\tif data:\n"
-#
-# if type == 'hash':
-# estr += "\t\t\tpass\n"
-# else:
-# # we have to make sure the array is large enough
-# estr += "\t\t\twhile len(data) < %d:\n" % len(keys)
-# estr += "\t\t\t\tdata.append(None)\n"
-#
-# estr += "\t\telse:\n"
-#
-# if type == 'array':
-# estr += "\t\t\tself.data = []\n"
-# estr += "\t\t\tfor i in range(%s):\n" % len(keys)
-# estr += "\t\t\t\tself.data.append(None)\n"
-# for i in range(len(keys)):
-# estr += "\tdef %s(self, *args):\n"\
-# "\t\tif len(args) != 0:\n"\
-# "\t\t\tself.data[%s] = args[0]\n"\
-# "\t\treturn self.data[%s]\n" % (keys[i], i, i)
-#
-# if type == 'hash':
-# estr += "\t\t\tself.data = {}\n"
-# estr += "\t\t\tfor i in %s:\n" % str(keys)
-# estr += "\t\t\t\tself.data[i] = None\n"
-# for i in keys:
-# estr += "\tdef %s(self, *args):\n"\
-# "\t\tif len(args) != 0:\n"\
-# "\t\t\tself.data['%s'] = args[0]\n"\
-# "\t\tval = None\n"\
-# "\t\ttry: val = self.data['%s']\n"\
-# "\t\texcept: return None\n"\
-# "\t\treturn val\n" % (i, i, i)
-#
-# estr += "setattr(osrfNetworkObject, '%s', %s)\n" % (hint,hint)
-# estr += "setattr(osrfNetworkObject.%s, '__keys', keys)" % hint
-# exec(estr)
-#
-#
-#
-## -------------------------------------------------------------------
-## Define the custom object parsing behavior
-## -------------------------------------------------------------------
-#def __parseNetObject(obj):
-# hint = None
-# islist = False
-# try:
-# hint = obj[JSON_CLASS_KEY]
-# obj = obj[JSON_PAYLOAD_KEY]
-# except: pass
-# if isinstance(obj,list):
-# islist = True
-# for i in range(len(obj)):
-# obj[i] = __parseNetObject(obj[i])
-# else:
-# if isinstance(obj,dict):
-# for k,v in obj.iteritems():
-# obj[k] = __parseNetObject(v)
-#
-# if hint: # Now, "bless" the object into an osrfNetworkObject
-# estr = 'obj = osrfNetworkObject.%s(obj)' % hint
-# try:
-# exec(estr)
-# except AttributeError:
-# # this object has not been registered, shove it into the default container
-# obj = osrfNetworkObject.__unknown(obj)
-#
-# return obj;
-#
-#
-## -------------------------------------------------------------------
-# Define the custom object encoding behavior
-# -------------------------------------------------------------------
-
-class osrfJSONNetworkEncoder(simplejson.JSONEncoder):
- def default(self, obj):
- if isinstance(obj, osrfNetworkObject):
- return {
- JSON_CLASS_KEY: obj.__class__.__name__,
- JSON_PAYLOAD_KEY: self.default(obj.getData())
- }
- return obj
-
-
-def osrfObjectToJSON(obj):
- """Turns a python object into a wrapped JSON object"""
- return simplejson.dumps(obj, cls=osrfJSONNetworkEncoder)
-
-
-def osrfJSONToObject(json):
- """Turns a JSON string into python objects"""
- obj = simplejson.loads(json)
- return parseNetObject(obj)
-
-def osrfParseJSONRaw(json):
- """Parses JSON the old fashioned way."""
- return simplejson.loads(json)
-
-def osrfToJSONRaw(obj):
- """Stringifies an object as JSON with no additional logic."""
- return simplejson.dumps(obj)
-
-def __tabs(t):
- r=''
- for i in range(t): r += ' '
- return r
-
-def osrfDebugNetworkObject(obj, t=1):
- """Returns a debug string for a given object.
-
- If it's an osrfNetworkObject and has registered keys, key/value p
- pairs are returned. Otherwise formatted JSON is returned"""
-
- s = ''
- if isinstance(obj, osrfNetworkObject) and len(obj.__keys):
- obj.__keys.sort()
-
- for k in obj.__keys:
-
- key = k
- while len(key) < 24: key += '.' # pad the names to make the values line up somewhat
- val = getattr(obj, k)()
-
- subobj = val and not (isinstance(val,unicode) or \
- isinstance(val, int) or isinstance(val, float) or isinstance(val, long))
-
-
- s += __tabs(t) + key + ' = '
-
- if subobj:
- s += '\n'
- val = osrfDebugNetworkObject(val, t+1)
-
- s += str(val)
-
- if not subobj: s += '\n'
-
- else:
- s = osrfFormatJSON(osrfObjectToJSON(obj))
- return s
-
-def osrfFormatJSON(json):
- """JSON pretty-printer"""
- r = ''
- t = 0
- instring = False
- inescape = False
- done = False
-
- for c in json:
-
- done = False
- if (c == '{' or c == '[') and not instring:
- t += 1
- r += c + '\n' + __tabs(t)
- done = True
-
- if (c == '}' or c == ']') and not instring:
- t -= 1
- r += '\n' + __tabs(t) + c
- done = True
-
- if c == ',' and not instring:
- r += c + '\n' + __tabs(t)
- done = True
-
- if c == '"' and not inescape:
- instring = not instring
-
- if inescape:
- inescape = False
-
- if c == '\\':
- inescape = True
-
- if not done:
- r += c
-
- return r
-
-
+++ /dev/null
-# -----------------------------------------------------------------------
-# Copyright (C) 2007 Georgia Public Library Service
-# Bill Erickson <billserickson@gmail.com>
-#
-# 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; either version 2
-# of the License, or (at your option) any later version.
-#
-# 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.
-# -----------------------------------------------------------------------
-
-from syslog import *
-import traceback, sys, os, re
-from osrf.const import *
-
-loglevel = 4
-
-def osrfInitLog(level, facility=None, file=None):
- """Initialize the logging subsystem."""
- global loglevel
- if facility: osrfInitSyslog(facility, level)
- loglevel = level
- syslog(LOG_DEBUG, "syslog initialized")
-
-
-# -----------------------------------------------------------------------
-# Define wrapper functions for the log levels
-# -----------------------------------------------------------------------
-def osrfLogInternal(s): __osrfLog(OSRF_LOG_INTERNAL,s)
-def osrfLogDebug(s): __osrfLog(OSRF_LOG_DEBUG,s)
-def osrfLogInfo(s): __osrfLog(OSRF_LOG_INFO,s)
-def osrfLogWarn(s): __osrfLog(OSRF_LOG_WARN,s)
-def osrfLogErr(s): __osrfLog(OSRF_LOG_ERR,s)
-
-
-frgx = re.compile('/.*/')
-
-def __osrfLog(level, msg):
- """Builds the log message and passes the message off to the logger."""
- global loglevel
- if int(level) > int(loglevel): return
-
- # find the caller info for logging the file and line number
- tb = traceback.extract_stack(limit=3)
- tb = tb[0]
- lvl = 'DEBG'
- slvl = LOG_DEBUG
-
- if level == OSRF_LOG_INTERNAL: lvl = 'INT '; slvl=LOG_DEBUG
- if level == OSRF_LOG_INFO: lvl = 'INFO'; slvl=LOG_INFO
- if level == OSRF_LOG_WARN: lvl = 'WARN'; slvl=LOG_WARNING
- if level == OSRF_LOG_ERR: lvl = 'ERR '; slvl=LOG_ERR
-
- file = frgx.sub('',tb[0])
- msg = '[%s:%d:%s:%s] %s' % (lvl, os.getpid(), file, tb[1], msg)
- syslog(slvl, msg)
-
- if level == OSRF_LOG_ERR:
- sys.stderr.write(msg + '\n')
-
-
-def osrfInitSyslog(facility, level):
- """Connect to syslog and set the logmask based on the level provided."""
-
- level = int(level)
-
- if facility == 'local0': facility = LOG_LOCAL0
- if facility == 'local1': facility = LOG_LOCAL1
- if facility == 'local2': facility = LOG_LOCAL2
- if facility == 'local3': facility = LOG_LOCAL3
- if facility == 'local4': facility = LOG_LOCAL4
- if facility == 'local5': facility = LOG_LOCAL5
- if facility == 'local6': facility = LOG_LOCAL6
- # XXX add other facility maps if necessary
- openlog(sys.argv[0], 0, facility)
-
- # this is redundant...
- mask = LOG_UPTO(LOG_ERR)
- if level >= 1: mask |= LOG_MASK(LOG_WARNING)
- if level >= 2: mask |= LOG_MASK(LOG_NOTICE)
- if level >= 3: mask |= LOG_MASK(LOG_INFO)
- if level >= 4: mask |= LOG_MASK(LOG_DEBUG)
- setlogmask(mask)
-
+++ /dev/null
-# -----------------------------------------------------------------------
-# Copyright (C) 2007 Georgia Public Library Service
-# Bill Erickson <billserickson@gmail.com>
-#
-# 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; either version 2
-# of the License, or (at your option) any later version.
-#
-# 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.
-# -----------------------------------------------------------------------
-
-
-from pyxmpp.jabber.client import JabberClient
-from pyxmpp.message import Message
-from pyxmpp.jid import JID
-from socket import gethostname
-from osrf.log import *
-import os, time
-import logging
-
-# - log jabber activity (for future reference)
-#logger=logging.getLogger()
-#logger.addHandler(logging.StreamHandler())
-#logger.addHandler(logging.FileHandler('j.log'))
-#logger.setLevel(logging.DEBUG)
-
-__network = None
-def osrfSetNetworkHandle(handle):
- """Sets the global network connection handle."""
- global __network
- __network = handle
-
-def osrfGetNetworkHandle():
- """Returns the global network connection handle."""
- global __network
- return __network
-
-
-class osrfNetworkMessage(object):
- """Network message
-
- attributes:
-
- sender - message sender
- to - message recipient
- body - the body of the message
- thread - the message thread
- """
-
- def __init__(self, message=None, **args):
- if message:
- self.body = message.get_body()
- self.thread = message.get_thread()
- self.to = message.get_to()
- if message.xmlnode.hasProp('router_from') and message.xmlnode.prop('router_from') != '':
- self.sender = message.xmlnode.prop('router_from')
- else: self.sender = message.get_from().as_utf8()
- else:
- if args.has_key('sender'): self.sender = args['sender']
- if args.has_key('to'): self.to = args['to']
- if args.has_key('body'): self.body = args['body']
- if args.has_key('thread'): self.thread = args['thread']
-
-
-class osrfNetwork(JabberClient):
- def __init__(self, **args):
- self.isconnected = False
-
- # Create a unique jabber resource
- resource = 'osrf_client'
- if args.has_key('resource'):
- resource = args['resource']
- resource += '_' + gethostname()+':'+ str(os.getpid())
- self.jid = JID(args['username'], args['host'], resource)
-
- osrfLogDebug("initializing network with JID %s and host=%s, port=%s, username=%s" %
- (self.jid.as_utf8(), args['host'], args['port'], args['username']))
-
- #initialize the superclass
- JabberClient.__init__(self, self.jid, args['password'], args['host'])
- self.queue = []
-
- def connect(self):
- JabberClient.connect(self)
- while not self.isconnected:
- stream = self.get_stream()
- act = stream.loop_iter(10)
- if not act: self.idle()
-
- def setRecvCallback(self, func):
- """The callback provided is called when a message is received.
-
- The only argument to the function is the received message. """
- self.recvCallback = func
-
- def session_started(self):
- osrfLogInfo("Successfully connected to the opensrf network")
- self.authenticated()
- self.stream.set_message_handler("normal",self.message_received)
- self.isconnected = True
-
- def send(self, message):
- """Sends the provided network message."""
- osrfLogInternal("jabber sending to %s: %s" % (message.to, message.body))
- msg = Message(None, None, message.to, None, None, None, message.body, message.thread)
- self.stream.send(msg)
-
- def message_received(self, stanza):
- """Handler for received messages."""
- osrfLogInternal("jabber received a message of type %s" % stanza.get_type())
- if stanza.get_type()=="headline":
- return True
- # check for errors
- osrfLogInternal("jabber received message from %s : %s"
- % (stanza.get_from().as_utf8(), stanza.get_body()))
- self.queue.append(osrfNetworkMessage(stanza))
- return True
-
- def recv(self, timeout=120):
- """Attempts to receive a message from the network.
-
- timeout - max number of seconds to wait for a message.
- If no message is received in 'timeout' seconds, None is returned. """
-
- msg = None
- if len(self.queue) == 0:
- while timeout >= 0 and len(self.queue) == 0:
- starttime = time.time()
- osrfLogInternal("going into stream loop at " + str(starttime))
- act = self.get_stream().loop_iter(timeout)
- endtime = time.time() - starttime
- timeout -= endtime
- osrfLogInternal("exiting stream loop after %s seconds" % str(endtime))
- osrfLogInternal("act = %s : queue length = %d" % (act, len(self.queue)) )
- if not act: self.idle()
-
- # if we've acquired a message, handle it
- if len(self.queue) > 0:
- self.recvCallback(self.queue.pop(0))
- return None
-
-
-
+++ /dev/null
-# -----------------------------------------------------------------------
-# Copyright (C) 2007 Georgia Public Library Service
-#
-# 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; either version 2
-# of the License, or (at your option) any later version.
-#
-# 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.
-# -----------------------------------------------------------------------
-
-
-JSON_PAYLOAD_KEY = '__p'
-JSON_CLASS_KEY = '__c'
-
-class osrfNetworkObject(object):
- """Base class for serializable network objects."""
- def getData(self):
- """Returns a dict of data contained by this object"""
- return self.data
-
-
-class __unknown(osrfNetworkObject):
- """Default class for un-registered network objects."""
- def __init__(self, data=None):
- self.data = data
-
-setattr(__unknown,'__keys', [])
-setattr(osrfNetworkObject,'__unknown', __unknown)
-
-
-def osrfNetworkRegisterHint(hint, keys, type='hash'):
- """Register a network hint.
-
- This creates a new class at osrfNetworkObject.<hint> with
- methods for accessing/mutating the object's data.
- Method names will match the names found in the keys array
-
- hint - The hint name to encode with the object
- type - The data container type.
- keys - An array of data keys. If type is an 'array', the order of
- the keys will determine how the data is accessed
- """
-
- #
- # XXX Surely there is a cleaner way to accomplish this via
- # the PythonAPI
- #
-
- estr = "class %s(osrfNetworkObject):\n" % hint
- estr += "\tdef __init__(self, data=None):\n"
- estr += "\t\tself.data = data\n"
- estr += "\t\tif data:\n"
-
- if type == 'hash':
- estr += "\t\t\tpass\n"
- else:
- # we have to make sure the array is large enough
- estr += "\t\t\twhile len(data) < %d:\n" % len(keys)
- estr += "\t\t\t\tdata.append(None)\n"
-
- estr += "\t\telse:\n"
-
- if type == 'array':
- estr += "\t\t\tself.data = []\n"
- estr += "\t\t\tfor i in range(%s):\n" % len(keys)
- estr += "\t\t\t\tself.data.append(None)\n"
- for i in range(len(keys)):
- estr += "\tdef %s(self, *args):\n"\
- "\t\tif len(args) != 0:\n"\
- "\t\t\tself.data[%s] = args[0]\n"\
- "\t\treturn self.data[%s]\n" % (keys[i], i, i)
-
- if type == 'hash':
- estr += "\t\t\tself.data = {}\n"
- estr += "\t\t\tfor i in %s:\n" % str(keys)
- estr += "\t\t\t\tself.data[i] = None\n"
- for i in keys:
- estr += "\tdef %s(self, *args):\n"\
- "\t\tif len(args) != 0:\n"\
- "\t\t\tself.data['%s'] = args[0]\n"\
- "\t\tval = None\n"\
- "\t\ttry: val = self.data['%s']\n"\
- "\t\texcept: return None\n"\
- "\t\treturn val\n" % (i, i, i)
-
- estr += "setattr(osrfNetworkObject, '%s', %s)\n" % (hint,hint)
- estr += "setattr(osrfNetworkObject.%s, '__keys', keys)" % hint
- exec(estr)
-
-
-
-# -------------------------------------------------------------------
-# Define the custom object parsing behavior
-# -------------------------------------------------------------------
-def parseNetObject(obj):
- hint = None
- islist = False
- try:
- hint = obj[JSON_CLASS_KEY]
- obj = obj[JSON_PAYLOAD_KEY]
- except: pass
- if isinstance(obj,list):
- islist = True
- for i in range(len(obj)):
- obj[i] = parseNetObject(obj[i])
- else:
- if isinstance(obj,dict):
- for k,v in obj.iteritems():
- obj[k] = parseNetObject(v)
-
- if hint: # Now, "bless" the object into an osrfNetworkObject
- estr = 'obj = osrfNetworkObject.%s(obj)' % hint
- try:
- exec(estr)
- except AttributeError:
- # this object has not been registered, shove it into the default container
- obj = osrfNetworkObject.__unknown(obj)
-
- return obj;
-
-
-
-
+++ /dev/null
-# -----------------------------------------------------------------------
-# Copyright (C) 2007 Georgia Public Library Service
-# Bill Erickson <billserickson@gmail.com>
-#
-# 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; either version 2
-# of the License, or (at your option) any later version.
-#
-# 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.
-# -----------------------------------------------------------------------
-
-from osrf.json import *
-from osrf.net_obj import *
-from osrf.conf import osrfConfigValue
-from osrf.net import osrfNetworkMessage, osrfGetNetworkHandle
-from osrf.log import *
-from osrf.const import *
-import random, sys, os, time
-
-
-# -----------------------------------------------------------------------
-# Go ahead and register the common network objects
-# -----------------------------------------------------------------------
-osrfNetworkRegisterHint('osrfMessage', ['threadTrace', 'type', 'payload'], 'hash')
-osrfNetworkRegisterHint('osrfMethod', ['method', 'params'], 'hash')
-osrfNetworkRegisterHint('osrfResult', ['status', 'statusCode', 'content'], 'hash')
-osrfNetworkRegisterHint('osrfConnectStatus', ['status','statusCode'], 'hash')
-osrfNetworkRegisterHint('osrfMethodException', ['status', 'statusCode'], 'hash')
-
-
-class osrfSession(object):
- """Abstract session superclass."""
-
- def __init__(self):
- # by default, we're connected to no one
- self.state = OSRF_APP_SESSION_DISCONNECTED
-
-
- def wait(self, timeout=120):
- """Wait up to <timeout> seconds for data to arrive on the network"""
- osrfLogInternal("osrfSession.wait(%d)" % timeout)
- handle = osrfGetNetworkHandle()
- handle.recv(timeout)
-
- def send(self, omessage):
- """Sends an OpenSRF message"""
- netMessage = osrfNetworkMessage(
- to = self.remoteId,
- body = osrfObjectToJSON([omessage]),
- thread = self.thread )
-
- handle = osrfGetNetworkHandle()
- handle.send(netMessage)
-
- def cleanup(self):
- """Removes the session from the global session cache."""
- del osrfClientSession.sessionCache[self.thread]
-
-class osrfClientSession(osrfSession):
- """Client session object. Use this to make server requests."""
-
- def __init__(self, service):
-
- # call superclass constructor
- osrfSession.__init__(self)
-
- # the remote service we want to make requests of
- self.service = service
-
- # find the remote service handle <router>@<domain>/<service>
- domain = osrfConfigValue('domains.domain', 0)
- router = osrfConfigValue('router_name')
- self.remoteId = "%s@%s/%s" % (router, domain, service)
- self.origRemoteId = self.remoteId
-
- # generate a random message thread
- self.thread = "%s%s%s" % (os.getpid(), str(random.randint(100,100000)), str(time.time()))
-
- # how many requests this session has taken part in
- self.nextId = 0
-
- # cache of request objects
- self.requests = {}
-
- # cache this session in the global session cache
- osrfClientSession.sessionCache[self.thread] = self
-
- def resetRequestTimeout(self, rid):
- req = self.findRequest(rid)
- if req:
- req.resetTimeout = True
-
-
- def request2(self, method, arr):
- """Creates a new request and sends the request to the server using a python array as the params."""
- return self.__request(method, arr)
-
- def request(self, method, *args):
- """Creates a new request and sends the request to the server using a variable argument list as params"""
- arr = list(args)
- return self.__request(method, arr)
-
- def __request(self, method, arr):
- """Builds the request object and sends it."""
- if self.state != OSRF_APP_SESSION_CONNECTED:
- self.resetRemoteId()
-
- osrfLogDebug("Sending request %s -> %s " % (self.service, method))
- req = osrfRequest(self, self.nextId, method, arr)
- self.requests[str(self.nextId)] = req
- self.nextId += 1
- req.send()
- return req
-
-
- def connect(self, timeout=10):
- """Connects to a remote service"""
-
- if self.state == OSRF_APP_SESSION_CONNECTED:
- return True
- self.state == OSRF_APP_SESSION_CONNECTING
-
- # construct and send a CONNECT message
- self.send(
- osrfNetworkObject.osrfMessage(
- { 'threadTrace' : 0,
- 'type' : OSRF_MESSAGE_TYPE_CONNECT
- }
- )
- )
-
- while timeout >= 0 and not self.state == OSRF_APP_SESSION_CONNECTED:
- start = time.time()
- self.wait(timeout)
- timeout -= time.time() - start
-
- if self.state != OSRF_APP_SESSION_CONNECTED:
- raise osrfServiceException("Unable to connect to " + self.service)
-
- return True
-
- def disconnect(self):
- """Disconnects from a remote service"""
-
- if self.state == OSRF_APP_SESSION_DISCONNECTED:
- return True
-
- self.send(
- osrfNetworkObject.osrfMessage(
- { 'threadTrace' : 0,
- 'type' : OSRF_MESSAGE_TYPE_DISCONNECT
- }
- )
- )
-
- self.state = OSRF_APP_SESSION_DISCONNECTED
-
-
-
-
- def setRemoteId(self, remoteid):
- self.remoteId = remoteid
- osrfLogInternal("Setting request remote ID to %s" % self.remoteId)
-
- def resetRemoteId(self):
- """Recovers the original remote id"""
- self.remoteId = self.origRemoteId
- osrfLogInternal("Resetting remote ID to %s" % self.remoteId)
-
- def pushResponseQueue(self, message):
- """Pushes the message payload onto the response queue
- for the request associated with the message's ID."""
- osrfLogDebug("pushing %s" % message.payload())
- try:
- self.findRequest(message.threadTrace()).pushResponse(message.payload())
- except Exception, e:
- osrfLogWarn("pushing respond to non-existent request %s : %s" % (message.threadTrace(), e))
-
- def findRequest(self, rid):
- """Returns the original request matching this message's threadTrace."""
- try:
- return self.requests[str(rid)]
- except KeyError:
- osrfLogDebug('findRequest(): non-existent request %s' % str(rid))
- return None
-
-
-
-osrfSession.sessionCache = {}
-def osrfFindSession(thread):
- """Finds a session in the global cache."""
- try:
- return osrfClientSession.sessionCache[thread]
- except: return None
-
-class osrfRequest(object):
- """Represents a single OpenSRF request.
- A request is made and any resulting respones are
- collected for the client."""
-
- def __init__(self, session, id, method=None, params=[]):
-
- self.session = session # my session handle
- self.id = id # my unique request ID
- self.method = method # method name
- self.params = params # my method params
- self.queue = [] # response queue
- self.resetTimeout = False # resets the recv timeout?
- self.complete = False # has the server told us this request is done?
- self.sendTime = 0 # local time the request was put on the wire
- self.completeTime = 0 # time the server told us the request was completed
- self.firstResponseTime = 0 # time it took for our first reponse to be received
-
- def send(self):
- """Sends a request message"""
-
- # construct the method object message with params and method name
- method = osrfNetworkObject.osrfMethod( {
- 'method' : self.method,
- 'params' : self.params
- } )
-
- # construct the osrf message with our method message embedded
- message = osrfNetworkObject.osrfMessage( {
- 'threadTrace' : self.id,
- 'type' : OSRF_MESSAGE_TYPE_REQUEST,
- 'payload' : method
- } )
-
- self.sendTime = time.time()
- self.session.send(message)
-
- def recv(self, timeout=120):
- """Waits up to <timeout> seconds for a response to this request.
-
- If a message is received in time, the response message is returned.
- Returns None otherwise."""
-
- self.session.wait(0)
-
- origTimeout = timeout
- while not self.complete and timeout >= 0 and len(self.queue) == 0:
- s = time.time()
- self.session.wait(timeout)
- timeout -= time.time() - s
- if self.resetTimeout:
- self.resetTimeout = False
- timeout = origTimeout
-
- now = time.time()
-
- # -----------------------------------------------------------------
- # log some statistics
- if len(self.queue) > 0:
- if not self.firstResponseTime:
- self.firstResponseTime = now
- osrfLogDebug("time elapsed before first response: %f" \
- % (self.firstResponseTime - self.sendTime))
-
- if self.complete:
- if not self.completeTime:
- self.completeTime = now
- osrfLogDebug("time elapsed before complete: %f" \
- % (self.completeTime - self.sendTime))
- # -----------------------------------------------------------------
-
-
- if len(self.queue) > 0:
- # we have a reponse, return it
- return self.queue.pop(0)
-
- return None
-
- def pushResponse(self, content):
- """Pushes a method response onto this requests response queue."""
- self.queue.append(content)
-
- def cleanup(self):
- """Cleans up request data from the cache.
-
- Do this when you are done with a request to prevent "leaked" cache memory."""
- del self.session.requests[str(self.id)]
-
- def setComplete(self):
- """Sets me as complete. This means the server has sent a 'request complete' message"""
- self.complete = True
-
-
-class osrfServerSession(osrfSession):
- """Implements a server-side session"""
- pass
-
-
-def osrfAtomicRequest(service, method, *args):
- ses = osrfClientSession(service)
- req = ses.request2('open-ils.cstore.direct.actor.user.retrieve', list(args)) # grab user with ID 1
- resp = req.recv()
- data = resp.content()
- req.cleanup()
- ses.cleanup()
- return data
-
-
-
+++ /dev/null
-# -----------------------------------------------------------------------
-# Copyright (C) 2007 Georgia Public Library Service
-# Bill Erickson <billserickson@gmail.com>
-#
-# 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; either version 2
-# of the License, or (at your option) any later version.
-#
-# 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.
-# -----------------------------------------------------------------------
-
-from osrf.utils import *
-from osrf.const import *
-from osrf.ex import *
-
-# global settings config object
-__conifg = None
-
-def osrfSettingsValue(path, idx=0):
- global __config
- val = osrfObjectFindPath(__config, path, idx)
- if not val:
- raise osrfConfigException("Config value not found: " + path)
- return val
-
-
-def osrfLoadSettings(hostname):
- global __config
-
- from osrf.system import osrfConnect
- from osrf.ses import osrfClientSession
-
- ses = osrfClientSession(OSRF_APP_SETTINGS)
- req = ses.request(OSRF_METHOD_GET_HOST_CONFIG, hostname)
- resp = req.recv(timeout=30)
- __config = resp.content()
- req.cleanup()
- ses.cleanup()
-
+++ /dev/null
-# -----------------------------------------------------------------------
-# Copyright (C) 2007 Georgia Public Library Service
-# Bill Erickson <billserickson@gmail.com>
-#
-# 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; either version 2
-# of the License, or (at your option) any later version.
-#
-# 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.
-# -----------------------------------------------------------------------
-
-from osrf.json import *
-from osrf.log import *
-from osrf.ex import *
-from osrf.ses import osrfFindSession, osrfClientSession, osrfServerSession
-from osrf.const import *
-from time import time
-
-
-def osrfPushStack(netMessage):
- ses = osrfFindSession(netMessage.thread)
-
- if not ses:
- # This is an incoming request from a client, create a new server session
- pass
-
- ses.setRemoteId(netMessage.sender)
-
- oMessages = osrfJSONToObject(netMessage.body)
-
- osrfLogInternal("osrfPushStack(): received %d messages" % len(oMessages))
-
- # Pass each bundled opensrf message to the message handler
- t = time()
- for m in oMessages:
- osrfHandleMessage(ses, m)
- t = time() - t
-
- if isinstance(ses, osrfServerSession):
- osrfLogInfo("Message processing duration %f" % t)
-
-def osrfHandleMessage(session, message):
-
- osrfLogInternal("osrfHandleMessage(): processing message of type %s" % message.type())
-
- if isinstance(session, osrfClientSession):
-
- if message.type() == OSRF_MESSAGE_TYPE_RESULT:
- session.pushResponseQueue(message)
- return
-
- if message.type() == OSRF_MESSAGE_TYPE_STATUS:
-
- statusCode = int(message.payload().statusCode())
- statusText = message.payload().status()
- osrfLogInternal("osrfHandleMessage(): processing STATUS, statusCode = %d" % statusCode)
-
- if statusCode == OSRF_STATUS_COMPLETE:
- # The server has informed us that this request is complete
- req = session.findRequest(message.threadTrace())
- if req:
- osrfLogInternal("marking request as complete: %d" % req.id)
- req.setComplete()
- return
-
- if statusCode == OSRF_STATUS_OK:
- # We have connected successfully
- osrfLogDebug("Successfully connected to " + session.service)
- session.state = OSRF_APP_SESSION_CONNECTED
- return
-
- if statusCode == OSRF_STATUS_CONTINUE:
- # server is telling us to reset our wait timeout and keep waiting for a response
- session.resetRequestTimeout(message.threadTrace())
- return;
-
- if statusCode == OSRF_STATUS_TIMEOUT:
- osrfLogDebug("The server did not receive a request from us in time...")
- session.state = OSRF_APP_SESSION_DISCONNECTED
- return
-
- if statusCode == OSRF_STATUS_NOTFOUND:
- osrfLogErr("Requested method was not found on the server: %s" % statusText)
- session.state = OSRF_APP_SESSION_DISCONNECTED
- raise osrfServiceException(statusText)
-
- raise osrfProtocolException("Unknown message status: %d" % statusCode)
-
-
-
-
+++ /dev/null
-# -----------------------------------------------------------------------
-# Copyright (C) 2007 Georgia Public Library Service
-# Bill Erickson <billserickson@gmail.com>
-#
-# 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; either version 2
-# of the License, or (at your option) any later version.
-#
-# 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.
-# -----------------------------------------------------------------------
-
-from osrf.conf import osrfConfig, osrfConfigValue
-from osrf.net import osrfNetwork, osrfSetNetworkHandle
-from osrf.stack import osrfPushStack
-from osrf.log import *
-from osrf.set import osrfLoadSettings
-import sys
-
-
-def osrfConnect(configFile):
- """ Connects to the opensrf network """
-
- # parse the config file
- configParser = osrfConfig(configFile)
- configParser.parseConfig()
-
- # set up logging
- osrfInitLog(osrfConfigValue('loglevel'), osrfConfigValue('syslog'))
-
- # connect to the opensrf network
- network = osrfNetwork(
- host=osrfConfigValue('domains.domain'),
- port=osrfConfigValue('port'),
- username=osrfConfigValue('username'),
- password=osrfConfigValue('passwd'))
- network.setRecvCallback(osrfPushStack)
- osrfSetNetworkHandle(network)
- network.connect()
-
- # load the domain-wide settings file
- osrfLoadSettings(osrfConfigValue('domains.domain'))
-
-
-
+++ /dev/null
-# -----------------------------------------------------------------------
-# Copyright (C) 2007 Georgia Public Library Service
-# Bill Erickson <billserickson@gmail.com>
-#
-# 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; either version 2
-# of the License, or (at your option) any later version.
-#
-# 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.
-# -----------------------------------------------------------------------
-
-import libxml2, re
-
-def osrfXMLFileToObject(filename):
- """Turns the contents of an XML file into a Python object"""
- doc = libxml2.parseFile(filename)
- xmlNode = doc.children.children
- return osrfXMLNodeToObject(xmlNode)
-
-def osrfXMLStringToObject(string):
- """Turns an XML string into a Python object"""
- doc = libxml2.parseString(string)
- xmlNode = doc.children.children
- return osrfXMLNodeToObject(xmlNode)
-
-def osrfXMLNodeToObject(xmlNode):
- """Turns an XML node into a Python object"""
- obj = {}
-
- while xmlNode:
- if xmlNode.type == 'element':
- nodeChild = xmlNode.children
- done = False
- nodeName = xmlNode.name
-
- while nodeChild:
- if nodeChild.type == 'element':
-
- # If a node has element children, create a new sub-object
- # for this node, attach an array for each type of child
- # and recursively collect the children data into the array(s)
-
- if not obj.has_key(nodeName):
- obj[nodeName] = {}
-
- sub_obj = osrfXMLNodeToObject(nodeChild);
-
- if not obj[nodeName].has_key(nodeChild.name):
- # we've encountered 1 sub-node with nodeChild's name
- obj[nodeName][nodeChild.name] = sub_obj[nodeChild.name]
-
- else:
- if isinstance(obj[nodeName][nodeChild.name], list):
- # we already have multiple sub-nodes with nodeChild's name
- obj[nodeName][nodeChild.name].append(sub_obj[nodeChild.name])
-
- else:
- # we already have 1 sub-node with nodeChild's name, make
- # it a list and append the current node
- val = obj[nodeName][nodeChild.name]
- obj[nodeName][nodeChild.name] = [ val, sub_obj[nodeChild.name] ]
-
- done = True
-
- nodeChild = nodeChild.next
-
- if not done:
- # If the node has no children, clean up the text content
- # and use that as the data
- data = re.compile('^\s*').sub('', xmlNode.content)
- data = re.compile('\s*$').sub('', data)
-
- obj[nodeName] = data
-
- xmlNode = xmlNode.next
-
- return obj
-
-
-def osrfObjectFindPath(obj, path, idx=None):
- """Searches an object along the given path for a value to return.
-
- Path separaters can be '/' or '.', '/' is tried first."""
-
- parts = []
-
- if re.compile('/').search(path):
- parts = path.split('/')
- else:
- parts = path.split('.')
-
- for part in parts:
- try:
- o = obj[part]
- except Exception:
- return None
- if isinstance(o,str):
- return o
- if isinstance(o,list):
- if( idx != None ):
- return o[idx]
- return o
- if isinstance(o,dict):
- obj = o
- else:
- return o
-
- return obj
-
-
-
-
+++ /dev/null
-#!/usr/bin/python2.4
-import os, sys, time, readline, atexit, re
-from string import *
-from osrf.system import osrfConnect
-from osrf.json import *
-from osrf.ses import osrfClientSession
-from osrf.conf import osrfConfigValue
-
-
-# -------------------------------------------------------------------
-# main listen loop
-# -------------------------------------------------------------------
-def do_loop():
- while True:
-
- try:
- #line = raw_input("srfsh% ")
- line = raw_input("\033[01;32msrfsh\033[01;34m% \033[00m")
- if not len(line):
- continue
- if lower(line) == 'exit' or lower(line) == 'quit':
- break
- parts = split(line)
-
- command = parts[0]
-
- if command == 'request':
- parts.pop(0)
- handle_request(parts)
- continue
-
- if command == 'math_bench':
- parts.pop(0)
- handle_math_bench(parts)
- continue
-
- if command == 'help':
- handle_help()
- continue
-
- if command == 'set':
- parts.pop(0)
- handle_set(parts)
-
- if command == 'get':
- parts.pop(0)
- handle_get(parts)
-
-
-
- except KeyboardInterrupt:
- print ""
-
- except EOFError:
- print "exiting..."
- sys.exit(0)
-
-
-# -------------------------------------------------------------------
-# Set env variables to control behavior
-# -------------------------------------------------------------------
-def handle_set(parts):
- m = re.compile('(.*)=(.*)').match(parts[0])
- key = m.group(1)
- val = m.group(2)
- set_var(key, val)
- print "%s = %s" % (key, val)
-
-def handle_get(parts):
- try:
- print get_var(parts[0])
- except:
- print ""
-
-
-# -------------------------------------------------------------------
-# Prints help info
-# -------------------------------------------------------------------
-def handle_help():
- print """
- help
- - show this menu
-
- math_bench <count>
- - runs <count> opensrf.math requests and reports the average time
-
- request <service> <method> [<param1>, <param2>, ...]
- - performs an opensrf request
-
- set VAR=<value>
- - sets an environment variable
-
- Environment variables:
- SRFSH_OUTPUT = pretty - print pretty JSON and key/value pairs for network objects
- = raw - print formatted JSON
- """
-
-
-
-
-# -------------------------------------------------------------------
-# performs an opesnrf request
-# -------------------------------------------------------------------
-def handle_request(parts):
- service = parts.pop(0)
- method = parts.pop(0)
- jstr = '[%s]' % join(parts)
- params = None
-
- try:
- params = osrfJSONToObject(jstr)
- except:
- print "Error parsing JSON: %s" % jstr
- return
-
- ses = osrfClientSession(service)
-
- end = None
- start = time.time()
-
- req = ses.request2(method, tuple(params))
-
-
- while True:
- resp = req.recv(timeout=120)
- if not end:
- total = time.time() - start
- if not resp: break
-
- otp = get_var('SRFSH_OUTPUT')
- if otp == 'pretty':
- print osrfDebugNetworkObject(resp.content())
- else:
- print osrfFormatJSON(osrfObjectToJSON(resp.content()))
-
- req.cleanup()
- ses.cleanup()
-
- print '-'*60
- print "Total request time: %f" % total
- print '-'*60
-
-
-def handle_math_bench(parts):
-
- count = int(parts.pop(0))
- ses = osrfClientSession('opensrf.math')
- times = []
-
- for i in range(100):
- if i % 10: sys.stdout.write('.')
- else: sys.stdout.write( str( i / 10 ) )
- print "";
-
-
- for i in range(count):
-
- starttime = time.time()
- req = ses.request('add', 1, 2)
- resp = req.recv(timeout=2)
- endtime = time.time()
-
- if resp.content() == 3:
- sys.stdout.write("+")
- sys.stdout.flush()
- times.append( endtime - starttime )
- else:
- print "What happened? %s" % str(resp.content())
-
- req.cleanup()
- if not ( (i+1) % 100):
- print ' [%d]' % (i+1)
-
- ses.cleanup()
- total = 0
- for i in times: total += i
- print "\naverage time %f" % (total / len(times))
-
-
-
-
-# -------------------------------------------------------------------
-# Defines the tab-completion handling and sets up the readline history
-# -------------------------------------------------------------------
-def setup_readline():
- class SrfshCompleter(object):
- def __init__(self, words):
- self.words = words
- self.prefix = None
-
- def complete(self, prefix, index):
- if prefix != self.prefix:
- # find all words that start with this prefix
- self.matching_words = [
- w for w in self.words if w.startswith(prefix)
- ]
- self.prefix = prefix
- try:
- return self.matching_words[index]
- except IndexError:
- return None
-
- words = 'request', 'help', 'exit', 'quit', 'opensrf.settings', 'opensrf.math', 'set'
- completer = SrfshCompleter(words)
- readline.parse_and_bind("tab: complete")
- readline.set_completer(completer.complete)
-
- histfile = os.path.join(get_var('HOME'), ".srfsh_history")
- try:
- readline.read_history_file(histfile)
- except IOError:
- pass
- atexit.register(readline.write_history_file, histfile)
-
-def do_connect():
- file = os.path.join(get_var('HOME'), ".srfsh.xml")
-
- print_green("Connecting to opensrf...")
- osrfConnect(file)
- print_red('OK\n')
-
-def load_plugins():
- # Load the user defined external plugins
- # XXX Make this a real module interface, with tab-complete words, commands, etc.
- plugins = osrfConfigValue('plugins')
- plugins = osrfConfigValue('plugins.plugin')
- if not isinstance(plugins, list):
- plugins = [plugins]
-
- for module in plugins:
- name = module['module']
- init = module['init']
- print_green("Loading module %s..." % name)
-
- try:
- str = 'from %s import %s\n%s()' % (name, init, init)
- exec(str)
- print_red('OK\n')
-
- except Exception, e:
- sys.stderr.write("\nError importing plugin %s, with init symbol %s: \n%s\n" % (name, init, e))
-
-def set_vars():
- if not get_var('SRFSH_OUTPUT'):
- set_var('SRFSH_OUTPUT', 'pretty')
-
-
-def set_var(key, val):
- os.environ[key] = val
-
-
-def get_var(key):
- try: return os.environ[key]
- except: return ''
-
-
-def print_green(str):
- sys.stdout.write("\033[01;32m")
- sys.stdout.write(str)
- sys.stdout.write("\033[00m")
- sys.stdout.flush()
-
-def print_red(str):
- sys.stdout.write("\033[01;31m")
- sys.stdout.write(str)
- sys.stdout.write("\033[00m")
- sys.stdout.flush()
-
-
-
-
-# Kick it off
-set_vars()
-setup_readline()
-do_connect()
-load_plugins()
-do_loop()
-
-
-
+++ /dev/null
-#MALLOC_CHECK_=1 # XXX debug only
-
-LDLIBS += -lxml2 -lopensrf -lobjson
-CFLAGS += -D_ROUTER
-
-all: opensrf_router
-#osrf_router
-
-install:
- cp opensrf_router $(BINDIR)
-
-#opensrf_router: router.o
-# $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) router.o -o $@
-#router.o: router.c router.h
-
-opensrf_router: osrf_router.o osrf_router_main.o
- $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) osrf_router.o osrf_router_main.o -o $@
-osrf_router.o: osrf_router.c osrf_router.h
-osrf_router_main.o: osrf_router_main.c
-
-clean:
- /bin/rm -f *.o opensrf_router
-
+++ /dev/null
-#include "osrf_router.h"
-
-#define ROUTER_SOCKFD connection->session->sock_id
-#define ROUTER_REGISTER "register"
-#define ROUTER_UNREGISTER "unregister"
-
-
-#define ROUTER_REQUEST_CLASS_LIST "opensrf.router.info.class.list"
-
-osrfRouter* osrfNewRouter(
- char* domain, char* name,
- char* resource, char* password, int port,
- osrfStringArray* trustedClients, osrfStringArray* trustedServers ) {
-
- if(!( domain && name && resource && password && port && trustedClients && trustedServers )) return NULL;
-
- osrfRouter* router = safe_malloc(sizeof(osrfRouter));
- router->domain = strdup(domain);
- router->name = strdup(name);
- router->password = strdup(password);
- router->resource = strdup(resource);
- router->port = port;
-
- router->trustedClients = trustedClients;
- router->trustedServers = trustedServers;
-
-
- router->classes = osrfNewHash();
- router->classes->freeItem = &osrfRouterClassFree;
-
- router->connection = client_init( domain, port, NULL, 0 );
-
- return router;
-}
-
-
-
-int osrfRouterConnect( osrfRouter* router ) {
- if(!router) return -1;
- int ret = client_connect( router->connection, router->name,
- router->password, router->resource, 10, AUTH_DIGEST );
- if( ret == 0 ) return -1;
- return 0;
-}
-
-
-void osrfRouterRun( osrfRouter* router ) {
- if(!(router && router->classes)) return;
-
- int routerfd = router->ROUTER_SOCKFD;
- int selectret = 0;
-
- while(1) {
-
- fd_set set;
- int maxfd = __osrfRouterFillFDSet( router, &set );
- int numhandled = 0;
-
- if( (selectret = select(maxfd + 1, &set, NULL, NULL, NULL)) < 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "Top level select call failed with errno %d", errno);
- continue;
- }
-
- /* see if there is a top level router message */
-
- if( FD_ISSET(routerfd, &set) ) {
- osrfLogDebug( OSRF_LOG_MARK, "Top router socket is active: %d", routerfd );
- numhandled++;
- osrfRouterHandleIncoming( router );
- }
-
-
- /* now check each of the connected classes and see if they have data to route */
- while( numhandled < selectret ) {
-
- osrfRouterClass* class;
- osrfHashIterator* itr = osrfNewHashIterator(router->classes);
-
- while( (class = osrfHashIteratorNext(itr)) ) {
-
- char* classname = itr->current;
-
- if( classname && (class = osrfRouterFindClass( router, classname )) ) {
-
- osrfLogDebug( OSRF_LOG_MARK, "Checking %s for activity...", classname );
-
- int sockfd = class->ROUTER_SOCKFD;
- if(FD_ISSET( sockfd, &set )) {
- osrfLogDebug( OSRF_LOG_MARK, "Socket is active: %d", sockfd );
- numhandled++;
- osrfRouterClassHandleIncoming( router, classname, class );
- }
- }
- }
-
- osrfHashIteratorFree(itr);
- }
- }
-}
-
-
-void osrfRouterHandleIncoming( osrfRouter* router ) {
- if(!router) return;
-
- transport_message* msg = NULL;
-
- //if( (msg = client_recv( router->connection, 0 )) ) {
- while( (msg = client_recv( router->connection, 0 )) ) {
-
- if( msg->sender ) {
-
- osrfLogDebug(OSRF_LOG_MARK,
- "osrfRouterHandleIncoming(): investigating message from %s", msg->sender);
-
- /* if the sender is not a trusted server, drop the message */
- int len = strlen(msg->sender) + 1;
- char domain[len];
- bzero(domain, len);
- jid_get_domain( msg->sender, domain, len - 1 );
-
- if(osrfStringArrayContains( router->trustedServers, domain))
- osrfRouterHandleMessage( router, msg );
- else
- osrfLogWarning( OSRF_LOG_MARK, "Received message from un-trusted server domain %s", msg->sender);
- }
-
- message_free(msg);
- }
-}
-
-int osrfRouterClassHandleIncoming( osrfRouter* router, char* classname, osrfRouterClass* class ) {
- if(!(router && class)) return -1;
-
- transport_message* msg;
- osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleIncoming()");
-
- while( (msg = client_recv( class->connection, 0 )) ) {
-
- osrfLogSetXid(msg->osrf_xid);
-
- if( msg->sender ) {
-
- osrfLogDebug(OSRF_LOG_MARK,
- "osrfRouterClassHandleIncoming(): investigating message from %s", msg->sender);
-
- /* if the client is not from a trusted domain, drop the message */
- int len = strlen(msg->sender) + 1;
- char domain[len];
- bzero(domain, len);
- jid_get_domain( msg->sender, domain, len - 1 );
-
- if(osrfStringArrayContains( router->trustedClients, domain)) {
-
- transport_message* bouncedMessage = NULL;
- if( msg->is_error ) {
-
- /* handle bounced message */
- if( !(bouncedMessage = osrfRouterClassHandleBounce( router, classname, class, msg )) )
- return -1; /* we have no one to send the requested message to */
-
- message_free( msg );
- msg = bouncedMessage;
- }
- osrfRouterClassHandleMessage( router, class, msg );
-
- } else {
- osrfLogWarning( OSRF_LOG_MARK, "Received client message from untrusted client domain %s", domain );
- }
- }
-
- osrfLogClearXid();
- message_free( msg );
- }
-
- return 0;
-}
-
-
-
-
-int osrfRouterHandleMessage( osrfRouter* router, transport_message* msg ) {
- if(!(router && msg)) return -1;
-
- if( !msg->router_command || !strcmp(msg->router_command,""))
- return osrfRouterHandleAppRequest( router, msg ); /* assume it's an app session level request */
-
- if(!msg->router_class) return -1;
-
- osrfRouterClass* class = NULL;
- if(!strcmp(msg->router_command, ROUTER_REGISTER)) {
- class = osrfRouterFindClass( router, msg->router_class );
-
- osrfLogInfo( OSRF_LOG_MARK, "Registering class %s", msg->router_class );
-
- if(!class) class = osrfRouterAddClass( router, msg->router_class );
-
- if(class) {
-
- if( osrfRouterClassFindNode( class, msg->sender ) )
- return 0;
- else
- osrfRouterClassAddNode( class, msg->sender );
-
- }
-
- } else if( !strcmp( msg->router_command, ROUTER_UNREGISTER ) ) {
-
- if( msg->router_class && strcmp( msg->router_class, "") ) {
- osrfLogInfo( OSRF_LOG_MARK, "Unregistering router class %s", msg->router_class );
- osrfRouterClassRemoveNode( router, msg->router_class, msg->sender );
- }
- }
-
- return 0;
-}
-
-
-
-osrfRouterClass* osrfRouterAddClass( osrfRouter* router, char* classname ) {
- if(!(router && router->classes && classname)) return NULL;
-
- osrfRouterClass* class = safe_malloc(sizeof(osrfRouterClass));
- class->nodes = osrfNewHash();
- class->itr = osrfNewHashIterator(class->nodes);
- class->nodes->freeItem = &osrfRouterNodeFree;
- class->router = router;
-
- class->connection = client_init( router->domain, router->port, NULL, 0 );
-
- if(!client_connect( class->connection, router->name,
- router->password, classname, 10, AUTH_DIGEST ) ) {
- osrfRouterClassFree( classname, class );
- return NULL;
- }
-
- osrfHashSet( router->classes, class, classname );
- return class;
-}
-
-
-int osrfRouterClassAddNode( osrfRouterClass* rclass, char* remoteId ) {
- if(!(rclass && rclass->nodes && remoteId)) return -1;
-
- osrfLogInfo( OSRF_LOG_MARK, "Adding router node for remote id %s", remoteId );
-
- osrfRouterNode* node = safe_malloc(sizeof(osrfRouterNode));
- node->count = 0;
- node->lastMessage = NULL;
- node->remoteId = strdup(remoteId);
-
- osrfHashSet( rclass->nodes, node, remoteId );
- return 0;
-}
-
-/* copy off the lastMessage, remove the offending node, send error if it's tht last node
- ? return NULL if it's the last node ?
- */
-
-transport_message* osrfRouterClassHandleBounce(
- osrfRouter* router, char* classname, osrfRouterClass* rclass, transport_message* msg ) {
-
- osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleBounce()");
-
- osrfLogInfo( OSRF_LOG_MARK, "Received network layer error message from %s", msg->sender );
- osrfRouterNode* node = osrfRouterClassFindNode( rclass, msg->sender );
- transport_message* lastSent = NULL;
-
- if( node && osrfHashGetCount(rclass->nodes) == 1 ) { /* the last node is dead */
-
- if( node->lastMessage ) {
- osrfLogWarning( OSRF_LOG_MARK, "We lost the last node in the class, responding with error and removing...");
-
- transport_message* error = message_init(
- node->lastMessage->body, node->lastMessage->subject,
- node->lastMessage->thread, node->lastMessage->router_from, node->lastMessage->recipient );
- message_set_osrf_xid(error, node->lastMessage->osrf_xid);
- set_msg_error( error, "cancel", 501 );
-
- /* send the error message back to the original sender */
- client_send_message( rclass->connection, error );
- message_free( error );
- }
-
- return NULL;
-
- } else {
-
- if( node ) {
- if( node->lastMessage ) {
- osrfLogDebug( OSRF_LOG_MARK, "Cloning lastMessage so next node can send it");
- lastSent = message_init( node->lastMessage->body,
- node->lastMessage->subject, node->lastMessage->thread, "", node->lastMessage->router_from );
- message_set_router_info( lastSent, node->lastMessage->router_from, NULL, NULL, NULL, 0 );
- message_set_osrf_xid( lastSent, node->lastMessage->osrf_xid );
- }
- } else {
-
- osrfLogInfo(OSRF_LOG_MARK, "network error occurred after we removed the class.. ignoring");
- return NULL;
- }
- }
-
- /* remove the dead node */
- osrfRouterClassRemoveNode( router, classname, msg->sender);
- return lastSent;
-}
-
-
-/**
- If we get a regular message, we send it to the next node in the list of nodes
- if we get an error, it's a bounce back from a previous attempt. We take the
- body and thread from the last sent on the node that had the bounced message
- and propogate them on to the new message being sent
- */
-int osrfRouterClassHandleMessage(
- osrfRouter* router, osrfRouterClass* rclass, transport_message* msg ) {
- if(!(router && rclass && msg)) return -1;
-
- osrfLogDebug( OSRF_LOG_MARK, "osrfRouterClassHandleMessage()");
-
- osrfRouterNode* node = osrfHashIteratorNext( rclass->itr );
- if(!node) {
- osrfHashIteratorReset(rclass->itr);
- node = osrfHashIteratorNext( rclass->itr );
- }
-
- if(node) {
-
- transport_message* new_msg= message_init( msg->body,
- msg->subject, msg->thread, node->remoteId, msg->sender );
- message_set_router_info( new_msg, msg->sender, NULL, NULL, NULL, 0 );
- message_set_osrf_xid( new_msg, msg->osrf_xid );
-
- osrfLogInfo( OSRF_LOG_MARK, "Routing message:\nfrom: [%s]\nto: [%s]",
- new_msg->router_from, new_msg->recipient );
-
- message_free( node->lastMessage );
- node->lastMessage = new_msg;
-
- if ( client_send_message( rclass->connection, new_msg ) == 0 )
- node->count++;
-
- else {
- message_prepare_xml(new_msg);
- osrfLogWarning( OSRF_LOG_MARK, "Error sending message from %s to %s\n%s",
- new_msg->sender, new_msg->recipient, new_msg->msg_xml );
- }
-
- }
-
- return 0;
-}
-
-
-int osrfRouterRemoveClass( osrfRouter* router, char* classname ) {
- if(!(router && router->classes && classname)) return -1;
- osrfLogInfo( OSRF_LOG_MARK, "Removing router class %s", classname );
- osrfHashRemove( router->classes, classname );
- return 0;
-}
-
-
-int osrfRouterClassRemoveNode(
- osrfRouter* router, char* classname, char* remoteId ) {
-
- if(!(router && router->classes && classname && remoteId)) return 0;
-
- osrfLogInfo( OSRF_LOG_MARK, "Removing router node %s", remoteId );
-
- osrfRouterClass* class = osrfRouterFindClass( router, classname );
-
- if( class ) {
-
- osrfHashRemove( class->nodes, remoteId );
- if( osrfHashGetCount(class->nodes) == 0 ) {
- osrfRouterRemoveClass( router, classname );
- return 1;
- }
-
- return 0;
- }
-
- return -1;
-}
-
-
-void osrfRouterClassFree( char* classname, void* c ) {
- if(!(classname && c)) return;
- osrfRouterClass* rclass = (osrfRouterClass*) c;
- client_disconnect( rclass->connection );
- client_free( rclass->connection );
-
- osrfHashIteratorReset( rclass->itr );
- osrfRouterNode* node;
-
- while( (node = osrfHashIteratorNext(rclass->itr)) )
- osrfRouterClassRemoveNode( rclass->router, classname, node->remoteId );
-
- osrfHashIteratorFree(rclass->itr);
- osrfHashFree(rclass->nodes);
-
- free(rclass);
-}
-
-
-void osrfRouterNodeFree( char* remoteId, void* n ) {
- if(!n) return;
- osrfRouterNode* node = (osrfRouterNode*) n;
- free(node->remoteId);
- message_free(node->lastMessage);
- free(node);
-}
-
-
-void osrfRouterFree( osrfRouter* router ) {
- if(!router) return;
-
- free(router->domain);
- free(router->name);
- free(router->resource);
- free(router->password);
-
- osrfStringArrayFree( router->trustedClients );
- osrfStringArrayFree( router->trustedServers );
-
- client_free( router->connection );
- free(router);
-}
-
-
-
-osrfRouterClass* osrfRouterFindClass( osrfRouter* router, char* classname ) {
- if(!( router && router->classes && classname )) return NULL;
- return (osrfRouterClass*) osrfHashGet( router->classes, classname );
-}
-
-
-osrfRouterNode* osrfRouterClassFindNode( osrfRouterClass* rclass, char* remoteId ) {
- if(!(rclass && remoteId)) return NULL;
- return (osrfRouterNode*) osrfHashGet( rclass->nodes, remoteId );
-}
-
-
-int __osrfRouterFillFDSet( osrfRouter* router, fd_set* set ) {
- if(!(router && router->classes && set)) return -1;
-
- FD_ZERO(set);
- int maxfd = router->ROUTER_SOCKFD;
- FD_SET(maxfd, set);
-
- int sockid;
-
- osrfRouterClass* class = NULL;
- osrfHashIterator* itr = osrfNewHashIterator(router->classes);
-
- while( (class = osrfHashIteratorNext(itr)) ) {
- char* classname = itr->current;
-
- if( classname && (class = osrfRouterFindClass( router, classname )) ) {
- sockid = class->ROUTER_SOCKFD;
-
- if( osrfUtilsCheckFileDescriptor( sockid ) ) {
-
- osrfLogWarning(OSRF_LOG_MARK,
- "Removing router class '%s' because of a bad top-level file descriptor [%d]", classname, sockid);
- osrfRouterRemoveClass( router, classname );
-
- } else {
- if( sockid > maxfd ) maxfd = sockid;
- FD_SET(sockid, set);
- }
- }
- }
-
- osrfHashIteratorFree(itr);
- return maxfd;
-}
-
-
-
-int osrfRouterHandleAppRequest( osrfRouter* router, transport_message* msg ) {
-
- int T = 32;
- osrfMessage* arr[T];
- memset(arr, 0, T );
-
- int num_msgs = osrf_message_deserialize( msg->body, arr, T );
- osrfMessage* omsg = NULL;
-
- int i;
- for( i = 0; i != num_msgs; i++ ) {
-
- if( !(omsg = arr[i]) ) continue;
-
- switch( omsg->m_type ) {
-
- case CONNECT:
- osrfRouterRespondConnect( router, msg, omsg );
- break;
-
- case REQUEST:
- osrfRouterProcessAppRequest( router, msg, omsg );
- break;
-
- default: break;
- }
-
- osrfMessageFree( omsg );
- }
-
- return 0;
-}
-
-int osrfRouterRespondConnect( osrfRouter* router, transport_message* msg, osrfMessage* omsg ) {
- if(!(router && msg && omsg)) return -1;
-
- osrfMessage* success = osrf_message_init( STATUS, omsg->thread_trace, omsg->protocol );
-
- osrfLogDebug( OSRF_LOG_MARK, "router recevied a CONNECT message from %s", msg->sender );
-
- osrf_message_set_status_info(
- success, "osrfConnectStatus", "Connection Successful", OSRF_STATUS_OK );
-
- char* data = osrf_message_serialize(success);
-
- transport_message* return_m = message_init(
- data, "", msg->thread, msg->sender, "" );
-
- client_send_message(router->connection, return_m);
-
- free(data);
- osrf_message_free(success);
- message_free(return_m);
-
- return 0;
-}
-
-
-
-int osrfRouterProcessAppRequest( osrfRouter* router, transport_message* msg, osrfMessage* omsg ) {
-
- if(!(router && msg && omsg && omsg->method_name)) return -1;
-
- osrfLogInfo( OSRF_LOG_MARK, "Router received app request: %s", omsg->method_name );
-
- jsonObject* jresponse = NULL;
- if(!strcmp( omsg->method_name, ROUTER_REQUEST_CLASS_LIST )) {
-
- int i;
- jresponse = jsonParseString("[]");
-
- osrfStringArray* keys = osrfHashKeys( router->classes );
- for( i = 0; i != keys->size; i++ )
- jsonObjectPush( jresponse, jsonNewObject(osrfStringArrayGetString( keys, i )) );
- osrfStringArrayFree(keys);
-
-
- } else {
-
- return osrfRouterHandleMethodNFound( router, msg, omsg );
- }
-
-
- osrfRouterHandleAppResponse( router, msg, omsg, jresponse );
- jsonObjectFree(jresponse);
-
- return 0;
-
-}
-
-
-
-int osrfRouterHandleMethodNFound(
- osrfRouter* router, transport_message* msg, osrfMessage* omsg ) {
-
- osrf_message* err = osrf_message_init( STATUS, omsg->thread_trace, 1);
- osrf_message_set_status_info( err,
- "osrfMethodException", "Router method not found", OSRF_STATUS_NOTFOUND );
-
- char* data = osrf_message_serialize(err);
-
- transport_message* tresponse = message_init(
- data, "", msg->thread, msg->sender, msg->recipient );
-
- client_send_message(router->connection, tresponse );
-
- free(data);
- osrf_message_free( err );
- message_free(tresponse);
- return 0;
-}
-
-
-
-int osrfRouterHandleAppResponse( osrfRouter* router,
- transport_message* msg, osrfMessage* omsg, jsonObject* response ) {
-
- if( response ) { /* send the response message */
-
- osrfMessage* oresponse = osrf_message_init(
- RESULT, omsg->thread_trace, omsg->protocol );
-
- char* json = jsonObjectToJSON(response);
- osrf_message_set_result_content( oresponse, json);
-
- char* data = osrf_message_serialize(oresponse);
- osrfLogDebug( OSRF_LOG_MARK, "Responding to client app request with data: \n%s\n", data );
-
- transport_message* tresponse = message_init(
- data, "", msg->thread, msg->sender, msg->recipient );
-
- client_send_message(router->connection, tresponse );
-
- osrfMessageFree(oresponse);
- message_free(tresponse);
- free(json);
- free(data);
- }
-
-
- /* now send the 'request complete' message */
- osrf_message* status = osrf_message_init( STATUS, omsg->thread_trace, 1);
- osrf_message_set_status_info( status, "osrfConnectStatus", "Request Complete", OSRF_STATUS_COMPLETE );
-
- char* statusdata = osrf_message_serialize(status);
-
- transport_message* sresponse = message_init(
- statusdata, "", msg->thread, msg->sender, msg->recipient );
- client_send_message(router->connection, sresponse );
-
-
- free(statusdata);
- osrfMessageFree(status);
- message_free(sresponse);
-
- return 0;
-}
-
-
-
-
+++ /dev/null
-#include <sys/select.h>
-#include <signal.h>
-#include <stdio.h>
-
-#include "opensrf/utils.h"
-#include "opensrf/log.h"
-#include "opensrf/osrf_list.h"
-#include "opensrf/osrf_hash.h"
-
-#include "opensrf/string_array.h"
-#include "opensrf/transport_client.h"
-#include "opensrf/transport_message.h"
-
-#include "opensrf/osrf_message.h"
-
-
-
-/* a router maintains a list of server classes */
-struct __osrfRouterStruct {
-
- osrfHash* classes; /* our list of server classes */
- char* domain; /* our login domain */
- char* name;
- char* resource;
- char* password;
- int port;
-
- osrfStringArray* trustedClients;
- osrfStringArray* trustedServers;
-
- transport_client* connection;
-};
-
-typedef struct __osrfRouterStruct osrfRouter;
-
-
-/* a class maintains a set of server nodes */
-struct __osrfRouterClassStruct {
- osrfRouter* router; /* our router handle */
- osrfHashIterator* itr;
- osrfHash* nodes;
- transport_client* connection;
-};
-typedef struct __osrfRouterClassStruct osrfRouterClass;
-
-/* represents a link to a single server's inbound connection */
-struct __osrfRouterNodeStruct {
- char* remoteId; /* send message to me via this login */
- int count; /* how many message have been sent to this node */
- transport_message* lastMessage;
-};
-typedef struct __osrfRouterNodeStruct osrfRouterNode;
-
-/**
- Allocates a new router.
- @param domain The jabber domain to connect to
- @param name The login name for the router
- @param resource The login resource for the router
- @param password The login password for the new router
- @param port The port to connect to the jabber server on
- @param trustedClients The array of client domains that we allow to send requests through us
- @param trustedServers The array of server domains that we allow to register, etc. with ust.
- @return The allocated router or NULL on memory error
- */
-osrfRouter* osrfNewRouter( char* domain, char* name, char* resource,
- char* password, int port, osrfStringArray* trustedClients, osrfStringArray* trustedServers );
-
-/**
- Connects the given router to the network
- */
-int osrfRouterConnect( osrfRouter* router );
-
-/**
- Waits for incoming data to route
- If this function returns, then the router's connection to the jabber server
- has failed.
- */
-void osrfRouterRun( osrfRouter* router );
-
-
-/**
- Allocates and adds a new router class handler to the router's list of handlers.
- Also connects the class handler to the network at <routername>@domain/<classname>
- @param router The current router instance
- @param classname The name of the class this node handles.
- @return 0 on success, -1 on connection error.
- */
-osrfRouterClass* osrfRouterAddClass( osrfRouter* router, char* classname );
-
-/**
- Adds a new server node to the given class.
- @param rclass The Router class to add the node to
- @param remoteId The remote login of this node
- @return 0 on success, -1 on generic error
- */
-int osrfRouterClassAddNode( osrfRouterClass* rclass, char* remoteId );
-
-
-/**
- Handles top level router messages
- @return 0 on success
- */
-int osrfRouterHandleMessage( osrfRouter* router, transport_message* msg );
-
-
-/**
- Handles class level requests
- @return 0 on success
- */
-int osrfRouterClassHandleMessage( osrfRouter* router,
- osrfRouterClass* rclass, transport_message* msg );
-
-/**
- Removes a given class from the router, freeing as it goes
- */
-int osrfRouterRemoveClass( osrfRouter* router, char* classname );
-
-/**
- Removes the given node from the class. Also, if this is that last node in the set,
- removes the class from the router
- @return 0 on successful removal with no class removal
- @return 1 on successful remove with class removal
- @return -1 error on removal
- */
-int osrfRouterClassRemoveNode( osrfRouter* router, char* classname, char* remoteId );
-
-/**
- Frees a router class object
- Takes a void* since it is freed by the hash code
- */
-void osrfRouterClassFree( char* classname, void* rclass );
-
-/**
- Frees a router node object
- Takes a void* since it is freed by the list code
- */
-void osrfRouterNodeFree( char* remoteId, void* node );
-
-
-/**
- Frees a router
- */
-void osrfRouterFree( osrfRouter* router );
-
-/**
- Finds the class associated with the given class name in the list of classes
- */
-osrfRouterClass* osrfRouterFindClass( osrfRouter* router, char* classname );
-
-/**
- Finds the router node within this class with the given remote id
- */
-osrfRouterNode* osrfRouterClassFindNode( osrfRouterClass* rclass, char* remoteId );
-
-
-/**
- Clears and populates the provided fd_set* with file descriptors
- from the router's top level connection as well as each of the
- router class connections
- @return The largest file descriptor found in the filling process
- */
-int __osrfRouterFillFDSet( osrfRouter* router, fd_set* set );
-
-
-
-/**
- Utility method for handling incoming requests to the router
- and making sure the sender is allowed.
- */
-void osrfRouterHandleIncoming( osrfRouter* router );
-
-/**
- Utility method for handling incoming requests to a router class,
- makes sure sender is a trusted client
- */
-int osrfRouterClassHandleIncoming( osrfRouter* router, char* classname, osrfRouterClass* class );
-
-/* handles case where router node is not longer reachable. copies over the
- data from the last sent message and returns a newly crafted suitable for treating
- as a newly inconing message. Removes the dead node and If there are no more
- nodes to send the new message to, returns NULL.
- */
-transport_message* osrfRouterClassHandleBounce(
- osrfRouter* router, char* classname, osrfRouterClass* rclass, transport_message* msg );
-
-
-
-/**
- handles messages that don't have a 'router_command' set. They are assumed to
- be app request messages
- */
-int osrfRouterHandleAppRequest( osrfRouter* router, transport_message* msg );
-
-
-/**
- Handles connects, disconnects, etc.
- */
-int osrfRouterHandeStatusMessage( osrfRouter* router, transport_message* msg );
-
-
-/**
- Handles REQUEST messages
- */
-int osrfRouterHandleRequestMessage( osrfRouter* router, transport_message* msg );
-
-
-
-int osrfRouterHandleAppRequest( osrfRouter* router, transport_message* msg );
-
-
-int osrfRouterRespondConnect( osrfRouter* router, transport_message* msg, osrfMessage* omsg );
-
-
-
-int osrfRouterProcessAppRequest( osrfRouter* router, transport_message* msg, osrfMessage* omsg );
-
-int osrfRouterHandleAppResponse( osrfRouter* router,
- transport_message* msg, osrfMessage* omsg, jsonObject* response );
-
-
-int osrfRouterHandleMethodNFound( osrfRouter* router, transport_message* msg, osrfMessage* omsg );
-
+++ /dev/null
-#include "osrf_router.h"
-#include "opensrf/osrfConfig.h"
-#include "opensrf/utils.h"
-#include "opensrf/log.h"
-#include <signal.h>
-
-osrfRouter* __osrfRouter = NULL;
-
-void routerSignalHandler( int signal ) {
- osrfLogWarning( OSRF_LOG_MARK, "Received signal [%d], cleaning up...", signal );
- osrfConfigCleanup();
- osrfRouterFree(__osrfRouter);
-}
-
-static int __setupRouter( char* config, char* context );
-
-
-int main( int argc, char* argv[] ) {
-
- if( argc < 3 ) {
- osrfLogError( OSRF_LOG_MARK, "Usage: %s <path_to_config_file> <config_context>", argv[0] );
- exit(0);
- }
-
- char* config = strdup( argv[1] );
- char* context = strdup( argv[2] );
- init_proc_title( argc, argv );
- set_proc_title( "OpenSRF Router" );
-
- return __setupRouter( config, context );
- free(config);
- free(context);
-
-}
-
-int __setupRouter( char* config, char* context ) {
-
- osrfLogInfo(OSRF_LOG_MARK, "Launching router with config "
- "%s and config context %s", config, context );
- osrfConfig* cfg = osrfConfigInit( config, context );
- osrfConfigSetDefaultConfig(cfg);
-
-
- char* server = osrfConfigGetValue(NULL, "/transport/server");
- char* port = osrfConfigGetValue(NULL, "/transport/port");
- char* username = osrfConfigGetValue(NULL, "/transport/username");
- char* password = osrfConfigGetValue(NULL, "/transport/password");
- char* resource = osrfConfigGetValue(NULL, "/transport/resource");
-
- /* set up the logger */
- char* level = osrfConfigGetValue(NULL, "/loglevel");
- char* log_file = osrfConfigGetValue(NULL, "/logfile");
- char* facility = osrfConfigGetValue(NULL, "/syslog");
-
- int llevel = 1;
- if(level) llevel = atoi(level);
-
- /*
- if(!log_init( llevel, log_file ))
- fprintf(stderr, "Unable to init logging, going to stderr...\n" );
- */
-
- if(!log_file) { fprintf(stderr, "Log file needed\n"); return -1; }
-
- if(!strcmp(log_file, "syslog")) {
- osrfLogInit( OSRF_LOG_TYPE_SYSLOG, "router", llevel );
- osrfLogSetSyslogFacility(osrfLogFacilityToInt(facility));
-
- } else {
- osrfLogInit( OSRF_LOG_TYPE_FILE, "router", llevel );
- osrfLogSetFile( log_file );
- }
-
- free(facility);
- free(level);
- free(log_file);
-
- osrfLogInfo( OSRF_LOG_MARK, "Router connecting as: server: %s port: %s "
- "user: %s resource: %s", server, port, username, resource );
-
- int iport = 0;
- if(port) iport = atoi( port );
-
- osrfStringArray* tclients = osrfNewStringArray(4);
- osrfStringArray* tservers = osrfNewStringArray(4);
- osrfConfigGetValueList(NULL, tservers, "/trusted_domains/server" );
- osrfConfigGetValueList(NULL, tclients, "/trusted_domains/client" );
-
- int i;
- for( i = 0; i != tservers->size; i++ )
- osrfLogInfo( OSRF_LOG_MARK, "Router adding trusted server: %s", osrfStringArrayGetString( tservers, i ) );
-
- for( i = 0; i != tclients->size; i++ )
- osrfLogInfo( OSRF_LOG_MARK, "Router adding trusted client: %s", osrfStringArrayGetString( tclients, i ) );
-
- if( tclients->size == 0 || tservers->size == 0 ) {
- osrfLogError( OSRF_LOG_MARK, "We need trusted servers and trusted client to run the router...");
- return -1;
- }
-
- osrfRouter* router = osrfNewRouter( server,
- username, resource, password, iport, tclients, tservers );
-
- signal(SIGHUP,routerSignalHandler);
- signal(SIGINT,routerSignalHandler);
- signal(SIGTERM,routerSignalHandler);
-
- if( (osrfRouterConnect(router)) != 0 ) {
- fprintf(stderr, "!!!! Unable to connect router to jabber server %s... exiting", server );
- return -1;
- }
-
- free(server); free(port);
- free(username); free(password);
-
- __osrfRouter = router;
- daemonize();
- osrfRouterRun( router );
-
- return -1;
-}
-
-
+++ /dev/null
-# if EXEC_DEFAULT is defined, then srfsh will send all unknown commands to the shell for execution
-
-LDLIBS += -lobjson -lreadline -lxml2 -lopensrf -lncurses
-LDFLAGS += -DEXEC_DEFAULT
-
-all: srfsh
-
-srfsh: srfsh.o
-srfsh.o: srfsh.c srfsh.h
-
-install:
- cp srfsh $(BINDIR)
-
-clean:
- /bin/rm -f *.o srfsh
+++ /dev/null
-#include "srfsh.h"
-
-int recv_timeout = 120;
-int is_from_script = 0;
-FILE* shell_writer = NULL;
-FILE* shell_reader = NULL;
-
-int main( int argc, char* argv[] ) {
-
- /* --------------------------------------------- */
- /* see if they have a .srfsh.xml in their home directory */
- char* home = getenv("HOME");
- int l = strlen(home) + 36;
- char fbuf[l];
- memset(fbuf, 0, l);
- sprintf(fbuf,"%s/.srfsh.xml",home);
-
- if(!access(fbuf, R_OK)) {
- if( ! osrf_system_bootstrap_client(fbuf, "srfsh") ) {
- fprintf(stderr,"Unable to bootstrap client for requests\n");
- osrfLogError( OSRF_LOG_MARK, "Unable to bootstrap client for requests");
- return -1;
- }
-
- } else {
- fprintf(stderr,"No Config file found at %s\n", fbuf );
- return -1;
- }
-
- if(argc > 1) {
- /* for now.. the first arg is used as a script file for processing */
- int f;
- if( (f = open(argv[1], O_RDONLY)) == -1 ) {
- osrfLogError( OSRF_LOG_MARK, "Unable to open file %s for reading, exiting...", argv[1]);
- return -1;
- }
-
- if(dup2(f, STDIN_FILENO) == -1) {
- osrfLogError( OSRF_LOG_MARK, "Unable to duplicate STDIN, exiting...");
- return -1;
- }
-
- close(f);
- is_from_script = 1;
- }
-
- /* --------------------------------------------- */
- load_history();
-
-
- client = osrf_system_get_transport_client();
-
- /* open the shell handle */
- shell_writer = popen( "bash", "w");
- //shell_reader = popen( "bash", "r");
-
- /* main process loop */
- char* request;
- while((request=readline(prompt))) {
-
- if( !strcasecmp(request, "exit") || !strcasecmp(request,"quit"))
- break;
-
- char* req_copy = strdup(request);
-
- parse_request( req_copy );
- if( request && strlen(request) > 1 ) {
- add_history(request);
- }
-
- free(request);
- free(req_copy);
-
- fflush(shell_writer);
- fflush(stderr);
- fflush(stdout);
- }
-
- if(history_file != NULL )
- write_history(history_file);
-
- free(request);
-
- osrf_system_shutdown();
- return 0;
-}
-
-void sig_child_handler( int s ) {
- child_dead = 1;
-}
-
-/*
-void sig_int_handler( int s ) {
- printf("\n");
- caught_sigint = 1;
- signal(SIGINT,sig_int_handler);
-}
-*/
-
-int load_history() {
-
- char* home = getenv("HOME");
- int l = strlen(home) + 24;
- char fbuf[l];
-
- memset(fbuf, 0, l);
- sprintf(fbuf,"%s/.srfsh_history",home);
- history_file = strdup(fbuf);
-
- if(!access(history_file, W_OK | R_OK )) {
- history_length = 5000;
- read_history(history_file);
- }
- return 1;
-}
-
-
-int parse_error( char* words[] ) {
-
- if( ! words )
- return 0;
-
-
- int i = 0;
- char* current;
- char buffer[256];
- memset(buffer, 0, 256);
- while( (current=words[i++]) ) {
- strcat(buffer, current);
- strcat(buffer, " ");
- }
- if( ! buffer || strlen(buffer) < 1 )
- printf("\n");
-
- fprintf( stderr, "???: %s\n", buffer );
- return 0;
-
-}
-
-
-int parse_request( char* request ) {
-
- if( request == NULL )
- return 0;
-
- int ret_val = 0;
- int i = 0;
- char* words[COMMAND_BUFSIZE];
- memset(words,0,COMMAND_BUFSIZE);
- char* req = request;
-
- char* cur_tok = strtok( req, " " );
-
- if( cur_tok == NULL )
- return 0;
-
- while(cur_tok != NULL) {
- words[i++] = cur_tok;
- cur_tok = strtok( NULL, " " );
- }
-
-
- // not sure why (strtok?), but this is necessary
- memset( words + i, 0, COMMAND_BUFSIZE - i );
-
- /* pass off to the top level command */
- if( !strcmp(words[0],"router") )
- ret_val = handle_router( words );
-
- /*
- else if( !strcmp(words[0],"time") )
- ret_val = handle_time( words );
- */
-
- else if (!strcmp(words[0],"request"))
- ret_val = handle_request( words, 0 );
-
- else if (!strcmp(words[0],"relay"))
- ret_val = handle_request( words, 1 );
-
- else if (!strcmp(words[0],"help"))
- ret_val = print_help();
-
- else if (!strcmp(words[0],"set"))
- ret_val = handle_set(words);
-
- else if (!strcmp(words[0],"print"))
- ret_val = handle_print(words);
-
- else if (!strcmp(words[0],"math_bench"))
- ret_val = handle_math(words);
-
- else if (!strcmp(words[0],"introspect"))
- ret_val = handle_introspect(words);
-
- else if (!strcmp(words[0],"login"))
- ret_val = handle_login(words);
-
- else if (words[0][0] == '!')
- ret_val = handle_exec( words, 1 );
-
- if(!ret_val) {
- #ifdef EXEC_DEFAULT
- return handle_exec( words, 0 );
- #else
- return parse_error( words );
- #endif
- }
-
- return 1;
-
-}
-
-
-int handle_introspect(char* words[]) {
-
- if(words[1] && words[2]) {
- fprintf(stderr, "--> %s\n", words[1]);
- char buf[256];
- memset(buf,0,256);
- sprintf( buf, "request %s opensrf.system.method %s", words[1], words[2] );
- return parse_request( buf );
-
- } else {
-
- if(words[1]) {
- fprintf(stderr, "--> %s\n", words[1]);
- char buf[256];
- memset(buf,0,256);
- sprintf( buf, "request %s opensrf.system.method.all", words[1] );
- return parse_request( buf );
- }
- }
-
- return 0;
-}
-
-
-int handle_login( char* words[]) {
-
- if( words[1] && words[2]) {
-
- char* username = words[1];
- char* password = words[2];
- char* type = words[3];
- char* orgloc = words[4];
- char* workstation = words[5];
- int orgloci = (orgloc) ? atoi(orgloc) : 0;
- if(!type) type = "opac";
-
- char buf[256];
- memset(buf,0,256);
-
- char buf2[256];
- memset(buf2,0,256);
-
- sprintf( buf,
- "request open-ils.auth open-ils.auth.authenticate.init \"%s\"", username );
- parse_request(buf);
-
- char* hash;
- if(last_result && last_result->_result_content) {
- jsonObject* r = last_result->_result_content;
- hash = jsonObjectGetString(r);
- } else return 0;
-
-
- char* pass_buf = md5sum(password);
-
- char both_buf[256];
- memset(both_buf,0,256);
- sprintf(both_buf,"%s%s",hash, pass_buf);
-
- char* mess_buf = md5sum(both_buf);
-
- /*
- sprintf( buf2, "request open-ils.auth open-ils.auth.authenticate.complete "
- "{ \"username\" : \"%s\", \"password\" : \"%s\", "
- "\"type\" : \"%s\", \"org\" : %d, \"workstation\": \"%s\"}",
- username, mess_buf, type, orgloci, workstation );
- */
-
- growing_buffer* argbuf = buffer_init(64);
- buffer_fadd(argbuf,
- "request open-ils.auth open-ils.auth.authenticate.complete "
- "{ \"username\" : \"%s\", \"password\" : \"%s\"", username, mess_buf );
-
- if(type) buffer_fadd( argbuf, ", \"type\" : \"%s\"", type );
- if(orgloci) buffer_fadd( argbuf, ", \"org\" : %d", orgloci );
- if(workstation) buffer_fadd( argbuf, ", \"workstation\" : \"%s\"", workstation);
- buffer_add(argbuf, "}");
-
- free(pass_buf);
- free(mess_buf);
-
- parse_request( argbuf->buf );
- buffer_free(argbuf);
-
- jsonObject* x = last_result->_result_content;
- double authtime = 0;
- if(x) {
- char* authtoken = jsonObjectGetString(
- jsonObjectGetKey(jsonObjectGetKey(x,"payload"), "authtoken"));
- authtime = jsonObjectGetNumber(
- jsonObjectGetKey(jsonObjectGetKey(x,"payload"), "authtime"));
- if(authtoken) login_session = strdup(authtoken);
- else login_session = NULL;
- }
- else login_session = NULL;
-
- printf("Login Session: %s. Session timeout: %f\n", login_session, authtime );
-
- return 1;
-
- }
-
- return 0;
-}
-
-int handle_set( char* words[]) {
-
- char* variable;
- if( (variable=words[1]) ) {
-
- char* val;
- if( (val=words[2]) ) {
-
- if(!strcmp(variable,"pretty_print")) {
- if(!strcmp(val,"true")) {
- pretty_print = 1;
- printf("pretty_print = true\n");
- return 1;
- }
- if(!strcmp(val,"false")) {
- pretty_print = 0;
- printf("pretty_print = false\n");
- return 1;
- }
- }
-
- if(!strcmp(variable,"raw_print")) {
- if(!strcmp(val,"true")) {
- raw_print = 1;
- printf("raw_print = true\n");
- return 1;
- }
- if(!strcmp(val,"false")) {
- raw_print = 0;
- printf("raw_print = false\n");
- return 1;
- }
- }
-
- }
- }
-
- return 0;
-}
-
-
-int handle_print( char* words[]) {
-
- char* variable;
- if( (variable=words[1]) ) {
- if(!strcmp(variable,"pretty_print")) {
- if(pretty_print) {
- printf("pretty_print = true\n");
- return 1;
- } else {
- printf("pretty_print = false\n");
- return 1;
- }
- }
-
- if(!strcmp(variable,"login")) {
- printf("login session = %s\n", login_session );
- return 1;
- }
-
- }
- return 0;
-}
-
-int handle_router( char* words[] ) {
-
- if(!client)
- return 1;
-
- int i;
-
- if( words[1] ) {
- if( !strcmp(words[1],"query") ) {
-
- if( words[2] && !strcmp(words[2],"servers") ) {
- for(i=3; i < COMMAND_BUFSIZE - 3 && words[i]; i++ ) {
- router_query_servers( words[i] );
- }
- return 1;
- }
- return 0;
- }
- return 0;
- }
- return 0;
-}
-
-
-/* if new shell, spawn a new child and subshell to do the work,
- otherwise pipe the request to the currently open (piped) shell */
-int handle_exec(char* words[], int new_shell) {
-
- if(!words[0]) return 0;
-
- if( words[0] && words[0][0] == '!') {
- int len = strlen(words[0]);
- char command[len];
- memset(command,0,len);
-
- int i; /* chop out the ! */
- for( i=1; i!= len; i++) {
- command[i-1] = words[0][i];
- }
-
- free(words[0]);
- words[0] = strdup(command);
- }
-
- if(new_shell) {
- signal(SIGCHLD, sig_child_handler);
-
- if(fork()) {
-
- waitpid(-1, 0, 0);
- if(child_dead) {
- signal(SIGCHLD,sig_child_handler);
- child_dead = 0;
- }
-
- } else {
- execvp( words[0], words );
- exit(0);
- }
-
- } else {
-
-
- growing_buffer* b = buffer_init(64);
- int i = 0;
- while(words[i])
- buffer_fadd( b, "%s ", words[i++] );
-
- buffer_add( b, "\n");
-
- //int reader;
- //int reader = dup2(STDOUT_FILENO, reader);
- //int reader = dup(STDOUT_FILENO);
- //close(STDOUT_FILENO);
-
- fprintf( shell_writer, b->buf );
- buffer_free(b);
-
- fflush(shell_writer);
- usleep(1000);
-
- /*
- char c[4096];
- bzero(c, 4096);
- read( reader, c, 4095 );
- fprintf(stderr, "read %s", c);
- dup2(reader, STDOUT_FILENO);
- */
-
- }
-
-
- return 1;
-}
-
-
-int handle_request( char* words[], int relay ) {
-
- if(!client)
- return 1;
-
- if(words[1]) {
- char* server = words[1];
- char* method = words[2];
- int i;
- growing_buffer* buffer = NULL;
- if(!relay) {
- buffer = buffer_init(128);
- buffer_add(buffer, "[");
- for(i = 3; words[i] != NULL; i++ ) {
- /* removes trailing semicolon if user accidentally enters it */
- if( words[i][strlen(words[i])-1] == ';' )
- words[i][strlen(words[i])-1] = '\0';
- buffer_add( buffer, words[i] );
- buffer_add(buffer, " ");
- }
- buffer_add(buffer, "]");
- }
-
- return send_request( server, method, buffer, relay );
- }
-
- return 0;
-}
-
-int send_request( char* server,
- char* method, growing_buffer* buffer, int relay ) {
- if( server == NULL || method == NULL )
- return 0;
-
- jsonObject* params = NULL;
- if( !relay ) {
- if( buffer != NULL && buffer->n_used > 0 )
- params = json_parse_string(buffer->buf);
- } else {
- if(!last_result || ! last_result->_result_content) {
- printf("We're not going to call 'relay' with no result params\n");
- return 1;
- }
- else {
- jsonObject* o = jsonNewObject(NULL);
- jsonObjectPush(o, last_result->_result_content );
- params = o;
- }
- }
-
-
- if(buffer->n_used > 0 && params == NULL) {
- fprintf(stderr, "JSON error detected, not executing\n");
- return 1;
- }
-
- osrf_app_session* session = osrf_app_client_session_init(server);
-
- if(!osrf_app_session_connect(session)) {
- osrfLogWarning( OSRF_LOG_MARK, "Unable to connect to remote service %s\n", server );
- return 1;
- }
-
- double start = get_timestamp_millis();
- //int req_id = osrf_app_session_make_request( session, params, method, 1, NULL );
- int req_id = osrf_app_session_make_req( session, params, method, 1, NULL );
-
-
- osrf_message* omsg = osrf_app_session_request_recv( session, req_id, recv_timeout );
-
- if(!omsg)
- printf("\nReceived no data from server\n");
-
-
- signal(SIGPIPE, SIG_IGN);
-
- FILE* less;
- if(!is_from_script) less = popen( "less -EX", "w");
- else less = stdout;
-
- if( less == NULL ) { less = stdout; }
-
- growing_buffer* resp_buffer = buffer_init(4096);
-
- while(omsg) {
-
- if(raw_print) {
-
- if(omsg->_result_content) {
-
- osrf_message_free(last_result);
- last_result = omsg;
-
- char* content;
-
- if( pretty_print && omsg->_result_content ) {
- char* j = jsonObjectToJSON(omsg->_result_content);
- //content = json_printer(j);
- content = jsonFormatString(j);
- free(j);
- } else
- content = jsonObjectGetString(omsg->_result_content);
-
- printf( "\nReceived Data: %s\n", content );
- free(content);
-
- } else {
-
- char code[16];
- memset(code, 0, 16);
- sprintf( code, "%d", omsg->status_code );
- buffer_add( resp_buffer, code );
-
- printf( "\nReceived Exception:\nName: %s\nStatus: %s\nStatus: %s\n",
- omsg->status_name, omsg->status_text, code );
-
- fflush(stdout);
- }
-
- } else {
-
- if(omsg->_result_content) {
-
- osrf_message_free(last_result);
- last_result = omsg;
-
- char* content;
-
- if( pretty_print && omsg->_result_content ) {
- char* j = jsonObjectToJSON(omsg->_result_content);
- //content = json_printer(j);
- content = jsonFormatString(j);
- free(j);
- } else
- content = jsonObjectGetString(omsg->_result_content);
-
- buffer_add( resp_buffer, "\nReceived Data: " );
- buffer_add( resp_buffer, content );
- buffer_add( resp_buffer, "\n" );
- free(content);
-
- } else {
-
- buffer_add( resp_buffer, "\nReceived Exception:\nName: " );
- buffer_add( resp_buffer, omsg->status_name );
- buffer_add( resp_buffer, "\nStatus: " );
- buffer_add( resp_buffer, omsg->status_text );
- buffer_add( resp_buffer, "\nStatus: " );
- char code[16];
- memset(code, 0, 16);
- sprintf( code, "%d", omsg->status_code );
- buffer_add( resp_buffer, code );
- }
- }
-
-
- omsg = osrf_app_session_request_recv( session, req_id, recv_timeout );
-
- }
-
- double end = get_timestamp_millis();
-
- fprintf( less, resp_buffer->buf );
- buffer_free( resp_buffer );
- fprintf( less, "\n------------------------------------\n");
- if( osrf_app_session_request_complete( session, req_id ))
- fprintf(less, "Request Completed Successfully\n");
-
-
- fprintf(less, "Request Time in seconds: %.6f\n", end - start );
- fprintf(less, "------------------------------------\n");
-
- pclose(less);
-
- osrf_app_session_request_finish( session, req_id );
- osrf_app_session_disconnect( session );
- osrf_app_session_destroy( session );
-
-
- return 1;
-
-
-}
-
-/*
-int handle_time( char* words[] ) {
-
- if( ! words[1] ) {
-
- char buf[36];
- memset(buf,0,36);
- get_timestamp(buf);
- printf( "%s\n", buf );
- return 1;
- }
-
- if( words[1] ) {
- time_t epoch = (time_t)atoi( words[1] );
- char* localtime = strdup( ctime( &epoch ) );
- printf( "%s => %s", words[1], localtime );
- free(localtime);
- return 1;
- }
-
- return 0;
-
-}
-*/
-
-
-
-int router_query_servers( char* router_server ) {
-
- if( ! router_server || strlen(router_server) == 0 )
- return 0;
-
- char rbuf[256];
- memset(rbuf,0,256);
- sprintf(rbuf,"router@%s/router", router_server );
-
- transport_message* send =
- message_init( "servers", NULL, NULL, rbuf, NULL );
- message_set_router_info( send, NULL, NULL, NULL, "query", 0 );
-
- client_send_message( client, send );
- message_free( send );
-
- transport_message* recv = client_recv( client, -1 );
- if( recv == NULL ) {
- fprintf(stderr, "NULL message received from router\n");
- return 1;
- }
-
- printf(
- "---------------------------------------------------------------------------------\n"
- "Received from 'server' query on %s\n"
- "---------------------------------------------------------------------------------\n"
- "original reg time | latest reg time | last used time | class | server\n"
- "---------------------------------------------------------------------------------\n"
- "%s"
- "---------------------------------------------------------------------------------\n"
- , router_server, recv->body );
-
- message_free( recv );
-
- return 1;
-}
-
-int print_help() {
-
- printf(
- "---------------------------------------------------------------------------------\n"
- "Commands:\n"
- "---------------------------------------------------------------------------------\n"
- "help - Display this message\n"
- "!<command> [args] - Forks and runs the given command in the shell\n"
- "time - Prints the current time\n"
- "time <timestamp> - Formats seconds since epoch into readable format\n"
- "set <variable> <value> - set a srfsh variable (e.g. set pretty_print true )\n"
- "print <variable> - Displays the value of a srfsh variable\n"
- "---------------------------------------------------------------------------------\n"
-
- "router query servers <server1 [, server2, ...]>\n"
- " - Returns stats on connected services\n"
- "\n"
- "\n"
- "request <service> <method> [ <json formatted string of params> ]\n"
- " - Anything passed in will be wrapped in a json array,\n"
- " so add commas if there is more than one param\n"
- "\n"
- "\n"
- "relay <service> <method>\n"
- " - Performs the requested query using the last received result as the param\n"
- "\n"
- "\n"
- "math_bench <num_batches> [0|1|2]\n"
- " - 0 means don't reconnect, 1 means reconnect after each batch of 4, and\n"
- " 2 means reconnect after every request\n"
- "\n"
- "introspect <service>\n"
- " - prints the API for the service\n"
- "\n"
- "\n"
- "---------------------------------------------------------------------------------\n"
- " Commands for Open-ILS\n"
- "---------------------------------------------------------------------------------\n"
- "login <username> <password>\n"
- " - Logs into the 'server' and displays the session id\n"
- " - To view the session id later, enter: print login\n"
- "---------------------------------------------------------------------------------\n"
- "\n"
- "\n"
- "Note: long output is piped through 'less'. To search in 'less', type: /<search>\n"
- "---------------------------------------------------------------------------------\n"
- "\n"
- );
-
- return 1;
-}
-
-
-
-char* tabs(int count) {
- growing_buffer* buf = buffer_init(24);
- int i;
- for(i=0;i!=count;i++)
- buffer_add(buf, " ");
-
- char* final = buffer_data( buf );
- buffer_free( buf );
- return final;
-}
-
-int handle_math( char* words[] ) {
- if( words[1] )
- return do_math( atoi(words[1]), 0 );
- return 0;
-}
-
-
-int do_math( int count, int style ) {
-
- osrf_app_session* session = osrf_app_client_session_init( "opensrf.math" );
- osrf_app_session_connect(session);
-
- jsonObject* params = json_parse_string("[]");
- jsonObjectPush(params,jsonNewObject("1"));
- jsonObjectPush(params,jsonNewObject("2"));
-
- char* methods[] = { "add", "sub", "mult", "div" };
- char* answers[] = { "3", "-1", "2", "0.500000" };
-
- float times[ count * 4 ];
- memset(times,0,count*4);
-
- int k;
- for(k=0;k!=100;k++) {
- if(!(k%10))
- fprintf(stderr,"|");
- else
- fprintf(stderr,".");
- }
-
- fprintf(stderr,"\n\n");
-
- int running = 0;
- int i;
- for(i=0; i!= count; i++) {
-
- int j;
- for(j=0; j != 4; j++) {
-
- ++running;
-
- double start = get_timestamp_millis();
- int req_id = osrf_app_session_make_req( session, params, methods[j], 1, NULL );
- osrf_message* omsg = osrf_app_session_request_recv( session, req_id, 5 );
- double end = get_timestamp_millis();
-
- times[(4*i) + j] = end - start;
-
- if(omsg) {
-
- if(omsg->_result_content) {
- char* jsn = jsonObjectToJSON(omsg->_result_content);
- if(!strcmp(jsn, answers[j]))
- fprintf(stderr, "+");
- else
- fprintf(stderr, "\n![%s] - should be %s\n", jsn, answers[j] );
- free(jsn);
- }
-
-
- osrf_message_free(omsg);
-
- } else { fprintf( stderr, "\nempty message for tt: %d\n", req_id ); }
-
- osrf_app_session_request_finish( session, req_id );
-
- if(style == 2)
- osrf_app_session_disconnect( session );
-
- if(!(running%100))
- fprintf(stderr,"\n");
- }
-
- if(style==1)
- osrf_app_session_disconnect( session );
- }
-
- osrf_app_session_destroy( session );
- jsonObjectFree(params);
-
- int c;
- float total = 0;
- for(c=0; c!= count*4; c++)
- total += times[c];
-
- float avg = total / (count*4);
- fprintf(stderr, "\n Average round trip time: %f\n", avg );
-
- return 1;
-}
+++ /dev/null
-#include "opensrf/transport_client.h"
-#include "opensrf/osrf_message.h"
-#include "opensrf/osrf_app_session.h"
-#include <time.h>
-#include <sys/timeb.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include "utils.h"
-#include "log.h"
-
-#include <signal.h>
-
-#include <stdio.h>
-#include <readline/readline.h>
-#include <readline/history.h>
-
-
-
-
-#define SRFSH_PORT 5222
-#define COMMAND_BUFSIZE 4096
-
-
-/* shell prompt */
-char* prompt = "srfsh# ";
-
-char* history_file = NULL;
-
-int child_dead = 0;
-
-char* login_session = NULL;
-
-/* true if we're pretty printing json results */
-int pretty_print = 1;
-/* true if we're bypassing 'less' */
-int raw_print = 0;
-
-/* our jabber connection */
-transport_client* client = NULL;
-
-/* the last result we received */
-osrf_message* last_result = NULL;
-
-/* functions */
-int parse_request( char* request );
-
-/* handles router requests */
-int handle_router( char* words[] );
-
-/* utility method for print time data */
-int handle_time( char* words[] );
-
-/* handles app level requests */
-int handle_request( char* words[], int relay );
-int handle_exec(char* words[], int new_shell);
-int handle_set( char* words[]);
-int handle_print( char* words[]);
-int send_request( char* server,
- char* method, growing_buffer* buffer, int relay );
-int parse_error( char* words[] );
-int router_query_servers( char* server );
-int srfsh_client_connect();
-int print_help();
-char* tabs(int count);
-void sig_child_handler( int s );
-void sig_int_handler( int s );
-
-int load_history();
-int handle_math( char* words[] );
-int do_math( int count, int style );
-int handle_introspect(char* words[]);
-int handle_login( char* words[]);
+++ /dev/null
-
-UTIL_HEADERS = md5.h log.h utils.h socket_bundle.h sha.h string_array.h xml_utils.h
-UTIL_OBJECTS = md5.o log.o utils.o socket_bundle.o sha.o string_array.o
-
-all: $(UTIL_OBJECTS) copy
-
-copy:
- cp $(UTIL_HEADERS) $(TMPDIR)
-
-log.o: log.c log.h
-utils.o: utils.c utils.h
-socket_bundle.o: socket_bundle.c socket_bundle.h
-md5.o: md5.c md5.h
-sha.o: sha.c sha.h
-string_array.o: string_array.c string_array.h
-
-
-clean:
- /bin/rm -f *.o
-
-
+++ /dev/null
-#!/usr/bin/perl
-use strict; use warnings;
-use Data::Dumper;
-use OpenILS::Utils::Fieldmapper;
-
-
-if(!$ARGV[1]) {
- print "usage: $0 <header_file> <source_file>\n";
- exit;
-}
-
-warn "Generating fieldmapper-c code...\n";
-
-#open(HEADER, ">fieldmapper.h");
-#open(SOURCE, ">fieldmapper.c");
-
-print $ARGV[0] . "\n";
-print $ARGV[1] . "\n";
-
-open(HEADER, ">$ARGV[0]");
-open(SOURCE, ">$ARGV[1]");
-
-my $map = $Fieldmapper::fieldmap;
-
-print HEADER <<C;
-
-#include "objson/object.h"
-#include "objson/json_parser.h"
-#include "utils.h"
-
-/* Fieldmapper-C. Autogenerated from fieldmapper-c.pl.\n\nNote that object*'s passed in as
-constructor parameters are copied in so the originals will need to be freed*/
-
-/* fm_obj is the generic placeholder object */
-struct fm_obj_struct {
- char* classname;
- object* array;
-};
-typedef struct fm_obj_struct fm_obj;
-
-/* takes a json object and builds a fieldmapper object. the object
- is then cast into an fm_obj and returned. To verify an object is
- what is expected, check fm_obj_thing->classname. */
-fm_obj* fm_factory(object*);
-
-/* builds a new fieldmapper object by class name */
-fm_obj* fm_factory_string(char*);
-
-void fm_free(fm_obj* fm);
-C
-
-print SOURCE <<C;
-#include "fieldmapper.h"
-
-void fm_free(fm_obj* fm) {
- if(!fm) return;
- free_object(fm->array);
- free(fm);
-}
-C
-
-my $factory_string = <<C;
-fm_obj* fm_factory(object* obj) {
-
- if(!obj) return NULL;
- if(!obj->classname) return NULL;
- fm_obj* fm = NULL;
-
-C
-
-my $fstring_string = <<C;
-fm_obj* fm_factory_string(char* string) {
- if(!string) return NULL;
- object* obj = new_object(NULL);
- object* tmp = NULL;
-C
-
-for my $object (keys %$map) {
-
- my $short_name = $map->{$object}->{hint};
- my $func_header_string = "";
- my $func_code_string = "";
- my $constructor_string = "";
-
- $factory_string .= <<CODE;
- if(!strcmp(obj->classname,"$short_name"))
- fm = (fm_obj*) fm_new_$short_name(obj);
-CODE
-
- $fstring_string .= <<CODE;
- if(!strcmp(string, "$short_name")) {
- obj->set_class(obj, "$short_name");
-CODE
-
- my $header_string = <<CODE;
-struct fm_${short_name}_struct {
- char* classname;
- object* array;
- char*\t\t(*to_string) (struct fm_${short_name}_struct*);
-CODE
-
- $func_header_string .= <<CODE;
-char* fm_${short_name}_to_string(fm_$short_name*);
-CODE
-
- my $to_string = <<CODE;
-char* fm_${short_name}_to_string(fm_$short_name* fm) {
- if(!fm || !fm->array) return NULL;
- growing_buffer* buf = buffer_init(256);
- buffer_fadd(buf, "%s => {\\n", fm->classname);
- object* o;
-CODE
-
- $constructor_string .= <<CODE;
-fm_$short_name* fm_new_$short_name(object* obj_array) {
-
- fm_$short_name* fm = (fm_$short_name*) safe_malloc(sizeof(fm_$short_name));
-
- /* build an empty array object */
- if(!obj_array) {
- fm->array = new_object(NULL);
- fm->array->is_array = 1;
- fm->array->set_class(fm->array, "$short_name");
-
- } else {
-
- /* we don't want invalid objects */
- if (!obj_array->classname) return NULL;
- if(strcmp(obj_array->classname, "$short_name")) return NULL;
-
- char* s = obj_array->to_json(obj_array);
- fm->array = json_parse_string(s);
- free(s);
- }
-
- fm->classname = fm->array->classname;
- fm->to_string = &fm_${short_name}_to_string;
-CODE
-
- for my $field (keys %{$map->{$object}->{fields}}) {
- my $position = $map->{$object}->{fields}->{$field}->{position};
-
- $to_string .= <<CODE;
- o = fm->array->get_index(fm->array, $position);
- if(o) {
- char* str = o->to_json(o);
- buffer_fadd(buf, " $field\\t: %s\\n", str);
- free(str);
- };
-CODE
-
- $fstring_string .= <<CODE;
- tmp = new_object(NULL);
- tmp->is_null = 1;
- obj->set_index(obj, $position, tmp);
-CODE
-
- $header_string .= <<CODE;
- object*\t(*get_$field) (struct fm_${short_name}_struct*);
- void\t\t(*set_$field) (struct fm_${short_name}_struct*, object*);
-CODE
-
- $constructor_string .= <<CODE;
- fm->set_$field = &fm_${short_name}_set_$field;
- fm->get_$field = &fm_${short_name}_get_$field;
-CODE
-
- $func_header_string .= <<CODE;
-object* fm_${short_name}_get_$field(fm_$short_name*);
-void fm_${short_name}_set_$field(fm_$short_name*, object*);
-CODE
-
- $func_code_string .= <<CODE
- object* fm_${short_name}_get_$field(fm_$short_name* fm) {
- if(!fm || !fm->array) return NULL;
- return fm->array->get_index(fm->array, $position);
- }
-
- void fm_${short_name}_set_$field(fm_$short_name* fm, object* obj) {
- if(!fm || !fm->array || !obj) return;
- fm->array->set_index(fm->array, $position, obj);
- }
-CODE
-
- }
-
- $fstring_string .= <<CODE;
- return (fm_obj*) fm_new_$short_name(obj);
- }
-CODE
-
- $to_string .= <<CODE;
- buffer_add(buf,"}\\n");
- char* b = buffer_data(buf);
- buffer_free(buf);
- return b;
-}
-CODE
-
- $constructor_string .= "\treturn fm;\n}\n";
- $header_string .= "};\n";
- $func_code_string = $constructor_string . $to_string . $func_code_string;
-
- $header_string .= "typedef struct fm_$short_name"."_struct fm_$short_name;\n\n";
- $header_string .= "fm_$short_name* fm_new_$short_name(object*);\n";
- $header_string .= "$func_header_string\n";
-
- print HEADER "\n$header_string\n";
- print SOURCE "\n$func_code_string\n";
-
-
-}
-
-$factory_string .= "\treturn fm;\n}\n";
-#$fstring_string .= "\treturn NULL;\n}\n";
-$fstring_string .= <<CODE;
- free_object(obj);
- return NULL;
-}
-CODE
-
-print SOURCE "\n$factory_string\n";
-print SOURCE "\n$fstring_string\n";
-
-close HEADER;
-close SOURCE;
-
-warn "done\n";
-
+++ /dev/null
-#include "log.h"
-
-int __osrfLogType = -1;
-int __osrfLogFacility = LOG_LOCAL0;
-int __osrfLogActFacility = LOG_LOCAL1;
-char* __osrfLogFile = NULL;
-char* __osrfLogAppname = NULL;
-int __osrfLogLevel = OSRF_LOG_INFO;
-int __osrfLogActivityEnabled = 1;
-int __osrfLogIsClient = 0;
-
-
-int __osrfLogXidInc = 0; /* increments with each new xid for uniqueness */
-char* __osrfLogXid = NULL; /* current xid */
-char* __osrfLogXidPfx = NULL; /* xid prefix string */
-
-
-void osrfLogCleanup() {
- free(__osrfLogAppname);
- free(__osrfLogFile);
-}
-
-
-void osrfLogInit( int type, const char* appname, int maxlevel ) {
- osrfLogSetType(type);
- if(appname) osrfLogSetAppname(appname);
- osrfLogSetLevel(maxlevel);
- if( type == OSRF_LOG_TYPE_SYSLOG )
- openlog(__osrfLogAppname, 0, __osrfLogFacility );
-}
-
-static void __osrfLogSetXid(char* xid) {
- if(xid) {
- if(__osrfLogXid) free(__osrfLogXid);
- __osrfLogXid = strdup(xid);
- }
-}
-
-void osrfLogClearXid() { __osrfLogSetXid(""); }
-void osrfLogSetXid(char* xid) {
- if(!__osrfLogIsClient) __osrfLogSetXid(xid);
-}
-
-void osrfLogMkXid() {
- if(__osrfLogIsClient) {
- char buf[32];
- memset(buf, 0x0, 32);
- snprintf(buf, 32, "%s%d", __osrfLogXidPfx, __osrfLogXidInc);
- __osrfLogSetXid(buf);
- __osrfLogXidInc++;
- }
-}
-
-char* osrfLogGetXid() {
- return __osrfLogXid;
-}
-
-void osrfLogSetIsClient(int is) {
- __osrfLogIsClient = is;
- if(!is) return;
- /* go ahead and create the xid prefix so it will be consistent later */
- static char buff[32];
- memset(buff, 0x0, 32);
- snprintf(buff, 32, "%d%ld", (int)time(NULL), (long) getpid());
- __osrfLogXidPfx = buff;
-}
-
-void osrfLogSetType( int logtype ) {
- if( logtype != OSRF_LOG_TYPE_FILE &&
- logtype != OSRF_LOG_TYPE_SYSLOG ) {
- fprintf(stderr, "Unrecognized log type. Logging to stderr\n");
- return;
- }
- __osrfLogType = logtype;
-}
-
-void osrfLogSetFile( const char* logfile ) {
- if(!logfile) return;
- if(__osrfLogFile) free(__osrfLogFile);
- __osrfLogFile = strdup(logfile);
-}
-
-void osrfLogSetActivityEnabled( int enabled ) {
- __osrfLogActivityEnabled = enabled;
-}
-
-void osrfLogSetAppname( const char* appname ) {
- if(!appname) return;
- if(__osrfLogAppname) free(__osrfLogAppname);
- __osrfLogAppname = strdup(appname);
-
- /* if syslogging, re-open the log with the appname */
- if( __osrfLogType == OSRF_LOG_TYPE_SYSLOG) {
- closelog();
- openlog(__osrfLogAppname, 0, __osrfLogFacility);
- }
-}
-
-void osrfLogSetSyslogFacility( int facility ) {
- __osrfLogFacility = facility;
-}
-void osrfLogSetSyslogActFacility( int facility ) {
- __osrfLogActFacility = facility;
-}
-
-void osrfLogSetLevel( int loglevel ) {
- __osrfLogLevel = loglevel;
-}
-
-void osrfLogError( const char* file, int line, const char* msg, ... )
- { OSRF_LOG_GO(file, line, msg, OSRF_LOG_ERROR); }
-void osrfLogWarning( const char* file, int line, const char* msg, ... )
- { OSRF_LOG_GO(file, line, msg, OSRF_LOG_WARNING); }
-void osrfLogInfo( const char* file, int line, const char* msg, ... )
- { OSRF_LOG_GO(file, line, msg, OSRF_LOG_INFO); }
-void osrfLogDebug( const char* file, int line, const char* msg, ... )
- { OSRF_LOG_GO(file, line, msg, OSRF_LOG_DEBUG); }
-void osrfLogInternal( const char* file, int line, const char* msg, ... )
- { OSRF_LOG_GO(file, line, msg, OSRF_LOG_INTERNAL); }
-void osrfLogActivity( const char* file, int line, const char* msg, ... ) {
- OSRF_LOG_GO(file, line, msg, OSRF_LOG_ACTIVITY);
- _osrfLogDetail( OSRF_LOG_INFO, file, line, VA_BUF ); /* also log at info level */
-}
-
-void _osrfLogDetail( int level, const char* filename, int line, char* msg ) {
-
- if( level == OSRF_LOG_ACTIVITY && ! __osrfLogActivityEnabled ) return;
- if( level > __osrfLogLevel ) return;
- if(!msg) return;
- if(!filename) filename = "";
-
- char* l = "INFO"; /* level name */
- int lvl = LOG_INFO; /* syslog level */
- int fac = __osrfLogFacility;
-
- switch( level ) {
- case OSRF_LOG_ERROR:
- l = "ERR ";
- lvl = LOG_ERR;
- break;
-
- case OSRF_LOG_WARNING:
- l = "WARN";
- lvl = LOG_WARNING;
- break;
-
- case OSRF_LOG_INFO:
- l = "INFO";
- lvl = LOG_INFO;
- break;
-
- case OSRF_LOG_DEBUG:
- l = "DEBG";
- lvl = LOG_DEBUG;
- break;
-
- case OSRF_LOG_INTERNAL:
- l = "INT ";
- lvl = LOG_DEBUG;
- break;
-
- case OSRF_LOG_ACTIVITY:
- l = "ACT";
- lvl = LOG_INFO;
- fac = __osrfLogActFacility;
- break;
- }
-
- char* xid = (__osrfLogXid) ? __osrfLogXid : "";
-
- if(__osrfLogType == OSRF_LOG_TYPE_SYSLOG ) {
- char buf[1536];
- memset(buf, 0x0, 1536);
- /* give syslog some breathing room, and be cute about it */
- strncat(buf, msg, 1535);
- buf[1532] = '.';
- buf[1533] = '.';
- buf[1534] = '.';
- buf[1535] = '\0';
- syslog( fac | lvl, "[%s:%ld:%s:%d:%s] %s", l, (long) getpid(), filename, line, xid, buf );
- }
-
- else if( __osrfLogType == OSRF_LOG_TYPE_FILE )
- _osrfLogToFile("[%s:%ld:%s:%d:%s] %s", l, (long) getpid(), filename, line, xid, msg );
-
-}
-
-
-void _osrfLogToFile( char* msg, ... ) {
-
- if(!msg) return;
- if(!__osrfLogFile) return;
- VA_LIST_TO_STRING(msg);
-
- if(!__osrfLogAppname) __osrfLogAppname = strdup("osrf");
- int l = strlen(VA_BUF) + strlen(__osrfLogAppname) + 36;
- char buf[l];
- bzero(buf,l);
-
- char datebuf[36];
- bzero(datebuf,36);
- time_t t = time(NULL);
- struct tm* tms = localtime(&t);
- strftime(datebuf, 36, "%Y-%m-%d %H:%M:%S", tms);
-
- FILE* file = fopen(__osrfLogFile, "a");
- if(!file) {
- fprintf(stderr, "Unable to fopen file %s for writing\n", __osrfLogFile);
- return;
- }
-
- fprintf(file, "%s %s %s\n", __osrfLogAppname, datebuf, VA_BUF );
- if( fclose(file) != 0 )
- osrfLogWarning(OSRF_LOG_MARK, "Error closing log file: %s", strerror(errno));
-
-}
-
-
-int osrfLogFacilityToInt( char* facility ) {
- if(!facility) return LOG_LOCAL0;
- if(strlen(facility) < 6) return LOG_LOCAL0;
- switch( facility[5] ) {
- case '0': return LOG_LOCAL0;
- case '1': return LOG_LOCAL1;
- case '2': return LOG_LOCAL2;
- case '3': return LOG_LOCAL3;
- case '4': return LOG_LOCAL4;
- case '5': return LOG_LOCAL5;
- case '6': return LOG_LOCAL6;
- case '7': return LOG_LOCAL7;
- }
- return LOG_LOCAL0;
-}
-
-
+++ /dev/null
-#include <syslog.h>
-#include <stdio.h>
-#include "utils.h"
-#include <time.h>
-#include <errno.h>
-
-#ifndef OSRF_LOG_INCLUDED
-#define OSRF_LOG_INCLUDED
-
-/* log levels */
-#define OSRF_LOG_ERROR 1
-#define OSRF_LOG_WARNING 2
-#define OSRF_LOG_INFO 3
-#define OSRF_LOG_DEBUG 4
-#define OSRF_LOG_INTERNAL 5
-#define OSRF_LOG_ACTIVITY -1
-
-#define OSRF_LOG_TYPE_FILE 1
-#define OSRF_LOG_TYPE_SYSLOG 2
-
-#define OSRF_LOG_MARK __FILE__, __LINE__
-
-
-#define OSRF_LOG_GO(f,li,m,l) \
- if(!m) return; \
- VA_LIST_TO_STRING(m); \
- _osrfLogDetail( l, f, li, VA_BUF );
-
-
-
-/* Initializes the logger. */
-void osrfLogInit( int type, const char* appname, int maxlevel );
-/** Sets the type of logging to perform. See log types */
-void osrfLogSetType( int logtype );
-/** Sets the systlog facility for the regular logs */
-void osrfLogSetSyslogFacility( int facility );
-/** Sets the systlog facility for the activity logs */
-void osrfLogSetSyslogActFacility( int facility );
-/** Sets the log file to use if we're logging to a file */
-void osrfLogSetFile( const char* logfile );
-/* once we know which application we're running, call this method to
- * set the appname so log lines can include the app name */
-void osrfLogSetAppname( const char* appname );
-/** Sets the global log level. Any log statements with a higher level
- * than "level" will not be logged */
-void osrfLogSetLevel( int loglevel );
-/* Log an error message */
-void osrfLogError( const char* file, int line, const char* msg, ... );
-/* Log a warning message */
-void osrfLogWarning( const char* file, int line, const char* msg, ... );
-/* log an info message */
-void osrfLogInfo( const char* file, int line, const char* msg, ... );
-/* Log a debug message */
-void osrfLogDebug( const char* file, int line, const char* msg, ... );
-/* Log an internal debug message */
-void osrfLogInternal( const char* file, int line, const char* msg, ... );
-/* Log an activity message */
-void osrfLogActivity( const char* file, int line, const char* msg, ... );
-
-void osrfLogCleanup();
-
-void osrfLogClearXid();
-void osrfLogSetXid(char* xid);
-void osrfLogMkXid();
-void osrfLogSetIsClient(int is);
-char* osrfLogGetXid();
-
-/* sets the activity flag */
-void osrfLogSetActivityEnabled( int enabled );
-
-/** Actually does the logging */
-void _osrfLogDetail( int level, const char* filename, int line, char* msg );
-
-void _osrfLogToFile( char* msg, ... );
-
-/* returns the int representation of the log facility based on the facility name
- * if the facility name is invalid, LOG_LOCAL0 is returned
- */
-int osrfLogFacilityToInt( char* facility );
-
-#endif
+++ /dev/null
-/* --- The data --- */
-
-const char data[] =
-"/* --- The MD5 routines --- */\n\n/* MD5 routines, after Ron R"
-"ivest */\n/* Written by David Madore <david.madore@ens.fr>, w"
-"ith code taken in\n * part from Colin Plumb. */\n/* Public dom"
-"ain (1999/11/24) */\n\n/* Note: these routines do not depend o"
-"n endianness. */\n\n/* === The header === */\n\n/* Put this in m"
-"d5.h if you don't like having everything in one big\n * file."
-" */\n\n#ifndef _DMADORE_MD5_H\n#define _DMADORE_MD5_H\n\nstruct m"
-"d5_ctx {\n /* The four chaining variables */\n unsigned long"
-" buf[4];\n /* Count number of message bits */\n unsigned lon"
-"g bits[2];\n /* Data being fed in */\n unsigned long in[16];"
-"\n /* Our position within the 512 bits (always between 0 and"
-" 63) */\n int b;\n};\n\nvoid MD5_transform (unsigned long buf[4"
-"], const unsigned long in[16]);\nvoid MD5_start (struct md5_c"
-"tx *context);\nvoid MD5_feed (struct md5_ctx *context, unsign"
-"ed char inb);\nvoid MD5_stop (struct md5_ctx *context, unsign"
-"ed char digest[16]);\n\n#endif /* not defined _DMADORE_MD5_H *"
-"/\n\n/* === The implementation === */\n\n#define F1(x, y, z) (z "
-"^ (x & (y ^ z)))\n#define F2(x, y, z) F1(z, x, y)\n#define F3("
-"x, y, z) (x ^ y ^ z)\n#define F4(x, y, z) (y ^ (x | ~z))\n\n#de"
-"fine MD5STEP(f, w, x, y, z, data, s) \\\n\t{ w += f (x, y, z) +"
-" data; w = w<<s | (w&0xffffffffUL)>>(32-s); \\\n\t w += x; }\n"
-"\nvoid\nMD5_transform (unsigned long buf[4], const unsigned lo"
-"ng in[16])\n{\n register unsigned long a, b, c, d;\n\n a = buf"
-"[0]; b = buf[1]; c = buf[2]; d = buf[3];\n MD5STEP(F1, a,"
-" b, c, d, in[0] + 0xd76aa478UL, 7);\n MD5STEP(F1, d, a, b, c"
-", in[1] + 0xe8c7b756UL, 12);\n MD5STEP(F1, c, d, a, b, in[2]"
-" + 0x242070dbUL, 17);\n MD5STEP(F1, b, c, d, a, in[3] + 0xc1"
-"bdceeeUL, 22);\n MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0fafU"
-"L, 7);\n MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62aUL, 12);\n"
-" MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613UL, 17);\n MD5ST"
-"EP(F1, b, c, d, a, in[7] + 0xfd469501UL, 22);\n MD5STEP(F1, "
-"a, b, c, d, in[8] + 0x698098d8UL, 7);\n MD5STEP(F1, d, a, b,"
-" c, in[9] + 0x8b44f7afUL, 12);\n MD5STEP(F1, c, d, a, b, in["
-"10] + 0xffff5bb1UL, 17);\n MD5STEP(F1, b, c, d, a, in[11] + "
-"0x895cd7beUL, 22);\n MD5STEP(F1, a, b, c, d, in[12] + 0x6b90"
-"1122UL, 7);\n MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193UL,"
-" 12);\n MD5STEP(F1, c, d, a, b, in[14] + 0xa679438eUL, 17);\n"
-" MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821UL, 22);\n MD5S"
-"TEP(F2, a, b, c, d, in[1] + 0xf61e2562UL, 5);\n MD5STEP(F2, "
-"d, a, b, c, in[6] + 0xc040b340UL, 9);\n MD5STEP(F2, c, d, a,"
-" b, in[11] + 0x265e5a51UL, 14);\n MD5STEP(F2, b, c, d, a, in"
-"[0] + 0xe9b6c7aaUL, 20);\n MD5STEP(F2, a, b, c, d, in[5] + 0"
-"xd62f105dUL, 5);\n MD5STEP(F2, d, a, b, c, in[10] + 0x024414"
-"53UL, 9);\n MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681UL, 1"
-"4);\n MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8UL, 20);\n M"
-"D5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6UL, 5);\n MD5STEP(F"
-"2, d, a, b, c, in[14] + 0xc33707d6UL, 9);\n MD5STEP(F2, c, d"
-", a, b, in[3] + 0xf4d50d87UL, 14);\n MD5STEP(F2, b, c, d, a,"
-" in[8] + 0x455a14edUL, 20);\n MD5STEP(F2, a, b, c, d, in[13]"
-" + 0xa9e3e905UL, 5);\n MD5STEP(F2, d, a, b, c, in[2] + 0xfce"
-"fa3f8UL, 9);\n MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9UL,"
-" 14);\n MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8aUL, 20);\n"
-" MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942UL, 4);\n MD5STE"
-"P(F3, d, a, b, c, in[8] + 0x8771f681UL, 11);\n MD5STEP(F3, c"
-", d, a, b, in[11] + 0x6d9d6122UL, 16);\n MD5STEP(F3, b, c, d"
-", a, in[14] + 0xfde5380cUL, 23);\n MD5STEP(F3, a, b, c, d, i"
-"n[1] + 0xa4beea44UL, 4);\n MD5STEP(F3, d, a, b, c, in[4] + 0"
-"x4bdecfa9UL, 11);\n MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b"
-"60UL, 16);\n MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70UL, "
-"23);\n MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6UL, 4);\n "
-"MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127faUL, 11);\n MD5STEP"
-"(F3, c, d, a, b, in[3] + 0xd4ef3085UL, 16);\n MD5STEP(F3, b,"
-" c, d, a, in[6] + 0x04881d05UL, 23);\n MD5STEP(F3, a, b, c, "
-"d, in[9] + 0xd9d4d039UL, 4);\n MD5STEP(F3, d, a, b, c, in[12"
-"] + 0xe6db99e5UL, 11);\n MD5STEP(F3, c, d, a, b, in[15] + 0x"
-"1fa27cf8UL, 16);\n MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac566"
-"5UL, 23);\n MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244UL, 6)"
-";\n MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97UL, 10);\n MD5"
-"STEP(F4, c, d, a, b, in[14] + 0xab9423a7UL, 15);\n MD5STEP(F"
-"4, b, c, d, a, in[5] + 0xfc93a039UL, 21);\n MD5STEP(F4, a, b"
-", c, d, in[12] + 0x655b59c3UL, 6);\n MD5STEP(F4, d, a, b, c,"
-" in[3] + 0x8f0ccc92UL, 10);\n MD5STEP(F4, c, d, a, b, in[10]"
-" + 0xffeff47dUL, 15);\n MD5STEP(F4, b, c, d, a, in[1] + 0x85"
-"845dd1UL, 21);\n MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4fU"
-"L, 6);\n MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0UL, 10);"
-"\n MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314UL, 15);\n MD5S"
-"TEP(F4, b, c, d, a, in[13] + 0x4e0811a1UL, 21);\n MD5STEP(F4"
-", a, b, c, d, in[4] + 0xf7537e82UL, 6);\n MD5STEP(F4, d, a, "
-"b, c, in[11] + 0xbd3af235UL, 10);\n MD5STEP(F4, c, d, a, b, "
-"in[2] + 0x2ad7d2bbUL, 15);\n MD5STEP(F4, b, c, d, a, in[9] +"
-" 0xeb86d391UL, 21);\n buf[0] += a; buf[1] += b; buf[2] += "
-"c; buf[3] += d;\n}\n\n#undef F1\n#undef F2\n#undef F3\n#undef F4\n"
-"#undef MD5STEP\n\nvoid\nMD5_start (struct md5_ctx *ctx)\n{\n int"
-" i;\n\n ctx->buf[0] = 0x67452301UL;\n ctx->buf[1] = 0xefcdab8"
-"9UL;\n ctx->buf[2] = 0x98badcfeUL;\n ctx->buf[3] = 0x1032547"
-"6UL;\n ctx->bits[0] = 0;\n ctx->bits[1] = 0;\n for ( i=0 ; i"
-"<16 ; i++ )\n ctx->in[i] = 0;\n ctx->b = 0;\n}\n\nvoid\nMD5_fe"
-"ed (struct md5_ctx *ctx, unsigned char inb)\n{\n int i;\n uns"
-"igned long temp;\n\n ctx->in[ctx->b/4] |= ((unsigned long)inb"
-") << ((ctx->b%4)*8);\n if ( ++ctx->b >= 64 )\n {\n MD5"
-"_transform (ctx->buf, ctx->in);\n ctx->b = 0;\n for "
-"( i=0 ; i<16 ; i++ )\n\tctx->in[i] = 0;\n }\n temp = ctx->bi"
-"ts[0];\n ctx->bits[0] += 8;\n if ( (temp&0xffffffffUL) > (ct"
-"x->bits[0]&0xffffffffUL) )\n ctx->bits[1]++;\n}\n\nvoid\nMD5_s"
-"top (struct md5_ctx *ctx, unsigned char digest[16])\n{\n int "
-"i;\n unsigned long bits[2];\n\n for ( i=0 ; i<2 ; i++ )\n b"
-"its[i] = ctx->bits[i];\n MD5_feed (ctx, 0x80);\n for ( ; ctx"
-"->b!=56 ; )\n MD5_feed (ctx, 0);\n for ( i=0 ; i<2 ; i++ )"
-"\n {\n MD5_feed (ctx, bits[i]&0xff);\n MD5_feed (c"
-"tx, (bits[i]>>8)&0xff);\n MD5_feed (ctx, (bits[i]>>16)&0"
-"xff);\n MD5_feed (ctx, (bits[i]>>24)&0xff);\n }\n for "
-"( i=0 ; i<4 ; i++ )\n {\n digest[4*i] = ctx->buf[i]&0x"
-"ff;\n digest[4*i+1] = (ctx->buf[i]>>8)&0xff;\n diges"
-"t[4*i+2] = (ctx->buf[i]>>16)&0xff;\n digest[4*i+3] = (ct"
-"x->buf[i]>>24)&0xff;\n }\n}\n\f\n/* --- The core of the progra"
-"m --- */\n\n#include <stdio.h>\n#include <string.h>\n\n#define LA"
-"RGE_ENOUGH 16384\n\nchar buffer[LARGE_ENOUGH];\n\nint\nmain (int "
-"argc, char *argv[])\n{\n unsigned int i;\n\n buffer[0] = 0;\n "
-"strcat (buffer, \"/* --- The data --- */\\n\\n\");\n strcat (buf"
-"fer, \"const char data[] =\");\n for ( i=0 ; data[i] ; i++ )\n "
-" {\n if ( i%60 == 0 )\n\tstrcat (buffer, \"\\n\\\"\");\n "
-"switch ( data[i] )\n\t{\n\tcase '\\\\':\n\tcase '\"':\n\t strcat (buff"
-"er, \"\\\\\");\n\t buffer[strlen(buffer)+1] = 0;\n\t buffer[strlen"
-"(buffer)] = data[i];\n\t break;\n\tcase '\\n':\n\t strcat (buffer"
-", \"\\\\n\");\n\t break;\n\tcase '\\t':\n\t strcat (buffer, \"\\\\t\");\n\t"
-" break;\n\tcase '\\f':\n\t strcat (buffer, \"\\\\f\");\n\t break;\n\td"
-"efault:\n\t buffer[strlen(buffer)+1] = 0;\n\t buffer[strlen(bu"
-"ffer)] = data[i];\n\t}\n if ( i%60 == 59 || !data[i+1] )\n\t"
-"strcat (buffer, \"\\\"\");\n }\n strcat (buffer, \";\\n\\f\\n\");\n "
-" strcat (buffer, data);\n if ( argc >= 2 && strcmp (argv[1],"
-" \"xyzzy\") == 0 )\n printf (\"%s\", buffer);\n else\n {\n "
-" struct md5_ctx ctx;\n unsigned char digest[16];\n\n "
-" MD5_start (&ctx);\n for ( i=0 ; buffer[i] ; i++ )\n\tMD5"
-"_feed (&ctx, buffer[i]);\n MD5_stop (&ctx, digest);\n "
-" for ( i=0 ; i<16 ; i++ )\n\tprintf (\"%02x\", digest[i]);\n "
-" printf (\"\\n\");\n }\n return 0;\n}\n";
-
-
-#include "md5.h"
-
-
-/* --- The MD5 routines --- */
-
-/* MD5 routines, after Ron Rivest */
-/* Written by David Madore <david.madore@ens.fr>, with code taken in
- * part from Colin Plumb. */
-/* Public domain (1999/11/24) */
-
-/* Note: these routines do not depend on endianness. */
-
-/* === The header === */
-
-/* Put this in md5.h if you don't like having everything in one big
- * file. */
-
-
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-#define MD5STEP(f, w, x, y, z, data, s) \
- { w += f (x, y, z) + data; w = w<<s | (w&0xffffffffUL)>>(32-s); \
- w += x; }
-
-void
-MD5_transform (unsigned long buf[4], const unsigned long in[16])
-{
- register unsigned long a, b, c, d;
-
- a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3];
- MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478UL, 7);
- MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756UL, 12);
- MD5STEP(F1, c, d, a, b, in[2] + 0x242070dbUL, 17);
- MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceeeUL, 22);
- MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0fafUL, 7);
- MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62aUL, 12);
- MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613UL, 17);
- MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501UL, 22);
- MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8UL, 7);
- MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7afUL, 12);
- MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1UL, 17);
- MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7beUL, 22);
- MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122UL, 7);
- MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193UL, 12);
- MD5STEP(F1, c, d, a, b, in[14] + 0xa679438eUL, 17);
- MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821UL, 22);
- MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562UL, 5);
- MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340UL, 9);
- MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51UL, 14);
- MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aaUL, 20);
- MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105dUL, 5);
- MD5STEP(F2, d, a, b, c, in[10] + 0x02441453UL, 9);
- MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681UL, 14);
- MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8UL, 20);
- MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6UL, 5);
- MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6UL, 9);
- MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87UL, 14);
- MD5STEP(F2, b, c, d, a, in[8] + 0x455a14edUL, 20);
- MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905UL, 5);
- MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8UL, 9);
- MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9UL, 14);
- MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8aUL, 20);
- MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942UL, 4);
- MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681UL, 11);
- MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122UL, 16);
- MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380cUL, 23);
- MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44UL, 4);
- MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9UL, 11);
- MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60UL, 16);
- MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70UL, 23);
- MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6UL, 4);
- MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127faUL, 11);
- MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085UL, 16);
- MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05UL, 23);
- MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039UL, 4);
- MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5UL, 11);
- MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8UL, 16);
- MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665UL, 23);
- MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244UL, 6);
- MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97UL, 10);
- MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7UL, 15);
- MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039UL, 21);
- MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3UL, 6);
- MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92UL, 10);
- MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47dUL, 15);
- MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1UL, 21);
- MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4fUL, 6);
- MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0UL, 10);
- MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314UL, 15);
- MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1UL, 21);
- MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82UL, 6);
- MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235UL, 10);
- MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bbUL, 15);
- MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391UL, 21);
- buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d;
-}
-
-#undef F1
-#undef F2
-#undef F3
-#undef F4
-#undef MD5STEP
-
-void
-MD5_start (struct md5_ctx *ctx)
-{
- int i;
-
- ctx->buf[0] = 0x67452301UL;
- ctx->buf[1] = 0xefcdab89UL;
- ctx->buf[2] = 0x98badcfeUL;
- ctx->buf[3] = 0x10325476UL;
- ctx->bits[0] = 0;
- ctx->bits[1] = 0;
- for ( i=0 ; i<16 ; i++ )
- ctx->in[i] = 0;
- ctx->b = 0;
-}
-
-void
-MD5_feed (struct md5_ctx *ctx, unsigned char inb)
-{
- int i;
- unsigned long temp;
-
- ctx->in[ctx->b/4] |= ((unsigned long)inb) << ((ctx->b%4)*8);
- if ( ++ctx->b >= 64 )
- {
- MD5_transform (ctx->buf, ctx->in);
- ctx->b = 0;
- for ( i=0 ; i<16 ; i++ )
- ctx->in[i] = 0;
- }
- temp = ctx->bits[0];
- ctx->bits[0] += 8;
- if ( (temp&0xffffffffUL) > (ctx->bits[0]&0xffffffffUL) )
- ctx->bits[1]++;
-}
-
-void
-MD5_stop (struct md5_ctx *ctx, unsigned char digest[16])
-{
- int i;
- unsigned long bits[2];
-
- for ( i=0 ; i<2 ; i++ )
- bits[i] = ctx->bits[i];
- MD5_feed (ctx, 0x80);
- for ( ; ctx->b!=56 ; )
- MD5_feed (ctx, 0);
- for ( i=0 ; i<2 ; i++ )
- {
- MD5_feed (ctx, bits[i]&0xff);
- MD5_feed (ctx, (bits[i]>>8)&0xff);
- MD5_feed (ctx, (bits[i]>>16)&0xff);
- MD5_feed (ctx, (bits[i]>>24)&0xff);
- }
- for ( i=0 ; i<4 ; i++ )
- {
- digest[4*i] = ctx->buf[i]&0xff;
- digest[4*i+1] = (ctx->buf[i]>>8)&0xff;
- digest[4*i+2] = (ctx->buf[i]>>16)&0xff;
- digest[4*i+3] = (ctx->buf[i]>>24)&0xff;
- }
-}
-\f
-/* --- The core of the program --- */
-
-#include <stdio.h>
-#include <string.h>
-
-#define LARGE_ENOUGH 16384
-
-char buffer[LARGE_ENOUGH];
-
-/*
-int
-main (int argc, char *argv[])
-{
- unsigned int i;
-
- buffer[0] = 0;
- strcat (buffer, \n\n");
- strcat (buffer, "const char data[] =");
- for ( i=0 ; data[i] ; i++ )
- {
- if ( i%60 == 0 )
- strcat (buffer, "\n\"");
- switch ( data[i] )
- {
- case '\\':
- case '"':
- strcat (buffer, "\\");
- buffer[strlen(buffer)+1] = 0;
- buffer[strlen(buffer)] = data[i];
- break;
- case '\n':
- strcat (buffer, "\\n");
- break;
- case '\t':
- strcat (buffer, "\\t");
- break;
- case '\f':
- strcat (buffer, "\\f");
- break;
- default:
- buffer[strlen(buffer)+1] = 0;
- buffer[strlen(buffer)] = data[i];
- }
- if ( i%60 == 59 || !data[i+1] )
- strcat (buffer, "\"");
- }
- strcat (buffer, ";\n\f\n");
- strcat (buffer, data);
- if ( argc >= 2 && strcmp (argv[1], "xyzzy") == 0 )
- printf ("%s", buffer);
- else
- {
- struct md5_ctx ctx;
- unsigned char digest[16];
-
- MD5_start (&ctx);
- for ( i=0 ; buffer[i] ; i++ )
- MD5_feed (&ctx, buffer[i]);
- MD5_stop (&ctx, digest);
- for ( i=0 ; i<16 ; i++ )
- printf ("%02x", digest[i]);
- printf ("\n");
- }
- return 0;
-}
-*/
+++ /dev/null
-/* --- The MD5 routines --- */
-
-/* MD5 routines, after Ron Rivest */
-/* Written by David Madore <david.madore@ens.fr>, with code taken in
- * part from Colin Plumb. */
-/* Public domain (1999/11/24) */
-
-/* Note: these routines do not depend on endianness. */
-
-/* === The header === */
-
-/* Put this in md5.h if you don't like having everything in one big
- * file. */
-
-#ifndef _DMADORE_MD5_H
-#define _DMADORE_MD5_H
-
-struct md5_ctx {
- /* The four chaining variables */
- unsigned long buf[4];
- /* Count number of message bits */
- unsigned long bits[2];
- /* Data being fed in */
- unsigned long in[16];
- /* Our position within the 512 bits (always between 0 and 63) */
- int b;
-};
-
-void MD5_transform (unsigned long buf[4], const unsigned long in[16]);
-void MD5_start (struct md5_ctx *context);
-void MD5_feed (struct md5_ctx *context, unsigned char inb);
-void MD5_stop (struct md5_ctx *context, unsigned char digest[16]);
-
-#endif /* not defined _DMADORE_MD5_H */
-
+++ /dev/null
-/*
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Gabber
- * Copyright (C) 1999-2000 Dave Smith & Julian Missig
- */
-
-
-/*
- Implements the Secure Hash Algorithm (SHA1)
-
- Copyright (C) 1999 Scott G. Miller
-
- Released under the terms of the GNU General Public License v2
- see file COPYING for details
-
- Credits:
- Robert Klep <robert@ilse.nl> -- Expansion function fix
- Thomas "temas" Muldowney <temas@box5.net>:
- -- shahash() for string fun
- -- Will add the int32 stuff in a few
-
- ---
- FIXME: This source takes int to be a 32 bit integer. This
- may vary from system to system. I'd use autoconf if I was familiar
- with it. Anyone want to help me out?
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#ifdef MACOS
-# include <string.h>
-#else
-# include <sys/stat.h>
-# include <sys/types.h>
-#endif
-
-#include <string.h>
-
-#ifndef WIN32
-# include <unistd.h>
-# define INT64 long long
-#else
-# include <string.h>
-# define snprintf _snprintf
-# define INT64 __int64
-#endif
-
-#define switch_endianness(x) (x<<24 & 0xff000000) | \
- (x<<8 & 0x00ff0000) | \
- (x>>8 & 0x0000ff00) | \
- (x>>24 & 0x000000ff)
-
-/* Initial hash values */
-#define Ai 0x67452301
-#define Bi 0xefcdab89
-#define Ci 0x98badcfe
-#define Di 0x10325476
-#define Ei 0xc3d2e1f0
-
-/* SHA1 round constants */
-#define K1 0x5a827999
-#define K2 0x6ed9eba1
-#define K3 0x8f1bbcdc
-#define K4 0xca62c1d6
-
-/* Round functions. Note that f2() is used in both rounds 2 and 4 */
-#define f1(B,C,D) ((B & C) | ((~B) & D))
-#define f2(B,C,D) (B ^ C ^ D)
-#define f3(B,C,D) ((B & C) | (B & D) | (C & D))
-
-/* left circular shift functions (rotate left) */
-#define rol1(x) ((x<<1) | ((x>>31) & 1))
-#define rol5(A) ((A<<5) | ((A>>27) & 0x1f))
-#define rol30(B) ((B<<30) | ((B>>2) & 0x3fffffff))
-
-/*
- Hashes 'data', which should be a pointer to 512 bits of data (sixteen
- 32 bit ints), into the ongoing 160 bit hash value (five 32 bit ints)
- 'hash'
-*/
-int
-sha_hash(int *data, int *hash)
-{
- int W[80];
- unsigned int A=hash[0], B=hash[1], C=hash[2], D=hash[3], E=hash[4];
- unsigned int t, x, TEMP;
-
- for (t=0; t<16; t++)
- {
-#ifndef WORDS_BIGENDIAN
- W[t]=switch_endianness(data[t]);
-#else
- W[t]=data[t];
-#endif
- }
-
-
- /* SHA1 Data expansion */
- for (t=16; t<80; t++)
- {
- x=W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
- W[t]=rol1(x);
- }
-
- /* SHA1 main loop (t=0 to 79)
- This is broken down into four subloops in order to use
- the correct round function and constant */
- for (t=0; t<20; t++)
- {
- TEMP=rol5(A) + f1(B,C,D) + E + W[t] + K1;
- E=D;
- D=C;
- C=rol30(B);
- B=A;
- A=TEMP;
- }
- for (; t<40; t++)
- {
- TEMP=rol5(A) + f2(B,C,D) + E + W[t] + K2;
- E=D;
- D=C;
- C=rol30(B);
- B=A;
- A=TEMP;
- }
- for (; t<60; t++)
- {
- TEMP=rol5(A) + f3(B,C,D) + E + W[t] + K3;
- E=D;
- D=C;
- C=rol30(B);
- B=A;
- A=TEMP;
- }
- for (; t<80; t++)
- {
- TEMP=rol5(A) + f2(B,C,D) + E + W[t] + K4;
- E=D;
- D=C;
- C=rol30(B);
- B=A;
- A=TEMP;
- }
- hash[0]+=A;
- hash[1]+=B;
- hash[2]+=C;
- hash[3]+=D;
- hash[4]+=E;
- return 0;
-}
-
-/*
- Takes a pointer to a 160 bit block of data (five 32 bit ints) and
- intializes it to the start constants of the SHA1 algorithm. This
- must be called before using hash in the call to sha_hash
-*/
-int
-sha_init(int *hash)
-{
- hash[0]=Ai;
- hash[1]=Bi;
- hash[2]=Ci;
- hash[3]=Di;
- hash[4]=Ei;
- return 0;
-}
-
-int strprintsha(char *dest, int *hashval)
-{
- int x;
- char *hashstr = dest;
- for (x=0; x<5; x++)
- {
- snprintf(hashstr, 9, "%08x", hashval[x]);
- hashstr+=8;
- }
- //snprintf(hashstr++, 1, "\0");
- hashstr[0] = '\0';
- hashstr++;
-
- return 0;
-}
-
-char *shahash(const char *str)
-{
- char read_buffer[65];
- //int read_buffer[64];
- int c=1, i;
-
- INT64 length=0;
-
- int strsz;
- static char final[40];
- int *hashval;
-
- hashval = (int *)malloc(20);
-
- sha_init(hashval);
-
- strsz = strlen(str);
-
- if(strsz == 0)
- {
- memset(read_buffer, 0, 65);
- read_buffer[0] = 0x80;
- sha_hash((int *)read_buffer, hashval);
- }
-
- while (strsz>0)
- {
- memset(read_buffer, 0, 65);
- strncpy((char*)read_buffer, str, 64);
- c = strlen((char *)read_buffer);
- length+=c;
- strsz-=c;
- if (strsz<=0)
- {
- length<<=3;
- read_buffer[c]=(char)0x80;
- for (i=c+1; i<64; i++)
- read_buffer[i]=0;
- if (c>55)
- {
- /* we need to do an entire new block */
- sha_hash((int *)read_buffer, hashval);
- for (i=0; i<14; i++)
- ((int*)read_buffer)[i]=0;
- }
-#ifndef WORDS_BIGENDIAN
- for (i=0; i<8; i++)
- {
- read_buffer[56+i]=(char)(length>>(56-(i*8))) & 0xff;
- }
-#else
- memcpy(read_buffer+56, &length, 8);
-#endif
- }
-
- sha_hash((int *)read_buffer, hashval);
- str+=64;
- }
-
- strprintsha((char *)final, hashval);
- free(hashval);
- return (char *)final;
-}
+++ /dev/null
-// sha.h
-// Jabber client library
-//
-// Original Code Copyright (C) 1999-2001 Dave Smith (dave@jabber.org)
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library 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
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
-// Contributor(s): Julian Missig
-//
-// This Original Code has been modified by IBM Corporation. Modifications
-// made by IBM described herein are Copyright (c) International Business
-// Machines Corporation, 2002.
-//
-// Date Modified by Description of modification
-// 01/20/2002 IBM Corp. Updated to libjudo 1.1.1
-// 2002-03-05 IBM Corp. Updated to libjudo 1.1.5
-// 2002-07-09 IBM Corp. Added Roster::getSession()
-//
-// =====================================================================================
-
-
-//#ifdef WIN32
- char* shahash(const char* str);
-//#else
-//extern "C" {
-// char* shahash(const char* str);
-//}
-//#endif
-
+++ /dev/null
-#include "socket_bundle.h"
-
-/* --------------------------------------------------------------------
- Test Code
- -------------------------------------------------------------------- */
-/*
-int count = 0;
-void printme(void* blob, socket_manager* mgr,
- int sock_fd, char* data, int parent_id) {
-
- fprintf(stderr, "Got data from socket %d with parent %d => %s",
- sock_fd, parent_id, data );
-
- socket_send(sock_fd, data);
-
- if(count++ > 2) {
- socket_disconnect(mgr, sock_fd);
- _socket_print_list(mgr);
- }
-}
-
-int main(int argc, char* argv[]) {
- socket_manager manager;
- memset(&manager, 0, sizeof(socket_manager));
- int port = 11000;
- if(argv[1])
- port = atoi(argv[1]);
-
- manager.data_received = &printme;
- socket_open_tcp_server(&manager, port);
-
- while(1)
- socket_wait_all(&manager, -1);
-
- return 0;
-}
-*/
-/* -------------------------------------------------------------------- */
-
-
-
-socket_node* _socket_add_node(socket_manager* mgr,
- int endpoint, int addr_type, int sock_fd, int parent_id ) {
-
- if(mgr == NULL) return NULL;
- osrfLogInternal( OSRF_LOG_MARK, "Adding socket node with fd %d", sock_fd);
- socket_node* new_node = safe_malloc(sizeof(socket_node));
-
- new_node->endpoint = endpoint;
- new_node->addr_type = addr_type;
- new_node->sock_fd = sock_fd;
- new_node->next = NULL;
- new_node->parent_id = 0;
- if(parent_id > 0)
- new_node->parent_id = parent_id;
-
- new_node->next = mgr->socket;
- mgr->socket = new_node;
- return new_node;
-}
-
-/* creates a new server socket node and adds it to the socket set.
- returns new socket fd on success. -1 on failure.
- socket_type is one of INET or UNIX */
-int socket_open_tcp_server(socket_manager* mgr, int port, char* listen_ip) {
-
- if( mgr == NULL ) {
- osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_server(): NULL mgr");
- return -1;
- }
-
- int sock_fd;
- struct sockaddr_in server_addr;
-
- errno = 0;
- sock_fd = socket(AF_INET, SOCK_STREAM, 0);
- if(sock_fd < 0) {
- osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_server(): Unable to create TCP socket: %s",
- strerror( errno ) );
- return -1;
- }
-
- server_addr.sin_family = AF_INET;
-
- if(listen_ip != NULL) {
- server_addr.sin_addr.s_addr = inet_addr(listen_ip);
- } else {
- server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- }
-
- server_addr.sin_port = htons(port);
-
- errno = 0;
- if(bind( sock_fd, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0) {
- osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_server(): cannot bind to port %d: %s",
- port, strerror( errno ) );
- return -1;
- }
-
- errno = 0;
- if(listen(sock_fd, 20) == -1) {
- osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_server(): listen() returned error: %s",
- strerror( errno ) );
- return -1;
- }
-
- _socket_add_node(mgr, SERVER_SOCKET, INET, sock_fd, 0);
- return sock_fd;
-}
-
-int socket_open_unix_server(socket_manager* mgr, char* path) {
- if(mgr == NULL || path == NULL) return -1;
-
- osrfLogDebug( OSRF_LOG_MARK, "opening unix socket at %s", path);
- int sock_fd;
- struct sockaddr_un server_addr;
-
- errno = 0;
- sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if(sock_fd < 0){
- osrfLogWarning( OSRF_LOG_MARK, "socket_open_unix_server(): socket() failed: %s",
- strerror( errno ) );
- return -1;
- }
-
- server_addr.sun_family = AF_UNIX;
- strcpy(server_addr.sun_path, path);
-
- errno = 0;
- if( bind(sock_fd, (struct sockaddr*) &server_addr,
- sizeof(struct sockaddr_un)) < 0) {
- osrfLogWarning( OSRF_LOG_MARK,
- "socket_open_unix_server(): cannot bind to unix port %s: %s",
- path, strerror( errno ) );
- return -1;
- }
-
- errno = 0;
- if(listen(sock_fd, 20) == -1) {
- osrfLogWarning( OSRF_LOG_MARK, "socket_open_unix_server(): listen() returned error: %s",
- strerror( errno ) );
- return -1;
- }
-
- osrfLogDebug( OSRF_LOG_MARK, "unix socket successfully opened");
-
- int i = 1;
-
- /* causing problems with router for some reason ... */
- //osrfLogDebug( OSRF_LOG_MARK, "Setting SO_REUSEADDR");
- //setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
-
- //osrfLogDebug( OSRF_LOG_MARK, "Setting TCP_NODELAY");
- setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, &i, sizeof(i));
-
- _socket_add_node(mgr, SERVER_SOCKET, UNIX, sock_fd, 0);
- return sock_fd;
-}
-
-
-
-int socket_open_udp_server(
- socket_manager* mgr, int port, char* listen_ip ) {
-
- int sockfd;
- struct sockaddr_in server_addr;
-
- errno = 0;
- if( (sockfd = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "Unable to create UDP socket: %s", strerror( errno ) );
- return -1;
- }
-
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = htons(port);
- if(listen_ip) server_addr.sin_addr.s_addr = inet_addr(listen_ip);
- else server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
-
- errno = 0;
- if( (bind (sockfd, (struct sockaddr *) &server_addr,sizeof(server_addr))) ) {
- osrfLogWarning( OSRF_LOG_MARK, "Unable to bind to UDP port %d: %s",
- port, strerror( errno ) );
- return -1;
- }
-
- _socket_add_node(mgr, SERVER_SOCKET, INET, sockfd, 0);
- return sockfd;
-}
-
-
-int socket_open_tcp_client(socket_manager* mgr, int port, char* dest_addr) {
-
- struct sockaddr_in remoteAddr, localAddr;
- struct hostent *hptr;
- int sock_fd;
-
- // ------------------------------------------------------------------
- // Create the socket
- // ------------------------------------------------------------------
- errno = 0;
- if( (sock_fd = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_client(): Cannot create TCP socket: %s",
- strerror( errno ) );
- return -1;
- }
-
- int i = 1;
- //osrfLogDebug( OSRF_LOG_MARK, "Setting TCP_NODELAY");
- setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, &i, sizeof(i));
-
-
- // ------------------------------------------------------------------
- // Get the hostname
- // ------------------------------------------------------------------
- errno = 0;
- if( (hptr = gethostbyname( dest_addr ) ) == NULL ) {
- osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_client(): Unknown Host => %s: %s",
- dest_addr, strerror( errno ) );
- return -1;
- }
-
- // ------------------------------------------------------------------
- // Construct server info struct
- // ------------------------------------------------------------------
- memset( &remoteAddr, 0, sizeof(remoteAddr));
- remoteAddr.sin_family = AF_INET;
- remoteAddr.sin_port = htons( port );
- memcpy( (char*) &remoteAddr.sin_addr.s_addr,
- hptr->h_addr_list[0], hptr->h_length );
-
- // ------------------------------------------------------------------
- // Construct local info struct
- // ------------------------------------------------------------------
- memset( &localAddr, 0, sizeof( localAddr ) );
- localAddr.sin_family = AF_INET;
- localAddr.sin_addr.s_addr = htonl( INADDR_ANY );
- localAddr.sin_port = htons(0);
-
- // ------------------------------------------------------------------
- // Bind to a local port
- // ------------------------------------------------------------------
- errno = 0;
- if( bind( sock_fd, (struct sockaddr *) &localAddr, sizeof( localAddr ) ) < 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_client(): Cannot bind to local port: %s",
- strerror( errno ) );
- return -1;
- }
-
- // ------------------------------------------------------------------
- // Connect to server
- // ------------------------------------------------------------------
- errno = 0;
- if( connect( sock_fd, (struct sockaddr*) &remoteAddr, sizeof( struct sockaddr_in ) ) < 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "socket_open_tcp_client(): Cannot connect to server %s: %s",
- dest_addr, strerror(errno) );
- return -1;
- }
-
- _socket_add_node(mgr, CLIENT_SOCKET, INET, sock_fd, -1 );
-
- return sock_fd;
-}
-
-
-int socket_open_udp_client(
- socket_manager* mgr, int port, char* dest_addr) {
-
- int sockfd;
- struct sockaddr_in client_addr, server_addr;
- struct hostent* host;
-
- errno = 0;
- if( (host = gethostbyname(dest_addr)) == NULL) {
- osrfLogWarning( OSRF_LOG_MARK, "Unable to resolve host: %s: %s",
- dest_addr, strerror( errno ) );
- return -1;
- }
-
- server_addr.sin_family = host->h_addrtype;
- memcpy((char *) &server_addr.sin_addr.s_addr,
- host->h_addr_list[0], host->h_length);
- server_addr.sin_port = htons(port);
-
- errno = 0;
- if( (sockfd = socket(AF_INET,SOCK_DGRAM,0)) < 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "socket_open_udp_client(): Unable to create UDP socket: %s", strerror( errno ) );
- return -1;
- }
-
- client_addr.sin_family = AF_INET;
- client_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- client_addr.sin_port = htons(0);
-
- errno = 0;
- if( (bind(sockfd, (struct sockaddr *) &client_addr, sizeof(client_addr))) < 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "Unable to bind UDP socket: %s", strerror( errno ) );
- return -1;
- }
-
- _socket_add_node(mgr, CLIENT_SOCKET, INET, sockfd, -1 );
-
- return sockfd;
-}
-
-
-int socket_open_unix_client(socket_manager* mgr, char* sock_path) {
-
- int sock_fd, len;
- struct sockaddr_un usock;
-
- errno = 0;
- if( (sock_fd = socket( AF_UNIX, SOCK_STREAM, 0 )) < 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "socket_open_unix_client(): Cannot create UNIX socket: %s", strerror( errno ) );
- return -1;
- }
-
- usock.sun_family = AF_UNIX;
- strcpy( usock.sun_path, sock_path );
-
- len = sizeof( usock.sun_family ) + strlen( usock.sun_path );
-
- errno = 0;
- if( connect( sock_fd, (struct sockaddr *) &usock, len ) < 0 ) {
- osrfLogWarning( OSRF_LOG_MARK, "Error connecting to unix socket: %s",
- strerror( errno ) );
- return -1;
- }
-
- _socket_add_node(mgr, CLIENT_SOCKET, UNIX, sock_fd, -1 );
-
- return sock_fd;
-}
-
-
-
-/* returns the socket_node with the given sock_fd */
-socket_node* socket_find_node(socket_manager* mgr, int sock_fd) {
- if(mgr == NULL) return NULL;
- socket_node* node = mgr->socket;
- while(node) {
- if(node->sock_fd == sock_fd)
- return node;
- node = node->next;
- }
- return NULL;
-}
-
-/* removes the node with the given sock_fd from the list and frees it */
-void socket_remove_node(socket_manager* mgr, int sock_fd) {
-
- if(mgr == NULL) return;
-
- osrfLogDebug( OSRF_LOG_MARK, "removing socket %d", sock_fd);
-
- socket_node* head = mgr->socket;
- socket_node* tail = head;
- if(head == NULL) return;
-
- /* if removing the first node in the list */
- if(head->sock_fd == sock_fd) {
- mgr->socket = head->next;
- free(head);
- return;
- }
-
- head = head->next;
-
- /* if removing any other node */
- while(head) {
- if(head->sock_fd == sock_fd) {
- tail->next = head->next;
- free(head);
- return;
- }
- tail = head;
- head = head->next;
- }
-}
-
-
-
-void _socket_print_list(socket_manager* mgr) {
- if(mgr == NULL) return;
- socket_node* node = mgr->socket;
- osrfLogDebug( OSRF_LOG_MARK, "socket_node list: [");
- while(node) {
- osrfLogDebug( OSRF_LOG_MARK, "sock_fd: %d | parent_id: %d",
- node->sock_fd, node->parent_id);
- node = node->next;
- }
- osrfLogDebug( OSRF_LOG_MARK, "]");
-}
-
-/* sends the given data to the given socket */
-int socket_send(int sock_fd, const char* data) {
- return _socket_send( sock_fd, data, 0);
-}
-
-
-int _socket_send(int sock_fd, const char* data, int flags) {
-
- signal(SIGPIPE, SIG_IGN); /* in case a unix socket was closed */
-
- errno = 0;
- size_t r = send( sock_fd, data, strlen(data), flags );
- int local_errno = errno;
-
- if( r == -1 ) {
- osrfLogWarning( OSRF_LOG_MARK, "_socket_send(): Error sending data with return %d", r );
- osrfLogWarning( OSRF_LOG_MARK, "Last Sys Error: %s", strerror(local_errno));
- return -1;
- }
-
- return 0;
-}
-
-
-int socket_send_nowait( int sock_fd, const char* data) {
- return _socket_send( sock_fd, data, MSG_DONTWAIT);
-}
-
-
-/*
- * Waits at most usecs microseconds for the send buffer of the given
- * socket to accept new data. This does not guarantee that the
- * socket will accept all the data we want to give it.
- */
-int socket_send_timeout( int sock_fd, const char* data, int usecs ) {
-
- fd_set write_set;
- FD_ZERO( &write_set );
- FD_SET( sock_fd, &write_set );
-
- int mil = 1000000;
- int secs = (int) usecs / mil;
- usecs = usecs - (secs * mil);
-
- struct timeval tv;
- tv.tv_sec = secs;
- tv.tv_usec = usecs;
-
- errno = 0;
- int ret = select( sock_fd + 1, NULL, &write_set, NULL, &tv);
- if( ret > 0 ) return _socket_send( sock_fd, data, 0);
-
- osrfLogError(OSRF_LOG_MARK, "socket_send_timeout(): "
- "timed out on send for socket %d after %d secs, %d usecs: %s",
- sock_fd, secs, usecs, strerror( errno ) );
-
- return -1;
-}
-
-
-/* disconnects the node with the given sock_fd and removes
- it from the socket set */
-void socket_disconnect(socket_manager* mgr, int sock_fd) {
- osrfLogInternal( OSRF_LOG_MARK, "Closing socket %d", sock_fd);
- close( sock_fd );
- socket_remove_node(mgr, sock_fd);
-}
-
-
-/* we assume that if select() fails, the socket is no longer valid */
-int socket_connected(int sock_fd) {
- fd_set read_set;
- FD_ZERO( &read_set );
- FD_SET( sock_fd, &read_set );
- if( select( sock_fd + 1, &read_set, NULL, NULL, NULL) == -1 )
- return 0;
- return 1;
-
-}
-
-/* this only waits on the server socket and does not handle the actual
- data coming in from the client..... XXX */
-int socket_wait(socket_manager* mgr, int timeout, int sock_fd) {
-
- int retval = 0;
- fd_set read_set;
- FD_ZERO( &read_set );
- FD_SET( sock_fd, &read_set );
-
- struct timeval tv;
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
- errno = 0;
-
- if( timeout < 0 ) {
-
- // If timeout is -1, we block indefinitely
- if( (retval = select( sock_fd + 1, &read_set, NULL, NULL, NULL)) == -1 ) {
- osrfLogDebug( OSRF_LOG_MARK, "Call to select() interrupted: Sys Error: %s", strerror(errno));
- return -1;
- }
-
- } else if( timeout > 0 ) { /* timeout of 0 means don't block */
-
- if( (retval = select( sock_fd + 1, &read_set, NULL, NULL, &tv)) == -1 ) {
- osrfLogDebug( OSRF_LOG_MARK, "Call to select() interrupted: Sys Error: %s", strerror(errno));
- return -1;
- }
- }
-
- osrfLogInternal( OSRF_LOG_MARK, "%d active sockets after select()", retval);
- return _socket_route_data_id(mgr, sock_fd);
-}
-
-
-int socket_wait_all(socket_manager* mgr, int timeout) {
-
- if(mgr == NULL) {
- osrfLogWarning( OSRF_LOG_MARK, "socket_wait_all(): null mgr" );
- return -1;
- }
-
- int retval = 0;
- fd_set read_set;
- FD_ZERO( &read_set );
-
- socket_node* node = mgr->socket;
- int max_fd = 0;
- while(node) {
- osrfLogInternal( OSRF_LOG_MARK, "Adding socket fd %d to select set",node->sock_fd);
- FD_SET( node->sock_fd, &read_set );
- if(node->sock_fd > max_fd) max_fd = node->sock_fd;
- node = node->next;
- }
- max_fd += 1;
-
- struct timeval tv;
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
- errno = 0;
-
- if( timeout < 0 ) {
-
- // If timeout is -1, there is no timeout passed to the call to select
- if( (retval = select( max_fd, &read_set, NULL, NULL, NULL)) == -1 ) {
- osrfLogWarning( OSRF_LOG_MARK, "select() call aborted: %s", strerror(errno));
- return -1;
- }
-
- } else if( timeout != 0 ) { /* timeout of 0 means don't block */
-
- if( (retval = select( max_fd, &read_set, NULL, NULL, &tv)) == -1 ) {
- osrfLogWarning( OSRF_LOG_MARK, "select() call aborted: %s", strerror(errno));
- return -1;
- }
- }
-
- osrfLogDebug( OSRF_LOG_MARK, "%d active sockets after select()", retval);
- return _socket_route_data(mgr, retval, &read_set);
-}
-
-/* determines if we'er receiving a new client or data
- on an existing client */
-int _socket_route_data(
- socket_manager* mgr, int num_active, fd_set* read_set) {
-
- if(!(mgr && read_set)) return -1;
-
- int last_failed_id = -1;
-
-
- /* come back here if someone yanks a socket_node from beneath us */
- while(1) {
-
- socket_node* node = mgr->socket;
- int handled = 0;
- int status = 0;
-
- while(node && (handled < num_active)) {
-
- int sock_fd = node->sock_fd;
-
- if(last_failed_id != -1) {
- /* in case it was not removed by our overlords */
- osrfLogInternal( OSRF_LOG_MARK, "Attempting to remove last_failed_id of %d", last_failed_id);
- socket_remove_node( mgr, last_failed_id );
- last_failed_id = -1;
- status = -1;
- break;
- }
-
- /* does this socket have data? */
- if( FD_ISSET( sock_fd, read_set ) ) {
-
- osrfLogInternal( OSRF_LOG_MARK, "Socket %d active", sock_fd);
- handled++;
- FD_CLR(sock_fd, read_set);
-
- if(node->endpoint == SERVER_SOCKET)
- _socket_handle_new_client(mgr, node);
-
- else
- status = _socket_handle_client_data(mgr, node);
-
- /* someone may have yanked a socket_node out from under
- us...start over with the first socket */
- if(status == -1) {
- last_failed_id = sock_fd;
- osrfLogInternal( OSRF_LOG_MARK, "Backtracking back to start of loop because "
- "of -1 return code from _socket_handle_client_data()");
- }
- }
-
- if(status == -1) break;
- node = node->next;
-
- } // is_set
-
- if(status == 0) break;
- if(status == -1) status = 0;
- }
-
- return 0;
-}
-
-
-int _socket_route_data_id( socket_manager* mgr, int sock_id) {
- socket_node* node = socket_find_node(mgr, sock_id);
- int status = 0;
-
- if(node) {
- if(node->endpoint == SERVER_SOCKET)
- _socket_handle_new_client(mgr, node);
-
- if(node->endpoint == CLIENT_SOCKET )
- status = _socket_handle_client_data(mgr, node);
-
- if(status == -1) {
- socket_remove_node(mgr, sock_id);
- return -1;
- }
- return 0;
- }
-
- return -1;
-}
-
-
-int _socket_handle_new_client(socket_manager* mgr, socket_node* node) {
- if(mgr == NULL || node == NULL) return -1;
-
- errno = 0;
- int new_sock_fd;
- new_sock_fd = accept(node->sock_fd, NULL, NULL);
- if(new_sock_fd < 0) {
- osrfLogWarning( OSRF_LOG_MARK, "_socket_handle_new_client(): accept() failed: %s",
- strerror( errno ) );
- return -1;
- }
-
- if(node->addr_type == INET) {
- _socket_add_node(mgr, CLIENT_SOCKET, INET, new_sock_fd, node->sock_fd);
- osrfLogDebug( OSRF_LOG_MARK, "Adding new INET client for %d", node->sock_fd);
-
- } else if(node->addr_type == UNIX) {
- _socket_add_node(mgr, CLIENT_SOCKET, UNIX, new_sock_fd, node->sock_fd);
- osrfLogDebug( OSRF_LOG_MARK, "Adding new UNIX client for %d", node->sock_fd);
- }
-
- return 0;
-}
-
-
-int _socket_handle_client_data(socket_manager* mgr, socket_node* node) {
- if(mgr == NULL || node == NULL) return -1;
-
- char buf[RBUFSIZE];
- int read_bytes;
- int sock_fd = node->sock_fd;
-
- memset(buf, 0, RBUFSIZE);
- set_fl(sock_fd, O_NONBLOCK);
-
- osrfLogInternal( OSRF_LOG_MARK, "%ld : Received data at %f\n", (long) getpid(), get_timestamp_millis());
-
- while( (read_bytes = recv(sock_fd, buf, RBUFSIZE-1, 0) ) > 0 ) {
- osrfLogInternal( OSRF_LOG_MARK, "Socket %d Read %d bytes and data: %s", sock_fd, read_bytes, buf);
- if(mgr->data_received)
- mgr->data_received(mgr->blob, mgr, sock_fd, buf, node->parent_id);
-
- memset(buf, 0, RBUFSIZE);
- }
- int local_errno = errno; /* capture errno as set by recv() */
-
- if(socket_find_node(mgr, sock_fd)) { /* someone may have closed this socket */
- clr_fl(sock_fd, O_NONBLOCK);
- if(read_bytes < 0) {
- if(local_errno != EAGAIN)
- osrfLogWarning(OSRF_LOG_MARK, " * Error reading socket with error %s", strerror(local_errno));
- }
-
- } else { return -1; } /* inform the caller that this node has been tampered with */
-
- if(read_bytes == 0) { /* socket closed by client */
- if(mgr->on_socket_closed) {
- mgr->on_socket_closed(mgr->blob, sock_fd);
- }
- return -1;
- }
-
- return 0;
-
-}
-
-
-void socket_manager_free(socket_manager* mgr) {
- if(mgr == NULL) return;
- socket_node* tmp;
- while(mgr->socket) {
- tmp = mgr->socket->next;
- socket_disconnect(mgr, mgr->socket->sock_fd);
- mgr->socket = tmp;
- }
- free(mgr);
-
-}
-
+++ /dev/null
-#include "utils.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <errno.h>
-
-#include "utils.h"
-#include "log.h"
-
-//---------------------------------------------------------------
-// Unix headers
-//---------------------------------------------------------------
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/un.h>
-
-#include <signal.h>
-
-#ifndef SOCKET_BUNDLE_H
-#define SOCKET_BUNDLE_H
-
-
-#define SERVER_SOCKET 1
-#define CLIENT_SOCKET 2
-
-#define INET 10
-#define UNIX 11
-
-/* buffer used to read from the sockets */
-#define RBUFSIZE 1024
-
-
-/* models a single socket connection */
-struct socket_node_struct {
- int endpoint; /* SERVER_SOCKET or CLIENT_SOCKET */
- int addr_type; /* INET or UNIX */
- int sock_fd;
- int parent_id; /* if we're a new client for a server socket,
- this points to the server socket we spawned from */
- struct socket_node_struct* next;
-};
-typedef struct socket_node_struct socket_node;
-
-
-/* Maintains the socket set */
-struct socket_manager_struct {
- /* callback for passing up any received data. sock_fd is the socket
- that read the data. parent_id (if > 0) is the socket id of the
- server that this socket spawned from (i.e. it's a new client connection) */
- void (*data_received)
- (void* blob, struct socket_manager_struct*,
- int sock_fd, char* data, int parent_id);
-
- void (*on_socket_closed) (void* blob, int sock_fd);
-
- socket_node* socket;
- void* blob;
-};
-typedef struct socket_manager_struct socket_manager;
-
-void socket_manager_free(socket_manager* mgr);
-
-/* creates a new server socket node and adds it to the socket set.
- returns socket id on success. -1 on failure.
- socket_type is one of INET or UNIX */
-int socket_open_tcp_server(socket_manager*, int port, char* listen_ip );
-
-int socket_open_unix_server(socket_manager* mgr, char* path);
-
-int socket_open_udp_server( socket_manager* mgr, int port, char* listen_ip );
-
-/* creates a client TCP socket and adds it to the socket set.
- returns 0 on success. -1 on failure. */
-int socket_open_tcp_client(socket_manager*, int port, char* dest_addr);
-
-/* creates a client UNIX socket and adds it to the socket set.
- returns 0 on success. -1 on failure. */
-int socket_open_unix_client(socket_manager*, char* sock_path);
-
-int socket_open_udp_client( socket_manager* mgr, int port, char* dest_addr);
-
-/* returns the socket_node with the given sock_fd */
-socket_node* socket_find_node(socket_manager*, int sock_fd);
-
-/* removes the node with the given sock_fd from the list and frees it */
-void socket_remove_node(socket_manager*, int sock_fd);
-
-
-/* sends the given data to the given socket. returns 0 on success, -1 otherwise */
-int socket_send(int sock_fd, const char* data);
-
-/* utility method */
-int _socket_send(int sock_fd, const char* data, int flags);
-
-
-/* sends the given data to the given socket.
- * sets the send flag MSG_DONTWAIT which will allow the
- * process to continue even if the socket buffer is full
- * returns 0 on success, -1 otherwise */
-int socket_send_nowait( int sock_fd, const char* data);
-
-/* waits at most usecs microseconds for the socket buffer to
- * be available */
-int socket_send_timeout( int sock_fd, const char* data, int usecs );
-
-/* disconnects the node with the given sock_fd and removes
- it from the socket set */
-void socket_disconnect(socket_manager*, int sock_fd);
-
-/* allocates and inserts a new socket node into the nodeset.
- if parent_id is positive and non-zero, it will be set */
-socket_node* _socket_add_node(socket_manager* mgr,
- int endpoint, int addr_type, int sock_fd, int parent_id );
-
-/* XXX This only works if 'sock_fd' is a client socket... */
-int socket_wait(socket_manager* mgr, int timeout, int sock_fd);
-
-/* waits on all sockets for incoming data.
- timeout == -1 | block indefinitely
- timeout == 0 | don't block, just read any available data off all sockets
- timeout == x | block for at most x seconds */
-int socket_wait_all(socket_manager* mgr, int timeout);
-
-/* iterates over the sockets in the set and handles active sockets.
- new sockets connecting to server sockets cause the creation
- of a new socket node.
- Any new data read is is passed off to the data_received callback
- as it arrives */
-int _socket_route_data(socket_manager* mgr, int num_active, fd_set* read_set);
-
-/* routes data from a single known socket */
-int _socket_route_data_id( socket_manager* mgr, int sock_id);
-
-/* utility function for displaying the currently attached sockets */
-void _socket_print_list(socket_manager* mgr);
-
-int socket_connected(int sock_fd);
-
-
-int _socket_handle_new_client(socket_manager* mgr, socket_node* node);
-int _socket_handle_client_data(socket_manager* mgr, socket_node* node);
-
-
-#endif
+++ /dev/null
-#include "socket_bundle.h"
-
-int count = 0;
-void printme(void* blob, socket_manager* mgr,
- int sock_fd, char* data, int parent_id) {
-
- fprintf(stderr, "Got data from socket %d with parent %d => %s",
- sock_fd, parent_id, data );
-
- socket_send(sock_fd, data);
-
- if(count++ > 2) {
-// socket_disconnect(mgr, sock_fd);
- _socket_print_list(mgr);
- socket_manager_free(mgr);
- exit(0);
- }
-}
-
-int main(int argc, char* argv[]) {
- socket_manager* manager = safe_malloc(sizeof(socket_manager));
- int port = 11000;
- if(argv[1])
- port = atoi(argv[1]);
-
- manager->data_received = &printme;
- socket_open_tcp_server(manager, port);
-
- while(1)
- socket_wait_all(manager, -1);
-
- return 0;
-}
+++ /dev/null
-#include "string_array.h"
-
-osrfStringArray* osrfNewStringArray(int size) {
- return init_string_array(size);
-}
-
-string_array* init_string_array(int size) {
- if(size > STRING_ARRAY_MAX_SIZE)
- osrfLogError( OSRF_LOG_MARK, "init_string_array size is too large");
-
- /*
- string_array* arr =
- (string_array*) safe_malloc(sizeof(string_array));
- */
- string_array* arr;
- OSRF_MALLOC( arr, sizeof(string_array));
-
- //arr->array = (char**) safe_malloc(size * sizeof(char*));
- OSRF_MALLOC(arr->array, size * sizeof(char*));
-
- arr->size = 0;
- arr->arr_size = size;
- return arr;
-}
-
-
-void osrfStringArrayAdd(osrfStringArray* arr, char* string) {
- string_array_add(arr, string);
-}
-
-void string_array_add(string_array* arr, char* str) {
- if(arr == NULL || str == NULL ) return;
- if( strlen(str) < 1 ) return;
-
- arr->size++;
-
- if( arr->size > STRING_ARRAY_MAX_SIZE )
- osrfLogError( OSRF_LOG_MARK, "string_array_add size is too large");
-
- /* if necessary, double capacity */
- if(arr->size >= arr->arr_size) {
- arr->arr_size *= 2;
- //char** tmp = (char**) safe_malloc(arr->arr_size * sizeof(char*));
- char** tmp;
- OSRF_MALLOC( tmp, arr->arr_size * sizeof(char*));
- int i;
-
- /* copy the string pointers over */
- for( i = 0; i!= arr->size; i++ )
- tmp[i] = arr->array[i];
-
- free(arr->array);
- arr->array = tmp;
- }
-
- arr->array[arr->size - 1] = strdup(str);
-}
-
-char* osrfStringArrayGetString(osrfStringArray* arr, int index) {
- return string_array_get_string(arr, index);
-}
-
-char* string_array_get_string(string_array* arr, int index) {
- if(!arr || index < 0 || index >= arr->size ) return NULL;
- return arr->array[index];
-}
-
-
-void osrfStringArrayFree(osrfStringArray* arr) {
- string_array_destroy(arr);
-}
-
-void string_array_destroy(string_array* arr) {
- if(arr) {
- int i = 0;
- while( i < arr->size ) free(arr->array[i++]);
- free(arr->array);
- free(arr);
- }
-}
-
-
-int osrfStringArrayContains( osrfStringArray* arr, char* string ) {
- if(!(arr && string)) return 0;
-
- int i;
- for( i = 0; i != arr->size; i++ ) {
- char* str = osrfStringArrayGetString(arr, i);
- if(str) {
- if(!strcmp(str, string)) return 1;
- }
- }
-
- return 0;
-}
-
-void osrfStringArrayRemove( osrfStringArray* arr, char* tstr) {
- if(!(arr && tstr)) return;
- int i;
- for( i = 0; i != arr->size; i++ ) {
- char* str = osrfStringArrayGetString(arr, i);
- if(str) {
- if(!strcmp(str, tstr)) {
- free(arr->array[i]);
- arr->array[i] = NULL;
- break;
- }
- }
- }
- for( ; i != arr->size; i++ )
- arr->array[i] = arr->array[i+1];
-
- arr->size--;
-}
-
-
+++ /dev/null
-#include <stdio.h>
-
-#include "utils.h"
-#include "log.h"
-
-#define STRING_ARRAY_MAX_SIZE 1024
-
-#ifndef STRING_ARRAY_H
-#define STRING_ARRAY_H
-
-struct string_array_struct {
- char** array;
- int size;
- int arr_size;
- int total_string_size;
-};
-typedef struct string_array_struct string_array;
-typedef struct string_array_struct osrfStringArray;
-
-osrfStringArray* init_string_array(int size);
-osrfStringArray* osrfNewStringArray(int size);
-
-void string_array_add(osrfStringArray*, char* string);
-void osrfStringArrayAdd(osrfStringArray*, char* string);
-
-char* string_array_get_string(osrfStringArray* arr, int index);
-char* osrfStringArrayGetString(osrfStringArray* arr, int index);
-
-/* returns true if this array contains the given string */
-int osrfStringArrayContains( osrfStringArray* arr, char* string );
-
-
-void string_array_destroy(osrfStringArray*);
-void osrfStringArrayFree(osrfStringArray*);
-
-/* total size of all included strings */
-int string_array_get_total_size(osrfStringArray* arr);
-
-void osrfStringArrayRemove( osrfStringArray* arr, char* str);
-
-#endif
+++ /dev/null
-/*
-Copyright (C) 2005 Georgia Public Library Service
-
-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; either version 2
-of the License, or (at your option) any later version.
-
-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.
-*/
-
-#include "utils.h"
-#include <errno.h>
-
-inline void* safe_malloc( int size ) {
- void* ptr = (void*) malloc( size );
- if( ptr == NULL ) {
- perror("safe_malloc(): Out of Memory" );
- exit(99);
- }
- memset( ptr, 0, size );
- return ptr;
-}
-
-
-char** __global_argv = NULL;
-int __global_argv_size = 0;
-
-int init_proc_title( int argc, char* argv[] ) {
-
- __global_argv = argv;
-
- int i = 0;
- while( i < argc ) {
- int len = strlen( __global_argv[i]);
- bzero( __global_argv[i++], len );
- __global_argv_size += len;
- }
-
- __global_argv_size -= 2;
- return 0;
-}
-
-int set_proc_title( char* format, ... ) {
- VA_LIST_TO_STRING(format);
- bzero( *(__global_argv), __global_argv_size );
- return snprintf( *(__global_argv), __global_argv_size, VA_BUF );
-}
-
-
-/* utility method for profiling */
-double get_timestamp_millis() {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- double time = (int)tv.tv_sec + ( ((double)tv.tv_usec / 1000000) );
- return time;
-}
-
-
-/* setting/clearing file flags */
-int set_fl( int fd, int flags ) {
-
- int val;
-
- if( (val = fcntl( fd, F_GETFL, 0) ) < 0 )
- return -1;
-
- val |= flags;
-
- if( fcntl( fd, F_SETFL, val ) < 0 )
- return -1;
-
- return 0;
-}
-
-int clr_fl( int fd, int flags ) {
-
- int val;
-
- if( (val = fcntl( fd, F_GETFL, 0) ) < 0 )
- return -1;
-
- val &= ~flags;
-
- if( fcntl( fd, F_SETFL, val ) < 0 )
- return -1;
-
- return 0;
-}
-
-long va_list_size(const char* format, va_list args) {
- int len = 0;
- len = vsnprintf(NULL, 0, format, args);
- va_end(args);
- len += 2;
- return len;
-}
-
-
-char* va_list_to_string(const char* format, ...) {
-
- long len = 0;
- va_list args;
- va_list a_copy;
-
- va_copy(a_copy, args);
-
- va_start(args, format);
- len = va_list_size(format, args);
-
- char buf[len];
- memset(buf, 0, len);
-
- va_start(a_copy, format);
- vsnprintf(buf, len - 1, format, a_copy);
- va_end(a_copy);
- return strdup(buf);
-}
-
-// ---------------------------------------------------------------------------------
-// Flesh out a ubiqitous growing string buffer
-// ---------------------------------------------------------------------------------
-
-growing_buffer* buffer_init(int num_initial_bytes) {
-
- if( num_initial_bytes > BUFFER_MAX_SIZE ) return NULL;
-
- size_t len = sizeof(growing_buffer);
-
- growing_buffer* gb;
- OSRF_MALLOC(gb, len);
-
- gb->n_used = 0;/* nothing stored so far */
- gb->size = num_initial_bytes;
- OSRF_MALLOC(gb->buf, gb->size + 1);
-
- return gb;
-}
-
-
-int buffer_fadd(growing_buffer* gb, const char* format, ... ) {
-
- if(!gb || !format) return 0;
-
- long len = 0;
- va_list args;
- va_list a_copy;
-
- va_copy(a_copy, args);
-
- va_start(args, format);
- len = va_list_size(format, args);
-
- char buf[len];
- memset(buf, 0, len);
-
- va_start(a_copy, format);
- vsnprintf(buf, len - 1, format, a_copy);
- va_end(a_copy);
-
- return buffer_add(gb, buf);
-
-}
-
-
-int buffer_add(growing_buffer* gb, char* data) {
- if(!(gb && data)) return 0;
-
- int data_len = strlen( data );
-
- if(data_len == 0) return 0;
-
- int total_len = data_len + gb->n_used;
-
- if( total_len >= gb->size ) {
- while( total_len >= gb->size ) {
- gb->size *= 2;
- }
-
- if( gb->size > BUFFER_MAX_SIZE ) {
- fprintf(stderr, "Buffer reached MAX_SIZE of %d", BUFFER_MAX_SIZE );
- buffer_free( gb );
- return 0;
- }
-
- char* new_data;
- OSRF_MALLOC(new_data, gb->size );
-
- strcpy( new_data, gb->buf );
- free( gb->buf );
- gb->buf = new_data;
- }
-
- strcat( gb->buf, data );
- gb->n_used = total_len;
- return total_len;
-}
-
-
-int buffer_reset( growing_buffer *gb){
- if( gb == NULL ) { return 0; }
- if( gb->buf == NULL ) { return 0; }
- memset( gb->buf, 0, gb->size );
- gb->n_used = 0;
- return 1;
-}
-
-/* Return a pointer to the text within a growing_buffer, */
-/* while destroying the growing_buffer itself. */
-
-char* buffer_release( growing_buffer* gb) {
- char* s = gb->buf;
- s[gb->n_used] = '\0';
- free( gb );
- return s;
-}
-
-/* Destroy a growing_buffer and the text it contains */
-
-int buffer_free( growing_buffer* gb ) {
- if( gb == NULL )
- return 0;
- free( gb->buf );
- free( gb );
- return 1;
-}
-
-char* buffer_data( growing_buffer *gb) {
- return strdup( gb->buf );
-}
-
-
-/*
-#define OSRF_BUFFER_ADD_CHAR(gb, c)\
- do {\
- if(gb) {\
- if(gb->n_used < gb->size - 1)\
- gb->buf[gb->n_used++] = c;\
- else\
- buffer_add_char(gb, c);\
- }\
- }while(0)
- */
-
-int buffer_add_char(growing_buffer* gb, char c) {
- char buf[2];
- buf[0] = c;
- buf[1] = '\0';
- buffer_add(gb, buf);
- return 1;
-}
-
-
-
-char* uescape( const char* string, int size, int full_escape ) {
-
- growing_buffer* buf = buffer_init(size + 64);
- int clen = 0;
- int idx = 0;
- unsigned long int c = 0x0;
-
- while (string[idx]) {
-
- c = 0x0;
-
- if ((unsigned char)string[idx] >= 0x80) { // not ASCII
-
- if ((unsigned char)string[idx] >= 0xC0 && (unsigned char)string[idx] <= 0xF4) { // starts a UTF8 string
-
- clen = 1;
- if (((unsigned char)string[idx] & 0xF0) == 0xF0) {
- clen = 3;
- c = (unsigned char)string[idx] ^ 0xF0;
-
- } else if (((unsigned char)string[idx] & 0xE0) == 0xE0) {
- clen = 2;
- c = (unsigned char)string[idx] ^ 0xE0;
-
- } else if (((unsigned char)string[idx] & 0xC0) == 0xC0) {
- clen = 1;
- c = (unsigned char)string[idx] ^ 0xC0;
- }
-
- for (;clen;clen--) {
-
- idx++; // look at the next byte
- c = (c << 6) | ((unsigned char)string[idx] & 0x3F); // add this byte worth
-
- }
-
- buffer_fadd(buf, "\\u%04x", c);
-
- } else {
- buffer_free(buf);
- return NULL;
- }
-
- } else {
- c = string[idx];
-
- /* escape the usual suspects */
- if(full_escape) {
- switch(c) {
- case '"':
- OSRF_BUFFER_ADD_CHAR(buf, '\\');
- OSRF_BUFFER_ADD_CHAR(buf, '"');
- break;
-
- case '\b':
- OSRF_BUFFER_ADD_CHAR(buf, '\\');
- OSRF_BUFFER_ADD_CHAR(buf, 'b');
- break;
-
- case '\f':
- OSRF_BUFFER_ADD_CHAR(buf, '\\');
- OSRF_BUFFER_ADD_CHAR(buf, 'f');
- break;
-
- case '\t':
- OSRF_BUFFER_ADD_CHAR(buf, '\\');
- OSRF_BUFFER_ADD_CHAR(buf, 't');
- break;
-
- case '\n':
- OSRF_BUFFER_ADD_CHAR(buf, '\\');
- OSRF_BUFFER_ADD_CHAR(buf, 'n');
- break;
-
- case '\r':
- OSRF_BUFFER_ADD_CHAR(buf, '\\');
- OSRF_BUFFER_ADD_CHAR(buf, 'r');
- break;
-
- case '\\':
- OSRF_BUFFER_ADD_CHAR(buf, '\\');
- OSRF_BUFFER_ADD_CHAR(buf, '\\');
- break;
-
- default:
- if( c < 32 ) buffer_fadd(buf, "\\u%04x", c);
- else OSRF_BUFFER_ADD_CHAR(buf, c);
- }
-
- } else {
- OSRF_BUFFER_ADD_CHAR(buf, c);
- }
- }
-
- idx++;
- }
-
- char* d = buffer_data(buf);
- buffer_free(buf);
- return d;
-}
-
-
-// A function to turn a process into a daemon and set it's process name in ps/top
-int daemonize() {
- int f = fork();
-
- if (f == -1) {
- perror("Failed to fork!");
- return -1;
-
- } else if (f == 0) { // We're in the child now...
- setsid();
- return 0;
-
- } else { // We're in the parent...
- exit(0);
- }
-}
-
-
-/* Return 1 if the string represents an integer, */
-/* as recognized by strtol(); Otherwise return 0. */
-
-int stringisnum(char* s) {
- char* w;
- strtol(s, &w, 10);
- return *w ? 0 : 1;
-}
-
-
-
-char* file_to_string(const char* filename) {
-
- if(!filename) return NULL;
-
- int len = 1024;
- char buf[len];
- bzero(buf, len);
- growing_buffer* gb = buffer_init(len);
-
- FILE* file = fopen(filename, "r");
- if(!file) {
- int l = strlen(filename) + 64;
- char b[l];
- snprintf(b,l,"Unable to open file [%s] in file_to_string()", filename);
- perror(b);
- return NULL;
- }
-
- while(fgets(buf, len - 1, file)) {
- buffer_add(gb, buf);
- bzero(buf, len);
- }
-
- fclose(file);
-
- char* data = buffer_data(gb);
- buffer_free(gb);
- return data;
-}
-
-
-char* md5sum( char* text, ... ) {
-
- struct md5_ctx ctx;
- unsigned char digest[16];
-
- MD5_start (&ctx);
-
- VA_LIST_TO_STRING(text);
-
- int i;
- for ( i=0 ; i != strlen(VA_BUF) ; i++ )
- MD5_feed (&ctx, VA_BUF[i]);
-
- MD5_stop (&ctx, digest);
-
- char buf[16];
- memset(buf,0,16);
-
- char final[256];
- memset(final,0,256);
-
- for ( i=0 ; i<16 ; i++ ) {
- sprintf(buf, "%02x", digest[i]);
- strcat( final, buf );
- }
-
- return strdup(final);
-
-}
-
-int osrfUtilsCheckFileDescriptor( int fd ) {
-
- fd_set tmpset;
- FD_ZERO(&tmpset);
- FD_SET(fd, &tmpset);
-
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- if( select(fd + 1, &tmpset, NULL, NULL, &tv) == -1 ) {
- if( errno == EBADF ) return -1;
- }
-
- return 0;
-}
-
+++ /dev/null
-/*
-Copyright (C) 2005 Georgia Public Library Service
-Bill Erickson <highfalutin@gmail.com>
-Mike Rylander <mrylander@gmail.com>
-
-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; either version 2
-of the License, or (at your option) any later version.
-
-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.
-*/
-
-#ifndef UTILS_H
-#define UTILS_H
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <string.h>
-//#include <sys/timeb.h>
-
-#include "md5.h"
-
-#define OSRF_MALLOC(ptr, size) \
- do {\
- ptr = (void*) malloc( size ); \
- if( ptr == NULL ) { \
- perror("OSRF_MALLOC(): Out of Memory" );\
- exit(99); \
- } \
- memset( ptr, 0, size );\
- } while(0)
-
-
-#define OSRF_BUFFER_ADD(gb, data) \
- do {\
- int __tl; \
- if(gb && data) {\
- __tl = strlen(data) + gb->n_used;\
- if( __tl < gb->size ) {\
- strcat(gb->buf, data);\
- gb->n_used = __tl; \
- } else { buffer_add(gb, data); }\
- }\
- } while(0)
-
-#define OSRF_BUFFER_ADD_CHAR(gb, c)\
- do {\
- if(gb) {\
- if(gb->n_used < gb->size - 1)\
- gb->buf[gb->n_used++] = c;\
- else\
- buffer_add_char(gb, c);\
- }\
- }while(0)
-
-
-
-
-/* turns a va_list into a string */
-#define VA_LIST_TO_STRING(x) \
- unsigned long __len = 0;\
- va_list args; \
- va_list a_copy;\
- va_copy(a_copy, args); \
- va_start(args, x); \
- __len = vsnprintf(NULL, 0, x, args); \
- va_end(args); \
- __len += 2; \
- char _b[__len]; \
- bzero(_b, __len); \
- va_start(a_copy, x); \
- vsnprintf(_b, __len - 1, x, a_copy); \
- va_end(a_copy); \
- char* VA_BUF = _b; \
-
-/* turns a long into a string */
-#define LONG_TO_STRING(l) \
- unsigned int __len = snprintf(NULL, 0, "%ld", l) + 2;\
- char __b[__len]; \
- bzero(__b, __len); \
- snprintf(__b, __len - 1, "%ld", l); \
- char* LONGSTR = __b;
-
-#define DOUBLE_TO_STRING(l) \
- unsigned int __len = snprintf(NULL, 0, "%f", l) + 2; \
- char __b[__len]; \
- bzero(__b, __len); \
- snprintf(__b, __len - 1, "%f", l); \
- char* DOUBLESTR = __b;
-
-#define LONG_DOUBLE_TO_STRING(l) \
- unsigned int __len = snprintf(NULL, 0, "%Lf", l) + 2; \
- char __b[__len]; \
- bzero(__b, __len); \
- snprintf(__b, __len - 1, "%Lf", l); \
- char* LONGDOUBLESTR = __b;
-
-
-#define INT_TO_STRING(l) \
- unsigned int __len = snprintf(NULL, 0, "%d", l) + 2; \
- char __b[__len]; \
- bzero(__b, __len); \
- snprintf(__b, __len - 1, "%d", l); \
- char* INTSTR = __b;
-
-
-/*
-#define MD5SUM(s) \
- struct md5_ctx ctx; \
- unsigned char digest[16];\
- MD5_start (&ctx);\
- int i;\
- for ( i=0 ; i != strlen(text) ; i++ ) MD5_feed (&ctx, text[i]);\
- MD5_stop (&ctx, digest);\
- char buf[16];\
- memset(buf,0,16);\
- char final[256];\
- memset(final,0,256);\
- for ( i=0 ; i<16 ; i++ ) {\
- sprintf(buf, "%02x", digest[i]);\
- strcat( final, buf );\
- }\
- char* MD5STR = final;
- */
-
-
-
-
-
-#define BUFFER_MAX_SIZE 10485760
-
-/* these are evil and should be condemned
- ! Only use these if you are done with argv[].
- call init_proc_title() first, then call
- set_proc_title.
- the title is only allowed to be as big as the
- initial process name of the process (full size of argv[]).
- truncation may occurr.
- */
-int init_proc_title( int argc, char* argv[] );
-int set_proc_title( char* format, ... );
-
-
-int daemonize();
-
-void* safe_malloc(int size);
-
-// ---------------------------------------------------------------------------------
-// Generic growing buffer. Add data all you want
-// ---------------------------------------------------------------------------------
-struct growing_buffer_struct {
- char *buf;
- int n_used;
- int size;
-};
-typedef struct growing_buffer_struct growing_buffer;
-
-growing_buffer* buffer_init( int initial_num_bytes);
-
-// XXX This isn't defined in utils.c!! removing for now...
-//int buffer_addchar(growing_buffer* gb, char c);
-
-int buffer_add(growing_buffer* gb, char* c);
-int buffer_fadd(growing_buffer* gb, const char* format, ... );
-int buffer_reset( growing_buffer* gb);
-char* buffer_data( growing_buffer* gb);
-char* buffer_release( growing_buffer* gb );
-int buffer_free( growing_buffer* gb );
-int buffer_add_char(growing_buffer* gb, char c);
-
-/* returns the size needed to fill in the vsnprintf buffer.
- * ! this calls va_end on the va_list argument*
- */
-long va_list_size(const char* format, va_list);
-
-/* turns a va list into a string, caller must free the
- allocated char */
-char* va_list_to_string(const char* format, ...);
-
-
-/* string escape utility method. escapes unicode embeded characters.
- escapes the usual \n, \t, etc.
- for example, if you provide a string like so:
-
- hello,
- you
-
- you would get back:
- hello,\n\tyou
-
- */
-char* uescape( const char* string, int size, int full_escape );
-
-/* utility methods */
-int set_fl( int fd, int flags );
-int clr_fl( int fd, int flags );
-
-
-
-// Utility method
-double get_timestamp_millis();
-
-
-/* returns true if the whole string is a number */
-int stringisnum(char* s);
-
-/* reads a file and returns the string version of the file
- user is responsible for freeing the returned char*
- */
-char* file_to_string(const char* filename);
-
-
-
-/**
- Calculates the md5 of the text provided.
- The returned string must be freed by the caller.
- */
-char* md5sum( char* text, ... );
-
-
-/**
- Checks the validity of the file descriptor
- returns -1 if the file descriptor is invalid
- returns 0 if the descriptor is OK
- */
-int osrfUtilsCheckFileDescriptor( int fd );
-
-#endif
+++ /dev/null
-#include "xml_utils.h"
-
-
-void recurse_doc( xmlNodePtr node ) {
- if( node == NULL ) return;
- printf("Recurse: %s => %s", node->name, node->content );
- xmlNodePtr t = node->children;
- while(t) {
- recurse_doc(t);
- t = t->next;
- }
-}
-
-
-
-jsonObject* xmlDocToJSON(xmlDocPtr doc) {
- if(!doc) return NULL;
- return _xmlToJSON(xmlDocGetRootElement(doc), NULL);
-}
-
-jsonObject* _xmlToJSON(xmlNodePtr node, jsonObject* obj) {
-
- if(!node) return NULL;
- if(xmlIsBlankNode(node)) return NULL;
- if(obj == NULL) obj = jsonNewObject(NULL);
-
- if(node->type == XML_TEXT_NODE) {
- jsonObjectSetString(obj, (char*) node->content);
-
- } else if(node->type == XML_ELEMENT_NODE || node->type == XML_ATTRIBUTE_NODE ) {
-
- jsonObject* new_obj = jsonNewObject(NULL);
-
- jsonObject* old;
-
- /* do the duplicate node / array shuffle */
- if( (old = jsonObjectGetKey(obj, (char*) node->name)) ) {
- if(old->type == JSON_ARRAY ) {
- jsonObjectPush(old, new_obj);
- } else {
- jsonObject* arr = jsonNewObject(NULL);
- jsonObjectPush(arr, jsonObjectClone(old));
- jsonObjectPush(arr, new_obj);
- jsonObjectSetKey(obj, (char*) node->name, arr);
- }
- } else {
- jsonObjectSetKey(obj, (char*) node->name, new_obj);
- }
-
- xmlNodePtr child = node->children;
- if (child) { // at least one...
- if (child != node->last) { // more than one -- ignore TEXT nodes
- while(child) {
- if (child->type != XML_TEXT_NODE) _xmlToJSON(child, new_obj);
- child = child->next;
- }
- } else {
- _xmlToJSON(child, new_obj);
- }
- }
- }
-
- return obj;
-}
-
-
-char* xmlDocToString(xmlDocPtr doc, int full) {
-
- if(!doc) return NULL;
-
- char* xml;
-
- if(full) {
-
- xmlChar* xmlbuf;
- int size;
- xmlDocDumpMemory(doc, &xmlbuf, &size);
- xml = strdup((char*) (xmlbuf));
- xmlFree(xmlbuf);
- return xml;
-
- } else {
-
- xmlBufferPtr xmlbuf = xmlBufferCreate();
- xmlNodeDump( xmlbuf, doc, xmlDocGetRootElement(doc), 0, 0);
- xml = strdup((char*) (xmlBufferContent(xmlbuf)));
- xmlBufferFree(xmlbuf);
- return xml;
-
- }
-}
-
-
-
-
-char* xmlSaxAttr( const xmlChar** atts, char* name ) {
- if( atts && name ) {
- int i;
- for(i = 0; (atts[i] != NULL); i++) {
- if(!strcmp(atts[i], name)) {
- if(atts[++i]) return (char*) atts[i];
- }
- }
- }
- return NULL;
-}
-
-
-int xmlAddAttrs( xmlNodePtr node, const xmlChar** atts ) {
- if( node && atts ) {
- int i;
- for(i = 0; (atts[i] != NULL); i++) {
- if(atts[i+1]) {
- xmlSetProp(node, atts[i], atts[i+1]);
- i++;
- }
- }
- }
- return 0;
-}
-
+++ /dev/null
-#ifndef _XML_UTILS_H
-#define _XML_UTILS_H
-
-#include "objson/object.h"
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-
-jsonObject* xmlDocToJSON(xmlDocPtr doc);
-
-/* helper function */
-jsonObject* _xmlToJSON(xmlNodePtr node, jsonObject*);
-
-/* debug function, prints each node and content */
-void recurse_doc( xmlNodePtr node );
-
-
-/* turns an XML doc into a char*.
- User is responsible for freeing the returned char*
- if(full), then we return the whole doc (xml declaration, etc.)
- else we return the doc from the root node down
- */
-char* xmlDocToString(xmlDocPtr doc, int full);
-
-
-/* Takes an xmlChar** from a SAX callback and returns the value
- for the attribute with name 'name'
- */
-char* xmlSaxAttr( const xmlChar** atts, char* name );
-
-/**
- Sets the xml attributes from atts to the given dom node
- */
-int xmlAddAttrs( xmlNodePtr node, const xmlChar** atts );
-
-
-#endif
+++ /dev/null
-SO=mod_xinclude.so
-
-# --------------------------------------------------------
-TMPDIR = /tmp/ilstmp/opensrf
-LIBDIR = /openils/lib
-CC_OPTS = -Wall -O2 -fPIC -I /usr/include/libxml2 -I /opt/include
-LD_OPTS = -lxml2
-APXS2 = /opt/bin/apxs
-# --------------------------------------------------------
-
-all: $(SO)
-
-install:
- cp $(TMPDIR)/$(SO) $(LIBDIR)/$(SO)
- $(APXS2) -i -a -n xinclude $(LIBDIR)/$(SO)
-
-$(SO): mod_xinclude.c
- $(CC) -c $(CC_OPTS) mod_xinclude.c
- $(CC) $(LD_OPTS) -shared -W1 mod_xinclude.o -o $(TMPDIR)/$(SO)
-
-clean:
- /bin/rm -f *.o *.so
+++ /dev/null
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_protocol.h"
-#include "apr_compat.h"
-#include "apr_strings.h"
-
-#include <libxml/parser.h>
-#include <libxml/xinclude.h>
-
-#define MODULE_NAME "xinclude_module"
-
-static int mod_xinclude_handler (request_rec *r) {
-
- /* make sure we're needed first thing*/
- if (strcmp(r->handler, MODULE_NAME ))
- return DECLINED;
-
- /* set content type */
- ap_set_content_type(r, "text/html");
-
-
- /* which file are we parsing */
- char* file = r->filename;
-
- if(!file) {
- fprintf(stderr, "No XML file to parse");
- fflush(stderr);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* parse the doc */
- xmlDocPtr doc = xmlParseFile(file);
-
- if(!doc) {
- fprintf(stderr, "Error parsing XML file %s\n", file);
- fflush(stderr);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* process the xincludes */
- int status = xmlXIncludeProcess(doc);
-
- if(status < 0) {
- fprintf(stderr, "Error processing XIncludes in XML file %s\n", file);
- fflush(stderr);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- xmlBufferPtr xmlbuf = xmlBufferCreate();
- xmlNodeDump( xmlbuf, doc, xmlDocGetRootElement(doc), 0, 0);
- char* xml = (char*) (xmlBufferContent(xmlbuf));
-
- ap_rputs(xml,r);
-
- xmlBufferFree(xmlbuf);
- xmlFreeDoc(doc);
-
- return OK;
-}
-
-
-static void mod_xinclude_register_hooks (apr_pool_t *p) {
- ap_hook_handler(mod_xinclude_handler, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA xinclude_module = {
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- mod_xinclude_register_hooks,
-};
-