1 #include "osrf_application.h"
3 #include "objson/object.h"
5 osrfApplication* __osrfAppList = NULL;
8 int osrfAppRegisterApplication( char* appName, char* soFile ) {
9 if(!appName || ! soFile) return -1;
12 info_handler("Registering application %s with file %s", appName, soFile );
14 osrfApplication* app = safe_malloc(sizeof(osrfApplication));
15 app->handle = dlopen (soFile, RTLD_NOW);
18 warning_handler("Failed to dlopen library file %s: %s", soFile, dlerror() );
19 dlerror(); /* clear the error */
24 app->name = strdup(appName);
26 /* this has to be done before initting the application */
27 app->next = __osrfAppList;
31 /* see if we can run the initialize method */
33 *(void **) (&init) = dlsym(app->handle, "osrfAppInitialize");
35 if( (error = dlerror()) != NULL ) {
36 warning_handler("! Unable to locate method symbol [osrfAppInitialize] for app %s: %s", appName, error );
42 if( (ret = (*init)()) ) {
43 warning_handler("Application %s returned non-zero value from "
44 "'osrfAppInitialize', not registering...", appName );
45 //free(app->name); /* need a method to remove an application from the list */
51 __osrfAppRegisterSysMethods(appName);
53 info_handler("Application %s registered successfully", appName );
59 int osrfAppRegisterMethod( char* appName,
60 char* methodName, char* symbolName, char* notes, char* params, int argc ) {
62 if( !appName || ! methodName || ! symbolName ) return -1;
64 osrfApplication* app = _osrfAppFindApplication(appName);
65 if(!app) return warning_handler("Unable to locate application %s", appName );
67 debug_handler("Registering method %s for app %s", methodName, appName );
69 osrfMethod* method = _osrfAppBuildMethod(
70 methodName, symbolName, notes, params, argc, 0 );
72 /* plug the method into the list of methods */
73 method->next = app->methods;
74 app->methods = method;
79 osrfMethod* _osrfAppBuildMethod( char* methodName,
80 char* symbolName, char* notes, char* params, int argc, int sysmethod ) {
82 osrfMethod* method = safe_malloc(sizeof(osrfMethod));
83 if(methodName) method->name = strdup(methodName);
84 if(symbolName) method->symbol = strdup(symbolName);
85 if(notes) method->notes = strdup(notes);
86 if(params) method->paramNotes = strdup(params);
88 method->sysmethod = sysmethod;
93 int _osrfAppRegisterSystemMethod( char* appName, char* methodName,
94 char* notes, char* params, int argc ) {
95 if(!(appName && methodName)) return -1;
96 osrfApplication* app = _osrfAppFindApplication(appName);
97 if(!app) return warning_handler("Unable to locate application %s", appName );
98 debug_handler("Registering system method %s for app %s", methodName, appName );
99 osrfMethod* method = _osrfAppBuildMethod(
100 methodName, NULL, notes, params, argc, 1 );
102 /* plug the method into the list of methods */
103 method->next = app->methods;
104 app->methods = method;
109 int __osrfAppRegisterSysMethods( char* app ) {
111 _osrfAppRegisterSystemMethod(
112 app, OSRF_SYSMETHOD_INTROSPECT,
113 "Return a list of methods whose names have the same initial "
114 "substring as that of the provided method name",
115 "( methodNameSubstring )", 1 );
117 _osrfAppRegisterSystemMethod(
118 app, OSRF_SYSMETHOD_INTROSPECT_ALL,
119 "Returns a complete list of methods", "()", 0 );
124 osrfApplication* _osrfAppFindApplication( char* name ) {
125 if(!name) return NULL;
126 osrfApplication* app = __osrfAppList;
128 if(!strcmp(app->name, name))
135 osrfMethod* __osrfAppFindMethod( osrfApplication* app, char* methodName ) {
136 if(!app || ! methodName) return NULL;
137 osrfMethod* method = app->methods;
139 if(!strcmp(method->name, methodName))
141 method = method->next;
146 osrfMethod* _osrfAppFindMethod( char* appName, char* methodName ) {
147 if(!appName || ! methodName) return NULL;
148 return __osrfAppFindMethod( _osrfAppFindApplication(appName), methodName );
152 int osrfAppRunMethod( char* appName, char* methodName,
153 osrfAppSession* ses, int reqId, jsonObject* params ) {
155 if( !(appName && methodName && ses) ) return -1;
158 osrfApplication* app;
160 osrfMethodContext context;
162 context.session = ses;
163 context.params = params;
164 context.request = reqId;
166 /* this is the method we're gonna run */
167 int (*meth) (osrfMethodContext*);
169 info_handler("Running method [%s] for app [%s] with request id %d and "
170 "thread trace %s", methodName, appName, reqId, ses->session_id );
172 if( !(app = _osrfAppFindApplication(appName)) )
173 return osrfAppRequestRespondException( ses,
174 reqId, "Application not found: %s", appName );
176 if( !(method = __osrfAppFindMethod( app, methodName )) )
177 return osrfAppRequestRespondException( ses, reqId,
178 "Method [%s] not found for service %s", methodName, appName );
180 context.method = method;
182 #ifdef OSRF_STRICT_PARAMS
183 if( method->argc > 0 ) {
184 if(!params || params->type != JSON_ARRAY || params->size < method->argc )
185 return osrfAppRequestRespondException( ses, reqId,
186 "Not enough params for method %s / service %s", methodName, appName );
190 if( method->sysmethod ) {
192 int sysres = __osrfAppRunSystemMethod(&context);
193 if(sysres == 0) return 0;
196 return osrfAppSessionStatus( ses, OSRF_STATUS_COMPLETE,
197 "osrfConnectStatus", reqId, "Request Complete" );
200 return osrfAppRequestRespondException(
201 ses, reqId, "An unknown server error occurred" );
205 /* open the method */
206 *(void **) (&meth) = dlsym(app->handle, method->symbol);
208 if( (error = dlerror()) != NULL ) {
209 return osrfAppRequestRespondException( ses, reqId,
210 "Unable to execute method [%s] for service %s", methodName, appName );
215 if( (ret = (*meth) (&context)) < 0 )
216 return osrfAppRequestRespondException(
217 ses, reqId, "An unknown server error occurred" );
220 osrfAppSessionStatus( ses, OSRF_STATUS_COMPLETE,
221 "osrfConnectStatus", reqId, "Request Complete" );
226 int osrfAppRequestRespondException( osrfAppSession* ses, int request, char* msg, ... ) {
229 VA_LIST_TO_STRING(msg);
230 osrfLog( OSRF_WARN, "Returning method exception with message: %s", VA_BUF );
231 osrfAppSessionStatus( ses, OSRF_STATUS_NOTFOUND, "osrfMethodException", request, VA_BUF );
236 static void __osrfAppSetIntrospectMethod( osrfMethodContext* ctx, osrfMethod* method, jsonObject* resp ) {
237 if(!(ctx && resp)) return;
238 jsonObjectSetKey(resp, "api_name", jsonNewObject(method->name));
239 jsonObjectSetKey(resp, "method", jsonNewObject(method->symbol));
240 jsonObjectSetKey(resp, "service", jsonNewObject(ctx->session->remote_service));
241 jsonObjectSetKey(resp, "notes", jsonNewObject(method->notes));
242 jsonObjectSetKey(resp, "argc", jsonNewNumberObject(method->argc));
243 jsonObjectSetKey(resp, "params", jsonNewObject(method->paramNotes) );
244 jsonObjectSetKey(resp, "sysmethod", jsonNewNumberObject(method->sysmethod) );
245 jsonObjectSetClass(resp, "method");
250 int __osrfAppRunSystemMethod(osrfMethodContext* ctx) {
251 OSRF_METHOD_VERIFY_CONTEXT(ctx);
253 if( !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT_ALL )) {
255 jsonObject* resp = NULL;
256 osrfApplication* app = _osrfAppFindApplication( ctx->session->remote_service );
258 osrfMethod* method = app->methods;
260 resp = jsonNewObject(NULL);
261 __osrfAppSetIntrospectMethod( ctx, method, resp );
262 osrfAppRequestRespond(ctx->session, ctx->request, resp);
263 jsonObjectFree(resp);
264 method = method->next;
273 if( !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT )) {
275 jsonObject* resp = NULL;
276 char* methodSubstring = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 0) );
277 osrfApplication* app = _osrfAppFindApplication( ctx->session->remote_service );
280 if(!methodSubstring) return 1; /* respond with no methods */
283 osrfMethod* method = app->methods;
285 if( (len = strlen(methodSubstring)) <= strlen(method->name) ) {
286 if( !strncmp( method->name, methodSubstring, len) ) {
287 resp = jsonNewObject(NULL);
288 __osrfAppSetIntrospectMethod( ctx, method, resp );
289 osrfAppRequestRespond(ctx->session, ctx->request, resp);
290 jsonObjectFree(resp);
293 method = method->next;