From 04fe0eb8c1d1fada0cf2fe721a2a42a2665b132f Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@9efc2488-bf62-4759-914b-345cdb29e865> Date: Mon, 26 Mar 2007 17:41:51 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create branch 'rel_1_0_4'. git-svn-id: svn://svn.open-ils.org/OpenSRF/branches/rel_1_0_4@854 9efc2488-bf62-4759-914b-345cdb29e865 --- bin/osrf_ctl.sh | 4 +- examples/bootstrap.conf.example | 11 --- examples/opensrf_core.xml.example | 20 ++-- src/Makefile | 13 +-- src/c-apps/osrf_math.c | 8 ++ src/gateway/osrf_json_gateway.c | 51 ++++++---- src/libstack/Makefile | 12 +-- src/libstack/osrf_app_session.c | 5 + src/libstack/osrf_app_session.h | 1 + src/libstack/osrf_application.c | 35 +++++++ src/libstack/osrf_application.h | 3 + src/libstack/osrf_hash.h | 4 +- src/libstack/osrf_prefork.c | 26 ++++- src/libstack/osrf_prefork.h | 2 +- src/libstack/osrf_stack.c | 2 + src/libstack/osrf_system.c | 5 + src/libtransport/transport_message.c | 57 ++++------- src/libtransport/transport_message.h | 4 + src/libtransport/transport_session.c | 8 +- src/libtransport/transport_session.h | 1 + src/objson/json_parser.c | 24 ++--- src/objson/object.c | 5 + src/objson/object.h | 2 + src/perlmods/OpenSRF/AppSession.pm | 9 +- src/perlmods/OpenSRF/Application.pm | 7 +- src/perlmods/OpenSRF/Application/Settings.pm | 4 + src/perlmods/OpenSRF/Transport.pm | 1 + .../OpenSRF/Transport/SlimJabber/Client.pm | 19 +++- .../Transport/SlimJabber/MessageWrapper.pm | 12 +++ src/perlmods/OpenSRF/UnixServer.pm | 17 ++-- src/perlmods/OpenSRF/Utils/Logger.pm | 28 +++++- src/router/osrf_router.c | 9 ++ src/utils/log.c | 48 +++++++++- src/utils/log.h | 6 ++ src/utils/utils.c | 95 ++++++++----------- 35 files changed, 361 insertions(+), 197 deletions(-) diff --git a/bin/osrf_ctl.sh b/bin/osrf_ctl.sh index ef7ce0e..02fb9a6 100755 --- a/bin/osrf_ctl.sh +++ b/bin/osrf_ctl.sh @@ -89,7 +89,9 @@ function do_action { pid=$(cat $pidfile); echo "Stopping $item : $pid"; - kill -s INT $pid; + kill -s INT $pid 2> /dev/null; + sleep 1; + kill -9 $pid 2> /dev/null; rm -f $pidfile; fi; diff --git a/examples/bootstrap.conf.example b/examples/bootstrap.conf.example index 0983c26..ce445f7 100644 --- a/examples/bootstrap.conf.example +++ b/examples/bootstrap.conf.example @@ -42,14 +42,3 @@ port = 5222 # -------------------------------------- -# log file names -[logs] -debug = debug.log -error = error.log -transport = transport.log -message = message.log -method = method.log -trace = trace.log -opac = opac.log - - diff --git a/examples/opensrf_core.xml.example b/examples/opensrf_core.xml.example index 3c9deb9..7d40849 100644 --- a/examples/opensrf_core.xml.example +++ b/examples/opensrf_core.xml.example @@ -13,12 +13,12 @@ list of router domains we should register with. We must at least have our default jabber domain in here --> - 127.0.0.1 + localhost - 127.0.0.1 + localhost client @@ -46,7 +46,7 @@ - 127.0.0.1 + localhost 5222 @@ -62,12 +62,16 @@ + + true + router - 127.0.0.1 + localhost - 127.0.0.1 + localhost - 127.0.0.1 + localhost - 127.0.0.1 + localhost 5222 diff --git a/src/Makefile b/src/Makefile index 7e2cefc..1955932 100644 --- a/src/Makefile +++ b/src/Makefile @@ -31,15 +31,13 @@ OPENSRF_TARGETS = libtransport/transport_session.o \ libstack/xml_utils.o \ libstack/osrf_transgroup.o \ libstack/osrf_list.o \ - libstack/osrf_big_list.o \ libstack/osrf_hash.o \ - libstack/osrf_big_hash.o \ utils/socket_bundle.o \ utils/string_array.o \ utils/utils.o \ utils/log.o \ utils/md5.o \ - utils/sha.o \ + utils/sha.o OPENSRF_HEADERS = libtransport/transport_session.h \ libtransport/transport_client.h \ @@ -56,16 +54,13 @@ OPENSRF_HEADERS = libtransport/transport_session.h \ libstack/xml_utils.h \ libstack/osrf_transgroup.h \ libstack/osrf_list.h \ - libstack/osrf_big_list.h \ libstack/osrf_hash.h \ - libstack/osrf_big_hash.h \ utils/socket_bundle.h \ utils/string_array.h \ utils/utils.h \ utils/log.h \ utils/md5.h \ - utils/sha.h \ - + utils/sha.h all: prep \ libopensrf.so \ @@ -95,7 +90,7 @@ libopensrf.so: objson/libobjson.so @echo stack make -C libstack @echo $@ - $(CC) -shared -W1 $(LDFLAGS) -lJudy -lxml2 -lmemcache -lobjson $(OPENSRF_TARGETS) -o $(TMPDIR)/$(LIBOPENSRF) + $(CC) -shared -W1 $(LDFLAGS) -lxml2 -lmemcache -lobjson $(OPENSRF_TARGETS) -o $(TMPDIR)/$(LIBOPENSRF) @echo apps make -C c-apps @@ -118,7 +113,7 @@ objson/libobjson.so: prep libstack/opensrf.o: libstack/opensrf.c libopensrf.so libstack/opensrf: libstack/opensrf.o @echo $@ - $(CC) $(CFLAGS) $(LDFLAGS) -lJudy -lxml2 -lopensrf -lobjson libstack/opensrf.o -o $@ + $(CC) $(CFLAGS) $(LDFLAGS) -lxml2 -lopensrf -lobjson libstack/opensrf.o -o $@ router: libopensrf.so diff --git a/src/c-apps/osrf_math.c b/src/c-apps/osrf_math.c index ce5e0ae..63d168a 100644 --- a/src/c-apps/osrf_math.c +++ b/src/c-apps/osrf_math.c @@ -7,6 +7,7 @@ int osrfAppInitialize(); int osrfAppChildInit(); +void osrfAppChildExit(); int osrfMathRun( osrfMethodContext* ); @@ -41,10 +42,17 @@ int osrfAppInitialize() { return 0; } +/* called when this process is just coming into existence */ int osrfAppChildInit() { return 0; } +/* called when this process is about to exit */ +void osrfAppChildExit() { + osrfLogDebug(OSRF_LOG_MARK, "Child is exiting..."); +} + + int osrfMathRun( osrfMethodContext* ctx ) { OSRF_METHOD_VERIFY_CONTEXT(ctx); /* see osrf_application.h */ diff --git a/src/gateway/osrf_json_gateway.c b/src/gateway/osrf_json_gateway.c index f370d0c..b9262e0 100644 --- a/src/gateway/osrf_json_gateway.c +++ b/src/gateway/osrf_json_gateway.c @@ -114,6 +114,15 @@ static int osrf_json_gateway_method_handler (request_rec *r) { a_l = apacheGetFirstParamValue( params, "api_level" ); mparams = apacheGetParamValues( params, "param" ); /* free me */ + /* set the user defined timeout value */ + int timeout = 60; + char* tout = apacheGetFirstParamValue( params, "timeout" ); /* request timeout in seconds */ + if( tout ) { + timeout = atoi(tout); + osrfLogDebug(OSRF_LOG_MARK, "Client supplied timeout of %d", timeout); + } + + if (a_l) api_level = atoi(a_l); @@ -146,22 +155,6 @@ static int osrf_json_gateway_method_handler (request_rec *r) { fflush(stderr); */ - - /* ----------------------------------------------------------------- */ - /* log all requests to the activity log */ - const char* authtoken = apr_table_get(r->headers_in, "X-OILS-Authtoken"); - if(!authtoken) authtoken = ""; - growing_buffer* act = buffer_init(128); - buffer_fadd(act, "[%s] [%s] %s %s", r->connection->remote_ip, authtoken, service, method ); - char* str; int i = 0; - while( (str = osrfStringArrayGetString(mparams, i++)) ) - if( i == 1 ) buffer_fadd(act, " %s", str); - else buffer_fadd(act, ", %s", str); - - osrfLogActivity( OSRF_LOG_MARK, act->buf ); - buffer_free(act); - /* ----------------------------------------------------------------- */ - osrfAppSession* session = osrf_app_client_session_init(service); double starttime = get_timestamp_millis(); @@ -176,6 +169,29 @@ static int osrf_json_gateway_method_handler (request_rec *r) { exit(1); } + + /* ----------------------------------------------------------------- */ + /* log all requests to the activity log */ + const char* authtoken = apr_table_get(r->headers_in, "X-OILS-Authtoken"); + if(!authtoken) authtoken = ""; + growing_buffer* act = buffer_init(128); + buffer_fadd(act, "[%s] [%s] %s %s", r->connection->remote_ip, authtoken, service, method ); + char* str; int i = 0; + while( (str = osrfStringArrayGetString(mparams, i++)) ) { + if( i == 1 ) { + OSRF_BUFFER_ADD(act, " "); + OSRF_BUFFER_ADD(act, str); + } else { + OSRF_BUFFER_ADD(act, ", "); + OSRF_BUFFER_ADD(act, str); + } + } + + osrfLogActivity( OSRF_LOG_MARK, act->buf ); + buffer_free(act); + /* ----------------------------------------------------------------- */ + + osrf_message* omsg = NULL; int statuscode = 200; @@ -191,7 +207,7 @@ static int osrf_json_gateway_method_handler (request_rec *r) { char* statustext = NULL; char* output = NULL; - while((omsg = osrfAppSessionRequestRecv( session, req_id, 60 ))) { + while((omsg = osrfAppSessionRequestRecv( session, req_id, timeout ))) { statuscode = omsg->status_code; jsonObject* res; @@ -283,6 +299,7 @@ static int osrf_json_gateway_method_handler (request_rec *r) { string_array_destroy(mparams); osrfLogDebug(OSRF_LOG_MARK, "Gateway served %d requests", ++numserved); + osrfLogClearXid(); return ret; } diff --git a/src/libstack/Makefile b/src/libstack/Makefile index 1de68e4..82fae9a 100644 --- a/src/libstack/Makefile +++ b/src/libstack/Makefile @@ -3,7 +3,7 @@ # 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 -LJudy +LDLIBS += -lxml2 -lobjson -ldl -lmemcache TARGETS = osrf_message.o \ osrf_app_session.o \ @@ -16,10 +16,8 @@ TARGETS = osrf_message.o \ osrf_cache.o \ osrf_transgroup.o \ osrf_list.o \ - osrf_big_list.o \ osrf_hash.o \ - osrf_big_hash.o \ - xml_utils.o + xml_utils.o HEADERS = osrf_message.h \ osrf_app_session.h \ @@ -32,9 +30,7 @@ HEADERS = osrf_message.h \ osrf_cache.h \ osrf_transgroup.h \ osrf_list.h \ - osrf_big_list.h \ osrf_hash.h \ - osrf_big_hash.h \ xml_utils.h all: xml_utils.o $(TARGETS) copy @@ -57,9 +53,9 @@ 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_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 +#osrf_big_hash.o: osrf_big_hash.c osrf_big_hash.h clean: diff --git a/src/libstack/osrf_app_session.c b/src/libstack/osrf_app_session.c index 0b35537..e3bfe5c 100644 --- a/src/libstack/osrf_app_session.c +++ b/src/libstack/osrf_app_session.c @@ -32,6 +32,8 @@ void osrfAppSessionCleanup() { osrfHashFree(osrfAppSessionCache); } + + /** Frees memory used by an app_request object */ void _osrf_app_request_free( void * req ){ if( req == NULL ) return; @@ -308,6 +310,8 @@ int osrf_app_session_make_req( 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) { @@ -502,6 +506,7 @@ int osrfAppSessionSendBatch( osrfAppSession* session, osrf_message* msgs[], int 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 ); diff --git a/src/libstack/osrf_app_session.h b/src/libstack/osrf_app_session.h index 0d8f814..af35af5 100644 --- a/src/libstack/osrf_app_session.h +++ b/src/libstack/osrf_app_session.h @@ -231,4 +231,5 @@ int osrfAppSessionStatus( osrfAppSession* ses, int type, char* name, int reqId, void osrfAppSessionCleanup(); + #endif diff --git a/src/libstack/osrf_application.c b/src/libstack/osrf_application.c index 238417e..1d62642 100644 --- a/src/libstack/osrf_application.c +++ b/src/libstack/osrf_application.c @@ -16,6 +16,7 @@ int osrfAppRegisterApplication( char* appName, char* 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() ); @@ -54,9 +55,31 @@ int osrfAppRegisterApplication( char* appName, char* soFile ) { 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; @@ -82,6 +105,18 @@ int osrfAppRunChildInit(char* appname) { } +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 ) { diff --git a/src/libstack/osrf_application.h b/src/libstack/osrf_application.h index 10f92ed..0980a81 100644 --- a/src/libstack/osrf_application.h +++ b/src/libstack/osrf_application.h @@ -79,6 +79,7 @@ struct _osrfApplicationStruct { void* handle; /* the lib handle */ osrfHash* methods; + void (*onExit) (void); }; typedef struct _osrfApplicationStruct osrfApplication; @@ -226,5 +227,7 @@ 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_hash.h b/src/libstack/osrf_hash.h index e5a898e..02e62c2 100644 --- a/src/libstack/osrf_hash.h +++ b/src/libstack/osrf_hash.h @@ -6,7 +6,9 @@ #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 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) \ diff --git a/src/libstack/osrf_prefork.c b/src/libstack/osrf_prefork.c index b2cad6c..7d48d82 100644 --- a/src/libstack/osrf_prefork.c +++ b/src/libstack/osrf_prefork.c @@ -126,6 +126,13 @@ int prefork_child_init_hook(prefork_child* child) { 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(); @@ -161,7 +168,7 @@ void prefork_child_process_request(prefork_child* child, char* data) { osrfLogError( OSRF_LOG_MARK, "Unable to bootstrap client in prefork_child_process_request()"); sleep(1); - exit(1); + osrf_prefork_child_exit(child); } } @@ -203,7 +210,7 @@ void prefork_child_process_request(prefork_child* child, char* data) { /* if no data was reveived within the timeout interval */ if( !recvd && (end - start) >= keepalive ) { - osrfLogInfo(OSRF_LOG_MARK, "No data was reveived in %d seconds, exiting stateful session", keepalive); + osrfLogInfo(OSRF_LOG_MARK, "No request was reveived in %d seconds, exiting stateful session", keepalive); osrfAppSessionStatus( session, OSRF_STATUS_TIMEOUT, @@ -306,15 +313,19 @@ prefork_child* launch_child( prefork_simple* forker ) { if( prefork_child_init_hook(child) == -1 ) { osrfLogError(OSRF_LOG_MARK, "Forker child going away because we could not connect to OpenSRF..."); - exit(1); + osrf_prefork_child_exit(child); } prefork_child_wait( child ); - exit(0); /* just to be sure */ + 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; @@ -562,6 +573,11 @@ void prefork_child_wait( prefork_child* child ) { if( errno == EAGAIN ) n = 0; + if( errno == EPIPE ) { + osrfLogWarning(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; @@ -581,7 +597,7 @@ void prefork_child_wait( prefork_child* child ) { osrfLogDebug( OSRF_LOG_MARK, "Child with max-requests=%d, num-served=%d exiting...[%d]", child->max_requests, i, getpid() ); - exit(0); + osrf_prefork_child_exit(child); /* just to be sure */ } diff --git a/src/libstack/osrf_prefork.h b/src/libstack/osrf_prefork.h index 28df9df..9515445 100644 --- a/src/libstack/osrf_prefork.h +++ b/src/libstack/osrf_prefork.h @@ -93,4 +93,4 @@ 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_stack.c b/src/libstack/osrf_stack.c index c327352..528abd0 100644 --- a/src/libstack/osrf_stack.c +++ b/src/libstack/osrf_stack.c @@ -38,6 +38,8 @@ osrfAppSession* osrf_stack_transport_handler( transport_message* msg, char* my_s 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 ); diff --git a/src/libstack/osrf_system.c b/src/libstack/osrf_system.c index 2c9ac60..3f24038 100644 --- a/src/libstack/osrf_system.c +++ b/src/libstack/osrf_system.c @@ -169,6 +169,11 @@ int osrf_system_bootstrap_client_resc( char* config_file, char* contextnode, cha char* domain = strdup(osrfStringArrayGetString( arr, 0 )); /* just the first for now */ osrfStringArrayFree(arr); + /* 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; diff --git a/src/libtransport/transport_message.c b/src/libtransport/transport_message.c index a6e7514..f0e63af 100644 --- a/src/libtransport/transport_message.c +++ b/src/libtransport/transport_message.c @@ -54,6 +54,12 @@ transport_message* new_message_from_xml( const char* msg_xml ) { 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); @@ -122,50 +128,19 @@ transport_message* new_message_from_xml( const char* msg_xml ) { if( new_msg->body == NULL ) new_msg->body = strdup(""); - int bufsize; - xmlChar* xmlbuf; - char* encoded_body; - - xmlDocDumpFormatMemory( msg_doc, &xmlbuf, &bufsize, 0 ); - encoded_body = strdup( (char*) xmlbuf ); - - if( encoded_body == NULL ) - osrfLogError(OSRF_LOG_MARK, "message_to_xml(): Out of Memory"); - - xmlFree(xmlbuf); - xmlFreeDoc(msg_doc); - xmlCleanupParser(); - - /*** remove the XML declaration */ - int len = strlen(encoded_body); - char tmp[len]; - memset( tmp, 0, len ); - int i; - int found_at = 0; - - /* when we reach the first >, take everything after it */ - for( i = 0; i!= len; i++ ) { - if( encoded_body[i] == 62) { /* ascii > */ - - /* found_at holds the starting index of the rest of the doc*/ - found_at = i + 1; - break; - } - } + new_msg->msg_xml = xmlDocToString(msg_doc, 0); + xmlFreeDoc(msg_doc); + xmlCleanupParser(); - if( found_at ) { - /* move the shortened doc into the tmp buffer */ - strncpy( tmp, encoded_body + found_at, len - found_at ); - /* move the tmp buffer back into the allocated space */ - memset( encoded_body, 0, len ); - strcpy( encoded_body, tmp ); - } - - new_msg->msg_xml = encoded_body; 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 ) { @@ -224,6 +199,7 @@ int message_free( transport_message* msg ){ 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); @@ -274,6 +250,7 @@ char* message_to_xml( const transport_message* msg ) { 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" ); diff --git a/src/libtransport/transport_message.h b/src/libtransport/transport_message.h index 5dbd631..4e94e24 100644 --- a/src/libtransport/transport_message.h +++ b/src/libtransport/transport_message.h @@ -7,6 +7,7 @@ #include #include "opensrf/utils.h" +#include "opensrf/xml_utils.h" #include "opensrf/log.h" #ifndef TRANSPORT_MESSAGE_H @@ -27,6 +28,7 @@ struct transport_message_struct { char* router_to; char* router_class; char* router_command; + char* osrf_xid; int is_error; char* error_type; int error_code; @@ -49,6 +51,8 @@ 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 diff --git a/src/libtransport/transport_session.c b/src/libtransport/transport_session.c index 9351c20..43bdcbc 100644 --- a/src/libtransport/transport_session.c +++ b/src/libtransport/transport_session.c @@ -30,6 +30,7 @@ transport_session* init_transport( char* server, /* 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 ); @@ -97,6 +98,7 @@ int session_free( transport_session* session ) { 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); @@ -117,7 +119,7 @@ int session_wait( transport_session* session, int timeout ) { int ret = socket_wait( session->sock_mgr, timeout, session->sock_id ); if( ret ) { - osrfLogError(OSRF_LOG_MARK, "socket_wait returned error code %d", ret); + osrfLogWarning(OSRF_LOG_MARK, "socket_wait returned error code %d", ret); session->state_machine->connected = 0; } return ret; @@ -331,6 +333,7 @@ void startElementHandler( 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" ) ); @@ -467,6 +470,8 @@ void endElementHandler( void *session, const xmlChar *name) { 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 ); } @@ -539,6 +544,7 @@ int reset_session_buffers( transport_session* ses ) { 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 ); diff --git a/src/libtransport/transport_session.h b/src/libtransport/transport_session.h index fa13704..ba02e5b 100644 --- a/src/libtransport/transport_session.h +++ b/src/libtransport/transport_session.h @@ -158,6 +158,7 @@ struct transport_session_struct { 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 diff --git a/src/objson/json_parser.c b/src/objson/json_parser.c index 80f2b53..d75431f 100644 --- a/src/objson/json_parser.c +++ b/src/objson/json_parser.c @@ -184,22 +184,22 @@ int json_parse_json_bool(char* string, unsigned long* index, jsonObject* obj, in char* ret = "json_parse_json_bool(): truncated bool"; - if( *index >= (current_strlen - 5)) + if( *index > (current_strlen - 4)) return json_handle_error(string, index, ret); - - if(!strncasecmp( string + (*index), "false", 5)) { - (*index) += 5; - obj->value.b = 0; + + if(!strncasecmp( string + (*index), "true", 4)) { + (*index) += 4; + obj->value.b = 1; obj->type = JSON_BOOL; return 0; } - if( *index >= (current_strlen - 4)) + if( *index > (current_strlen - 5)) return json_handle_error(string, index, ret); - - if(!strncasecmp( string + (*index), "true", 4)) { - (*index) += 4; - obj->value.b = 1; + + if(!strncasecmp( string + (*index), "false", 5)) { + (*index) += 5; + obj->value.b = 0; obj->type = JSON_BOOL; return 0; } @@ -490,8 +490,8 @@ int json_parse_json_string(char* string, unsigned long* index, jsonObject* obj, /* ----------------------------------------------------------------------- */ /* The following chunk was borrowed with permission from json-c http://oss.metaparadigm.com/json-c/ */ - unsigned char utf_out[3]; - memset(utf_out,0,3); + unsigned char utf_out[4]; + memset(utf_out,0,4); #define hexdigit(x) ( ((x) <= '9') ? (x) - '0' : ((x) & 7) + 9) diff --git a/src/objson/object.c b/src/objson/object.c index c781c30..782379b 100644 --- a/src/objson/object.c +++ b/src/objson/object.c @@ -805,3 +805,8 @@ char* jsonObjectToSimpleString( const jsonObject* o ) { } +int jsonBoolIsTrue( const jsonObject* o ) { + return (o && o->type == JSON_BOOL && o->value.b); +} + + diff --git a/src/objson/object.h b/src/objson/object.h index 0b3887d..baa63e9 100644 --- a/src/objson/object.h +++ b/src/objson/object.h @@ -254,6 +254,8 @@ jsonObject* jsonObjectClone( const jsonObject* o ); */ char* jsonObjectToSimpleString( const jsonObject* o ); +int jsonBoolIsTrue( const jsonObject* o ); + /* ------------------------------------------------------------------------ */ /* XPATH */ diff --git a/src/perlmods/OpenSRF/AppSession.pm b/src/perlmods/OpenSRF/AppSession.pm index e4435b1..6c32af1 100644 --- a/src/perlmods/OpenSRF/AppSession.pm +++ b/src/perlmods/OpenSRF/AppSession.pm @@ -409,6 +409,9 @@ sub request { my $meth = shift; return unless $self; + # tell the logger to create a new xid - the logger will decide if it's really necessary + $logger->mk_osrf_xid; + my $method; if (!ref $meth) { $method = new OpenSRF::DomainObject::oilsMethod ( method => $meth ); @@ -528,13 +531,13 @@ sub send { } } - $logger->debug( "AppSession sending doc: " . JSON->perl2JSON(\@doc), INTERNAL ); - + my $json = JSON->perl2JSON(\@doc); + $logger->internal("AppSession sending doc: $json"); $self->{peer_handle}->send( to => $self->remote_id, thread => $self->session_id, - body => JSON->perl2JSON(\@doc) ); + body => $json ); if( $disconnect) { $self->state( DISCONNECTED ); diff --git a/src/perlmods/OpenSRF/Application.pm b/src/perlmods/OpenSRF/Application.pm index 2723690..0b3f9b7 100644 --- a/src/perlmods/OpenSRF/Application.pm +++ b/src/perlmods/OpenSRF/Application.pm @@ -5,11 +5,12 @@ use base qw/OpenSRF/; use OpenSRF::AppSession; use OpenSRF::DomainObject::oilsMethod; use OpenSRF::DomainObject::oilsResponse qw/:status/; -use OpenSRF::Utils::Logger qw/:level/; +use OpenSRF::Utils::Logger qw/:level $logger/; use Data::Dumper; use Time::HiRes qw/time/; use OpenSRF::EX qw/:try/; use Carp; +use JSON; #use OpenSRF::UnixServer; # to get the server class from UnixServer::App sub DESTROY{}; @@ -94,8 +95,10 @@ sub handler { if ($session->last_message_type eq 'REQUEST') { + my @p = $app_msg->params; my $method_name = $app_msg->method; my $method_proto = $session->last_message_api_level; + $logger->info("CALL: $method_name [".join(', ',@p)."]"); my $coderef = $app->method_lookup( $method_name, $method_proto, 1, 1 ); @@ -164,9 +167,7 @@ sub handler { } my $start = time(); - warn "About to run...\n"; $resp = $coderef->run( $appreq, @args); - warn "Done running...\n"; my $time = sprintf '%.3f', time() - $start; $log->debug( "Method duration for [$method_name]: ". $time ); diff --git a/src/perlmods/OpenSRF/Application/Settings.pm b/src/perlmods/OpenSRF/Application/Settings.pm index 8c2e8d6..561b1d8 100644 --- a/src/perlmods/OpenSRF/Application/Settings.pm +++ b/src/perlmods/OpenSRF/Application/Settings.pm @@ -1,8 +1,12 @@ package OpenSRF::Application::Settings; use OpenSRF::Application; use OpenSRF::Utils::SettingsParser; +use OpenSRF::Utils::Logger qw/$logger/; use base 'OpenSRF::Application'; +sub child_exit { + $logger->debug("settings server child exiting...$$"); +} __PACKAGE__->register_method( method => 'get_host_config', api_name => 'opensrf.settings.host_config.get' ); diff --git a/src/perlmods/OpenSRF/Transport.pm b/src/perlmods/OpenSRF/Transport.pm index bfc25d1..4ee322c 100644 --- a/src/perlmods/OpenSRF/Transport.pm +++ b/src/perlmods/OpenSRF/Transport.pm @@ -89,6 +89,7 @@ sub handler { my $body = $helper->get_body(); my $type = $helper->get_msg_type(); + $logger->set_osrf_xid($helper->get_osrf_xid); if (defined($type) and $type eq 'error') { throw OpenSRF::EX::Session ("$remote_id IS NOT CONNECTED TO THE NETWORK!!!"); diff --git a/src/perlmods/OpenSRF/Transport/SlimJabber/Client.pm b/src/perlmods/OpenSRF/Transport/SlimJabber/Client.pm index 77daf79..657f719 100644 --- a/src/perlmods/OpenSRF/Transport/SlimJabber/Client.pm +++ b/src/perlmods/OpenSRF/Transport/SlimJabber/Client.pm @@ -178,6 +178,7 @@ sub set_block { sub timed_read { my ($self, $timeout) = @_; + $timeout = defined($timeout) ? int($timeout) : undef; $logger->transport( "Temp Buffer Contained: \n". $self->{temp_buffer}, INTERNAL) if $self->{temp_buffer}; if( $self->can( "app" ) ) { @@ -253,10 +254,11 @@ sub timed_read { $self->{temp_buffer} = ''; ##### - my $ff = fcntl($fh, F_GETFL, 0); - if ($ff == ($ff | O_NONBLOCK) and $timeout > 0 ) { + # This code is no longer in use + #my $ff = fcntl($fh, F_GETFL, 0); + #if ($ff == ($ff | O_NONBLOCK) and $timeout > 0 ) { #throw OpenSRF::EX::ERROR ("File flags are set to NONBLOCK but timeout is $timeout", ERROR ); - } + #} my $t_buf = ""; my $read_size = 1024; my $f = 0; @@ -267,6 +269,12 @@ sub timed_read { "Lost jabber client in timed_read()"); } + # XXX Change me to debug/internal at some point, this is for testing... + # XXX Found a race condition where reading >= $read_size bytes of data + # will fail if the log line below is removed. + $logger->info("timed_read() read $n bytes of data"); + + $buffer .= $t_buf; if( $n < $read_size ) { #reset_fl( $fh, $f ) if $f; @@ -406,7 +414,7 @@ sub send { $msg->setBody( $body ); $msg->set_router_command( $router_command ); $msg->set_router_class( $router_class ); - + $msg->set_osrf_xid($logger->get_osrf_xid); $logger->transport( "JabberClient Sending message to $to with thread $thread and body: \n$body", INTERNAL ); @@ -542,7 +550,8 @@ sub process { my( $self, $timeout ) = @_; $timeout ||= 0; - undef $timeout if ( $timeout == -1 ); + $timeout = int($timeout); + undef $timeout if ( $timeout < 0 ); unless( $self->{_socket}->connected ) { OpenSRF::EX::JabberDisconnected->throw( diff --git a/src/perlmods/OpenSRF/Transport/SlimJabber/MessageWrapper.pm b/src/perlmods/OpenSRF/Transport/SlimJabber/MessageWrapper.pm index b337dff..3f5393c 100644 --- a/src/perlmods/OpenSRF/Transport/SlimJabber/MessageWrapper.pm +++ b/src/perlmods/OpenSRF/Transport/SlimJabber/MessageWrapper.pm @@ -111,4 +111,16 @@ sub set_router_class { } } +sub set_osrf_xid { + my( $self, $xid ) = @_; + $self->{msg_node}->setAttribute( osrf_xid => $xid ); +} + + +sub get_osrf_xid { + my $self = shift; + $self->{msg_node}->getAttribute('osrf_xid'); +} + + 1; diff --git a/src/perlmods/OpenSRF/UnixServer.pm b/src/perlmods/OpenSRF/UnixServer.pm index b80a9b5..f20b960 100644 --- a/src/perlmods/OpenSRF/UnixServer.pm +++ b/src/perlmods/OpenSRF/UnixServer.pm @@ -2,7 +2,7 @@ package OpenSRF::UnixServer; use strict; use warnings; use base qw/OpenSRF/; use OpenSRF::EX qw(:try); -use OpenSRF::Utils::Logger qw(:level); +use OpenSRF::Utils::Logger qw(:level $logger); use OpenSRF::Transport::PeerHandle; use OpenSRF::Application; use OpenSRF::AppSession; @@ -18,12 +18,8 @@ use Carp; use IO::Socket::INET; use IO::Socket::UNIX; -# XXX Need to add actual logging statements in the code -my $logger = "OpenSRF::Utils::Logger"; - sub DESTROY { confess "Dying $$"; } - =head1 What am I All inbound messages are passed on to the UnixServer for processing. @@ -226,10 +222,6 @@ sub configure_hook { return OpenSRF::Application->application_implementation; } -sub child_finish_hook { - my $self = shift; -} - sub child_init_hook { $0 =~ s/master/drone/g; @@ -259,5 +251,12 @@ sub child_init_hook { return OpenSRF::Transport::PeerHandle->retrieve; } +sub child_finish_hook { + $logger->debug("attempting to call child exit handler..."); + OpenSRF::Application->application_implementation->child_exit + if (OpenSRF::Application->application_implementation->can('child_exit')); +} + + 1; diff --git a/src/perlmods/OpenSRF/Utils/Logger.pm b/src/perlmods/OpenSRF/Utils/Logger.pm index 69d79d2..bbeff7a 100644 --- a/src/perlmods/OpenSRF/Utils/Logger.pm +++ b/src/perlmods/OpenSRF/Utils/Logger.pm @@ -53,6 +53,8 @@ sub DEBUG { return 4; } sub INTERNAL { return 5; } sub ALL { return 100; } +my $isclient; # true if we control the osrf_xid + # load up our config options sub set_config { @@ -97,7 +99,7 @@ sub set_config { } else { $actfile = "$logdir/$actfile"; } - #warn "Level: $loglevel, Fac: $facility, Act: $actfac\n"; + $isclient = (OpenSRF::Utils::Config->current->bootstrap->client =~ /^true$/iog) ? 1 : 0; } sub _fac_to_const { @@ -186,7 +188,26 @@ sub transport { } +# ---------------------------------------------------------------------- +# creates a new xid if necessary +# ---------------------------------------------------------------------- +my $osrf_xid = ''; +my $osrf_xid_inc = 0; +sub mk_osrf_xid { + return unless $isclient; + $osrf_xid_inc++; + return $osrf_xid = "$^T${$}$osrf_xid_inc"; +} + +sub set_osrf_xid { + return if $isclient; # if we're a client, we control our xid + $osrf_xid = $_[1]; +} + +sub get_osrf_xid { return $osrf_xid; } +# ---------------------------------------------------------------------- + sub _log_message { my( $msg, $level ) = @_; return if $level > $loglevel; @@ -201,12 +222,13 @@ sub _log_message { elsif ($level == INTERNAL()) {$l = LOG_DEBUG; $n = "INTL"; } elsif ($level == ACTIVITY()) {$l = LOG_INFO; $n = "ACT"; $fac = $actfac; } - #my( $pack, $file, $line_no ) = @caller; + my( undef, $file, $line_no ) = caller(1); + $file =~ s#/.*/##og; # help syslog with the formatting $msg =~ s/\%/\%\%/gso if( is_act_syslog() or is_syslog() ); - $msg = "[$n:"."$$".":::] $msg"; + $msg = "[$n:"."$$".":$file:$line_no:$osrf_xid] $msg"; $msg = substr($msg, 0, 1536); diff --git a/src/router/osrf_router.c b/src/router/osrf_router.c index 4e61992..8308851 100644 --- a/src/router/osrf_router.c +++ b/src/router/osrf_router.c @@ -136,6 +136,8 @@ int osrfRouterClassHandleIncoming( osrfRouter* router, char* classname, osrfRout while( (msg = client_recv( class->connection, 0 )) ) { + osrfLogSetXid(msg->osrf_xid); + if( msg->sender ) { osrfLogDebug(OSRF_LOG_MARK, @@ -166,6 +168,7 @@ int osrfRouterClassHandleIncoming( osrfRouter* router, char* classname, osrfRout } } + osrfLogClearXid(); message_free( msg ); } @@ -270,6 +273,7 @@ transport_message* osrfRouterClassHandleBounce( transport_message* error = message_init( node->lastMessage->body, node->lastMessage->subject, node->lastMessage->thread, node->lastMessage->router_from, node->lastMessage->recipient ); + message_set_osrf_xid(error, node->lastMessage->osrf_xid); set_msg_error( error, "cancel", 501 ); /* send the error message back to the original sender */ @@ -287,6 +291,7 @@ transport_message* osrfRouterClassHandleBounce( lastSent = message_init( node->lastMessage->body, node->lastMessage->subject, node->lastMessage->thread, "", node->lastMessage->router_from ); message_set_router_info( lastSent, node->lastMessage->router_from, NULL, NULL, NULL, 0 ); + message_set_osrf_xid( lastSent, node->lastMessage->osrf_xid ); } } else { @@ -324,6 +329,7 @@ int osrfRouterClassHandleMessage( transport_message* new_msg= message_init( msg->body, msg->subject, msg->thread, node->remoteId, msg->sender ); message_set_router_info( new_msg, msg->sender, NULL, NULL, NULL, 0 ); + message_set_osrf_xid( new_msg, msg->osrf_xid ); osrfLogInfo( OSRF_LOG_MARK, "Routing message:\nfrom: [%s]\nto: [%s]", new_msg->router_from, new_msg->recipient ); @@ -390,6 +396,9 @@ void osrfRouterClassFree( char* classname, void* c ) { while( (node = osrfHashIteratorNext(rclass->itr)) ) osrfRouterClassRemoveNode( rclass->router, classname, node->remoteId ); + osrfHashIteratorFree(rclass->itr); + osrfHashFree(rclass->nodes); + free(rclass); } diff --git a/src/utils/log.c b/src/utils/log.c index 92791c2..be2abe0 100644 --- a/src/utils/log.c +++ b/src/utils/log.c @@ -7,6 +7,12 @@ char* __osrfLogFile = NULL; char* __osrfLogAppname = NULL; int __osrfLogLevel = OSRF_LOG_INFO; int __osrfLogActivityEnabled = 1; +int __osrfLogIsClient = 0; + + +int __osrfLogXidInc = 0; /* increments with each new xid for uniqueness */ +char* __osrfLogXid = NULL; /* current xid */ +char* __osrfLogXidPfx = NULL; /* xid prefix string */ void osrfLogCleanup() { @@ -23,6 +29,42 @@ void osrfLogInit( int type, const char* appname, int maxlevel ) { openlog(__osrfLogAppname, 0, __osrfLogFacility ); } +static void __osrfLogSetXid(char* xid) { + if(xid) { + if(__osrfLogXid) free(__osrfLogXid); + __osrfLogXid = strdup(xid); + } +} + +void osrfLogClearXid() { __osrfLogSetXid(""); } +void osrfLogSetXid(char* xid) { + if(!__osrfLogIsClient) __osrfLogSetXid(xid); +} + +void osrfLogMkXid() { + if(__osrfLogIsClient) { + char buf[32]; + memset(buf, 0x0, 32); + snprintf(buf, 32, "%s%d", __osrfLogXidPfx, __osrfLogXidInc); + __osrfLogSetXid(buf); + __osrfLogXidInc++; + } +} + +char* osrfLogGetXid() { + return __osrfLogXid; +} + +void osrfLogSetIsClient(int is) { + __osrfLogIsClient = is; + if(!is) return; + /* go ahead and create the xid prefix so it will be consistent later */ + static char buff[32]; + memset(buff, 0x0, 32); + snprintf(buff, 32, "%d%d", (int)time(NULL), getpid()); + __osrfLogXidPfx = buff; +} + void osrfLogSetType( int logtype ) { if( logtype != OSRF_LOG_TYPE_FILE && logtype != OSRF_LOG_TYPE_SYSLOG ) { @@ -124,6 +166,8 @@ void _osrfLogDetail( int level, const char* filename, int line, char* msg ) { break; } + char* xid = (__osrfLogXid) ? __osrfLogXid : ""; + if(__osrfLogType == OSRF_LOG_TYPE_SYSLOG ) { char buf[1536]; memset(buf, 0x0, 1536); @@ -133,11 +177,11 @@ void _osrfLogDetail( int level, const char* filename, int line, char* msg ) { buf[1533] = '.'; buf[1534] = '.'; buf[1535] = '\0'; - syslog( fac | lvl, "[%s:%d:%s:%d] %s", l, getpid(), filename, line, buf ); + syslog( fac | lvl, "[%s:%d:%s:%d:%s] %s", l, getpid(), filename, line, xid, buf ); } else if( __osrfLogType == OSRF_LOG_TYPE_FILE ) - _osrfLogToFile("[%s:%d:%s:%d] %s", l, getpid(), filename, line, msg ); + _osrfLogToFile("[%s:%d:%s:%d:%s] %s", l, getpid(), filename, line, xid, msg ); } diff --git a/src/utils/log.h b/src/utils/log.h index 8764443..588bb1b 100644 --- a/src/utils/log.h +++ b/src/utils/log.h @@ -59,6 +59,12 @@ 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 ); diff --git a/src/utils/utils.c b/src/utils/utils.c index 4a7e1b3..a226cab 100644 --- a/src/utils/utils.c +++ b/src/utils/utils.c @@ -17,7 +17,6 @@ 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 ) { @@ -255,56 +254,44 @@ int buffer_add_char(growing_buffer* gb, char c) { char* uescape( const char* string, int size, int full_escape ) { growing_buffer* buf = buffer_init(size + 64); + int clen = 0; int idx = 0; - long unsigned int c = 0; + unsigned long int c = 0x0; while (string[idx]) { - - c ^= c; - - if ((string[idx] & 0xF0) == 0xF0) { - c = string[idx]<<18; - - if( size - idx < 4 ) return NULL; - - idx++; - c |= (string[idx] & 0x3F)<<12; - - idx++; - c |= (string[idx] & 0x3F)<<6; - - idx++; - c |= (string[idx] & 0x3F); - - c ^= 0xFF000000; - - buffer_fadd(buf, "\\u%0.4x", c); - - } else if ((string[idx] & 0xE0) == 0xE0) { - c = string[idx]<<12; - if( size - idx < 3 ) return NULL; - - idx++; - c |= (string[idx] & 0x3F)<<6; - - idx++; - c |= (string[idx] & 0x3F); - - c ^= 0xFFF80000; - - buffer_fadd(buf, "\\u%0.4x", c); - - } else if ((string[idx] & 0xC0) == 0xC0) { - // Two byte char - c = string[idx]<<6; - if( size - idx < 2 ) return NULL; - - idx++; - c |= (string[idx] & 0x3F); - - c ^= 0xFFFFF000; - - buffer_fadd(buf, "\\u%0.4x", c); + + 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 { + return NULL; + } } else { c = string[idx]; @@ -347,17 +334,9 @@ char* uescape( const char* string, int size, int full_escape ) { OSRF_BUFFER_ADD_CHAR(buf, '\\'); break; - case 30: /* record separator */ - OSRF_BUFFER_ADD(buf, "\\u001E"); - break; - - case 1: /* record separator */ - OSRF_BUFFER_ADD(buf, "\\u0001"); - break; - - default: - OSRF_BUFFER_ADD_CHAR(buf, c); + if( c < 32 ) buffer_fadd(buf, "\\u%04x", c); + else OSRF_BUFFER_ADD_CHAR(buf, c); } } else { -- 2.43.2