Look for calls and callbacks according to the mode

This commit is contained in:
Pierre Pronchery 2020-03-29 10:53:55 +02:00
parent eb3fe28e7c
commit c4e1784816

View File

@ -90,6 +90,9 @@ struct _AppInterface
AppStatus * status; AppStatus * status;
AppInterfaceCall * calls; AppInterfaceCall * calls;
size_t calls_cnt; size_t calls_cnt;
AppInterfaceCall * callbacks;
size_t callbacks_cnt;
/* XXX for hash_foreach() in _new_interface_do() */
int error; int error;
}; };
@ -226,51 +229,38 @@ static String * _new_interface(String const * app)
/* appinterface_new_interface */ /* appinterface_new_interface */
static int _new_interface_append(AppInterface * ai, VariableType type, static AppInterfaceCall * _new_interface_append_call(AppInterface * ai,
char const * method); VariableType type, char const * method);
static int _new_interface_append_arg(AppInterface * ai, char const * arg); static AppInterfaceCall * _new_interface_append_callback(AppInterface * ai,
VariableType type, char const * method);
static int _new_interface_append_arg(AppInterfaceCall * call, char const * arg);
AppInterface * _new_interface_do(AppTransportMode mode, String const * app, AppInterface * _new_interface_do(AppTransportMode mode, String const * app,
String const * pathname); String const * pathname);
static int _new_interface_do_appstatus(AppInterface * appinterface); static int _new_interface_do_appstatus(AppInterface * appinterface);
static int _new_interface_foreach(char const * key, Hash * value, static int _new_interface_foreach_calls(char const * key, Hash * value,
AppInterface * appinterface); AppInterface * appinterface);
static int _new_interface_foreach_callbacks(char const * key, Hash * value,
AppInterface * appinterface);
static AppInterface * _new_interface_mode_client(AppTransportMode mode,
String const * app, String const * pathname);
static AppInterface * _new_interface_mode_server(AppTransportMode mode,
String const * app, String const * pathname);
AppInterface * appinterface_new_interface(AppTransportMode mode, AppInterface * appinterface_new_interface(AppTransportMode mode,
String const * app, String const * pathname) String const * app, String const * pathname)
{ {
AppInterface * ai; switch(mode)
Plugin * handle;
size_t i;
String * name;
if((handle = plugin_new_self()) == NULL)
return NULL;
if((ai = _new_interface_do(mode, app, pathname)) == NULL)
return NULL;
for(i = 0; i < ai->calls_cnt; i++)
{ {
if((name = string_new_append(ai->name, "_", ai->calls[i].name, case ATM_CLIENT:
NULL)) == NULL) return _new_interface_mode_client(mode, app, pathname);
{ case ATM_SERVER:
appinterface_delete(ai); return _new_interface_mode_server(mode, app, pathname);
ai = NULL;
break;
}
ai->calls[i].func = plugin_lookup(handle, name);
string_delete(name);
if(ai->calls[i].func == NULL)
{
appinterface_delete(ai);
ai = NULL;
break;
}
} }
plugin_delete(handle); return NULL;
return ai;
} }
static int _new_interface_append(AppInterface * ai, VariableType type, static AppInterfaceCall * _new_interface_append_call(AppInterface * ai,
char const * method) VariableType type, char const * method)
{ {
AppInterfaceCall * p; AppInterfaceCall * p;
@ -278,25 +268,47 @@ static int _new_interface_append(AppInterface * ai, VariableType type,
fprintf(stderr, "DEBUG: %s(%d, \"%s\")\n", __func__, type, method); fprintf(stderr, "DEBUG: %s(%d, \"%s\")\n", __func__, type, method);
#endif #endif
if((p = realloc(ai->calls, sizeof(*p) * (ai->calls_cnt + 1))) == NULL) if((p = realloc(ai->calls, sizeof(*p) * (ai->calls_cnt + 1))) == NULL)
return -1; return NULL;
ai->calls = p; ai->calls = p;
p = &ai->calls[ai->calls_cnt]; p = &ai->calls[ai->calls_cnt];
if((p->name = string_new(method)) == NULL) if((p->name = string_new(method)) == NULL)
return -1; return NULL;
p->type.type = type & AICT_MASK; p->type.type = type & AICT_MASK;
p->type.direction = type & AICD_MASK; p->type.direction = type & AICD_MASK;
p->args = NULL; p->args = NULL;
p->args_cnt = 0; p->args_cnt = 0;
ai->calls_cnt++; ai->calls_cnt++;
return 0; return p;
} }
static int _new_interface_append_arg(AppInterface * ai, char const * arg) static AppInterfaceCall * _new_interface_append_callback(AppInterface * ai,
VariableType type, char const * method)
{
AppInterfaceCall * p;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%d, \"%s\")\n", __func__, type, method);
#endif
if((p = realloc(ai->callbacks, sizeof(*p) * (ai->callbacks_cnt + 1)))
== NULL)
return NULL;
ai->callbacks = p;
p = &ai->callbacks[ai->callbacks_cnt];
if((p->name = string_new(method)) == NULL)
return NULL;
p->type.type = type & AICT_MASK;
p->type.direction = type & AICD_MASK;
p->args = NULL;
p->args_cnt = 0;
ai->callbacks_cnt++;
return p;
}
static int _new_interface_append_arg(AppInterfaceCall * call, char const * arg)
{ {
char buf[16]; char buf[16];
char * p; char * p;
int type; int type;
AppInterfaceCall * q;
AppInterfaceCallArg * r; AppInterfaceCallArg * r;
#ifdef DEBUG #ifdef DEBUG
@ -307,11 +319,10 @@ static int _new_interface_append_arg(AppInterface * ai, char const * arg)
*p = '\0'; *p = '\0';
if((type = _string_enum(buf, _string_type)) < 0) if((type = _string_enum(buf, _string_type)) < 0)
return -1; return -1;
q = &ai->calls[ai->calls_cnt - 1]; if((r = realloc(call->args, sizeof(*r) * (call->args_cnt + 1))) == NULL)
if((r = realloc(q->args, sizeof(*r) * (q->args_cnt + 1))) == NULL)
return error_set_code(-errno, "%s", strerror(errno)); return error_set_code(-errno, "%s", strerror(errno));
q->args = r; call->args = r;
r = &q->args[q->args_cnt++]; r = &call->args[call->args_cnt++];
r->type = type & AICT_MASK; r->type = type & AICT_MASK;
r->direction = type & AICD_MASK; r->direction = type & AICD_MASK;
#ifdef DEBUG #ifdef DEBUG
@ -336,6 +347,8 @@ AppInterface * _new_interface_do(AppTransportMode mode, String const * app,
appinterface->status = NULL; appinterface->status = NULL;
appinterface->calls = NULL; appinterface->calls = NULL;
appinterface->calls_cnt = 0; appinterface->calls_cnt = 0;
appinterface->callbacks = NULL;
appinterface->callbacks_cnt = 0;
appinterface->error = 0; appinterface->error = 0;
if(appinterface->name == NULL if(appinterface->name == NULL
|| appinterface->config == NULL || appinterface->config == NULL
@ -346,7 +359,11 @@ AppInterface * _new_interface_do(AppTransportMode mode, String const * app,
return NULL; return NULL;
} }
appinterface->error = 0; appinterface->error = 0;
hash_foreach(appinterface->config, (HashForeach)_new_interface_foreach, hash_foreach(appinterface->config,
(HashForeach)_new_interface_foreach_calls,
appinterface);
hash_foreach(appinterface->config,
(HashForeach)_new_interface_foreach_callbacks,
appinterface); appinterface);
if(appinterface->error != 0) if(appinterface->error != 0)
{ {
@ -365,15 +382,15 @@ static int _new_interface_do_appstatus(AppInterface * appinterface)
return 0; return 0;
} }
static int _new_interface_foreach(char const * key, Hash * value, static int _new_interface_foreach_callbacks(char const * key, Hash * value,
AppInterface * appinterface) AppInterface * appinterface)
{ {
String const * prefix = (appinterface->mode == ATM_SERVER) String const * prefix = APPINTERFACE_CALLBACK_PREFIX;
? APPINTERFACE_CALL_PREFIX : APPINTERFACE_CALLBACK_PREFIX;
unsigned int i; unsigned int i;
char buf[8]; char buf[8];
int type = VT_NULL; int type = VT_NULL;
char const * p; char const * p;
AppInterfaceCall * callback;
if(key == NULL || strncmp(prefix, key, string_length(prefix)) != 0) if(key == NULL || strncmp(prefix, key, string_length(prefix)) != 0)
return 0; return 0;
@ -381,13 +398,12 @@ static int _new_interface_foreach(char const * key, Hash * value,
if((p = hash_get(value, "ret")) != NULL if((p = hash_get(value, "ret")) != NULL
&& (type = _string_enum(p, _string_type)) < 0) && (type = _string_enum(p, _string_type)) < 0)
{ {
appinterface->error = error_set_code(1, "%s: %s%s", p, appinterface->error = error_set_code(1, "%s: %s", p,
"Invalid return type for ", "Invalid return type for callback");
(appinterface->mode == ATM_SERVER)
? "call" : "callback");
return -appinterface->error; return -appinterface->error;
} }
if(_new_interface_append(appinterface, type, key) != 0) if((callback = _new_interface_append_callback(appinterface, type, key))
== NULL)
{ {
appinterface->error = 1; appinterface->error = 1;
return -appinterface->error; return -appinterface->error;
@ -397,7 +413,7 @@ static int _new_interface_foreach(char const * key, Hash * value,
snprintf(buf, sizeof(buf), "arg%u", i + 1); snprintf(buf, sizeof(buf), "arg%u", i + 1);
if((p = hash_get(value, buf)) == NULL) if((p = hash_get(value, buf)) == NULL)
break; break;
if(_new_interface_append_arg(appinterface, p) != 0) if(_new_interface_append_arg(callback, p) != 0)
{ {
/* FIXME may crash here? */ /* FIXME may crash here? */
appinterface->error = 1; appinterface->error = 1;
@ -407,6 +423,123 @@ static int _new_interface_foreach(char const * key, Hash * value,
return 0; return 0;
} }
static int _new_interface_foreach_calls(char const * key, Hash * value,
AppInterface * appinterface)
{
String const * prefix = APPINTERFACE_CALL_PREFIX;
unsigned int i;
char buf[8];
int type = VT_NULL;
char const * p;
AppInterfaceCall * call;
if(key == NULL || strncmp(prefix, key, string_length(prefix)) != 0)
return 0;
key += string_length(prefix);
if((p = hash_get(value, "ret")) != NULL
&& (type = _string_enum(p, _string_type)) < 0)
{
appinterface->error = error_set_code(1, "%s: %s", p,
"Invalid return type for call");
return -appinterface->error;
}
if((call = _new_interface_append_call(appinterface, type, key)) == NULL)
{
appinterface->error = 1;
return -appinterface->error;
}
for(i = 0; i < APPSERVER_MAX_ARGUMENTS; i++)
{
snprintf(buf, sizeof(buf), "arg%u", i + 1);
if((p = hash_get(value, buf)) == NULL)
break;
if(_new_interface_append_arg(call, p) != 0)
{
/* FIXME may crash here? */
appinterface->error = 1;
return -1;
}
}
return 0;
}
AppInterface * _new_interface_mode_client(AppTransportMode mode,
String const * app, String const * pathname)
{
AppInterface * ai;
Plugin * plugin;
size_t i;
String * name;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%u, \"%s\", \"%s\")\n", __func__, mode, app,
pathname);
#endif
if((plugin = plugin_new_self()) == NULL)
return NULL;
if((ai = _new_interface_do(mode, app, pathname)) == NULL)
{
plugin_delete(plugin);
return NULL;
}
for(i = 0; i < ai->callbacks_cnt; i++)
{
if((name = string_new_append(ai->name, "_",
ai->callbacks[i].name, NULL))
== NULL)
break;
ai->callbacks[i].func = plugin_lookup(plugin, name);
string_delete(name);
if(ai->callbacks[i].func == NULL)
break;
}
plugin_delete(plugin);
if(i != ai->callbacks_cnt)
{
appinterface_delete(ai);
return NULL;
}
return ai;
}
AppInterface * _new_interface_mode_server(AppTransportMode mode,
String const * app, String const * pathname)
{
AppInterface * ai;
Plugin * plugin;
size_t i;
String * name;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%u, \"%s\", \"%s\")\n", __func__, mode, app,
pathname);
#endif
if((plugin = plugin_new_self()) == NULL)
return NULL;
if((ai = _new_interface_do(mode, app, pathname)) == NULL)
{
plugin_delete(plugin);
return NULL;
}
for(i = 0; i < ai->calls_cnt; i++)
{
if((name = string_new_append(ai->name, "_", ai->calls[i].name,
NULL)) == NULL)
break;
ai->calls[i].func = plugin_lookup(plugin, name);
string_delete(name);
if(ai->calls[i].func == NULL)
break;
}
plugin_delete(plugin);
if(i != ai->calls_cnt)
{
appinterface_delete(ai);
return NULL;
}
return ai;
}
/* appinterface_delete */ /* appinterface_delete */
void appinterface_delete(AppInterface * appinterface) void appinterface_delete(AppInterface * appinterface)