Пример #1
0
static int handler(request_rec *r) {
    int stat = OK;
	if(strcmp(r->handler, MODULE_NAME)) return DECLINED;
    if(r->header_only) return stat;

	r->allowed |= (AP_METHOD_BIT << M_GET);
	r->allowed |= (AP_METHOD_BIT << M_POST);

	osrfLogSetAppname("osrf_http_translator");
	osrfAppSessionSetIngress(TRANSLATOR_INGRESS);
    testConnection(r);
    crossOriginHeaders(r, allowedOrigins);

	osrfLogMkXid();
    osrfHttpTranslator* trans = osrfNewHttpTranslator(r);
    if(trans->body) {
        stat = osrfHttpTranslatorProcess(trans);
        //osrfHttpTranslatorDebug(trans);
        osrfLogInfo(OSRF_LOG_MARK, "translator resulted in status %d", stat);
    } else {
        osrfLogWarning(OSRF_LOG_MARK, "no message body to process");
    }
    osrfHttpTranslatorFree(trans);
	return stat;
}
Пример #2
0
/**
	@brief Record some options for later reference by the logging routines.
	@param type Type of logging; i.e. where the log messages go.
	@param appname Pointer to the application name (may be NULL).
	@param maxlevel Which levels of message to issue or suppress.

	Typically the values for these parameters come from a configuration file.

	There are three valid values for @a type:

	- OSRF_LOG_TYPE_FILE -- write messages to a log file
	- OSRF_LOG_TYPE_SYSLOG -- write messages to the syslog facility
	- OSRF_LOG_TYPE_STDERR  -- write messages to standard error

	If @a type has any other value, log messages will be written to standard error.

	The logging type may be set separately by calling osrfLogSetType().  See also
	osrfLogToStderr() and osrfRestoreLogType().

	The @a appname string prefaces every log message.  The default application name, if
	not overridden by this function or by osrfLogSetAppname(), is "osrf".

	Here are the valid values for @a maxlevel, with the corresponding macros:

	- 1 OSRF_LOG_ERROR
	- 2 OSRF_LOG_WARNING
	- 3 OSRF_LOG_INFO (the default)
	- 4 OSRF_LOG_DEBUG
	- 5 OSRF_LOG_INTERNAL

	With the special exception of activity messages (see osrfLogActivity()), the logging
	routines will suppress any messages at a level greater than that specified by
	@a maxlevel.  Setting @a maxlevel to zero or less suppresses all levels of message.
	Setting it to 5 or more enables all levels of message.

	The message level may be set separately by calling osrfLogSetLevel().
*/
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 );
}
Пример #3
0
/**
	@brief Register an application.
	@param appName Name of the application.
	@param soFile Name of the shared object file to be loaded for this application.
	@return Zero if successful, or -1 upon error.

	Open the shared object file and call its osrfAppInitialize() function, if it has one.
	Register the standard system methods for it.  Arrange for the application name to
	appear in subsequent log messages.
*/
int osrfAppRegisterApplication( const char* appName, const char* soFile ) {
	if( !appName || ! soFile ) return -1;
	char* error;

	osrfLogSetAppname( appName );

	if( !_osrfAppHash ) {
		_osrfAppHash = osrfNewHash();
		osrfHashSetCallback( _osrfAppHash, osrfAppFree );
	}

	osrfLogInfo( OSRF_LOG_MARK, "Registering application %s with file %s", appName, soFile );

	// Open the shared object.
	void* handle = dlopen( soFile, RTLD_NOW );
	if( ! handle ) {
		const char* msg = dlerror();
		osrfLogError( OSRF_LOG_MARK, "Failed to dlopen library file %s: %s", soFile, msg );
		return -1;
	}

	// Construct the osrfApplication.
	osrfApplication* app = safe_malloc(sizeof(osrfApplication));
	app->handle = handle;
	app->methods = osrfNewHash();
	osrfHashSetCallback( app->methods, osrfMethodFree );
	app->onExit = NULL;

	// Add the newly-constructed app to the list.
	osrfHashSet( _osrfAppHash, app, appName );

	// Try to run the initialize method.  Typically it will register one or more
	// methods of the application.
	int (*init) (void);
	*(void **) (&init) = dlsym( 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 );
			osrfHashRemove( _osrfAppHash, appName );
			return ret;
		}
	}

	register_system_methods( app );
	osrfLogInfo( OSRF_LOG_MARK, "Application %s registered successfully", appName );
	osrfAppSetOnExit( app, appName );

	return 0;
}
Пример #4
0
static int osrf_json_gateway_method_handler (request_rec *r) {

	/* make sure we're needed first thing*/
	if (strcmp(r->handler, MODULE_NAME )) return DECLINED;


	osrf_json_gateway_dir_config* dir_conf =
		ap_get_module_config(r->per_dir_config, &osrf_json_gateway_module);


	/* provide 2 different JSON parsers and serializers to support legacy JSON */
	jsonObject* (*parseJSONFunc) (const char*) = legacy_jsonParseString;
	char* (*jsonToStringFunc) (const jsonObject*) = legacy_jsonObjectToJSON;

	if(dir_conf->legacyJSON) {
		ap_log_rerror( APLOG_MARK, APLOG_DEBUG, 0, r, "Using legacy JSON");

	} else {
		parseJSONFunc = jsonParse;
		jsonToStringFunc = jsonObjectToJSON;
	}


	osrfLogDebug(OSRF_LOG_MARK, "osrf gateway: entered request handler");

	/* verify we are connected */
	if( !bootstrapped || !osrfSystemGetTransportClient()) {
		ap_log_rerror( APLOG_MARK, APLOG_ERR, 0, r, "Cannot process request "
				"because the OpenSRF JSON gateway has not been bootstrapped...");
		usleep( 100000 ); /* 100 milliseconds */
		exit(1);
	}

	osrfLogSetAppname("osrf_json_gw");

	char* osrf_locale   = NULL;
	char* param_locale  = NULL;  /* locale for this call */
	char* service       = NULL;  /* service to connect to */
	char* method        = NULL;  /* method to perform */
	char* format        = NULL;  /* method to perform */
	char* a_l           = NULL;  /* request api level */
	char* input_format  = NULL;  /* POST data format, defaults to 'format' */
	int   isXML         = 0;
	int   api_level     = 1;

	r->allowed |= (AP_METHOD_BIT << M_GET);
	r->allowed |= (AP_METHOD_BIT << M_POST);

	osrfLogDebug(OSRF_LOG_MARK, "osrf gateway: parsing URL params");
	osrfStringArray* mparams = NULL;
	osrfStringArray* params  = apacheParseParms(r); /* free me */
	param_locale             = apacheGetFirstParamValue( params, "locale" );
	service                  = apacheGetFirstParamValue( params, "service" );
	method                   = apacheGetFirstParamValue( params, "method" );
	format                   = apacheGetFirstParamValue( params, "format" );
	input_format             = apacheGetFirstParamValue( params, "input_format" );
	a_l                      = apacheGetFirstParamValue( params, "api_level" );
	mparams                  = apacheGetParamValues( params, "param" ); /* free me */

	if(format == NULL)
		format = strdup( "json" );
	if(input_format == NULL)
		input_format = strdup( format );

	/* 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);
		free( tout );
	}

	if (a_l) {
		api_level = atoi(a_l);
		free( a_l );
	}

	if (!strcasecmp(format, "xml")) {
		isXML = 1;
		ap_set_content_type(r, "application/xml");
	} else {
		ap_set_content_type(r, "text/plain");
	}

	free( format );
	int ret = OK;

	/* ----------------------------------------------------------------- */
	/* Grab the requested locale using the Accept-Language header*/


	if ( !param_locale ) {
		if ( apr_table_get(r->headers_in, "X-OpenSRF-Language") ) {
			param_locale = strdup( apr_table_get(r->headers_in, "X-OpenSRF-Language") );
		} else if ( apr_table_get(r->headers_in, "Accept-Language") ) {
			param_locale = strdup( apr_table_get(r->headers_in, "Accept-Language") );
		}
	}


	if (param_locale) {
		growing_buffer* osrf_locale_buf = buffer_init(16);
		if (index(param_locale, ',')) {
			int ind = index(param_locale, ',') - param_locale;
			int i;
			for ( i = 0; i < ind && i < 128; i++ )
				buffer_add_char( osrf_locale_buf, param_locale[i] );
		} else {
			buffer_add( osrf_locale_buf, param_locale );
		}

		free(param_locale);
		osrf_locale = buffer_release( osrf_locale_buf );
	} else {
		osrf_locale = strdup( osrf_json_default_locale );
	}
	/* ----------------------------------------------------------------- */


	if(!(service && method)) {

		osrfLogError(OSRF_LOG_MARK,
			"Service [%s] not found or not allowed", service);
		ret = HTTP_NOT_FOUND;

	} else {

		/* This will log all heaers to the apache error log
		const apr_array_header_t* arr = apr_table_elts(r->headers_in);
		const void* ptr;

		while( (ptr = apr_array_pop(arr)) ) {
			apr_table_entry_t* e = (apr_table_entry_t*) ptr;
			fprintf(stderr, "Table entry: %s : %s\n", e->key, e->val );
		}
		fflush(stderr);
		*/

		osrfAppSession* session = osrfAppSessionClientInit(service);
		osrf_app_session_set_locale(session, osrf_locale);

		double starttime = get_timestamp_millis();
		int req_id = -1;

		if(!strcasecmp(input_format, "json")) {
			jsonObject * arr = jsonNewObject(NULL);

			const char* str;
			int i = 0;

			while( (str = osrfStringArrayGetString(mparams, i++)) )
				jsonObjectPush(arr, parseJSONFunc(str));

			req_id = osrfAppSessionSendRequest( session, arr, method, api_level );
			jsonObjectFree(arr);
		} else {

			/**
			* If we receive XML method params, convert each param to a JSON object
			* and pass the array of JSON object params to the method */
			if(!strcasecmp(input_format, "xml")) {
				jsonObject* jsonParams = jsonNewObject(NULL);

				const char* str;
				int i = 0;
				while( (str = osrfStringArrayGetString(mparams, i++)) ) {
					jsonObjectPush(jsonParams, jsonXMLToJSONObject(str));
				}

				req_id = osrfAppSessionSendRequest( session, jsonParams, method, api_level );
				jsonObjectFree(jsonParams);
			}
		}


		if( req_id == -1 ) {
			osrfLogError(OSRF_LOG_MARK, "I am unable to communicate with opensrf..going away...");
			osrfAppSessionFree(session);
			/* we don't want to spawn an intense re-forking storm
			 * if there is no jabber server.. so give it some time before we die */
			usleep( 100000 ); /* 100 milliseconds */
			exit(1);
		}


		/* ----------------------------------------------------------------- */
		/* log all requests to the activity log */
		const char* authtoken = apr_table_get(r->headers_in, "X-OILS-Authtoken");
		if(!authtoken) authtoken = "";
		growing_buffer* act = buffer_init(128);
		buffer_fadd(act, "[%s] [%s] [%s] %s %s", r->connection->remote_ip,
			authtoken, osrf_locale, service, method );
		const 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);
		/* ----------------------------------------------------------------- */


		osrfMessage* omsg = NULL;

		int statuscode = 200;

		/* kick off the object */
		if (isXML)
			ap_rputs( "<response xmlns=\"http://opensrf.org/-/namespaces/gateway/v1\"><payload>",
				r );
		else
			ap_rputs("{\"payload\":[", r);

		int morethan1       = 0;
		char* statusname    = NULL;
		char* statustext    = NULL;
		char* output        = NULL;

		while((omsg = osrfAppSessionRequestRecv( session, req_id, timeout ))) {

			statuscode = omsg->status_code;
			const jsonObject* res;

			if( ( res = osrfMessageGetResult(omsg)) ) {

				if (isXML) {
					output = jsonObjectToXML( res );
				} else {
					output = jsonToStringFunc( res );
					if( morethan1 ) ap_rputs(",", r); /* comma between JSON array items */
				}
				ap_rputs(output, r);
				free(output);
				morethan1 = 1;

			} else {

				if( statuscode > 299 ) { /* the request returned a low level error */
					statusname = omsg->status_name ? strdup(omsg->status_name)
						: strdup("Unknown Error");
					statustext = omsg->status_text ? strdup(omsg->status_text) 
						: strdup("No Error Message");
					osrfLogError( OSRF_LOG_MARK,  "Gateway received error: %s", statustext );
				}
			}

			osrfMessageFree(omsg);
			if(statusname) break;
		}

		double duration = get_timestamp_millis() - starttime;
		osrfLogDebug(OSRF_LOG_MARK, "gateway request took %f seconds", duration);


		if (isXML)
			ap_rputs("</payload>", r);
		else
			ap_rputs("]",r); /* finish off the payload array */

		if(statusname) {

			/* add a debug field if the request died */
			ap_log_rerror( APLOG_MARK, APLOG_INFO, 0, r,
					"OpenSRF JSON Request returned error: %s -> %s", statusname, statustext );
			int l = strlen(statusname) + strlen(statustext) + 32;
			char buf[l];

			if (isXML)
				snprintf( buf, sizeof(buf), "<debug>\"%s : %s\"</debug>", statusname, statustext );

			else {
				char bb[l];
				snprintf(bb, sizeof(bb),  "%s : %s", statusname, statustext);
				jsonObject* tmp = jsonNewObject(bb);
				char* j = jsonToStringFunc(tmp);
				snprintf( buf, sizeof(buf), ",\"debug\": %s", j);
				free(j);
				jsonObjectFree(tmp);
			}

			ap_rputs(buf, r);

			free(statusname);
			free(statustext);
		}

		/* insert the status code */
		char buf[32];

		if (isXML)
			snprintf(buf, sizeof(buf), "<status>%d</status>", statuscode );
		else
			snprintf(buf, sizeof(buf), ",\"status\":%d", statuscode );

		ap_rputs( buf, r );

		if (isXML)
			ap_rputs("</response>", r);
		else
			ap_rputs( "}", r ); /* finish off the object */

		osrfAppSessionFree(session);
	}

	osrfLogInfo(OSRF_LOG_MARK, "Completed processing service=%s, method=%s", service, method);
	osrfStringArrayFree(params);
	osrfStringArrayFree(mparams);
	free( osrf_locale );
	free( input_format );
	free( method );
	free( service );

	osrfLogDebug(OSRF_LOG_MARK, "Gateway served %d requests", ++numserved);
	osrfLogClearXid();

	return ret;
}
/**
 * Connect to OpenSRF, create the main pool, responder thread
 * session cache and session pool.
 */
