libApp

/* $Id$ */
/* Copyright (c) 2011-2020 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS System libApp */
/* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#ifdef DEBUG
# include <stdio.h>
#endif
#include <string.h>
#include <errno.h>
#include <System.h>
#include "App/appmessage.h"
#include "App/appserver.h"
#include "apptransport.h"
#include "appinterface.h"
#include "../config.h"
/* AppServer */
/* private */
/* types */
struct _AppServer
{
App * app;
char * name;
AppServerOptions options;
AppInterface * interface;
Event * event;
int event_free;
AppTransport * transport;
AppTransportHelper helper;
};
/* prototypes */
/* helpers */
static int _appserver_helper_message(void * data, AppTransport * transport,
AppTransportClient * client, AppMessage * message);
/* public */
/* functions */
/* appserver_new */
AppServer * appserver_new(App * self, AppServerOptions options,
const char * app, char const * name)
{
return appserver_new_event(self, options, app, name, NULL);
}
/* appserver_new_event */
AppServer * appserver_new_event(App * self, AppServerOptions options,
char const * app, char const * name, Event * event)
{
AppServer * appserver;
if((appserver = object_new(sizeof(*appserver))) == NULL)
return NULL;
appserver->app = self;
appserver->name = string_new(app);
appserver->options = options;
appserver->interface = appinterface_new(ATM_SERVER, app);
appserver->helper.data = appserver;
appserver->helper.message = _appserver_helper_message;
appserver->event = (event != NULL) ? event : event_new();
appserver->event_free = (event != NULL) ? 0 : 1;
appserver->transport = apptransport_new_app(ATM_SERVER,
&appserver->helper, app, name, appserver->event);
/* check for errors */
if(appserver->name == NULL || appserver->interface == NULL
|| appserver->transport == NULL
|| appserver->event == NULL
|| (((options & ASO_REGISTER) == ASO_REGISTER)
&& appserver_register(appserver, NULL) != 0))
{
appserver_delete(appserver);
return NULL;
}
return appserver;
}
/* appserver_delete */
void appserver_delete(AppServer * appserver)
{
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s()\n", __func__);
#endif
if(appserver->interface != NULL)
appinterface_delete(appserver->interface);
if(appserver->event_free != 0)
event_delete(appserver->event);
object_delete(appserver);
}
/* accessors */
/* appserver_get_app */
char const * appserver_get_app(AppServer * appserver)
{
return appinterface_get_app(appserver->interface);
}
/* appserver_get_status */
AppStatus * appserver_get_status(AppServer * appserver)
{
return appinterface_get_status(appserver->interface);
}
/* useful */
/* appserver_loop */
int appserver_loop(AppServer * appserver)
{
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s()\n", __func__);
#endif
return event_loop(appserver->event);
}
/* appserver_register */
int appserver_register(AppServer * appserver, char const * name)
{
return apptransport_server_register(appserver->transport,
appserver->name, name);
}
/* 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;
#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;
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, method, name))
/* XXX report errors */
return -1;
/* FIXME provide the actual AppServerClient */
ret = appinterface_call_variablev(appserver->interface, appserver->app,
NULL, result, method, 0, NULL);
if(result != NULL)
variable_delete(result);
return ret;
}