all:
- @source install.conf && make -s -C src all
+ @echo -e "\n * Run 'make verbose' to see full make output\n"
+ source install.conf && make -s -C src all
+
+verbose:
+ source install.conf && make -C src all
jserver:
- @source install.conf && make -s -C src jserver
+ source install.conf && make -s -C src jserver
install:
- @source install.conf && make -s -C src install
+ source install.conf && make -s -C src install
jserver-install:
- @source install.conf && make -s -C src jserver-install
+ source install.conf && make -s -C src jserver-install
clean:
- @make -s -C src clean
+ make -s -C src clean
--- /dev/null
+
+#include <string.h>
+#include <stdio.h>
+
+/* the JSON parser, so we can read the response we're XMLizing */
+#include <objson/object.h>
+#include <objson/json_parser.h>
+#include <opensrf/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.
+*/
+
+
+
+
+/* ---------------------------------------------------------------------------------------
+ JSON parser.
+ * --------------------------------------------------------------------------------------- */
+#ifndef JSON_PARSER_H
+#define JSON_PARSER_H
+
+#include <stdio.h>
+#include <objson/object.h>
+#include <opensrf/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.
+*/
+
+
+/* ---------------------------------------------------------------------------------------
+ libjson
+ * --------------------------------------------------------------------------------------- */
+
+#ifndef _JSON_OBJECT_H
+#define _JSON_OBJECT_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <opensrf/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
+
+#include <stdio.h>
+#include <string.h>
+#include <libxml/globals.h>
+#include <libxml/xmlerror.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+
+#include <objson/object.h>
+#include <objson/json_parser.h>
+#include <opensrf/utils.h>
+#include <opensrf/osrf_list.h>
+
+
+jsonObject* jsonXMLToJSONObject(const char* xml);
+
+
+
--- /dev/null
+#include <opensrf/utils.h>
+
+#include <syslog.h>
+#include <stdio.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__
+
+
+/* Initializes the logger. */
+void osrfLogInit( int type, const char* appname, int maxlevel );
+
+/** 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 );
+
+/** Set or Get the global log level. Any log statements with a higher level
+ * than "level" will not be logged */
+void osrfLogSetLevel( int loglevel );
+int osrfLogGetLevel( void );
+
+/* 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 );
+
+/* 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 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
+/*
+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 <opensrf/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
+#ifndef _OSRF_APP_SESSION
+#define _OSRF_APP_SESSION
+
+#include <opensrf/transport_client.h>
+#include <opensrf/osrf_message.h>
+#include <opensrf/osrf_system.h>
+#include <opensrf/string_array.h>
+#include <opensrf/osrfConfig.h>
+#include <opensrf/osrf_hash.h>
+#include <opensrf/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 <opensrf/utils.h>
+#include <opensrf/log.h>
+#include <opensrf/osrf_app_session.h>
+#include <opensrf/osrf_hash.h>
+
+#include <objson/object.h>
+#include <stdio.h>
+#include <dlfcn.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
+#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
+#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 <objson/object.h>
+#include <objson/json_parser.h>
+#include <memcache.h>
+#include <opensrf/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
+#ifndef OSRF_HASH_H
+#define OSRF_HASH_H
+
+#include <opensrf/utils.h>
+#include <opensrf/string_array.h>
+#include <opensrf/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
+#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 <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 <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 <opensrf/osrf_stack.h>
+#include <opensrf/osrf_settings.h>
+#include <opensrf/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
+#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 <opensrf/osrf_app_session.h>
+
+#include <objson/object.h>
+#include <objson/json_parser.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 <opensrf/transport_client.h>
+#include <opensrf/osrf_message.h>
+#include <opensrf/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
+#ifndef OSRF_SYSTEM_H
+#define OSRF_SYSTEM_H
+
+#include <opensrf/transport_client.h>
+#include <opensrf/utils.h>
+#include <opensrf/log.h>
+#include <opensrf/osrf_settings.h>
+#include <opensrf/osrfConfig.h>
+#include <opensrf/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 <opensrf/transport_client.h>
+#include <opensrf/transport_message.h>
+#include <opensrf/osrf_list.h>
+#include <opensrf/osrf_hash.h>
+#include <opensrf/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
+// 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 <opensrf/utils.h>
+#include <opensrf/log.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.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
+
+
+/* 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);
+
+/* sends the given data to the given socket. returns 0 on success, -1 otherwise */
+int socket_send(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);
+
+/* 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);
+
+/* utility function for displaying the currently attached sockets */
+void _socket_print_list(socket_manager* mgr);
+
+int socket_connected(int sock_fd);
+
+#endif
--- /dev/null
+#include <stdio.h>
+
+#include <opensrf/utils.h>
+#include <opensrf/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
+#include <opensrf/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 <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
+// ---------------------------------------------------------------------------------
+// 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 <opensrf/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.
+*/
+
+#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
+#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
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
+export LDFLAGS += -Wl,-rpath=$(LIBDIR) -L $(TMPDIR) -L .
+export CFLAGS += -pipe -g -Wall -O2 -fPIC -I ../../include/ -I$(LIBXML2_HEADERS) -I$(APACHE2_HEADERS) \
+ -I$(LIBXML2_HEADERS)/libxml -I$(APR_HEADERS)
all: prep \
- libopensrf.so \
- libstack/opensrf \
+ opensrf \
router \
srfsh \
jserver \
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
+# --------------------------------------------------------------------------------
+# BINARIES and LIBS
+# --------------------------------------------------------------------------------
-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
-
+prep:
+ mkdir -p $(TMPDIR)
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 $@
-
+opensrf: objson/libobjson.so
+ make -C libopensrf
+ make -C c-apps
-router: libopensrf.so
+router: opensrf
@echo $@
make -C router
-srfsh: libopensrf.so
+srfsh: opensrf
@echo $@
make -C srfsh
-gateway: libopensrf.so
+gateway: opensrf
@echo $@
make -C gateway
-jserver: libopensrf.so
+jserver: opensrf
@echo $@
make -C jserver
# --------------------------------------------------------------------------------
# INSTALL
# --------------------------------------------------------------------------------
+
+# make sure the install directories exist
install-prep:
@echo $@
mkdir -p $(LIBDIR)
mkdir -p $(BINDIR)
mkdir -p $(PERLDIR)
mkdir -p $(INCLUDEDIR)
- mkdir -p $(INCLUDEDIR)/$(OPENSRF)
mkdir -p $(ETCDIR)
objson-install: install-prep
@echo $@
make -C objson install
-libopensrf-install: install-prep
+# installs libopensrf.so, opensrf-c, headers, example configs, and osrf_ctl.sh
+opensrf-install: objson-install
@echo $@
- cp $(TMPDIR)/$(LIBOPENSRF) $(LIBDIR)
+ cp $(TMPDIR)/libopensrf.so $(LIBDIR)/libopensrf.so
+ cp -r ../include/opensrf $(INCLUDEDIR)
+ cp libopensrf/opensrf $(BINDIR)/opensrf-c
+ make -C c-apps install
+ 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)
gateway-install: install-prep opensrf-install
@echo $@
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 libopensrf 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
+#include <opensrf/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 <opensrf/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 <opensrf/log.h>
+
+static int _osrfLogType = -1;
+static int _osrfLogFacility = LOG_LOCAL0;
+static int _osrfLogActFacility = LOG_LOCAL1;
+static char* _osrfLogFile = NULL;
+static char* _osrfLogAppname = NULL;
+static int _osrfLogLevel = OSRF_LOG_INFO;
+static int _osrfLogActivityEnabled = 1;
+static int _osrfLogIsClient = 0;
+
+static char* _osrfLogXid = NULL; /* current xid */
+static char* _osrfLogXidPfx = NULL; /* xid prefix string */
+
+static void osrfLogSetType( int logtype );
+static void _osrfLogDetail( int level, const char* filename, int line, char* msg );
+static void _osrfLogToFile( char* msg, ... );
+static void _osrfLogSetXid(char* xid);
+
+#define OSRF_LOG_GO(f,li,m,l) \
+ if(!m) return; \
+ VA_LIST_TO_STRING(m); \
+ _osrfLogDetail( l, f, li, VA_BUF );
+
+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) {
+ static int _osrfLogXidInc = 0; /* increments with each new xid for uniqueness */
+ 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;
+}
+
+/** Sets the type of logging to perform. See log types */
+static 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;
+}
+
+/** Sets the global log level. Any log statements with a higher level
+ * than "level" will not be logged */
+void osrfLogSetLevel( int loglevel ) {
+ _osrfLogLevel = loglevel;
+}
+
+/** Gets the current global log level. **/
+int osrfLogGetLevel( void ) {
+ return _osrfLogLevel;
+}
+
+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 */
+}
+
+/** Actually does the logging */
+static 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 );
+
+}
+
+
+static 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
+/* --- 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"
+#include "opensrf/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
+#include <opensrf/osrf_system.h>
+//#include <opensrf/osrf_hash.h>
+//#include <opensrf/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" );
+
+ int ret = osrfSystemBootstrap( host, config, context );
+
+ if (ret != 0) {
+ osrfLogError(
+ OSRF_LOG_MARK,
+ "Server Loop returned an error condition, exiting with %d",
+ ret
+ );
+ }
+
+
+ free(host);
+ free(config);
+ free(context);
+
+ return ret;
+}
+
+
--- /dev/null
+/* defines the currently used bootstrap config file */
+#include <opensrf/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;
+
+ // Load XML from the configuration file
+
+ xmlDocPtr doc = xmlParseFile(configFile);
+ if(!doc) {
+ fprintf( stderr, "osrfConfigInit: Unable to parse XML config file %s\n", configFile);
+ osrfLogWarning( OSRF_LOG_MARK, "Unable to parse XML config file %s", configFile);
+ return NULL;
+ }
+
+ // Translate it into a jsonObject
+
+ jsonObject* json_config = xmlDocToJSON(doc);
+ xmlFreeDoc(doc);
+
+ if(!json_config ) {
+ fprintf( stderr, "osrfConfigInit: xmlDocToJSON failed for config %s\n", configFile);
+ osrfLogWarning( OSRF_LOG_MARK, "xmlDocToJSON failed for config %s", configFile);
+ return NULL;
+ }
+
+ // Build an osrfConfig and return it by pointer
+
+ osrfConfig* cfg = safe_malloc(sizeof(osrfConfig));
+
+ if(configContext) cfg->configContext = strdup(configContext);
+ else cfg->configContext = NULL;
+
+ cfg->config = json_config;
+
+ 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
+#include <opensrf/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
+#include <opensrf/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 <opensrf/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
+#include <opensrf/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
+/*
+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 <opensrf/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
+#include <opensrf/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
+#include <opensrf/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
+#include <opensrf/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/osrf_prefork.h>
+#include <opensrf/osrf_app_session.h>
+#include <opensrf/osrf_application.h>
+#include <signal.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 <opensrf/osrf_settings.h>
+
+osrf_host_config* config = NULL;
+
+char* osrf_settings_host_value(char* format, ...) {
+ VA_LIST_TO_STRING(format);
+
+ if( ! config ) {
+ const char * msg = "NULL config pointer";
+ fprintf( stderr, "osrf_settings_host_value: %s\n", msg );
+ osrfLogError( OSRF_LOG_MARK, msg );
+ exit( 99 );
+ }
+
+ 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) {
+ osrfLogError( OSRF_LOG_MARK, "No osrf_message received from host %s (timeout?)", hostname);
+ } else if(!omsg->_result_content) {
+ osrf_message_free(omsg);
+ osrfLogError(
+ OSRF_LOG_MARK,
+ "NULL or non-existant osrf_message result content received from host %s, "
+ "broken message or no settings for host",
+ hostname
+ );
+ } else {
+ 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
+#include <opensrf/osrf_stack.h>
+#include <opensrf/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/osrf_system.h>
+#include <opensrf/osrf_application.h>
+#include <opensrf/osrf_prefork.h>
+#include <signal.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 for host %s from configuration file %s",
+ hostname, configfile );
+ return -1;
+ }
+
+ int retcode = osrf_settings_retrieve(hostname);
+ osrf_system_disconnect_client();
+
+ if( retcode ) {
+ osrfLogError( OSRF_LOG_MARK,
+ "Unable to retrieve settings for host %s from configuration file %s",
+ hostname, configfile );
+ return -1;
+ }
+
+ 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
+#include <opensrf/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
+/*
+ * 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
+#include <opensrf/socket_bundle.h>
+
+/* buffer used to read from the sockets */
+#define RBUFSIZE 1024
+
+static socket_node* _socket_add_node(socket_manager* mgr,
+ int endpoint, int addr_type, int sock_fd, int parent_id );
+static socket_node* socket_find_node(socket_manager* mgr, int sock_fd);
+static void socket_remove_node(socket_manager*, int sock_fd);
+static int _socket_send(int sock_fd, const char* data, int flags);
+static int _socket_route_data(socket_manager* mgr, int num_active, fd_set* read_set);
+static int _socket_route_data_id( socket_manager* mgr, int sock_id);
+static int _socket_handle_new_client(socket_manager* mgr, socket_node* node);
+static int _socket_handle_client_data(socket_manager* mgr, socket_node* node);
+
+
+/* --------------------------------------------------------------------
+ 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;
+}
+*/
+/* -------------------------------------------------------------------- */
+
+
+/* allocates and inserts a new socket node into the nodeset.
+ if parent_id is positive and non-zero, it will be set */
+static 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 */
+static 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 */
+static 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);
+}
+
+/* utility method */
+static 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;
+}
+
+
+/* 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) {
+// 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);
+}
+
+/* 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 */
+/* determines if we're receiving a new client or data
+ on an existing client */
+static 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;
+}
+
+
+/* routes data from a single known socket */
+static 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;
+}
+
+
+static 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;
+}
+
+
+static 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 <opensrf/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 <opensrf/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 <opensrf/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 <opensrf/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 <opensrf/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
+/*
+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 <opensrf/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;
+}
+
+/****************
+ The following static variables, and the following two functions,
+ overwrite the argv array passed to main(). The purpose is to
+ change the program name as reported by ps and similar utilities.
+
+ Warning: this code makes the non-portable assumption that the
+ strings to which argv[] points are contiguous in memory. The
+ C Standard makes no such guarantee.
+ ****************/
+static char** global_argv = NULL;
+static 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
+#include <opensrf/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
-# 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" );
-
- int ret = osrfSystemBootstrap( host, config, context );
-
- if (ret != 0) {
- osrfLogError(
- OSRF_LOG_MARK,
- "Server Loop returned an error condition, exiting with %d",
- ret
- );
- }
-
-
- free(host);
- free(config);
- free(context);
-
- return ret;
-}
-
-
+++ /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;
-
- // Load XML from the configuration file
-
- xmlDocPtr doc = xmlParseFile(configFile);
- if(!doc) {
- fprintf( stderr, "osrfConfigInit: Unable to parse XML config file %s\n", configFile);
- osrfLogWarning( OSRF_LOG_MARK, "Unable to parse XML config file %s", configFile);
- return NULL;
- }
-
- // Translate it into a jsonObject
-
- jsonObject* json_config = xmlDocToJSON(doc);
- xmlFreeDoc(doc);
-
- if(!json_config ) {
- fprintf( stderr, "osrfConfigInit: xmlDocToJSON failed for config %s\n", configFile);
- osrfLogWarning( OSRF_LOG_MARK, "xmlDocToJSON failed for config %s", configFile);
- return NULL;
- }
-
- // Build an osrfConfig and return it by pointer
-
- osrfConfig* cfg = safe_malloc(sizeof(osrfConfig));
-
- if(configContext) cfg->configContext = strdup(configContext);
- else cfg->configContext = NULL;
-
- cfg->config = json_config;
-
- 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);
-
- if( ! config ) {
- const char * msg = "NULL config pointer";
- fprintf( stderr, "osrf_settings_host_value: %s\n", msg );
- osrfLogError( OSRF_LOG_MARK, msg );
- exit( 99 );
- }
-
- 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) {
- osrfLogError( OSRF_LOG_MARK, "No osrf_message received from host %s (timeout?)", hostname);
- } else if(!omsg->_result_content) {
- osrf_message_free(omsg);
- osrfLogError(
- OSRF_LOG_MARK,
- "NULL or non-existant osrf_message result content received from host %s, "
- "broken message or no settings for host",
- hostname
- );
- } else {
- 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 for host %s from configuration file %s",
- hostname, configfile );
- return -1;
- }
-
- int retcode = osrf_settings_retrieve(hostname);
- osrf_system_disconnect_client();
-
- if( retcode ) {
- osrfLogError( OSRF_LOG_MARK,
- "Unable to retrieve settings for host %s from configuration file %s",
- hostname, configfile );
- return -1;
- }
-
- 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
#
# --------------------------------------------------------------------
-OBJS = md5.o utils.o json2xml.o object.o json_parser.o xml2json.o
-UTIL_DIR = ../utils
-DEST_INCLUDE = objson
-CFLAGS += -DSTRICT_JSON_WRITE #-DSTRICT_JSON_READ
+OBJS = utils.o json2xml.o object.o json_parser.o xml2json.o
+CFLAGS += -DSTRICT_JSON_WRITE -DOSRF_DISABLE_MD5
+TARGETS = object.o json_parser.o json2xml.o xml2json.o ../libopensrf/utils.o ../libopensrf/md5.o
+JSON_INC = ../../include/objson
-JSON_HEADERS = object.h json_parser.h json2xml.h xml2json.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
-json2xml.o: json2xml.h json2xml.c
-xml2json.o: xml2json.h xml2json.c
+all: libobjson.so
+object.o: object.c $(JSON_INC)/object.h
+json_parser.o: json_parser.c $(JSON_INC)/json_parser.h
+json2xml.o: json2xml.c $(JSON_INC)/json2xml.h
+xml2json.o: xml2json.c $(JSON_INC)/xml2json.h
+../libopensrf/utils.o: ../libopensrf/utils.c ../../include/opensrf/utils.h
+../libopensrf/md5.o: ../libopensrf/md5.c ../../include/opensrf/md5.h
install:
- mkdir -p $(INCLUDEDIR)/$(DEST_INCLUDE)
- cp $(TMPDIR)/$(DEST_INCLUDE)/*.h $(INCLUDEDIR)/objson/
+ cp -r ../../include/objson $(INCLUDEDIR)
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 $@
+libobjson.so: $(TARGETS)
+ $(CC) -shared -W1 $(TARGETS) -o $(TMPDIR)/libobjson.so
clean:
- /bin/rm -f *.o *.so utils.c utils.h libobjson.so
+ /bin/rm -f *.o *.so
-#include "json2xml.h"
+#include <objson/json2xml.h>
static char* _escape_xml (char*);
static int _recurse_jsonObjectToXML(jsonObject*, growing_buffer*);
+++ /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 "opensrf/utils.h"
-#include "utils.h"
-
-char* jsonObjectToXML(jsonObject*);
-
*/
-#include "json_parser.h"
+#include <objson/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
+++ /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 "opensrf/utils.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
GNU General Public License for more details.
*/
-#include "object.h"
-#include "json_parser.h"
+#include <objson/object.h>
+#include <objson/json_parser.h>
/* ---------------------------------------------------------------------- */
+++ /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 "opensrf/utils.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
-
-
*/
//#include "utils.h"
-#include "object.h"
-#include "json_parser.h"
+#include <objson/object.h>
+#include <objson/json_parser.h>
#include <stdio.h>
#include <fcntl.h>
-#include "xml2json.h"
+#include <objson/xml2json.h>
struct osrfXMLGatewayParserStruct {
osrfList* objStack;
+++ /dev/null
-
-#include <stdio.h>
-#include <string.h>
-#include <libxml/globals.h>
-#include <libxml/xmlerror.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xmlmemory.h>
-
-#include "object.h"
-#include "json_parser.h"
-#include "utils.h"
-#include "osrf_list.h"
-
-
-
-jsonObject* jsonXMLToJSONObject(const char* xml);
-
-
-
-#include "opensrf/transport_client.h"
-#include "opensrf/osrf_message.h"
-#include "opensrf/osrf_app_session.h"
+#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 <opensrf/utils.h>
+#include <opensrf/log.h>
#include <signal.h>
+++ /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"
-
-static int _osrfLogType = -1;
-static int _osrfLogFacility = LOG_LOCAL0;
-static int _osrfLogActFacility = LOG_LOCAL1;
-static char* _osrfLogFile = NULL;
-static char* _osrfLogAppname = NULL;
-static int _osrfLogLevel = OSRF_LOG_INFO;
-static int _osrfLogActivityEnabled = 1;
-static int _osrfLogIsClient = 0;
-
-static char* _osrfLogXid = NULL; /* current xid */
-static char* _osrfLogXidPfx = NULL; /* xid prefix string */
-
-static void osrfLogSetType( int logtype );
-static void _osrfLogDetail( int level, const char* filename, int line, char* msg );
-static void _osrfLogToFile( char* msg, ... );
-static void _osrfLogSetXid(char* xid);
-
-#define OSRF_LOG_GO(f,li,m,l) \
- if(!m) return; \
- VA_LIST_TO_STRING(m); \
- _osrfLogDetail( l, f, li, VA_BUF );
-
-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) {
- static int _osrfLogXidInc = 0; /* increments with each new xid for uniqueness */
- 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;
-}
-
-/** Sets the type of logging to perform. See log types */
-static 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;
-}
-
-/** Sets the global log level. Any log statements with a higher level
- * than "level" will not be logged */
-void osrfLogSetLevel( int loglevel ) {
- _osrfLogLevel = loglevel;
-}
-
-/** Gets the current global log level. **/
-int osrfLogGetLevel( void ) {
- return _osrfLogLevel;
-}
-
-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 */
-}
-
-/** Actually does the logging */
-static 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 );
-
-}
-
-
-static 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__
-
-
-/* Initializes the logger. */
-void osrfLogInit( int type, const char* appname, int maxlevel );
-
-/** 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 );
-
-/** Set or Get the global log level. Any log statements with a higher level
- * than "level" will not be logged */
-void osrfLogSetLevel( int loglevel );
-int osrfLogGetLevel( void );
-
-/* 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 );
-
-/* 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"
-
-/* buffer used to read from the sockets */
-#define RBUFSIZE 1024
-
-static socket_node* _socket_add_node(socket_manager* mgr,
- int endpoint, int addr_type, int sock_fd, int parent_id );
-static socket_node* socket_find_node(socket_manager* mgr, int sock_fd);
-static void socket_remove_node(socket_manager*, int sock_fd);
-static int _socket_send(int sock_fd, const char* data, int flags);
-static int _socket_route_data(socket_manager* mgr, int num_active, fd_set* read_set);
-static int _socket_route_data_id( socket_manager* mgr, int sock_id);
-static int _socket_handle_new_client(socket_manager* mgr, socket_node* node);
-static int _socket_handle_client_data(socket_manager* mgr, socket_node* node);
-
-
-/* --------------------------------------------------------------------
- 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;
-}
-*/
-/* -------------------------------------------------------------------- */
-
-
-/* allocates and inserts a new socket node into the nodeset.
- if parent_id is positive and non-zero, it will be set */
-static 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 */
-static 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 */
-static 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);
-}
-
-/* utility method */
-static 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;
-}
-
-
-/* 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) {
-// 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);
-}
-
-/* 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 */
-/* determines if we're receiving a new client or data
- on an existing client */
-static 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;
-}
-
-
-/* routes data from a single known socket */
-static 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;
-}
-
-
-static 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;
-}
-
-
-static 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
-
-
-/* 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);
-
-/* sends the given data to the given socket. returns 0 on success, -1 otherwise */
-int socket_send(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);
-
-/* 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);
-
-/* utility function for displaying the currently attached sockets */
-void _socket_print_list(socket_manager* mgr);
-
-int socket_connected(int sock_fd);
-
-#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;
-}
-
-/****************
- The following static variables, and the following two functions,
- overwrite the argv array passed to main(). The purpose is to
- change the program name as reported by ps and similar utilities.
-
- Warning: this code makes the non-portable assumption that the
- strings to which argv[] points are contiguous in memory. The
- C Standard makes no such guarantee.
- ****************/
-static char** global_argv = NULL;
-static 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,
-};
-