From: erickson Date: Thu, 21 Jun 2007 16:19:20 +0000 (+0000) Subject: Merged libopensrf source directories (libtransport, libstack, and utils) into a singl... X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=81c6a66fe6c54e8756e6741ec570bb6fbdafd6dc;p=opensrf%2Fbjwebb.git Merged libopensrf source directories (libtransport, libstack, and utils) into a single libopensrf directory Moved opensrf headers to trunk/include/opensrf Moved objson headers to trunk/include/objson Updated #include's throughout to be fully qualified. e.g. , Removed old, unused trunk/src/xinclude code Cleaned up Makefiles to support new directory layout git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@957 9efc2488-bf62-4759-914b-345cdb29e865 --- diff --git a/Makefile b/Makefile index a23c57c..8441861 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,18 @@ 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 diff --git a/include/objson/json2xml.h b/include/objson/json2xml.h new file mode 100644 index 0000000..9eaa1c0 --- /dev/null +++ b/include/objson/json2xml.h @@ -0,0 +1,11 @@ + +#include +#include + +/* the JSON parser, so we can read the response we're XMLizing */ +#include +#include +#include + +char* jsonObjectToXML(jsonObject*); + diff --git a/include/objson/json_parser.h b/include/objson/json_parser.h new file mode 100644 index 0000000..ede5d91 --- /dev/null +++ b/include/objson/json_parser.h @@ -0,0 +1,86 @@ +/* +Copyright (C) 2005 Georgia Public Library Service +Bill Erickson + +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 +#include +#include + + + +/* 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 diff --git a/include/objson/object.h b/include/objson/object.h new file mode 100644 index 0000000..8d62c1a --- /dev/null +++ b/include/objson/object.h @@ -0,0 +1,286 @@ +/* +Copyright (C) 2005 Georgia Public Library Service +Bill Erickson + +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 +#include +#include +#include + +#include + +/* 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 + + diff --git a/include/objson/xml2json.h b/include/objson/xml2json.h new file mode 100644 index 0000000..a9ded67 --- /dev/null +++ b/include/objson/xml2json.h @@ -0,0 +1,19 @@ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +jsonObject* jsonXMLToJSONObject(const char* xml); + + + diff --git a/include/opensrf/log.h b/include/opensrf/log.h new file mode 100644 index 0000000..4aafad3 --- /dev/null +++ b/include/opensrf/log.h @@ -0,0 +1,80 @@ +#include + +#include +#include +#include +#include + +#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 diff --git a/include/opensrf/md5.h b/include/opensrf/md5.h new file mode 100644 index 0000000..53dd2b1 --- /dev/null +++ b/include/opensrf/md5.h @@ -0,0 +1,35 @@ +/* --- The MD5 routines --- */ + +/* MD5 routines, after Ron Rivest */ +/* Written by David Madore , 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 */ + diff --git a/include/opensrf/osrfConfig.h b/include/opensrf/osrfConfig.h new file mode 100644 index 0000000..75dbcfd --- /dev/null +++ b/include/opensrf/osrfConfig.h @@ -0,0 +1,103 @@ +/* +Copyright (C) 2005 Georgia Public Library Service +Bill Erickson + +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 +#include +#include +#include + +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: /// + 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 diff --git a/include/opensrf/osrf_app_session.h b/include/opensrf/osrf_app_session.h new file mode 100644 index 0000000..aae373c --- /dev/null +++ b/include/opensrf/osrf_app_session.h @@ -0,0 +1,234 @@ +#ifndef _OSRF_APP_SESSION +#define _OSRF_APP_SESSION + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + + +#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 diff --git a/include/opensrf/osrf_application.h b/include/opensrf/osrf_application.h new file mode 100644 index 0000000..ac548a2 --- /dev/null +++ b/include/opensrf/osrf_application.h @@ -0,0 +1,234 @@ +#include +#include +#include +#include + +#include +#include +#include + + +/** + 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(); + + diff --git a/include/opensrf/osrf_big_hash.h b/include/opensrf/osrf_big_hash.h new file mode 100644 index 0000000..a738755 --- /dev/null +++ b/include/opensrf/osrf_big_hash.h @@ -0,0 +1,87 @@ +#ifndef OSRF_HASH_H +#define OSRF_HASH_H + +#include +#include +#include + +#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 diff --git a/include/opensrf/osrf_big_list.h b/include/opensrf/osrf_big_list.h new file mode 100644 index 0000000..ebe3da7 --- /dev/null +++ b/include/opensrf/osrf_big_list.h @@ -0,0 +1,142 @@ +#ifndef OSRF_BIG_LIST_H +#define OSRF_BIG_LIST_H + + +#include +#include +#include + +/** + 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 diff --git a/include/opensrf/osrf_cache.h b/include/opensrf/osrf_cache.h new file mode 100644 index 0000000..5a755ff --- /dev/null +++ b/include/opensrf/osrf_cache.h @@ -0,0 +1,83 @@ +/* +Copyright (C) 2005 Georgia Public Library Service +Bill Erickson + +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 +#include +#include +#include + +/** + 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, ... ); + + + diff --git a/include/opensrf/osrf_hash.h b/include/opensrf/osrf_hash.h new file mode 100644 index 0000000..132e43e --- /dev/null +++ b/include/opensrf/osrf_hash.h @@ -0,0 +1,115 @@ +#ifndef OSRF_HASH_H +#define OSRF_HASH_H + +#include +#include +#include + +/* 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 diff --git a/include/opensrf/osrf_list.h b/include/opensrf/osrf_list.h new file mode 100644 index 0000000..f59669a --- /dev/null +++ b/include/opensrf/osrf_list.h @@ -0,0 +1,155 @@ +#ifndef OSRF_LIST_H +#define OSRF_LIST_H + +#include + +#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 diff --git a/include/opensrf/osrf_message.h b/include/opensrf/osrf_message.h new file mode 100644 index 0000000..12e14c6 --- /dev/null +++ b/include/opensrf/osrf_message.h @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include + + +/* libxml stuff for the config reader */ +#include +#include +#include +#include +#include + + + +#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 diff --git a/include/opensrf/osrf_prefork.h b/include/opensrf/osrf_prefork.h new file mode 100644 index 0000000..543343c --- /dev/null +++ b/include/opensrf/osrf_prefork.h @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +//#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* ); diff --git a/include/opensrf/osrf_settings.h b/include/opensrf/osrf_settings.h new file mode 100644 index 0000000..9aa0d47 --- /dev/null +++ b/include/opensrf/osrf_settings.h @@ -0,0 +1,31 @@ +#ifndef OSRF_SETTINGS_H +#define OSRF_SETTINGS_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +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 + diff --git a/include/opensrf/osrf_stack.h b/include/opensrf/osrf_stack.h new file mode 100644 index 0000000..da2db3d --- /dev/null +++ b/include/opensrf/osrf_stack.h @@ -0,0 +1,19 @@ +#include +#include +#include + +#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 diff --git a/include/opensrf/osrf_system.h b/include/opensrf/osrf_system.h new file mode 100644 index 0000000..540e8d1 --- /dev/null +++ b/include/opensrf/osrf_system.h @@ -0,0 +1,57 @@ +#ifndef OSRF_SYSTEM_H +#define OSRF_SYSTEM_H + +#include +#include +#include +#include +#include +#include + + + +/** 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 diff --git a/include/opensrf/osrf_transgroup.h b/include/opensrf/osrf_transgroup.h new file mode 100644 index 0000000..9788d93 --- /dev/null +++ b/include/opensrf/osrf_transgroup.h @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include +#include + +/** + 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 ); + + diff --git a/include/opensrf/sha.h b/include/opensrf/sha.h new file mode 100644 index 0000000..6c3d2d4 --- /dev/null +++ b/include/opensrf/sha.h @@ -0,0 +1,41 @@ +// 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 + diff --git a/include/opensrf/socket_bundle.h b/include/opensrf/socket_bundle.h new file mode 100644 index 0000000..f290cdc --- /dev/null +++ b/include/opensrf/socket_bundle.h @@ -0,0 +1,111 @@ +#include +#include + +#include +#include +#include +#include + + +//--------------------------------------------------------------- +// Unix headers +//--------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 diff --git a/include/opensrf/string_array.h b/include/opensrf/string_array.h new file mode 100644 index 0000000..77b3de0 --- /dev/null +++ b/include/opensrf/string_array.h @@ -0,0 +1,41 @@ +#include + +#include +#include + +#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 diff --git a/include/opensrf/transport_client.h b/include/opensrf/transport_client.h new file mode 100644 index 0000000..e61f840 --- /dev/null +++ b/include/opensrf/transport_client.h @@ -0,0 +1,92 @@ +#include +#include +#include + +#include + +#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 diff --git a/include/opensrf/transport_message.h b/include/opensrf/transport_message.h new file mode 100644 index 0000000..ddd8f39 --- /dev/null +++ b/include/opensrf/transport_message.h @@ -0,0 +1,99 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 diff --git a/include/opensrf/transport_session.h b/include/opensrf/transport_session.h new file mode 100644 index 0000000..5aa8597 --- /dev/null +++ b/include/opensrf/transport_session.h @@ -0,0 +1,234 @@ +// --------------------------------------------------------------------------------- +// 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 + +#include +#include +#include + +#include "sha.h" + +#include +#include +#include +#include +#include /* only for xmlNewInputFromFile() */ +#include +#include +#include + +#ifndef TRANSPORT_SESSION_H +#define TRANSPORT_SESSION_H + +#define CONNECTING_1 1 /* just starting the connection to Jabber */ +#define CONNECTING_2 2 /* First packet sent and 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 diff --git a/include/opensrf/utils.h b/include/opensrf/utils.h new file mode 100644 index 0000000..7bbade0 --- /dev/null +++ b/include/opensrf/utils.h @@ -0,0 +1,239 @@ +/* +Copyright (C) 2005 Georgia Public Library Service +Bill Erickson +Mike Rylander + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +#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 diff --git a/include/opensrf/xml_utils.h b/include/opensrf/xml_utils.h new file mode 100644 index 0000000..2b3a030 --- /dev/null +++ b/include/opensrf/xml_utils.h @@ -0,0 +1,36 @@ +#ifndef _XML_UTILS_H +#define _XML_UTILS_H + +#include +#include +#include + +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 diff --git a/src/Makefile b/src/Makefile index 4ff75c2..0cf5657 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,62 +9,12 @@ export PERLDIR = $(LIBDIR)/perl5 export INCLUDEDIR = $(PREFIX)/include export LDLIBS += -export LDFLAGS += -Wl,-rpath=$(LIBDIR) -L $(TMPDIR) -L . -L /opt/lib -export CFLAGS += -pipe -g -Wall -O2 -fPIC -I$(LIBXML2_HEADERS) -I$(APACHE2_HEADERS) \ - -I$(LIBXML2_HEADERS)/libxml -I$(TMP) \ - -I$(APR_HEADERS) -I$(TMPDIR) - -LIBOPENSRF = libopensrf.so - -OPENSRF_TARGETS = libtransport/transport_session.o \ - libtransport/transport_client.o \ - libtransport/transport_message.o \ - libstack/osrf_app_session.o \ - libstack/osrf_stack.o \ - libstack/osrfConfig.o \ - libstack/osrf_settings.o \ - libstack/osrf_message.o \ - libstack/osrf_prefork.o \ - libstack/osrf_system.o \ - libstack/osrf_application.o \ - libstack/osrf_cache.o \ - libstack/xml_utils.o \ - libstack/osrf_transgroup.o \ - libstack/osrf_list.o \ - libstack/osrf_hash.o \ - utils/socket_bundle.o \ - utils/string_array.o \ - utils/utils.o \ - utils/log.o \ - utils/md5.o \ - utils/sha.o - -OPENSRF_HEADERS = libtransport/transport_session.h \ - libtransport/transport_client.h \ - libtransport/transport_message.h \ - libstack/osrf_app_session.h \ - libstack/osrf_stack.h \ - libstack/osrfConfig.h \ - libstack/osrf_settings.h \ - libstack/osrf_message.h \ - libstack/osrf_prefork.h \ - libstack/osrf_system.h \ - libstack/osrf_application.h \ - libstack/osrf_cache.h \ - libstack/xml_utils.h \ - libstack/osrf_transgroup.h \ - libstack/osrf_list.h \ - libstack/osrf_hash.h \ - utils/socket_bundle.h \ - utils/string_array.h \ - utils/utils.h \ - utils/log.h \ - utils/md5.h \ - utils/sha.h +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 \ @@ -79,56 +29,35 @@ install: install-prep \ 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 @@ -136,22 +65,32 @@ jserver: libopensrf.so # -------------------------------------------------------------------------------- # 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 $@ @@ -172,28 +111,19 @@ jserver-install: install-prep 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 diff --git a/src/libopensrf/basic_client.c b/src/libopensrf/basic_client.c new file mode 100644 index 0000000..5cf8f76 --- /dev/null +++ b/src/libopensrf/basic_client.c @@ -0,0 +1,81 @@ +#include +#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 \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; + +} + + + + diff --git a/src/libopensrf/component.c b/src/libopensrf/component.c new file mode 100644 index 0000000..c63dd44 --- /dev/null +++ b/src/libopensrf/component.c @@ -0,0 +1,52 @@ +#include +#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 ", 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; + +} + + + + diff --git a/src/libopensrf/log.c b/src/libopensrf/log.c new file mode 100644 index 0000000..35d2756 --- /dev/null +++ b/src/libopensrf/log.c @@ -0,0 +1,252 @@ +#include + +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; +} + + diff --git a/src/libopensrf/md5.c b/src/libopensrf/md5.c new file mode 100644 index 0000000..c8d7688 --- /dev/null +++ b/src/libopensrf/md5.c @@ -0,0 +1,367 @@ +/* --- The data --- */ + +const char data[] = +"/* --- The MD5 routines --- */\n\n/* MD5 routines, after Ron R" +"ivest */\n/* Written by David Madore , 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<>(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 \n#include \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 , 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<>(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; + } +} + +/* --- The core of the program --- */ + +#include +#include + +#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; +} +*/ diff --git a/src/libopensrf/opensrf.c b/src/libopensrf/opensrf.c new file mode 100644 index 0000000..5532f73 --- /dev/null +++ b/src/libopensrf/opensrf.c @@ -0,0 +1,42 @@ +#include +//#include +//#include + +int main( int argc, char* argv[] ) { + + if( argc < 4 ) { + fprintf(stderr, "Usage: %s \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; +} + + diff --git a/src/libopensrf/osrfConfig.c b/src/libopensrf/osrfConfig.c new file mode 100644 index 0000000..7fd9dbd --- /dev/null +++ b/src/libopensrf/osrfConfig.c @@ -0,0 +1,135 @@ +/* defines the currently used bootstrap config file */ +#include + +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; +} + diff --git a/src/libopensrf/osrf_app_session.c b/src/libopensrf/osrf_app_session.c new file mode 100644 index 0000000..d89c445 --- /dev/null +++ b/src/libopensrf/osrf_app_session.c @@ -0,0 +1,660 @@ +#include +#include + +/* 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; +} + + + + + + diff --git a/src/libopensrf/osrf_application.c b/src/libopensrf/osrf_application.c new file mode 100644 index 0000000..1f12b86 --- /dev/null +++ b/src/libopensrf/osrf_application.c @@ -0,0 +1,477 @@ +#include +#include + +//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; +} + diff --git a/src/libopensrf/osrf_big_hash.c b/src/libopensrf/osrf_big_hash.c new file mode 100644 index 0000000..3e69f2f --- /dev/null +++ b/src/libopensrf/osrf_big_hash.c @@ -0,0 +1,173 @@ +#include + +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; +} + + + diff --git a/src/libopensrf/osrf_big_list.c b/src/libopensrf/osrf_big_list.c new file mode 100644 index 0000000..26ff7b6 --- /dev/null +++ b/src/libopensrf/osrf_big_list.c @@ -0,0 +1,174 @@ +#include + + +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; +} diff --git a/src/libopensrf/osrf_cache.c b/src/libopensrf/osrf_cache.c new file mode 100644 index 0000000..940af11 --- /dev/null +++ b/src/libopensrf/osrf_cache.c @@ -0,0 +1,99 @@ +/* +Copyright (C) 2005 Georgia Public Library Service +Bill Erickson + +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 + +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; +} + + diff --git a/src/libopensrf/osrf_hash.c b/src/libopensrf/osrf_hash.c new file mode 100644 index 0000000..e00f09c --- /dev/null +++ b/src/libopensrf/osrf_hash.c @@ -0,0 +1,242 @@ +#include + +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; +} diff --git a/src/libopensrf/osrf_list.c b/src/libopensrf/osrf_list.c new file mode 100644 index 0000000..2d37b02 --- /dev/null +++ b/src/libopensrf/osrf_list.c @@ -0,0 +1,154 @@ +#include + +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; +} diff --git a/src/libopensrf/osrf_message.c b/src/libopensrf/osrf_message.c new file mode 100644 index 0000000..313216a --- /dev/null +++ b/src/libopensrf/osrf_message.c @@ -0,0 +1,330 @@ +#include + +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; +} + diff --git a/src/libopensrf/osrf_prefork.c b/src/libopensrf/osrf_prefork.c new file mode 100644 index 0000000..01a97cc --- /dev/null +++ b/src/libopensrf/osrf_prefork.c @@ -0,0 +1,765 @@ +#include +#include +#include +#include + +/* 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; +} + diff --git a/src/libopensrf/osrf_settings.c b/src/libopensrf/osrf_settings.c new file mode 100644 index 0000000..a732b08 --- /dev/null +++ b/src/libopensrf/osrf_settings.c @@ -0,0 +1,88 @@ +#include + +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); +} diff --git a/src/libopensrf/osrf_stack.c b/src/libopensrf/osrf_stack.c new file mode 100644 index 0000000..231ccbc --- /dev/null +++ b/src/libopensrf/osrf_stack.c @@ -0,0 +1,263 @@ +#include +#include + +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; +} + + diff --git a/src/libopensrf/osrf_system.c b/src/libopensrf/osrf_system.c new file mode 100644 index 0000000..c378b7b --- /dev/null +++ b/src/libopensrf/osrf_system.c @@ -0,0 +1,326 @@ +#include +#include +#include +#include + +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; +} + + + + diff --git a/src/libopensrf/osrf_transgroup.c b/src/libopensrf/osrf_transgroup.c new file mode 100644 index 0000000..72b203f --- /dev/null +++ b/src/libopensrf/osrf_transgroup.c @@ -0,0 +1,244 @@ +#include +#include + + +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; +} + + diff --git a/src/libopensrf/sha.c b/src/libopensrf/sha.c new file mode 100644 index 0000000..14791bd --- /dev/null +++ b/src/libopensrf/sha.c @@ -0,0 +1,264 @@ +/* + * 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 -- Expansion function fix + Thomas "temas" Muldowney : + -- 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 +#endif + +#include +#include +#include +#ifdef MACOS +# include +#else +# include +# include +#endif + +#include + +#ifndef WIN32 +# include +# define INT64 long long +#else +# include +# 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; +} diff --git a/src/libopensrf/socket_bundle.c b/src/libopensrf/socket_bundle.c new file mode 100644 index 0000000..6196410 --- /dev/null +++ b/src/libopensrf/socket_bundle.c @@ -0,0 +1,743 @@ +#include + +/* 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); + +} + diff --git a/src/libopensrf/socket_test.c b/src/libopensrf/socket_test.c new file mode 100644 index 0000000..c921ac6 --- /dev/null +++ b/src/libopensrf/socket_test.c @@ -0,0 +1,33 @@ +#include + +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; +} diff --git a/src/libopensrf/string_array.c b/src/libopensrf/string_array.c new file mode 100644 index 0000000..3197718 --- /dev/null +++ b/src/libopensrf/string_array.c @@ -0,0 +1,116 @@ +#include + +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--; +} + + diff --git a/src/libopensrf/transport_client.c b/src/libopensrf/transport_client.c new file mode 100644 index 0000000..9a14291 --- /dev/null +++ b/src/libopensrf/transport_client.c @@ -0,0 +1,225 @@ +#include + + +//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; +} + diff --git a/src/libopensrf/transport_message.c b/src/libopensrf/transport_message.c new file mode 100644 index 0000000..5c6862b --- /dev/null +++ b/src/libopensrf/transport_message.c @@ -0,0 +1,357 @@ +#include + + +// --------------------------------------------------------------------------------- +// 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 "", 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; +} diff --git a/src/libopensrf/transport_session.c b/src/libopensrf/transport_session.c new file mode 100644 index 0000000..43483f0 --- /dev/null +++ b/src/libopensrf/transport_session.c @@ -0,0 +1,635 @@ +#include + + + +// --------------------------------------------------------------------------------- +// 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, + "", + 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, "%s", 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, + "", + 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, + "" + "%s%s%s", + 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, + "" + "%s%s%s", + 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 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 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, ""); + socket_send(session->sock_id, ""); + socket_disconnect(session->sock_mgr, session->sock_id); + return 0; + //return tcp_disconnect( session->sock_obj ); +} + diff --git a/src/libopensrf/utils.c b/src/libopensrf/utils.c new file mode 100644 index 0000000..07ed9a2 --- /dev/null +++ b/src/libopensrf/utils.c @@ -0,0 +1,475 @@ +/* +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 +#include + +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; +} + diff --git a/src/libopensrf/xml_utils.c b/src/libopensrf/xml_utils.c new file mode 100644 index 0000000..e3ef206 --- /dev/null +++ b/src/libopensrf/xml_utils.c @@ -0,0 +1,121 @@ +#include + + +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; +} + diff --git a/src/libstack/Makefile b/src/libstack/Makefile deleted file mode 100644 index 82fae9a..0000000 --- a/src/libstack/Makefile +++ /dev/null @@ -1,63 +0,0 @@ -# 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 - diff --git a/src/libstack/opensrf.c b/src/libstack/opensrf.c deleted file mode 100644 index 9291930..0000000 --- a/src/libstack/opensrf.c +++ /dev/null @@ -1,42 +0,0 @@ -#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 \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; -} - - diff --git a/src/libstack/osrfConfig.c b/src/libstack/osrfConfig.c deleted file mode 100644 index b02b6fd..0000000 --- a/src/libstack/osrfConfig.c +++ /dev/null @@ -1,135 +0,0 @@ -/* 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; -} - diff --git a/src/libstack/osrfConfig.h b/src/libstack/osrfConfig.h deleted file mode 100644 index c0a6459..0000000 --- a/src/libstack/osrfConfig.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -Copyright (C) 2005 Georgia Public Library Service -Bill Erickson - -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: /// - 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 diff --git a/src/libstack/osrf_app_session.c b/src/libstack/osrf_app_session.c deleted file mode 100644 index 095e50e..0000000 --- a/src/libstack/osrf_app_session.c +++ /dev/null @@ -1,660 +0,0 @@ -#include "osrf_app_session.h" -#include - -/* 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; -} - - - - - - diff --git a/src/libstack/osrf_app_session.h b/src/libstack/osrf_app_session.h deleted file mode 100644 index af35af5..0000000 --- a/src/libstack/osrf_app_session.h +++ /dev/null @@ -1,235 +0,0 @@ -#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 diff --git a/src/libstack/osrf_application.c b/src/libstack/osrf_application.c deleted file mode 100644 index 1d62642..0000000 --- a/src/libstack/osrf_application.c +++ /dev/null @@ -1,477 +0,0 @@ -#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; -} - diff --git a/src/libstack/osrf_application.h b/src/libstack/osrf_application.h deleted file mode 100644 index 0980a81..0000000 --- a/src/libstack/osrf_application.h +++ /dev/null @@ -1,233 +0,0 @@ -#include -#include -#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(); - - diff --git a/src/libstack/osrf_big_hash.c b/src/libstack/osrf_big_hash.c deleted file mode 100644 index 41d5131..0000000 --- a/src/libstack/osrf_big_hash.c +++ /dev/null @@ -1,173 +0,0 @@ -#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; -} - - - diff --git a/src/libstack/osrf_big_hash.h b/src/libstack/osrf_big_hash.h deleted file mode 100644 index 22e0a46..0000000 --- a/src/libstack/osrf_big_hash.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef OSRF_HASH_H -#define OSRF_HASH_H - -#include -#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 diff --git a/src/libstack/osrf_big_list.c b/src/libstack/osrf_big_list.c deleted file mode 100644 index 5d7e3dc..0000000 --- a/src/libstack/osrf_big_list.c +++ /dev/null @@ -1,174 +0,0 @@ -#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; -} diff --git a/src/libstack/osrf_big_list.h b/src/libstack/osrf_big_list.h deleted file mode 100644 index 523f28d..0000000 --- a/src/libstack/osrf_big_list.h +++ /dev/null @@ -1,142 +0,0 @@ -#ifndef OSRF_BIG_LIST_H -#define OSRF_BIG_LIST_H - - -#include -#include "opensrf/utils.h" -#include - -/** - 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 diff --git a/src/libstack/osrf_cache.c b/src/libstack/osrf_cache.c deleted file mode 100644 index 13cb272..0000000 --- a/src/libstack/osrf_cache.c +++ /dev/null @@ -1,99 +0,0 @@ -/* -Copyright (C) 2005 Georgia Public Library Service -Bill Erickson - -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; -} - - diff --git a/src/libstack/osrf_cache.h b/src/libstack/osrf_cache.h deleted file mode 100644 index 317cdd0..0000000 --- a/src/libstack/osrf_cache.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright (C) 2005 Georgia Public Library Service -Bill Erickson - -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, ... ); - - - diff --git a/src/libstack/osrf_hash.c b/src/libstack/osrf_hash.c deleted file mode 100644 index 778c282..0000000 --- a/src/libstack/osrf_hash.c +++ /dev/null @@ -1,242 +0,0 @@ -#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; -} diff --git a/src/libstack/osrf_hash.h b/src/libstack/osrf_hash.h deleted file mode 100644 index 02e62c2..0000000 --- a/src/libstack/osrf_hash.h +++ /dev/null @@ -1,115 +0,0 @@ -#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 diff --git a/src/libstack/osrf_list.c b/src/libstack/osrf_list.c deleted file mode 100644 index 0e58f0f..0000000 --- a/src/libstack/osrf_list.c +++ /dev/null @@ -1,154 +0,0 @@ -#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; -} diff --git a/src/libstack/osrf_list.h b/src/libstack/osrf_list.h deleted file mode 100644 index d829ab7..0000000 --- a/src/libstack/osrf_list.h +++ /dev/null @@ -1,155 +0,0 @@ -#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 diff --git a/src/libstack/osrf_message.c b/src/libstack/osrf_message.c deleted file mode 100644 index beb52d0..0000000 --- a/src/libstack/osrf_message.c +++ /dev/null @@ -1,330 +0,0 @@ -#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; -} - diff --git a/src/libstack/osrf_message.h b/src/libstack/osrf_message.h deleted file mode 100644 index b87a97e..0000000 --- a/src/libstack/osrf_message.h +++ /dev/null @@ -1,121 +0,0 @@ -#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 -#include -#include -#include -#include - - - -#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 diff --git a/src/libstack/osrf_prefork.c b/src/libstack/osrf_prefork.c deleted file mode 100644 index 1ea5959..0000000 --- a/src/libstack/osrf_prefork.c +++ /dev/null @@ -1,765 +0,0 @@ -#include "osrf_prefork.h" -#include -#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; -} - diff --git a/src/libstack/osrf_prefork.h b/src/libstack/osrf_prefork.h deleted file mode 100644 index 9515445..0000000 --- a/src/libstack/osrf_prefork.h +++ /dev/null @@ -1,96 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#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* ); diff --git a/src/libstack/osrf_settings.c b/src/libstack/osrf_settings.c deleted file mode 100644 index 26e3b8f..0000000 --- a/src/libstack/osrf_settings.c +++ /dev/null @@ -1,88 +0,0 @@ -#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); -} diff --git a/src/libstack/osrf_settings.h b/src/libstack/osrf_settings.h deleted file mode 100644 index fecfc32..0000000 --- a/src/libstack/osrf_settings.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef OSRF_SETTINGS_H -#define OSRF_SETTINGS_H - -#include -#include -#include -#include -#include -#include - -#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 - diff --git a/src/libstack/osrf_stack.c b/src/libstack/osrf_stack.c deleted file mode 100644 index fe59c92..0000000 --- a/src/libstack/osrf_stack.c +++ /dev/null @@ -1,263 +0,0 @@ -#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; -} - - diff --git a/src/libstack/osrf_stack.h b/src/libstack/osrf_stack.h deleted file mode 100644 index 0ef6d00..0000000 --- a/src/libstack/osrf_stack.h +++ /dev/null @@ -1,19 +0,0 @@ -#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 diff --git a/src/libstack/osrf_system.c b/src/libstack/osrf_system.c deleted file mode 100644 index dc6b2ba..0000000 --- a/src/libstack/osrf_system.c +++ /dev/null @@ -1,326 +0,0 @@ -#include "osrf_system.h" -#include -#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; -} - - - - diff --git a/src/libstack/osrf_system.h b/src/libstack/osrf_system.h deleted file mode 100644 index 3a87008..0000000 --- a/src/libstack/osrf_system.h +++ /dev/null @@ -1,57 +0,0 @@ -#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 diff --git a/src/libstack/osrf_transgroup.c b/src/libstack/osrf_transgroup.c deleted file mode 100644 index 1d3d3f4..0000000 --- a/src/libstack/osrf_transgroup.c +++ /dev/null @@ -1,244 +0,0 @@ -#include "osrf_transgroup.h" -#include - - -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; -} - - diff --git a/src/libstack/osrf_transgroup.h b/src/libstack/osrf_transgroup.h deleted file mode 100644 index 57ee1be..0000000 --- a/src/libstack/osrf_transgroup.h +++ /dev/null @@ -1,122 +0,0 @@ -#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 - -/** - 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 ); - - diff --git a/src/libtransport/Makefile b/src/libtransport/Makefile deleted file mode 100644 index 643e81c..0000000 --- a/src/libtransport/Makefile +++ /dev/null @@ -1,18 +0,0 @@ - -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 diff --git a/src/libtransport/basic_client.c b/src/libtransport/basic_client.c deleted file mode 100644 index d7fa9a1..0000000 --- a/src/libtransport/basic_client.c +++ /dev/null @@ -1,81 +0,0 @@ -#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 \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; - -} - - - - diff --git a/src/libtransport/component.c b/src/libtransport/component.c deleted file mode 100644 index 1f909d2..0000000 --- a/src/libtransport/component.c +++ /dev/null @@ -1,52 +0,0 @@ -#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 ", 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; - -} - - - - diff --git a/src/libtransport/transport_client.c b/src/libtransport/transport_client.c deleted file mode 100644 index a318127..0000000 --- a/src/libtransport/transport_client.c +++ /dev/null @@ -1,225 +0,0 @@ -#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; -} - diff --git a/src/libtransport/transport_client.h b/src/libtransport/transport_client.h deleted file mode 100644 index 50a2c66..0000000 --- a/src/libtransport/transport_client.h +++ /dev/null @@ -1,92 +0,0 @@ -#include "transport_session.h" -#include "opensrf/utils.h" -#include "opensrf/log.h" - -#include - -#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 diff --git a/src/libtransport/transport_message.c b/src/libtransport/transport_message.c deleted file mode 100644 index f0e63af..0000000 --- a/src/libtransport/transport_message.c +++ /dev/null @@ -1,357 +0,0 @@ -#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 "", 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; -} diff --git a/src/libtransport/transport_message.h b/src/libtransport/transport_message.h deleted file mode 100644 index 4e94e24..0000000 --- a/src/libtransport/transport_message.h +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#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 diff --git a/src/libtransport/transport_session.c b/src/libtransport/transport_session.c deleted file mode 100644 index c62306c..0000000 --- a/src/libtransport/transport_session.c +++ /dev/null @@ -1,635 +0,0 @@ -#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, - "", - 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, "%s", 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, - "", - 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, - "" - "%s%s%s", - 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, - "" - "%s%s%s", - 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 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 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, ""); - socket_send(session->sock_id, ""); - socket_disconnect(session->sock_mgr, session->sock_id); - return 0; - //return tcp_disconnect( session->sock_obj ); -} - diff --git a/src/libtransport/transport_session.h b/src/libtransport/transport_session.h deleted file mode 100644 index 78d108b..0000000 --- a/src/libtransport/transport_session.h +++ /dev/null @@ -1,234 +0,0 @@ -// --------------------------------------------------------------------------------- -// 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 -#include -#include -#include -#include /* only for xmlNewInputFromFile() */ -#include -#include -#include - -#ifndef TRANSPORT_SESSION_H -#define TRANSPORT_SESSION_H - -#define CONNECTING_1 1 /* just starting the connection to Jabber */ -#define CONNECTING_2 2 /* First packet sent and 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 diff --git a/src/objson/Makefile b/src/objson/Makefile index 5f26dae..a113a92 100644 --- a/src/objson/Makefile +++ b/src/objson/Makefile @@ -26,45 +26,28 @@ # # -------------------------------------------------------------------- -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 diff --git a/src/objson/json2xml.c b/src/objson/json2xml.c index ef4fa19..5abf2ed 100644 --- a/src/objson/json2xml.c +++ b/src/objson/json2xml.c @@ -1,5 +1,5 @@ -#include "json2xml.h" +#include static char* _escape_xml (char*); static int _recurse_jsonObjectToXML(jsonObject*, growing_buffer*); diff --git a/src/objson/json2xml.h b/src/objson/json2xml.h deleted file mode 100644 index e4d2b44..0000000 --- a/src/objson/json2xml.h +++ /dev/null @@ -1,12 +0,0 @@ - -#include -#include - -/* 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*); - diff --git a/src/objson/json_parser.c b/src/objson/json_parser.c index d75431f..8313872 100644 --- a/src/objson/json_parser.c +++ b/src/objson/json_parser.c @@ -14,7 +14,7 @@ GNU General Public License for more details. */ -#include "json_parser.h" +#include /* keep a copy of the length of the current json string so we don't * have to calculate it in each function diff --git a/src/objson/json_parser.h b/src/objson/json_parser.h deleted file mode 100644 index bba852f..0000000 --- a/src/objson/json_parser.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -Copyright (C) 2005 Georgia Public Library Service -Bill Erickson - -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 -#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 diff --git a/src/objson/object.c b/src/objson/object.c index 782379b..3983576 100644 --- a/src/objson/object.c +++ b/src/objson/object.c @@ -13,8 +13,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ -#include "object.h" -#include "json_parser.h" +#include +#include /* ---------------------------------------------------------------------- */ diff --git a/src/objson/object.h b/src/objson/object.h deleted file mode 100644 index 8764e89..0000000 --- a/src/objson/object.h +++ /dev/null @@ -1,287 +0,0 @@ -/* -Copyright (C) 2005 Georgia Public Library Service -Bill Erickson - -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 -#include -#include -#include - -//#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 - - diff --git a/src/objson/objson_test.c b/src/objson/objson_test.c index 20cf2ff..5813780 100644 --- a/src/objson/objson_test.c +++ b/src/objson/objson_test.c @@ -14,8 +14,8 @@ GNU General Public License for more details. */ //#include "utils.h" -#include "object.h" -#include "json_parser.h" +#include +#include #include #include diff --git a/src/objson/xml2json.c b/src/objson/xml2json.c index efdcfb0..d3dfaa0 100644 --- a/src/objson/xml2json.c +++ b/src/objson/xml2json.c @@ -1,4 +1,4 @@ -#include "xml2json.h" +#include struct osrfXMLGatewayParserStruct { osrfList* objStack; diff --git a/src/objson/xml2json.h b/src/objson/xml2json.h deleted file mode 100644 index 35ed4ac..0000000 --- a/src/objson/xml2json.h +++ /dev/null @@ -1,20 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include - -#include "object.h" -#include "json_parser.h" -#include "utils.h" -#include "osrf_list.h" - - - -jsonObject* jsonXMLToJSONObject(const char* xml); - - - diff --git a/src/srfsh/srfsh.h b/src/srfsh/srfsh.h index f6fc7ca..6497231 100644 --- a/src/srfsh/srfsh.h +++ b/src/srfsh/srfsh.h @@ -1,13 +1,13 @@ -#include "opensrf/transport_client.h" -#include "opensrf/osrf_message.h" -#include "opensrf/osrf_app_session.h" +#include +#include +#include #include #include #include #include -#include "utils.h" -#include "log.h" +#include +#include #include diff --git a/src/utils/Makefile b/src/utils/Makefile deleted file mode 100644 index 77eae02..0000000 --- a/src/utils/Makefile +++ /dev/null @@ -1,21 +0,0 @@ - -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 - - diff --git a/src/utils/fieldmapper-c.pl b/src/utils/fieldmapper-c.pl deleted file mode 100755 index 80a59e5..0000000 --- a/src/utils/fieldmapper-c.pl +++ /dev/null @@ -1,229 +0,0 @@ -#!/usr/bin/perl -use strict; use warnings; -use Data::Dumper; -use OpenILS::Utils::Fieldmapper; - - -if(!$ARGV[1]) { - print "usage: $0 \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 <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 <array); - free(fm); -} -C - -my $factory_string = <classname) return NULL; - fm_obj* fm = NULL; - -C - -my $fstring_string = <{$object}->{hint}; - my $func_header_string = ""; - my $func_code_string = ""; - my $constructor_string = ""; - - $factory_string .= <classname,"$short_name")) - fm = (fm_obj*) fm_new_$short_name(obj); -CODE - - $fstring_string .= <set_class(obj, "$short_name"); -CODE - - my $header_string = <array) return NULL; - growing_buffer* buf = buffer_init(256); - buffer_fadd(buf, "%s => {\\n", fm->classname); - object* o; -CODE - - $constructor_string .= <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 .= <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 .= <is_null = 1; - obj->set_index(obj, $position, tmp); -CODE - - $header_string .= <set_$field = &fm_${short_name}_set_$field; - fm->get_$field = &fm_${short_name}_get_$field; -CODE - - $func_header_string .= <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 .= < _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; -} - - diff --git a/src/utils/log.h b/src/utils/log.h deleted file mode 100644 index 1928d41..0000000 --- a/src/utils/log.h +++ /dev/null @@ -1,79 +0,0 @@ -#include -#include -#include "utils.h" -#include -#include - -#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 diff --git a/src/utils/md5.c b/src/utils/md5.c deleted file mode 100644 index 7da3d60..0000000 --- a/src/utils/md5.c +++ /dev/null @@ -1,366 +0,0 @@ -/* --- The data --- */ - -const char data[] = -"/* --- The MD5 routines --- */\n\n/* MD5 routines, after Ron R" -"ivest */\n/* Written by David Madore , 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<>(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 \n#include \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 , 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<>(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; - } -} - -/* --- The core of the program --- */ - -#include -#include - -#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; -} -*/ diff --git a/src/utils/md5.h b/src/utils/md5.h deleted file mode 100644 index 53dd2b1..0000000 --- a/src/utils/md5.h +++ /dev/null @@ -1,35 +0,0 @@ -/* --- The MD5 routines --- */ - -/* MD5 routines, after Ron Rivest */ -/* Written by David Madore , 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 */ - diff --git a/src/utils/sha.c b/src/utils/sha.c deleted file mode 100644 index 14791bd..0000000 --- a/src/utils/sha.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * 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 -- Expansion function fix - Thomas "temas" Muldowney : - -- 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 -#endif - -#include -#include -#include -#ifdef MACOS -# include -#else -# include -# include -#endif - -#include - -#ifndef WIN32 -# include -# define INT64 long long -#else -# include -# 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; -} diff --git a/src/utils/sha.h b/src/utils/sha.h deleted file mode 100644 index 6c3d2d4..0000000 --- a/src/utils/sha.h +++ /dev/null @@ -1,41 +0,0 @@ -// 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 - diff --git a/src/utils/socket_bundle.c b/src/utils/socket_bundle.c deleted file mode 100644 index 4356ef6..0000000 --- a/src/utils/socket_bundle.c +++ /dev/null @@ -1,743 +0,0 @@ -#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); - -} - diff --git a/src/utils/socket_bundle.h b/src/utils/socket_bundle.h deleted file mode 100644 index 28a5405..0000000 --- a/src/utils/socket_bundle.h +++ /dev/null @@ -1,112 +0,0 @@ -#include "utils.h" - -#include -#include -#include -#include - -#include "utils.h" -#include "log.h" - -//--------------------------------------------------------------- -// Unix headers -//--------------------------------------------------------------- -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#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 diff --git a/src/utils/socket_test.c b/src/utils/socket_test.c deleted file mode 100644 index 4bc7653..0000000 --- a/src/utils/socket_test.c +++ /dev/null @@ -1,33 +0,0 @@ -#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; -} diff --git a/src/utils/string_array.c b/src/utils/string_array.c deleted file mode 100644 index ee8c542..0000000 --- a/src/utils/string_array.c +++ /dev/null @@ -1,116 +0,0 @@ -#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--; -} - - diff --git a/src/utils/string_array.h b/src/utils/string_array.h deleted file mode 100644 index c235b93..0000000 --- a/src/utils/string_array.h +++ /dev/null @@ -1,41 +0,0 @@ -#include - -#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 diff --git a/src/utils/utils.c b/src/utils/utils.c deleted file mode 100644 index 47b3d2f..0000000 --- a/src/utils/utils.c +++ /dev/null @@ -1,475 +0,0 @@ -/* -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 - -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; -} - diff --git a/src/utils/utils.h b/src/utils/utils.h deleted file mode 100644 index 7bbade0..0000000 --- a/src/utils/utils.h +++ /dev/null @@ -1,239 +0,0 @@ -/* -Copyright (C) 2005 Georgia Public Library Service -Bill Erickson -Mike Rylander - -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include - -#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 diff --git a/src/utils/xml_utils.c b/src/utils/xml_utils.c deleted file mode 100644 index cb2164f..0000000 --- a/src/utils/xml_utils.c +++ /dev/null @@ -1,121 +0,0 @@ -#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; -} - diff --git a/src/utils/xml_utils.h b/src/utils/xml_utils.h deleted file mode 100644 index a329061..0000000 --- a/src/utils/xml_utils.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef _XML_UTILS_H -#define _XML_UTILS_H - -#include "objson/object.h" -#include -#include - -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 diff --git a/src/xinclude/Makefile b/src/xinclude/Makefile deleted file mode 100644 index ba537e9..0000000 --- a/src/xinclude/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -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 diff --git a/src/xinclude/mod_xinclude.c b/src/xinclude/mod_xinclude.c deleted file mode 100644 index 08fee22..0000000 --- a/src/xinclude/mod_xinclude.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "httpd.h" -#include "http_config.h" -#include "http_core.h" -#include "http_protocol.h" -#include "apr_compat.h" -#include "apr_strings.h" - -#include -#include - -#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, -}; -