Preparing to issue method calls (server-side)

This commit is contained in:
Pierre Pronchery 2014-04-17 02:29:04 +02:00
parent b662922337
commit 83fb382a14
12 changed files with 167 additions and 80 deletions

View File

@ -35,7 +35,7 @@ AppClient * appclient_new_event(char const * app, char const * name,
void appclient_delete(AppClient * appclient);
/* useful */
int appclient_call(AppClient * appclient, Variable * ret, char const * function,
...);
int appclient_call(AppClient * appclient, Variable ** ret,
char const * method, ...);
#endif /* !LIBAPP_APP_APPCLIENT_H */

View File

@ -59,7 +59,8 @@ typedef struct _AppTransportPluginHelper
unsigned int code, char const * message);
/* clients */
AppTransportClient * (*client_new)(AppTransport * transport);
AppTransportClient * (*client_new)(AppTransport * transport,
char const * name);
void (*client_delete)(AppTransport * transport,
AppTransportClient * client);
int (*client_receive)(AppTransport * transport,

View File

@ -117,7 +117,7 @@ char const * appclient_get_app(AppClient * appclient)
/* useful */
/* appclient_call */
int appclient_call(AppClient * appclient, Variable * result,
int appclient_call(AppClient * appclient, Variable ** result,
char const * function, ...)
{
int ret;

View File

@ -105,9 +105,10 @@ typedef struct _AppInterfaceCall
struct _AppInterface
{
String * name;
Config * config;
AppInterfaceCall * calls;
size_t calls_cnt;
uint16_t port;
int error;
};
@ -155,7 +156,7 @@ static int _string_enum(String const * string, StringEnum * se)
size_t i;
if(string == NULL)
return -error_set_code(1, "%s", strerror(EINVAL));
return -error_set_code(-EINVAL, "%s", strerror(EINVAL));
for(i = 0; se[i].string != NULL; i++)
if(string_compare(string, se[i].string) == 0)
return se[i].value;
@ -196,41 +197,35 @@ AppInterface * appinterface_new(char const * app)
{
AppInterface * appinterface;
String * pathname = NULL;
Config * config = NULL;
char const * p;
if(app == NULL)
return NULL; /* FIXME report error */
if((appinterface = object_new(sizeof(*appinterface))) == NULL)
return NULL;
appinterface->name = string_new(app);
appinterface->config = config_new();
appinterface->calls = NULL;
appinterface->calls_cnt = 0;
appinterface->port = 0;
appinterface->error = 0;
if(appinterface->name == NULL
|| (pathname = string_new_append(
SYSCONFDIR "/AppInterface/", app,
".interface", NULL)) == NULL
|| (config = config_new()) == NULL
|| config_load(config, pathname) != 0)
|| appinterface->config == NULL
|| config_load(appinterface->config, pathname) != 0)
{
if(config != NULL)
config_delete(config);
string_delete(pathname);
appinterface_delete(appinterface);
return NULL;
}
if((p = config_get(config, NULL, "port")) != NULL)
appinterface->port = atoi(p);
appinterface->error = 0;
hash_foreach(config, (HashForeach)_new_foreach, appinterface);
hash_foreach(appinterface->config, (HashForeach)_new_foreach,
appinterface);
if(appinterface->error != 0)
{
appinterface_delete(appinterface);
return NULL;
}
config_delete(config);
return appinterface;
}
@ -314,7 +309,7 @@ static int _new_append_arg(AppInterface * ai, char const * arg)
return -1;
q = &ai->calls[ai->calls_cnt - 1];
if((r = realloc(q->args, sizeof(*r) * (q->args_cnt + 1))) == NULL)
return -error_set_code(1, "%s", strerror(errno));
return error_set_code(-errno, "%s", strerror(errno));
q->args = r;
r = &q->args[q->args_cnt++];
r->type = type & AICT_MASK;
@ -364,6 +359,8 @@ void appinterface_delete(AppInterface * appinterface)
{
size_t i;
if(appinterface->config != NULL)
config_delete(appinterface->config);
for(i = 0; i < appinterface->calls_cnt; i++)
{
string_delete(appinterface->calls[i].name);
@ -376,6 +373,32 @@ void appinterface_delete(AppInterface * appinterface)
/* accessors */
/* appinterface_can_call */
int appinterface_can_call(AppInterface * appinterface, char const * name,
char const * method)
{
int ret = 0;
String * section;
String const * allow;
String const * deny;
if((section = string_new_append("call::", method, NULL)) == NULL)
/* XXX report as an error */
return 0;
allow = config_get(appinterface->config, section, "allow");
deny = config_get(appinterface->config, section, "deny");
/* FIXME implement pattern matching */
if(allow == NULL && deny == NULL)
ret = 1;
else if(deny != NULL)
ret = (strcmp(deny, name) == 0) ? 0 : 1;
else
ret = (strcmp(allow, name) == 0) ? 1 : 0;
string_delete(section);
return ret;
}
/* appinterface_get_name */
char const * appinterface_get_app(AppInterface * appinterface)
{
@ -383,13 +406,6 @@ char const * appinterface_get_app(AppInterface * appinterface)
}
/* appinterface_get_port */
int appinterface_get_port(AppInterface * appinterface)
{
return appinterface->port;
}
/* appinterface_get_args_count */
int appinterface_get_args_count(AppInterface * appinterface, size_t * count,
char const * function)
@ -604,7 +620,7 @@ static int _send_bytes(char const * data, size_t datalen, char * buf,
if(*pos + datalen > buflen)
{
errno = ENOBUFS;
return error_set_code(1, "%s", strerror(ENOBUFS));
return error_set_code(-errno, "%s", strerror(errno));
}
memcpy(&buf[*pos], data, datalen);
*pos += datalen;
@ -627,7 +643,7 @@ static int _send_string(char const * string, char buf[], size_t buflen,
return 0;
}
errno = ENOBUFS;
return error_set_code(1, "%s", strerror(ENOBUFS));
return error_set_code(-errno, "%s", strerror(errno));
}
@ -788,7 +804,7 @@ int appinterface_call_receive(AppInterface * appinterface, int32_t * ret,
/* appinterface_callv */
int appinterface_callv(AppInterface * appinterface, Variable * result,
int appinterface_callv(AppInterface * appinterface, Variable ** result,
char const * function, size_t argc, Variable ** argv)
{
/* FIXME implement */
@ -849,7 +865,7 @@ static int _receive_args(AppInterfaceCall * call, int * ret, char buf[],
size_t i;
if((args = malloc(sizeof(*args) * call->args_cnt)) == NULL)
return error_set_code(1, "%s", strerror(errno));
return error_set_code(-errno, "%s", strerror(errno));
if((i = _args_pre_exec(call, buf, buflen, pos, args)) != call->args_cnt)
{
_args_post_exec(call, bufw, bufwlen, bufwpos, args, i);
@ -995,7 +1011,7 @@ static int _pre_exec_in(AppInterfaceCallArg * aica, char buf[], size_t buflen,
case AICT_UINT64:
case AICT_DOUBLE:
errno = ENOSYS;
return -error_set_code(1, "%s", strerror(ENOSYS));
return error_set_code(-errno, "%s", strerror(errno));
case AICT_BUFFER:
if(_read_bytes(&size, sizeof(size), buf, buflen, pos)
!= 0)
@ -1081,7 +1097,7 @@ static int _read_bytes(void * data, size_t datalen, char buf[], size_t buflen,
if(datalen > buflen - *pos)
{
errno = EAGAIN;
return -error_set_code(1, "%s", strerror(EAGAIN));
return error_set_code(-errno, "%s", strerror(errno));
}
memcpy(data, &buf[*pos], datalen);
(*pos) += datalen;
@ -1198,7 +1214,7 @@ static int _post_exec_out(AppInterfaceCallArg * aica, char buf[], size_t buflen,
if(aica->size > buflen)
{
errno = ENOBUFS;
return -error_set_code(1, "%s", strerror(ENOBUFS));
return error_set_code(-errno, "%s", strerror(errno));
}
switch(aica->type)
{
@ -1229,7 +1245,7 @@ static int _post_exec_out(AppInterfaceCallArg * aica, char buf[], size_t buflen,
case AICT_UINT64:
case AICT_DOUBLE:
errno = ENOSYS;
return -error_set_code(1, "%s", strerror(ENOSYS));
return error_set_code(-errno, "%s", strerror(errno));
case AICT_BUFFER:
b = arg;
size = htonl(buffer_get_size(b)); /* size of buffer */
@ -1265,7 +1281,7 @@ static int _post_exec_free_in(AppInterfaceCallArg * aica, void * arg)
case AICT_DOUBLE:
/* FIXME not supported */
errno = ENOSYS;
return -error_set_code(1, "%s", strerror(ENOSYS));
return error_set_code(-errno, "%s", strerror(errno));
case AICT_BUFFER:
buffer_delete(b);
break;
@ -1299,7 +1315,7 @@ static int _post_exec_free_out(AppInterfaceCallArg * aica, void * arg)
break;
case AICT_STRING: /* FIXME not supported */
errno = ENOSYS;
return -error_set_code(1, "%s", strerror(ENOSYS));
return error_set_code(-errno, "%s", strerror(errno));
}
return 0;
}

View File

@ -33,6 +33,9 @@ AppInterface * appinterface_new_server(char const * app);
void appinterface_delete(AppInterface * appinterface);
/* accessors */
int appinterface_can_call(AppInterface * appinterface, char const * name,
char const * method);
char const * appinterface_get_app(AppInterface * appinterface);
int appinterface_get_args_count(AppInterface * appinterface, size_t * count,
char const * function);
@ -45,7 +48,7 @@ int appinterface_call_receive(AppInterface * appinterface, int32_t * ret,
int appinterface_receive(AppInterface * appinterface, int * ret, char buf[],
size_t buflen, char bufw[], size_t bufwlen, size_t * bufwpos);
int appinterface_callv(AppInterface * appinterface, Variable * result,
char const * function, size_t argc, Variable ** argv);
int appinterface_callv(AppInterface * appinterface, Variable ** result,
char const * method, size_t argc, Variable ** argv);
#endif /* !LIBAPP_APPINTERFACE_H */

View File

@ -120,14 +120,47 @@ int appserver_loop(AppServer * appserver)
/* private */
/* appserver_helper_message */
static int _helper_message_call(AppServer * appserver, AppTransport * transport,
AppTransportClient * client, AppMessage * message);
static int _appserver_helper_message(void * data, AppTransport * transport,
AppTransportClient * client, AppMessage * message)
{
AppServer * appserver = data;
if(client == NULL)
/* XXX report error */
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%p, %u)\n", __func__, (void *)client,
appmessage_get_type(message));
#endif
/* FIXME can it happen? */
if(message == NULL)
/* XXX report errors */
return -1;
/* FIXME implement */
return 0;
switch(appmessage_get_type(message))
{
case AMT_CALL:
return _helper_message_call(appserver, transport,
client, message);
}
return -1;
}
static int _helper_message_call(AppServer * appserver, AppTransport * transport,
AppTransportClient * client, AppMessage * message)
{
int ret;
String const * name;
String const * method;
Variable * result = NULL;
name = (client != NULL) ? apptransport_client_get_name(client) : NULL;
method = appmessage_get_method(message);
if(!appinterface_can_call(appserver->interface, name, method))
/* XXX report errors */
return -1;
ret = appinterface_callv(appserver->interface, &result, method, 0,
NULL);
if(result != NULL)
variable_delete(result);
return ret;
}

View File

@ -25,6 +25,9 @@
#include "appmessage.h"
#include "apptransport.h"
#include "../config.h"
/* FIXME:
* clarify parsing name strings (if there is a colon, there is a transport,
* although possibly empty) */
#ifndef PREFIX
# define PREFIX "/usr/local"
@ -56,6 +59,7 @@ struct _AppTransport
struct _AppTransportClient
{
AppTransport * transport;
char * name;
};
@ -66,7 +70,7 @@ static int _apptransport_helper_status(AppTransport * transport,
char const * message);
static AppTransportClient * _apptransport_helper_client_new(
AppTransport * transport);
AppTransport * transport, char const * name);
static void _apptransport_helper_client_delete(AppTransport * transport,
AppTransportClient * client);
@ -227,6 +231,13 @@ String const * apptransport_get_transport(AppTransport * transport)
}
/* apptransport_client_get_name */
String const * apptransport_client_get_name(AppTransportClient * client)
{
return client->name;
}
/* useful */
/* apptransport_client_send */
int apptransport_client_send(AppTransport * transport, AppMessage * message,
@ -275,7 +286,7 @@ static int _apptransport_helper_status(AppTransport * transport,
/* apptransport_helper_client_new */
static AppTransportClient * _apptransport_helper_client_new(
AppTransport * transport)
AppTransport * transport, char const * name)
{
AppTransportClient * client;
@ -285,6 +296,7 @@ static AppTransportClient * _apptransport_helper_client_new(
if((client = object_new(sizeof(*client))) == NULL)
return NULL;
client->transport = transport;
client->name = (name != NULL) ? string_new(name) : NULL;
return client;
}
@ -315,6 +327,7 @@ static int _apptransport_helper_client_receive(AppTransport * transport,
if(transport->mode != ATM_SERVER)
/* XXX improve the error message */
return -error_set_code(1, "Not a server");
/* XXX check for errors? */
transport->helper.message(transport->helper.data, transport, client,
message);
/* check if an acknowledgement is requested */

View File

@ -28,7 +28,7 @@
typedef struct _AppTransportHelper
{
void * data;
void (*message)(void * data, AppTransport * transport,
int (*message)(void * data, AppTransport * transport,
AppTransportClient * client, AppMessage * message);
} AppTransportHelper;
@ -46,6 +46,8 @@ void apptransport_delete(AppTransport * transport);
String const * apptransport_get_name(AppTransport * transport);
String const * apptransport_get_transport(AppTransport * transport);
String const * apptransport_client_get_name(AppTransportClient * client);
/* useful */
/* ATM_CLIENT */
int apptransport_client_send(AppTransport * transport, AppMessage * message,

View File

@ -61,7 +61,7 @@ typedef struct _TCPSocket
int fd;
struct sockaddr * sa;
socklen_t sa_size;
socklen_t sa_len;
/* input queue */
char * bufin;
@ -122,9 +122,9 @@ static int _tcp_server_add_client(TCP * tcp, TCPSocket * client);
/* sockets */
static int _tcp_socket_init(TCPSocket * tcpsocket, int domain, TCP * tcp);
static void _tcp_socket_init_fd(TCPSocket * tcpsocket, TCP * tcp, int fd,
struct sockaddr * sa, socklen_t sa_size);
struct sockaddr * sa, socklen_t sa_len);
static TCPSocket * _tcp_socket_new_fd(TCP * tcp, int fd, struct sockaddr * sa,
socklen_t sa_size);
socklen_t sa_len);
static void _tcp_socket_delete(TCPSocket * tcpsocket);
static void _tcp_socket_destroy(TCPSocket * tcpsocket);
@ -427,14 +427,20 @@ static int _tcp_error(char const * message, int code)
static int _tcp_server_add_client(TCP * tcp, TCPSocket * client)
{
TCPSocket ** p;
char host[NI_MAXHOST];
char const * name = host;
if((p = realloc(tcp->u.server.clients, sizeof(*p)
* (tcp->u.server.clients_cnt + 1)))
== NULL)
return -1;
tcp->u.server.clients = p;
if((client->client = tcp->helper->client_new(tcp->helper->transport))
== NULL)
/* XXX may not be instant */
if(getnameinfo(client->sa, client->sa_len, host, sizeof(host), NULL, 0,
0) != 0)
name = NULL;
if((client->client = tcp->helper->client_new(tcp->helper->transport,
name)) == NULL)
return -1;
tcp->u.server.clients[tcp->u.server.clients_cnt++] = client;
return 0;
@ -467,13 +473,13 @@ static int _tcp_socket_init(TCPSocket * tcpsocket, int domain, TCP * tcp)
/* tcp_socket_init_fd */
static void _tcp_socket_init_fd(TCPSocket * tcpsocket, TCP * tcp, int fd,
struct sockaddr * sa, socklen_t sa_size)
struct sockaddr * sa, socklen_t sa_len)
{
tcpsocket->tcp = tcp;
tcpsocket->client = NULL;
tcpsocket->fd = fd;
tcpsocket->sa = sa;
tcpsocket->sa_size = sa_size;
tcpsocket->sa_len = sa_len;
tcpsocket->bufin = NULL;
tcpsocket->bufin_cnt = 0;
tcpsocket->bufout = NULL;
@ -483,13 +489,13 @@ static void _tcp_socket_init_fd(TCPSocket * tcpsocket, TCP * tcp, int fd,
/* tcp_socket_new_fd */
static TCPSocket * _tcp_socket_new_fd(TCP * tcp, int fd, struct sockaddr * sa,
socklen_t sa_size)
socklen_t sa_len)
{
TCPSocket * tcpsocket;
if((tcpsocket = object_new(sizeof(*tcpsocket))) == NULL)
return NULL;
_tcp_socket_init_fd(tcpsocket, tcp, fd, sa, sa_size);
_tcp_socket_init_fd(tcpsocket, tcp, fd, sa, sa_len);
return tcpsocket;
}
@ -574,12 +580,12 @@ static int _tcp_socket_queue(TCPSocket * tcpsocket, Buffer * buffer)
/* callbacks */
/* tcp_callback_accept */
static int _accept_client(TCP * tcp, int fd, struct sockaddr * sa,
socklen_t sa_size);
socklen_t sa_len);
static int _tcp_callback_accept(int fd, TCP * tcp)
{
struct sockaddr * sa;
socklen_t sa_size = tcp->ai_addrlen;
socklen_t sa_len = tcp->ai_addrlen;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%d)\n", __func__, fd);
@ -587,15 +593,15 @@ static int _tcp_callback_accept(int fd, TCP * tcp)
/* check parameters */
if(tcp->u.server.fd != fd)
return -1;
if((sa = malloc(sa_size)) == NULL)
if((sa = malloc(sa_len)) == NULL)
/* XXX this may not be enough to recover */
sa_size = 0;
if((fd = accept(fd, sa, &sa_size)) < 0)
sa_len = 0;
if((fd = accept(fd, sa, &sa_len)) < 0)
{
free(sa);
return _tcp_error("accept", 1);
}
if(_accept_client(tcp, fd, sa, sa_size) != 0)
if(_accept_client(tcp, fd, sa, sa_len) != 0)
{
/* just close the connection and keep serving */
/* FIXME report error */
@ -610,14 +616,14 @@ static int _tcp_callback_accept(int fd, TCP * tcp)
}
static int _accept_client(TCP * tcp, int fd, struct sockaddr * sa,
socklen_t sa_size)
socklen_t sa_len)
{
TCPSocket * tcpsocket;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%d)\n", __func__, fd);
#endif
if((tcpsocket = _tcp_socket_new_fd(tcp, fd, sa, sa_size)) == NULL)
if((tcpsocket = _tcp_socket_new_fd(tcp, fd, sa, sa_len)) == NULL)
return -1;
if(_tcp_server_add_client(tcp, tcpsocket) != 0)
{

View File

@ -12,6 +12,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* TODO:
* - expire clients after a timeout */
@ -391,10 +393,17 @@ static int _udp_client_init(UDPClient * client, struct sockaddr * sa,
socklen_t sa_len, UDP * udp)
{
AppTransportPluginHelper * helper = udp->helper;
char host[NI_MAXHOST];
char const * name = host;
if((client->sa = malloc(sa_len)) == NULL)
return -1;
if((client->client = helper->client_new(helper->transport)) == NULL)
/* XXX may not be instant */
if(getnameinfo(client->sa, client->sa_len, host, sizeof(host), NULL, 0,
NI_DGRAM) != 0)
name = NULL;
if((client->client = helper->client_new(helper->transport, name))
== NULL)
{
free(client->sa);
return -1;

View File

@ -48,7 +48,7 @@ static int _transport_helper_status(AppTransport * transport,
char const * message);
static AppTransportClient * _transport_helper_client_new(
AppTransport * transport);
AppTransport * transport, char const * name);
static void _transport_helper_client_delete(AppTransport * transport,
AppTransportClient * client);
static int _transport_helper_client_receive(AppTransport * transport,
@ -138,10 +138,10 @@ static int _transport(char const * protocol, char const * name)
/* helpers */
/* transport_helper_client_new */
static AppTransportClient * _transport_helper_client_new(
AppTransport * transport)
AppTransport * transport, char const * name)
{
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s()\n", __func__);
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, name);
#endif
/* FIXME really implement */
return (AppTransportClient *)transport;

View File

@ -91,14 +91,12 @@ static int _appclient(int verbose, char const * app, char const * name,
static int _appclient_call(int verbose, AppClient * ac, AppClientCall * call)
{
int ret = 0;
Variable * v;
int res = 0;
Variable * v = NULL;
int res;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s()\n", __func__);
#endif
if((v = variable_new(VT_INT32, &res)) == NULL)
return -1;
if(verbose != 0)
printf("Calling %s() with %lu arguments\n", call->name,
(unsigned long)call->args_cnt);
@ -110,7 +108,7 @@ static int _appclient_call(int verbose, AppClient * ac, AppClientCall * call)
fprintf(stderr, "DEBUG: %s() %s() res=%d\n", __func__,
call->name, res);
#endif
ret = appclient_call(ac, v, call->name, NULL);
ret = appclient_call(ac, &v, call->name, NULL);
break;
case 1:
#ifdef DEBUG
@ -118,16 +116,16 @@ static int _appclient_call(int verbose, AppClient * ac, AppClientCall * call)
call->name, call->args[0].integer);
#endif
if(call->args[0].type == ACCAT_DOUBLE)
ret = appclient_call(ac, v, call->name,
ret = appclient_call(ac, &v, call->name,
call->args[0]._double);
else if(call->args[0].type == ACCAT_FLOAT)
ret = appclient_call(ac, v, call->name,
ret = appclient_call(ac, &v, call->name,
call->args[0]._float);
else if(call->args[0].type == ACCAT_INTEGER)
ret = appclient_call(ac, v, call->name,
ret = appclient_call(ac, &v, call->name,
call->args[0].integer);
else if(call->args[0].type == ACCAT_STRING)
ret = appclient_call(ac, v, call->name,
ret = appclient_call(ac, &v, call->name,
call->args[0].string);
else
ret = error_set_code(1, "%s",
@ -141,7 +139,7 @@ static int _appclient_call(int verbose, AppClient * ac, AppClientCall * call)
call->args[0].integer,
call->args[1].integer);
#endif
ret = appclient_call(ac, v, call->name,
ret = appclient_call(ac, &v, call->name,
call->args[0].integer,
call->args[1].integer);
break;
@ -156,7 +154,7 @@ static int _appclient_call(int verbose, AppClient * ac, AppClientCall * call)
call->args[1]._float,
call->args[2]._float);
#endif
ret = appclient_call(ac, v, call->name,
ret = appclient_call(ac, &v, call->name,
call->args[0]._float,
call->args[1]._float,
call->args[2]._float);
@ -170,7 +168,7 @@ static int _appclient_call(int verbose, AppClient * ac, AppClientCall * call)
call->args[1].integer,
call->args[2].integer);
#endif
ret = appclient_call(ac, v, call->name,
ret = appclient_call(ac, &v, call->name,
call->args[0].integer,
call->args[1].integer,
call->args[2].integer);
@ -184,7 +182,7 @@ static int _appclient_call(int verbose, AppClient * ac, AppClientCall * call)
call->args[2]._float,
call->args[3]._float);
#endif
ret = appclient_call(ac, v, call->name,
ret = appclient_call(ac, &v, call->name,
call->args[0]._float,
call->args[1]._float,
call->args[2]._float,
@ -195,8 +193,14 @@ static int _appclient_call(int verbose, AppClient * ac, AppClientCall * call)
"Unsupported number of arguments");
}
if(ret == 0 && verbose)
printf("\"%s\"%s%d\n", call->name, " returned ", res);
variable_delete(v);
{
if(v != NULL && variable_get_as(v, VT_INT32, &res) == 0)
printf("\"%s\"%s%d\n", call->name, " returned ", res);
else
printf("\"%s\"%s\n", call->name, " returned");
}
if(v != NULL)
variable_delete(v);
return ret;
}