From acd4e6fc8dcebf4ce8500163befa43d316f79649 Mon Sep 17 00:00:00 2001 From: erickson Date: Fri, 2 Sep 2005 19:38:35 +0000 Subject: [PATCH] Young C server code added git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@518 9efc2488-bf62-4759-914b-345cdb29e865 --- bin/opensrf_all | 4 +- src/Makefile | 15 +++- src/libstack/Makefile | 30 +++++-- src/libstack/opensrf.c | 18 +++++ src/libstack/osrf_app_session.c | 48 +++++++++-- src/libstack/osrf_app_session.h | 8 ++ src/libstack/osrf_application.c | 153 +++++++++++++++++++++++++++++++++++ src/libstack/osrf_application.h | 128 +++++++++++++++++++++++++++++ src/libstack/osrf_prefork.c | 51 +++++++++--- src/libstack/osrf_prefork.h | 4 + src/libstack/osrf_settings.c | 3 +- src/libstack/osrf_stack.c | 70 +++++++++++----- src/libstack/osrf_system.c | 91 ++++++++++++++++++++- src/libstack/osrf_system.h | 23 +++++- src/libtransport/transport_message.c | 11 ++- src/perlmods/OpenSRF/System.pm | 2 +- src/utils/socket_bundle.c | 4 +- 17 files changed, 603 insertions(+), 60 deletions(-) create mode 100644 src/libstack/opensrf.c create mode 100644 src/libstack/osrf_application.c create mode 100644 src/libstack/osrf_application.h diff --git a/bin/opensrf_all b/bin/opensrf_all index 9014411..f84a747 100755 --- a/bin/opensrf_all +++ b/bin/opensrf_all @@ -122,12 +122,12 @@ function stopMe { echo "Stopping OpenSRF..."; "$BINDIR/opensrf_ctl" stop; - sleep 2; + sleep 1; echo "Stopping The Router..."; killall router; - sleep 2; + sleep 1; echo "Stopping Chop Chop..."; killall jserver-c; diff --git a/src/Makefile b/src/Makefile index 5458e25..6ff8ea7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -25,6 +25,7 @@ OPENSRF_TARGETS = libtransport/transport_session.o \ libstack/osrf_message.o \ libstack/osrf_prefork.o \ libstack/osrf_system.o \ + libstack/osrf_application.o \ libstack/xml_utils.o \ utils/socket_bundle.o \ utils/string_array.o \ @@ -43,6 +44,7 @@ OPENSRF_HEADERS = libtransport/transport_session.h \ libstack/osrf_message.h \ libstack/osrf_prefork.h \ libstack/osrf_system.h \ + libstack/osrf_application.h \ libstack/xml_utils.h \ utils/socket_bundle.h \ utils/string_array.h \ @@ -52,7 +54,7 @@ OPENSRF_HEADERS = libtransport/transport_session.h \ utils/sha.h \ -all: prep libopensrf.so router srfsh jserver gateway +all: prep libopensrf.so libstack/opensrf router srfsh jserver gateway install: install-prep opensrf-install gateway-install router-install \ srfsh-install jserver-install perl-install objson-install @@ -69,12 +71,15 @@ libopensrf.so: objson/libobjson.so make -C libstack @echo $@ $(CC) -shared -W1 $(LDFLAGS) -lobjson $(OPENSRF_TARGETS) -o $(TMPDIR)/$(LIBOPENSRF) + @echo apps + make -C c-apps opensrf-install: @echo $@ cp $(TMPDIR)/$(LIBOPENSRF) $(LIBDIR)/$(LIBOPENSRF) cp $(OPENSRF_HEADERS) $(INCLUDEDIR)/opensrf/ + make -C c-apps install objson/libobjson.so: @@ -84,6 +89,11 @@ objson/libobjson.so: # -------------------------------------------------------------------------------- # BINARIES # -------------------------------------------------------------------------------- +libstack/opensrf.o: libstack/opensrf.c +libstack/opensrf: libstack/opensrf.o + $(CC) $(CFLAGS) $(LDFLAGS) -lxml2 -lopensrf -lobjson libstack/opensrf.o -o $@ + + router: libopensrf.so @echo $@ make -C router @@ -162,7 +172,8 @@ 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) + /bin/rm -rf $(TMPDIR) *.o diff --git a/src/libstack/Makefile b/src/libstack/Makefile index 0579807..f8887e5 100644 --- a/src/libstack/Makefile +++ b/src/libstack/Makefile @@ -1,11 +1,28 @@ -CFLAGS += -DASSUME_STATELESS -LDLIBS += -lxml2 -lobjson +CFLAGS += -DASSUME_STATELESS -rdynamic -fno-strict-aliasing +LDLIBS += -lxml2 -lobjson -ldl -TARGETS = osrf_message.o osrf_app_session.o osrf_stack.o osrf_system.o osrf_settings.o osrf_prefork.o osrfConfig.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 xml_utils.h +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 \ + xml_utils.o -all: xml_utils.o $(TARGETS) copy +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 \ + xml_utils.h + +all: xml_utils.o $(TARGETS) copy xml_utils.o: cp ../utils/xml_utils.h . @@ -22,6 +39,7 @@ 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 clean: - /bin/rm -f *.o libopensrf_stack.so test xml_utils.h xml_utils.c + /bin/rm -f *.o libopensrf_stack.so xml_utils.h xml_utils.c diff --git a/src/libstack/opensrf.c b/src/libstack/opensrf.c new file mode 100644 index 0000000..6e77ace --- /dev/null +++ b/src/libstack/opensrf.c @@ -0,0 +1,18 @@ +#include "osrf_system.h" + +int main( int argc, char* argv[] ) { + + if( argc < 4 ) { + fprintf(stderr, "Host, Bootstrap, and context required\n"); + return 1; + } + + fprintf(stderr, "Loading OpenSRF host %s with bootstrap config %s " + "and config context %s\n", argv[1], argv[2], argv[3] ); + + osrfSystemBootstrap( argv[1], argv[2], argv[3] ); + + return 0; +} + + diff --git a/src/libstack/osrf_app_session.c b/src/libstack/osrf_app_session.c index 6080561..60b767f 100644 --- a/src/libstack/osrf_app_session.c +++ b/src/libstack/osrf_app_session.c @@ -293,10 +293,11 @@ osrf_app_session* osrf_app_client_session_init( char* remote_service ) { osrf_app_session* osrf_app_server_session_init( char* session_id, char* our_app, char* remote_id ) { - osrf_app_session* session = osrf_app_session_find_session( session_id ); - if(session) - return session; + info_handler("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)); @@ -305,6 +306,7 @@ osrf_app_session* osrf_app_server_session_init( warning_handler("No transport client for service '%s'", our_app ); return NULL; } + session->request_queue = NULL; session->remote_id = strdup(remote_id); session->orig_remote_id = strdup(remote_id); @@ -317,12 +319,9 @@ osrf_app_session* osrf_app_server_session_init( session->stateless = 0; #endif - debug_handler( "Building a new server session [%s] with id [%s]", - session->remote_service, session_id ); - session->thread_trace = 0; session->state = OSRF_SESSION_DISCONNECTED; - session->type = OSRF_SESSION_CLIENT; + session->type = OSRF_SESSION_SERVER; session->next = NULL; _osrf_app_session_push_session( session ); @@ -683,3 +682,38 @@ osrf_message* osrf_app_session_request_recv( 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 ); + 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 osrfAppSessionStatus( osrfAppSession* ses, int type, int reqId, char* message ) { + + if(ses) { + osrf_message* msg = osrf_message_init( STATUS, reqId, 1); + osrf_message_set_status_info( msg, "Server Error", 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 index 50d283a..3b57880 100644 --- a/src/libstack/osrf_app_session.h +++ b/src/libstack/osrf_app_session.h @@ -2,6 +2,7 @@ #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" @@ -42,6 +43,7 @@ struct osrf_app_request_struct { struct osrf_app_request_struct* next; }; typedef struct osrf_app_request_struct osrf_app_request; +typedef struct osrf_app_request_struct osrfAppRequest; struct osrf_app_session_struct { @@ -78,6 +80,7 @@ struct osrf_app_session_struct { }; typedef struct osrf_app_session_struct osrf_app_session; +typedef struct osrf_app_session_struct osrfAppSession; @@ -209,4 +212,9 @@ 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 osrfAppRequestRespond( osrfAppSession* ses, int requestId, jsonObject* data ); + +int osrfAppSessionStatus( osrfAppSession* ses, int type, int reqId, char* message ); + + #endif diff --git a/src/libstack/osrf_application.c b/src/libstack/osrf_application.c new file mode 100644 index 0000000..8ede790 --- /dev/null +++ b/src/libstack/osrf_application.c @@ -0,0 +1,153 @@ + +#include "osrf_application.h" + +osrfApplication* __osrfAppList = NULL; + + +int osrfAppRegisterApplication( char* appName, char* soFile ) { + if(!appName || ! soFile) return -1; + char* error; + + info_handler("Registering application %s with file %s", appName, soFile ); + + osrfApplication* app = safe_malloc(sizeof(osrfApplication)); + app->handle = dlopen (soFile, RTLD_NOW); + + if(!app->handle) { + warning_handler("Failed to dlopen library file %s: %s", soFile, dlerror() ); + dlerror(); /* clear the error */ + free(app); + return -1; + } + + app->name = strdup(appName); + + /* this has to be done before initting the application */ + app->next = __osrfAppList; + __osrfAppList = app; + + + /* see if we can run the initialize method */ + int (*init) (void); + *(void **) (&init) = dlsym(app->handle, "initialize"); + + if( (error = dlerror()) != NULL ) { + warning_handler("! Unable to locate method symbol [initialize] for app %s: %s", appName, error ); + + } else { + + /* run the method */ + int ret; + if( (ret = (*init)()) ) { + warning_handler("Application %s returned non-zero value from " + "'initialize', not registering...", appName ); + //free(app->name); /* need a method to remove an application from the list */ + //free(app); + return ret; + } + } + + + info_handler("Application %s registered successfully", appName ); + + + return 0; +} + + +int osrfAppRegisterMethod( char* appName, + char* methodName, char* symbolName, char* notes, int argc ) { + if( !appName || ! methodName || ! symbolName ) return -1; + + osrfApplication* app = _osrfAppFindApplication(appName); + if(!app) return warning_handler("Unable to locate application %s", appName ); + + debug_handler("Registering method %s for app %s", appName, methodName ); + + osrfMethod* method = safe_malloc(sizeof(osrfMethod)); + method->name = strdup(methodName); + method->symbol = strdup(symbolName); + if(notes) method->notes = strdup(notes); + method->argc = argc; + + /* plug the method into the list of methods */ + method->next = app->methods; + app->methods = method; + return 0; +} + +osrfApplication* _osrfAppFindApplication( char* name ) { + if(!name) return NULL; + osrfApplication* app = __osrfAppList; + while(app) { + if(!strcmp(app->name, name)) + return app; + app = app->next; + } + return NULL; +} + +osrfMethod* __osrfAppFindMethod( osrfApplication* app, char* methodName ) { + if(!app || ! methodName) return NULL; + osrfMethod* method = app->methods; + while(method) { + if(!strcmp(method->name, methodName)) + return method; + method = method->next; + } + return NULL; +} + +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; + + info_handler("Running method [%s] for app [%s] with request id %d and " + "thread trace %s", methodName, appName, reqId, ses->session_id ); + + osrfApplication* app = _osrfAppFindApplication(appName); + if(!app) return warning_handler( "Application not found: %s", appName ); + + osrfMethod* method = __osrfAppFindMethod( app, methodName ); + if(!method) return warning_handler( "NOT FOUND: app %s / method %s", appName, methodName ); + + /* this is the method we're gonna run */ + int (*meth) (osrfMethodDispatcher*); + + /* open the method */ + *(void **) (&meth) = dlsym(app->handle, method->symbol); + + if( (error = dlerror()) != NULL ) { + return warning_handler("Unable to locate method symbol [%s] " + "for method %s and app %s", method->symbol, method->name, app->name ); + } + + osrfMethodDispatcher d; + d.session = ses; + d.method = method; + d.params = params; + d.request = reqId; + + /* run the method */ + int ret = (*meth) (&d); + + debug_handler("method returned %d", ret ); + + + if(ret == -1) { + /* return an internal server error ? */ + } + + return 0; +} + + + diff --git a/src/libstack/osrf_application.h b/src/libstack/osrf_application.h new file mode 100644 index 0000000..1724f80 --- /dev/null +++ b/src/libstack/osrf_application.h @@ -0,0 +1,128 @@ + +#include +#include +#include "opensrf/utils.h" +#include "opensrf/logging.h" +#include "objson/object.h" +#include "osrf_app_session.h" + +#define OSRF_METHOD_CHECK_PARAMS(x,y) \ + if( ! x || ! y ) return -1; \ + if(y->type != JSON_ARRAY ) return -1; \ + char* __j = jsonObjectToJSON(y);\ + if(__j) { \ + debug_handler("Service: %s | Params: %s", x->remote_service, __j);free(__j);} + + +/** + This macro verifies methods receive the correct parameters + It also creates local variables "session", "method", + "params", and "request" + */ + +#define OSRF_METHOD_VERIFY_DISPATCHER(__d) \ + if(!__d) return -1; \ + \ + osrfAppSession* session = __d->session; \ + osrfMethod* method = __d->method; \ + jsonObject* params = __d->params; \ + int request = __d->request; \ + \ + if( !(session && method && params) ) return -1; \ + if( !params->type == JSON_ARRAY ) return -1; \ + if( !method->name ) return -1; \ + \ + char* __j = jsonObjectToJSON(params);\ + if(__j) { \ + debug_handler("Service: %s | Params: %s", session->remote_service, __j);free(__j);} + + + + + +struct _osrfApplicationStruct { + char* name; /* the name of our application */ + void* handle; /* the lib handle */ + struct _osrfMethodStruct* methods; /* list of methods */ + struct _osrfApplicationStruct* next; /* next application */ +}; +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 */ + void* methodHandle; /* cached version of the method handle */ + struct _osrfMethodStruct* next; +}; +typedef struct _osrfMethodStruct osrfMethod; + +struct _osrfMethodDispatcherStruct { + osrfAppSession* session; + osrfMethod* method; + jsonObject* params; + int request; +}; +typedef struct _osrfMethodDispatcherStruct osrfMethodDispatcher; + + +/** + 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 + @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 + @return 0 on success, -1 on error + */ +int osrfAppRegisterMethod( char* appName, + char* methodName, char* symbolName, char* notes, int argc ); + +/** + 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 ); + + diff --git a/src/libstack/osrf_prefork.c b/src/libstack/osrf_prefork.c index 8e718be..f34f9a5 100644 --- a/src/libstack/osrf_prefork.c +++ b/src/libstack/osrf_prefork.c @@ -43,7 +43,7 @@ int osrf_prefork_run(char* appname) { free(resc); prefork_simple* forker = prefork_simple_init( - osrf_system_get_transport_client(), maxr, minc, maxc); + osrfSystemGetTransportClient(), maxr, minc, maxc); forker->appname = strdup(appname); @@ -51,6 +51,8 @@ int osrf_prefork_run(char* appname) { fatal_handler("osrf_prefork_run() failed to create prefork_simple object"); prefork_launch_children(forker); + + osrf_prefork_register_routers(appname); info_handler("Launching osrf_forker for app %s", appname); prefork_run(forker); @@ -61,8 +63,34 @@ int osrf_prefork_run(char* appname) { } -void osrf_prefork_register_routers() { - //char* router = osrf_config_value("//%s/ +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(); + + info_handler("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 ); + info_handler("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); } void prefork_child_init_hook(prefork_child* child) { @@ -228,10 +256,9 @@ void prefork_run(prefork_simple* forker) { } debug_handler("Forker going into wait for data..."); - sleep(2); cur_msg = client_recv( forker->connection, -1 ); - fprintf(stderr, "Got Data %f\n", get_timestamp_millis() ); + //fprintf(stderr, "Got Data %f\n", get_timestamp_millis() ); if( cur_msg == NULL ) continue; @@ -260,14 +287,14 @@ void prefork_run(prefork_simple* forker) { debug_handler( "Writing to child fd %d", cur_child->write_data_fd ); int written = 0; - fprintf(stderr, "Writing Data %f\n", get_timestamp_millis() ); + //fprintf(stderr, "Writing Data %f\n", get_timestamp_millis() ); if( (written = write( cur_child->write_data_fd, data, strlen(data) + 1 )) < 0 ) { warning_handler("Write returned error %d", errno); cur_child = cur_child->next; continue; } - fprintf(stderr, "Wrote %d bytes to child\n", written); + //fprintf(stderr, "Wrote %d bytes to child\n", written); forker->first_child = cur_child->next; honored = 1; @@ -305,7 +332,7 @@ void prefork_run(prefork_simple* forker) { reap_children(forker); - fprintf(stderr, "Parent done with request %f\n", get_timestamp_millis() ); + //fprintf(stderr, "Parent done with request %f\n", get_timestamp_millis() ); } // honored? @@ -358,7 +385,7 @@ void check_children( prefork_simple* forker ) { 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 ); + //printf( "Server received status from a child %d\n", cur_child->pid ); debug_handler( "Server received status from a child %d", cur_child->pid ); num_handled++; @@ -394,16 +421,16 @@ void prefork_child_wait( prefork_child* child ) { buffer_add( gbuf, buf ); memset( buf, 0, READ_BUFSIZE ); - fprintf(stderr, "Child read %d bytes\n", n); + //fprintf(stderr, "Child read %d bytes\n", n); if( n == READ_BUFSIZE ) { - fprintf(stderr, "We read READ_BUFSIZE data....\n"); + //fprintf(stderr, "We read READ_BUFSIZE data....\n"); /* XXX */ /* either we have exactly READ_BUFSIZE data, or there's more waiting that we need to grab*/ /* must set to non-block for reading more */ } else { - fprintf(stderr, "Read Data %f\n", get_timestamp_millis() ); + //fprintf(stderr, "Read Data %f\n", get_timestamp_millis() ); prefork_child_process_request(child, gbuf->buf); buffer_reset( gbuf ); break; diff --git a/src/libstack/osrf_prefork.h b/src/libstack/osrf_prefork.h index a2dfdb8..22d7742 100644 --- a/src/libstack/osrf_prefork.h +++ b/src/libstack/osrf_prefork.h @@ -9,6 +9,7 @@ #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" @@ -88,3 +89,6 @@ int prefork_free( prefork_simple* ); int prefork_child_free( prefork_child* ); +void osrf_prefork_register_routers( char* appname ); + + diff --git a/src/libstack/osrf_settings.c b/src/libstack/osrf_settings.c index 286a1eb..2f2860d 100644 --- a/src/libstack/osrf_settings.c +++ b/src/libstack/osrf_settings.c @@ -21,7 +21,8 @@ int osrf_settings_retrieve(char* hostname) { if(!config) { osrf_app_session* session = osrf_app_client_session_init("opensrf.settings"); - jsonObject* params = jsonNewObject(hostname); + 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 ); diff --git a/src/libstack/osrf_stack.c b/src/libstack/osrf_stack.c index 3f73dbf..e6e1cb0 100644 --- a/src/libstack/osrf_stack.c +++ b/src/libstack/osrf_stack.c @@ -1,4 +1,5 @@ #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* ); @@ -33,6 +34,8 @@ int osrf_stack_process( transport_client* client, int timeout ) { // ----------------------------------------------------------------------------- int osrf_stack_transport_handler( transport_message* msg, char* my_service ) { + if(!msg) return -1; + debug_handler( "Transport handler received new message \nfrom %s " "to %s with body \n\n%s\n", msg->sender, msg->recipient, msg->body ); @@ -43,14 +46,11 @@ int osrf_stack_transport_handler( transport_message* msg, char* my_service ) { osrf_app_session* session = osrf_app_session_find_session( msg->thread ); - if( session == NULL ) { /* we must be a server, build a new session */ - info_handler( "Received message for nonexistant session. Dropping..." ); - //osrf_app_server_session_init( msg->thread, my_service, msg->sender); - message_free( msg ); - return 1; - } + if( session == NULL ) + session = osrf_app_server_session_init( msg->thread, my_service, msg->sender); - //debug_handler("Session [%s] found, building message", msg->thread ); + if(!msg->is_error) + debug_handler("Session [%s] found or built", session->session_id ); osrf_app_session_set_remote( session, msg->sender ); osrf_message* arr[OSRF_MAX_MSGS_PER_PACKET]; @@ -96,14 +96,17 @@ int osrf_stack_message_handler( osrf_app_session* session, osrf_message* msg ) { 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) + if(ret_msg) { + debug_handler("passing message %d / session %s to app handler", + msg->thread_trace, session->session_id ); osrf_stack_application_handler( session, ret_msg ); - else + } else osrf_message_free(msg); return 1; @@ -146,7 +149,8 @@ osrf_message* _do_client( osrf_app_session* session, osrf_message* msg ) { case OSRF_STATUS_EXPFAILED: osrf_app_session_reset_remote( session ); session->state = OSRF_SESSION_DISCONNECTED; - osrf_app_session_request_resend( session, msg->thread_trace ); + /* set the session to 'stateful' then resend */ + // osrf_app_session_request_resend( session, msg->thread_trace ); return NULL; case OSRF_STATUS_TIMEOUT: @@ -183,30 +187,58 @@ osrf_message* _do_client( osrf_app_session* session, osrf_message* msg ) { * 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; - if( msg->m_type == STATUS ) { return NULL; } + if(session == NULL || msg == NULL) return NULL; + + debug_handler("Server received message of type %d", msg->m_type ); + + switch( msg->m_type ) { + + case STATUS: + return NULL; + + case DISCONNECT: + osrf_app_session_destroy(session); + return NULL; + + case CONNECT: + /* handle connect message */ + return NULL; - warning_handler( "We dont' do servers yet !!" ); + case REQUEST: - return msg; + debug_handler("server passing message %d to application handler " + "for session %s", msg->thread_trace, session->session_id ); + return msg; + + default: + warning_handler("Server cannot handle message of type %d", msg->m_type ); + 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) { + 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; } - warning_handler( "application_handler can't handle whatever you sent, type %d", msg->m_type); + 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 ); + return 1; } + diff --git a/src/libstack/osrf_system.c b/src/libstack/osrf_system.c index f8cf8dd..97b2e59 100644 --- a/src/libstack/osrf_system.c +++ b/src/libstack/osrf_system.c @@ -1,7 +1,16 @@ #include "osrf_system.h" +#include +#include "osrf_application.h" +#include "osrf_prefork.h" + +void __osrfSystemSignalHandler( int sig ); transport_client* __osrfGlobalTransportClient; +transport_client* osrfSystemGetTransportClient() { + return __osrfGlobalTransportClient; +} + transport_client* osrf_system_get_transport_client() { return __osrfGlobalTransportClient; } @@ -10,10 +19,79 @@ 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 ); +} + + +int osrfSystemBootstrap( char* hostname, char* configfile, char* contextNode ) { + if( !(configfile && contextNode) ) return -1; + + /* first we grab the settings */ + if(!osrfSystemBootstrapClientResc(configfile, contextNode, "settings_grabber" )) { + return fatal_handler("Unable to bootstrap"); + } + + osrf_settings_retrieve(hostname); + osrf_system_disconnect_client(); + + jsonObject* apps = osrf_settings_host_value_object("/activeapps/appname"); + osrfStringArray* arr = osrfNewStringArray(8); + + 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* libfile = osrf_settings_host_value("/apps/%s/implementation", appname); + info_handler("Launching application %s with implementation %s", appname, libfile); + + if(! (appname && libfile) ) { + warning_handler("Missing appname / libfile in settings config"); + continue; + } + + int pid; + + if( (pid = fork()) ) { + // storage pid in local table for re-launching dead children... + info_handler("Launched application child %d", pid); + + } else { + + osrfAppRegisterApplication( appname, libfile ); + osrf_prefork_run(appname); + exit(0); + } + } + } + + /** daemonize me **/ + + /* let our children do their thing */ + while(1) { + signal(SIGCHLD, __osrfSystemSignalHandler); + sleep(10000); + } + + return 0; +} + int osrf_system_bootstrap_client_resc( char* config_file, char* contextnode, char* resource ) { if( !( config_file && contextnode ) && ! osrfConfigHasDefaultConfig() ) - fatal_handler("No Config File Specified\n" ); + return fatal_handler("No Config File Specified\n" ); if( config_file ) { osrfConfigCleanup(); @@ -91,3 +169,14 @@ int osrf_system_shutdown() { +void __osrfSystemSignalHandler( int sig ) { + + pid_t pid; + int status; + + while( (pid = waitpid(-1, &status, WNOHANG)) > 0) { + warning_handler("We lost child %d", pid); + } + + /** relaunch the server **/ +} diff --git a/src/libstack/osrf_system.h b/src/libstack/osrf_system.h index 414b7d3..7200e14 100644 --- a/src/libstack/osrf_system.h +++ b/src/libstack/osrf_system.h @@ -16,16 +16,31 @@ 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(); transport_client* osrf_system_get_transport_client(); /* disconnects and destroys the current client connection */ int osrf_system_disconnect_client(); int osrf_system_shutdown(); -char* osrf_get_config_context(); - -char* osrf_get_bootstrap_config(); - #endif diff --git a/src/libtransport/transport_message.c b/src/libtransport/transport_message.c index 7af26a0..12ee0d1 100644 --- a/src/libtransport/transport_message.c +++ b/src/libtransport/transport_message.c @@ -55,10 +55,15 @@ transport_message* new_message_from_xml( const char* msg_xml ) { xmlChar* router_class= xmlGetProp( root, BAD_CAST "router_class" ); xmlChar* broadcast = xmlGetProp( root, BAD_CAST "broadcast" ); - if( sender ) { - new_msg->sender = strdup((char*)sender); - xmlFree(sender); + 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); diff --git a/src/perlmods/OpenSRF/System.pm b/src/perlmods/OpenSRF/System.pm index 87d7848..8d4e1b1 100644 --- a/src/perlmods/OpenSRF/System.pm +++ b/src/perlmods/OpenSRF/System.pm @@ -143,7 +143,7 @@ sub bootstrap { my $client = OpenSRF::Utils::SettingsClient->new(); my $apps = $client->config_value("activeapps", "appname"); - if(!ref($apps) eq "ARRAY") { $apps = [$apps]; } + if(ref($apps) ne "ARRAY") { $apps = [$apps]; } if(!defined($apps) || @$apps == 0) { print "No apps to load, exiting..."; diff --git a/src/utils/socket_bundle.c b/src/utils/socket_bundle.c index dc4a8e2..f2976dd 100644 --- a/src/utils/socket_bundle.c +++ b/src/utils/socket_bundle.c @@ -306,7 +306,7 @@ int socket_send(int sock_fd, const char* data) { debug_handler( "socket_bundle sending to %d data %s", sock_fd, data); - info_handler("%d : Sending data at %lf\n", getpid(), get_timestamp_millis()); + debug_handler("%d : Sending data at %lf\n", getpid(), get_timestamp_millis()); signal(SIGPIPE, SIG_IGN); /* in case a unix socket was closed */ if( send( sock_fd, data, strlen(data), 0 ) < 0 ) { return warning_handler( "tcp_server_send(): Error sending data" ); @@ -536,7 +536,7 @@ int _socket_handle_client_data(socket_manager* mgr, socket_node* node) { set_fl(sock_fd, O_NONBLOCK); debug_handler("Gathering client data for %d", node->sock_fd); - info_handler("%d : Received data at %lf\n", getpid(), get_timestamp_millis()); + debug_handler("%d : Received data at %lf\n", getpid(), get_timestamp_millis()); while( (read_bytes = recv(sock_fd, buf, RBUFSIZE-1, 0) ) > 0 ) { debug_handler("Socket %d Read %d bytes and data: %s", sock_fd, read_bytes, buf); -- 2.11.0