int child_init(const WebSocketServer *server) {
    request_rec *r = server->request(server);

    // osrf_handle will already be connected if this is not the first request
    // served by this process.
    if ( !(osrf_handle = osrfSystemGetTransportClient()) ) {
        
        // load config values from the env
        char* timeout = getenv("OSRF_WEBSOCKET_IDLE_TIMEOUT");
        if (timeout) {
            if (!atoi(timeout)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 
                    "WS: invalid OSRF_WEBSOCKET_IDLE_TIMEOUT: %s", timeout);
            } else {
                idle_timeout_interval = (time_t) atoi(timeout);
            }
        }

        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 
            "WS: timeout set to %d", idle_timeout_interval);

        timeout = getenv("OSRF_WEBSOCKET_MAX_REQUEST_WAIT_TIME");
        if (timeout) {
            if (!atoi(timeout)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 
                    "WS: invalid OSRF_WEBSOCKET_MAX_REQUEST_WAIT_TIME: %s", 
                    timeout
                );
            } else {
                max_request_wait_time = (time_t) atoi(timeout);
            }
        }

        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 
            "WS: max request wait time set to %d", max_request_wait_time);

        char* interval = getenv("OSRF_WEBSOCKET_IDLE_CHECK_INTERVAL");
        if (interval) {
            if (!atoi(interval)) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 
                    "WS: invalid OSRF_WEBSOCKET_IDLE_CHECK_INTERVAL: %s", 
                    interval
                );
            } else {
                idle_check_interval = (time_t) atoi(interval);
            }
        } 

        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 
            "WS: idle check interval set to %d", idle_check_interval);

      
        char* cfile = getenv("OSRF_WEBSOCKET_CONFIG_FILE");
        if (cfile) {
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                "WS: config file set to %s", cfile);
            config_file = cfile;
        }

        char* ctxt = getenv("OSRF_WEBSOCKET_CONFIG_CTXT");
        if (ctxt) {
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 
                "WS: config context set to %s", ctxt);
            config_ctxt = ctxt;
        }

        // connect to opensrf
        if (!osrfSystemBootstrapClientResc(
                config_file, config_ctxt, "websocket")) {   

            osrfLogError(OSRF_LOG_MARK, 
                "WS unable to bootstrap OpenSRF client with config %s "
                "and context %s", config_file, config_ctxt
            ); 
            return 1;
        }

        osrfLogSetAppname("osrf_websocket_translator");
        osrf_handle = osrfSystemGetTransportClient();
    }

    signal(SIGUSR1, sigusr1_handler);
    return APR_SUCCESS;
}