Compare commits
16 Commits
master
...
khorben/ma
Author | SHA1 | Date | |
---|---|---|---|
6714ce2458 | |||
c685a92f6f | |||
e73edbf782 | |||
56681c5b2b | |||
f07fe73b04 | |||
24e0b47aa8 | |||
36ad7752cc | |||
946ef7de6f | |||
a8fea8d096 | |||
d50f9c4b3f | |||
92c72c9631 | |||
bf8ab98365 | |||
395eb4a97f | |||
67c615e8df | |||
7ac93b664d | |||
c4dafd31b6 |
|
@ -21,6 +21,7 @@
|
|||
# include <System/buffer.h>
|
||||
# include <System/string.h>
|
||||
# include <System/variable.h>
|
||||
# include <System/Marshall.h>
|
||||
# include "app.h"
|
||||
# include "appstatus.h"
|
||||
|
||||
|
@ -41,9 +42,9 @@ typedef uint32_t AppMessageID;
|
|||
/* calls */
|
||||
typedef enum _AppMessageCallDirection
|
||||
{
|
||||
AMCD_IN = 1,
|
||||
AMCD_OUT,
|
||||
AMCD_IN_OUT
|
||||
AMCD_IN = MCD_IN,
|
||||
AMCD_OUT = MCD_OUT,
|
||||
AMCD_IN_OUT = MCD_IN_OUT
|
||||
} AppMessageCallDirection;
|
||||
|
||||
typedef struct _AppMessageCallArgument
|
||||
|
@ -58,6 +59,10 @@ typedef struct _AppMessageCallArgument
|
|||
(type | (direction) << 8), (variable)
|
||||
|
||||
|
||||
/* constants */
|
||||
# define APPMESSAGE_MAX_SIZE 32768
|
||||
|
||||
|
||||
/* functions */
|
||||
AppMessage * appmessage_new_deserialize(Buffer * buffer);
|
||||
/* calls */
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include <errno.h>
|
||||
#include <System.h>
|
||||
#include "App/appclient.h"
|
||||
#include "App/appmessage.h"
|
||||
#include "appmessage.h"
|
||||
#include "apptransport.h"
|
||||
#include "appinterface.h"
|
||||
|
||||
|
@ -40,10 +40,15 @@ struct _AppClient
|
|||
int event_free;
|
||||
AppTransport * transport;
|
||||
AppTransportHelper helper;
|
||||
AppMessageID id;
|
||||
int flag;
|
||||
};
|
||||
|
||||
|
||||
/* prototypes */
|
||||
static int _appclient_call_message(AppClient * appclient,
|
||||
AppMessage * appmessage, Variable * result);
|
||||
|
||||
/* helpers */
|
||||
static int _appclient_helper_message(void * data, AppTransport * transport,
|
||||
AppTransportClient * client, AppMessage * message);
|
||||
|
@ -78,6 +83,8 @@ AppClient * appclient_new_event(App * self, char const * app,
|
|||
appclient->event_free = (event != NULL) ? 0 : 1;
|
||||
appclient->transport = apptransport_new_app(ATM_CLIENT,
|
||||
&appclient->helper, app, name, appclient->event);
|
||||
appclient->id = 0;
|
||||
appclient->flag = 0;
|
||||
/* check for errors */
|
||||
if(appclient->interface == NULL
|
||||
|| appclient->transport == NULL
|
||||
|
@ -151,8 +158,8 @@ int appclient_callv(AppClient * appclient,
|
|||
if((message = appinterface_messagev(appclient->interface, method, ap))
|
||||
== NULL)
|
||||
return -1;
|
||||
/* FIXME obtain the answer (AICD_{,IN}OUT) */
|
||||
ret = apptransport_client_send(appclient->transport, message, 1);
|
||||
/* FIXME implement the result */
|
||||
ret = _appclient_call_message(appclient, message, NULL);
|
||||
appmessage_delete(message);
|
||||
return ret;
|
||||
}
|
||||
|
@ -182,8 +189,7 @@ int appclient_call_variables(AppClient * appclient,
|
|||
if((message = appinterface_message_variables(appclient->interface,
|
||||
method, args)) == NULL)
|
||||
return -1;
|
||||
/* FIXME obtain the answer (AICD_{,IN}OUT) */
|
||||
ret = apptransport_client_send(appclient->transport, message, 1);
|
||||
ret = _appclient_call_message(appclient, message, result);
|
||||
appmessage_delete(message);
|
||||
return ret;
|
||||
}
|
||||
|
@ -199,15 +205,34 @@ int appclient_call_variablev(AppClient * appclient,
|
|||
if((message = appinterface_message_variablev(appclient->interface,
|
||||
method, args)) == NULL)
|
||||
return -1;
|
||||
/* FIXME obtain the answer (AICD_{,IN}OUT) */
|
||||
ret = apptransport_client_send(appclient->transport, message, 1);
|
||||
ret = _appclient_call_message(appclient, message, result);
|
||||
appmessage_delete(message);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* private */
|
||||
/* appclient_call_message */
|
||||
static int _appclient_call_message(AppClient * appclient,
|
||||
AppMessage * appmessage, Variable * result)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if((ret = apptransport_client_send(appclient->transport, appmessage,
|
||||
ATF_ACKNOWLEDGE)) != 0)
|
||||
return ret;
|
||||
appclient->id = appmessage_get_id(appmessage);
|
||||
appclient->flag = 1;
|
||||
event_loop_while(appclient->event, &appclient->flag);
|
||||
/* FIXME obtain the answer (AICD_{,IN}OUT) and set the result */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* helpers */
|
||||
/* appclient_helper_message */
|
||||
static int _helper_message_acknowledgement(AppClient * appclient,
|
||||
AppMessage * message);
|
||||
static int _helper_message_call(AppClient * appclient, AppTransport * transport,
|
||||
AppMessage * message);
|
||||
|
||||
|
@ -221,6 +246,9 @@ static int _appclient_helper_message(void * data, AppTransport * transport,
|
|||
return -1;
|
||||
switch(appmessage_get_type(message))
|
||||
{
|
||||
case AMT_ACKNOWLEDGEMENT:
|
||||
return _helper_message_acknowledgement(appclient,
|
||||
message);
|
||||
case AMT_CALL:
|
||||
return _helper_message_call(appclient, transport,
|
||||
message);
|
||||
|
@ -229,6 +257,15 @@ static int _appclient_helper_message(void * data, AppTransport * transport,
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int _helper_message_acknowledgement(AppClient * appclient,
|
||||
AppMessage * message)
|
||||
{
|
||||
/* stop looping if we were expecting this acknowledgement */
|
||||
if(appmessage_get_id(message) == appclient->id)
|
||||
appclient->flag = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _helper_message_call(AppClient * appclient, AppTransport * transport,
|
||||
AppMessage * message)
|
||||
{
|
||||
|
|
|
@ -43,32 +43,19 @@
|
|||
/* AppInterface */
|
||||
/* private */
|
||||
/* types */
|
||||
/* XXX get rid of this */
|
||||
#define VT_COUNT (VT_LAST + 1)
|
||||
#define AICT_MASK 077
|
||||
|
||||
#ifdef DEBUG
|
||||
static const String * AICTString[VT_COUNT] =
|
||||
{
|
||||
"void", "bool", "int8", "uint8", "int16", "uint16", "int32", "uint32",
|
||||
"int64", "uint64", "float", "double", "Buffer", "String", "Array",
|
||||
"Compound"
|
||||
"Compound", "Pointer"
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef enum _AppInterfaceCallDirection
|
||||
{
|
||||
AICD_IN = 0100,
|
||||
AICD_OUT = 0200,
|
||||
AICD_IN_OUT = 0300,
|
||||
} AppInterfaceCallDirection;
|
||||
#define AICD_MASK 0700
|
||||
|
||||
typedef struct _AppInterfaceCallArg
|
||||
{
|
||||
VariableType type;
|
||||
AppInterfaceCallDirection direction;
|
||||
size_t size;
|
||||
MarshallCallDirection direction;
|
||||
} AppInterfaceCallArg;
|
||||
|
||||
typedef struct _AppInterfaceCall
|
||||
|
@ -95,11 +82,12 @@ struct _AppInterface
|
|||
int error;
|
||||
};
|
||||
|
||||
typedef struct _StringEnum
|
||||
typedef struct _StringTypeDirection
|
||||
{
|
||||
char const * string;
|
||||
int value;
|
||||
} StringEnum;
|
||||
VariableType type;
|
||||
MarshallCallDirection direction;
|
||||
} StringTypeDirection;
|
||||
|
||||
|
||||
/* constants */
|
||||
|
@ -108,57 +96,57 @@ typedef struct _StringEnum
|
|||
|
||||
|
||||
/* variables */
|
||||
static const StringEnum _string_type[] =
|
||||
static const StringTypeDirection _string_type_direction[] =
|
||||
{
|
||||
{ "VOID", VT_NULL | AICD_IN },
|
||||
{ "VOID", VT_NULL, MCD_IN },
|
||||
/* implicit input */
|
||||
{ "BOOL", VT_BOOL | AICD_IN },
|
||||
{ "INT8", VT_INT8 | AICD_IN },
|
||||
{ "UINT8", VT_UINT8 | AICD_IN },
|
||||
{ "INT16", VT_INT16 | AICD_IN },
|
||||
{ "UINT16", VT_UINT16 | AICD_IN },
|
||||
{ "INT32", VT_INT32 | AICD_IN },
|
||||
{ "UINT32", VT_UINT32 | AICD_IN },
|
||||
{ "INT64", VT_INT64 | AICD_IN },
|
||||
{ "UINT64", VT_UINT64 | AICD_IN },
|
||||
{ "STRING", VT_STRING | AICD_IN },
|
||||
{ "BUFFER", VT_BUFFER | AICD_IN },
|
||||
{ "FLOAT", VT_FLOAT | AICD_IN },
|
||||
{ "DOUBLE", VT_DOUBLE | AICD_IN },
|
||||
{ "BOOL", VT_BOOL, MCD_IN },
|
||||
{ "INT8", VT_INT8, MCD_IN },
|
||||
{ "UINT8", VT_UINT8, MCD_IN },
|
||||
{ "INT16", VT_INT16, MCD_IN },
|
||||
{ "UINT16", VT_UINT16, MCD_IN },
|
||||
{ "INT32", VT_INT32, MCD_IN },
|
||||
{ "UINT32", VT_UINT32, MCD_IN },
|
||||
{ "INT64", VT_INT64, MCD_IN },
|
||||
{ "UINT64", VT_UINT64, MCD_IN },
|
||||
{ "STRING", VT_STRING, MCD_IN },
|
||||
{ "BUFFER", VT_BUFFER, MCD_IN },
|
||||
{ "FLOAT", VT_FLOAT, MCD_IN },
|
||||
{ "DOUBLE", VT_DOUBLE, MCD_IN },
|
||||
/* input aliases */
|
||||
{ "BOOL_IN", VT_BOOL | AICD_IN },
|
||||
{ "INT8_IN", VT_INT8 | AICD_IN },
|
||||
{ "UINT8_IN", VT_UINT8 | AICD_IN },
|
||||
{ "INT16_IN", VT_INT16 | AICD_IN },
|
||||
{ "UINT16_IN", VT_UINT16 | AICD_IN },
|
||||
{ "INT32_IN", VT_INT32 | AICD_IN },
|
||||
{ "UINT32_IN", VT_UINT32 | AICD_IN },
|
||||
{ "INT64_IN", VT_INT64 | AICD_IN },
|
||||
{ "UINT64_IN", VT_UINT64 | AICD_IN },
|
||||
{ "STRING_IN", VT_STRING | AICD_IN },
|
||||
{ "BUFFER_IN", VT_BUFFER | AICD_IN },
|
||||
{ "FLOAT_IN", VT_FLOAT | AICD_IN },
|
||||
{ "DOUBLE_IN", VT_DOUBLE | AICD_IN },
|
||||
{ "BOOL_IN", VT_BOOL, MCD_IN },
|
||||
{ "INT8_IN", VT_INT8, MCD_IN },
|
||||
{ "UINT8_IN", VT_UINT8, MCD_IN },
|
||||
{ "INT16_IN", VT_INT16, MCD_IN },
|
||||
{ "UINT16_IN", VT_UINT16, MCD_IN },
|
||||
{ "INT32_IN", VT_INT32, MCD_IN },
|
||||
{ "UINT32_IN", VT_UINT32, MCD_IN },
|
||||
{ "INT64_IN", VT_INT64, MCD_IN },
|
||||
{ "UINT64_IN", VT_UINT64, MCD_IN },
|
||||
{ "STRING_IN", VT_STRING, MCD_IN },
|
||||
{ "BUFFER_IN", VT_BUFFER, MCD_IN },
|
||||
{ "FLOAT_IN", VT_FLOAT, MCD_IN },
|
||||
{ "DOUBLE_IN", VT_DOUBLE, MCD_IN },
|
||||
/* output only */
|
||||
{ "BOOL_OUT", VT_BOOL | AICD_OUT },
|
||||
{ "INT8_OUT", VT_INT8 | AICD_OUT },
|
||||
{ "UINT8_OUT", VT_UINT8 | AICD_OUT },
|
||||
{ "INT16_OUT", VT_INT16 | AICD_OUT },
|
||||
{ "UINT16_OUT", VT_UINT16 | AICD_OUT },
|
||||
{ "INT32_OUT", VT_INT32 | AICD_OUT },
|
||||
{ "UINT32_OUT", VT_UINT32 | AICD_OUT },
|
||||
{ "INT64_OUT", VT_INT64 | AICD_OUT },
|
||||
{ "UINT64_OUT", VT_UINT64 | AICD_OUT },
|
||||
{ "STRING_OUT", VT_STRING | AICD_OUT },
|
||||
{ "BUFFER_OUT", VT_BUFFER | AICD_OUT },
|
||||
{ "FLOAT_OUT", VT_FLOAT | AICD_OUT },
|
||||
{ "DOUBLE_OUT", VT_DOUBLE | AICD_OUT },
|
||||
{ NULL, 0 }
|
||||
{ "BOOL_OUT", VT_BOOL, MCD_OUT },
|
||||
{ "INT8_OUT", VT_INT8, MCD_OUT },
|
||||
{ "UINT8_OUT", VT_UINT8, MCD_OUT },
|
||||
{ "INT16_OUT", VT_INT16, MCD_OUT },
|
||||
{ "UINT16_OUT", VT_UINT16, MCD_OUT },
|
||||
{ "INT32_OUT", VT_INT32, MCD_OUT },
|
||||
{ "UINT32_OUT", VT_UINT32, MCD_OUT },
|
||||
{ "INT64_OUT", VT_INT64, MCD_OUT },
|
||||
{ "UINT64_OUT", VT_UINT64, MCD_OUT },
|
||||
{ "STRING_OUT", VT_STRING, MCD_OUT },
|
||||
{ "BUFFER_OUT", VT_BUFFER, MCD_OUT },
|
||||
{ "FLOAT_OUT", VT_FLOAT, MCD_OUT },
|
||||
{ "DOUBLE_OUT", VT_DOUBLE, MCD_OUT },
|
||||
};
|
||||
|
||||
|
||||
/* prototypes */
|
||||
static int _string_enum(String const * string, StringEnum const * se);
|
||||
static int _string_get_type_direction(String const * string,
|
||||
VariableType * type, AppMessageCallDirection * direction);
|
||||
|
||||
/* accessors */
|
||||
static AppInterfaceCall * _appinterface_get_call(AppInterface * appinterface,
|
||||
|
@ -166,8 +154,8 @@ static AppInterfaceCall * _appinterface_get_call(AppInterface * appinterface,
|
|||
|
||||
/* useful */
|
||||
static Variable ** _appinterface_argv_new(AppInterfaceCall * call,
|
||||
va_list ap);
|
||||
static void _appinterface_argv_free(Variable ** argv, size_t argc);
|
||||
va_list args);
|
||||
static void _appinterface_argv_delete(Variable ** argv, size_t argc);
|
||||
static int _appinterface_call(App * app, AppServerClient * asc,
|
||||
Variable * result, AppInterfaceCall * call,
|
||||
size_t argc, Variable ** argv);
|
||||
|
@ -176,17 +164,25 @@ static AppMessage * _appinterface_message(AppInterfaceCall * call,
|
|||
|
||||
|
||||
/* functions */
|
||||
/* string_enum */
|
||||
/* FIXME move to string.c */
|
||||
static int _string_enum(String const * string, StringEnum const * se)
|
||||
/* string_get_direction_type */
|
||||
static int _string_get_type_direction(String const * string,
|
||||
VariableType * type, AppMessageCallDirection * direction)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if(string == NULL)
|
||||
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;
|
||||
for(i = 0; i < sizeof(_string_type_direction)
|
||||
/ sizeof(*_string_type_direction); i++)
|
||||
if(string_compare(_string_type_direction[i].string, string)
|
||||
== 0)
|
||||
{
|
||||
if(type != NULL)
|
||||
*type = _string_type_direction[i].type;
|
||||
if(direction != NULL)
|
||||
*direction = _string_type_direction[i].direction;
|
||||
return 0;
|
||||
}
|
||||
return -error_set_code(1, "%s\"%s\"", "Unknown enumerated value for ",
|
||||
string);
|
||||
}
|
||||
|
@ -234,7 +230,8 @@ static AppInterfaceCall * _new_interface_append_call(AppInterface * ai,
|
|||
VariableType type, char const * method);
|
||||
static AppInterfaceCall * _new_interface_append_callback(AppInterface * ai,
|
||||
VariableType type, char const * method);
|
||||
static int _new_interface_append_arg(AppInterfaceCall * call, char const * arg);
|
||||
static int _new_interface_append_arg(AppInterfaceCall * call,
|
||||
String const * arg);
|
||||
AppInterface * _new_interface_do(AppTransportMode mode, String const * app,
|
||||
String const * pathname);
|
||||
static int _new_interface_do_appstatus(AppInterface * appinterface);
|
||||
|
@ -274,8 +271,7 @@ static AppInterfaceCall * _new_interface_append_call(AppInterface * ai,
|
|||
p = &ai->calls[ai->calls_cnt];
|
||||
if((p->name = string_new(method)) == NULL)
|
||||
return NULL;
|
||||
p->type.type = type & AICT_MASK;
|
||||
p->type.direction = type & AICD_MASK;
|
||||
p->type.type = type;
|
||||
p->args = NULL;
|
||||
p->args_cnt = 0;
|
||||
ai->calls_cnt++;
|
||||
|
@ -297,19 +293,20 @@ static AppInterfaceCall * _new_interface_append_callback(AppInterface * ai,
|
|||
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->type.type = type;
|
||||
p->args = NULL;
|
||||
p->args_cnt = 0;
|
||||
ai->callbacks_cnt++;
|
||||
return p;
|
||||
}
|
||||
|
||||
static int _new_interface_append_arg(AppInterfaceCall * call, char const * arg)
|
||||
static int _new_interface_append_arg(AppInterfaceCall * call,
|
||||
String const * arg)
|
||||
{
|
||||
char buf[16];
|
||||
char * p;
|
||||
int type;
|
||||
VariableType type;
|
||||
AppMessageCallDirection direction;
|
||||
AppInterfaceCallArg * r;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -318,14 +315,14 @@ static int _new_interface_append_arg(AppInterfaceCall * call, char const * arg)
|
|||
snprintf(buf, sizeof(buf), "%s", arg);
|
||||
if((p = strchr(buf, ',')) != NULL)
|
||||
*p = '\0';
|
||||
if((type = _string_enum(buf, _string_type)) < 0)
|
||||
if(_string_get_type_direction(buf, &type, &direction) != 0)
|
||||
return -1;
|
||||
if((r = realloc(call->args, sizeof(*r) * (call->args_cnt + 1))) == NULL)
|
||||
return error_set_code(-errno, "%s", strerror(errno));
|
||||
call->args = r;
|
||||
r = &call->args[call->args_cnt++];
|
||||
r->type = type & AICT_MASK;
|
||||
r->direction = type & AICD_MASK;
|
||||
r->type = type;
|
||||
r->direction = direction;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: type %s, direction: %d\n", AICTString[r->type],
|
||||
r->direction);
|
||||
|
@ -389,7 +386,7 @@ static int _new_interface_foreach_callbacks(char const * key, Hash * value,
|
|||
String const * prefix = APPINTERFACE_CALLBACK_PREFIX;
|
||||
unsigned int i;
|
||||
char buf[8];
|
||||
int type = VT_NULL;
|
||||
VariableType type = VT_NULL;
|
||||
char const * p;
|
||||
AppInterfaceCall * callback;
|
||||
|
||||
|
@ -397,7 +394,7 @@ static int _new_interface_foreach_callbacks(char const * key, Hash * value,
|
|||
return 0;
|
||||
key += string_get_length(prefix);
|
||||
if((p = hash_get(value, "ret")) != NULL
|
||||
&& (type = _string_enum(p, _string_type)) < 0)
|
||||
&& _string_get_type_direction(p, &type, NULL) != 0)
|
||||
{
|
||||
appinterface->error = error_set_code(1, "%s: %s", p,
|
||||
"Invalid return type for callback");
|
||||
|
@ -430,7 +427,7 @@ static int _new_interface_foreach_calls(char const * key, Hash * value,
|
|||
String const * prefix = APPINTERFACE_CALL_PREFIX;
|
||||
unsigned int i;
|
||||
char buf[8];
|
||||
int type = VT_NULL;
|
||||
VariableType type = VT_NULL;
|
||||
char const * p;
|
||||
AppInterfaceCall * call;
|
||||
|
||||
|
@ -438,7 +435,7 @@ static int _new_interface_foreach_calls(char const * key, Hash * value,
|
|||
return 0;
|
||||
key += string_get_length(prefix);
|
||||
if((p = hash_get(value, "ret")) != NULL
|
||||
&& (type = _string_enum(p, _string_type)) < 0)
|
||||
&& _string_get_type_direction(p, &type, NULL) != 0)
|
||||
{
|
||||
appinterface->error = error_set_code(1, "%s: %s", p,
|
||||
"Invalid return type for call");
|
||||
|
@ -669,8 +666,8 @@ int appinterface_callv(AppInterface * appinterface, App * app,
|
|||
return -1;
|
||||
}
|
||||
if(ret == 0)
|
||||
ret = _appinterface_call(app, asc, r, call,
|
||||
call->args_cnt, argv);
|
||||
ret = _appinterface_call(app, asc, r, call, call->args_cnt,
|
||||
argv);
|
||||
if(r != NULL)
|
||||
{
|
||||
if(ret == 0 && result != NULL)
|
||||
|
@ -679,7 +676,7 @@ int appinterface_callv(AppInterface * appinterface, App * app,
|
|||
variable_delete(r);
|
||||
}
|
||||
/* FIXME also implement AICD_{,IN}OUT */
|
||||
_appinterface_argv_free(argv, call->args_cnt);
|
||||
_appinterface_argv_delete(argv, call->args_cnt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -710,7 +707,7 @@ AppMessage * appinterface_messagev(AppInterface * appinterface,
|
|||
if((argv = _appinterface_argv_new(call, ap)) == NULL)
|
||||
return NULL;
|
||||
message = _appinterface_message(call, call->args_cnt, argv);
|
||||
_appinterface_argv_free(argv, call->args_cnt);
|
||||
_appinterface_argv_delete(argv, call->args_cnt);
|
||||
return message;
|
||||
}
|
||||
|
||||
|
@ -740,13 +737,14 @@ AppMessage * appinterface_message_variablev(AppInterface * appinterface,
|
|||
return NULL;
|
||||
if(call->args_cnt == 0)
|
||||
argv = NULL;
|
||||
else if((argv = malloc(sizeof(*argv) * call->args_cnt)) == NULL)
|
||||
else if((argv = object_new(sizeof(*argv) * call->args_cnt)) == NULL)
|
||||
/* XXX report error */
|
||||
return NULL;
|
||||
else
|
||||
for(i = 0; i < call->args_cnt; i++)
|
||||
argv[i] = va_arg(ap, Variable *);
|
||||
message = _appinterface_message(call, call->args_cnt, argv);
|
||||
free(argv);
|
||||
object_delete(argv);
|
||||
return message;
|
||||
}
|
||||
|
||||
|
@ -785,14 +783,14 @@ static Variable ** _appinterface_argv_new(AppInterfaceCall * call, va_list ap)
|
|||
{
|
||||
switch(call->args[i].direction)
|
||||
{
|
||||
case AICD_IN:
|
||||
case AMCD_IN:
|
||||
argv[i] = _argv_new_in(call->args[i].type, ap);
|
||||
break;
|
||||
case AICD_IN_OUT:
|
||||
case AMCD_IN_OUT:
|
||||
argv[i] = _argv_new_in_out(call->args[i].type,
|
||||
ap);
|
||||
break;
|
||||
case AICD_OUT:
|
||||
case AMCD_OUT:
|
||||
argv[i] = _argv_new_out(call->args[i].type,
|
||||
ap);
|
||||
break;
|
||||
|
@ -803,7 +801,7 @@ static Variable ** _appinterface_argv_new(AppInterfaceCall * call, va_list ap)
|
|||
}
|
||||
if(argv[i] == NULL)
|
||||
{
|
||||
_appinterface_argv_free(argv, i);
|
||||
_appinterface_argv_delete(argv, i);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -832,6 +830,7 @@ static Variable * _argv_new_in_out(VariableType type, va_list ap)
|
|||
Buffer * buf;
|
||||
float * fp;
|
||||
double * dp;
|
||||
void ** pp;
|
||||
} u;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -880,29 +879,16 @@ static Variable * _argv_new_in_out(VariableType type, va_list ap)
|
|||
case VT_BUFFER:
|
||||
u.buf = va_arg(ap, Buffer *);
|
||||
return variable_new(type, u.buf);
|
||||
case VT_POINTER:
|
||||
u.pp = va_arg(ap, void **);
|
||||
return variable_new(type, u.pp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Variable * _argv_new_out(VariableType type, va_list ap)
|
||||
{
|
||||
union
|
||||
{
|
||||
bool * bp;
|
||||
int8_t * i8p;
|
||||
uint8_t * u8p;
|
||||
int16_t * i16p;
|
||||
uint16_t * u16p;
|
||||
int32_t * i32p;
|
||||
uint32_t * u32p;
|
||||
int64_t * i64p;
|
||||
uint64_t * u64p;
|
||||
char ** strp;
|
||||
Buffer * buf;
|
||||
float * fp;
|
||||
double * dp;
|
||||
} u;
|
||||
void * p;
|
||||
Variable * ret;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, type);
|
||||
|
@ -910,70 +896,36 @@ static Variable * _argv_new_out(VariableType type, va_list ap)
|
|||
switch(type)
|
||||
{
|
||||
case VT_BOOL:
|
||||
u.bp = va_arg(ap, bool *);
|
||||
p = u.bp;
|
||||
break;
|
||||
return variable_new(type, false);
|
||||
case VT_INT8:
|
||||
u.i8p = va_arg(ap, int8_t *);
|
||||
p = u.i8p;
|
||||
break;
|
||||
case VT_UINT8:
|
||||
u.u8p = va_arg(ap, uint8_t *);
|
||||
p = u.u8p;
|
||||
break;
|
||||
case VT_INT16:
|
||||
u.i16p = va_arg(ap, int16_t *);
|
||||
p = u.i16p;
|
||||
break;
|
||||
case VT_UINT16:
|
||||
u.u16p = va_arg(ap, uint16_t *);
|
||||
p = u.u16p;
|
||||
break;
|
||||
case VT_INT32:
|
||||
u.i32p = va_arg(ap, int32_t *);
|
||||
p = u.i32p;
|
||||
break;
|
||||
case VT_UINT32:
|
||||
u.u32p = va_arg(ap, uint32_t *);
|
||||
p = u.u32p;
|
||||
break;
|
||||
return variable_new(type, 0);
|
||||
case VT_INT64:
|
||||
u.i64p = va_arg(ap, int64_t *);
|
||||
p = u.i64p;
|
||||
break;
|
||||
case VT_UINT64:
|
||||
u.u64p = va_arg(ap, uint64_t *);
|
||||
p = u.u64p;
|
||||
break;
|
||||
return variable_new(type, (uint64_t)0);
|
||||
case VT_STRING:
|
||||
u.strp = va_arg(ap, char **);
|
||||
p = u.strp;
|
||||
break;
|
||||
return variable_new(type, "");
|
||||
case VT_BUFFER:
|
||||
u.buf = va_arg(ap, Buffer *);
|
||||
p = u.buf;
|
||||
break;
|
||||
case VT_FLOAT:
|
||||
u.fp = va_arg(ap, float *);
|
||||
p = u.fp;
|
||||
break;
|
||||
case VT_DOUBLE:
|
||||
u.dp = va_arg(ap, double *);
|
||||
p = u.dp;
|
||||
break;
|
||||
case VT_NULL:
|
||||
default:
|
||||
p = NULL;
|
||||
break;
|
||||
}
|
||||
if(p == NULL)
|
||||
return NULL;
|
||||
return variable_new(type, NULL);
|
||||
case VT_FLOAT:
|
||||
case VT_DOUBLE:
|
||||
return variable_new(type, 0.0);
|
||||
case VT_POINTER:
|
||||
return variable_new(type, NULL);
|
||||
case VT_NULL:
|
||||
return variable_new(type);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* appinterface_argv_free */
|
||||
static void _appinterface_argv_free(Variable ** argv, size_t argc)
|
||||
/* appinterface_argv_delete */
|
||||
static void _appinterface_argv_delete(Variable ** argv, size_t argc)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
|
|
|
@ -47,8 +47,8 @@ AppStatus * appinterface_get_status(AppInterface * appinterface);
|
|||
|
||||
/* useful */
|
||||
int appinterface_callv(AppInterface * appinterface, App * app,
|
||||
AppServerClient * asc, void ** result,
|
||||
char const * method, va_list args);
|
||||
AppServerClient * asc, void ** result, char const * method,
|
||||
va_list args);
|
||||
int appinterface_call_variablev(AppInterface * appinterface, App * app,
|
||||
AppServerClient * asc, Variable * result, char const * method,
|
||||
size_t argc, Variable ** argv);
|
||||
|
|
173
src/appmessage.c
173
src/appmessage.c
|
@ -213,13 +213,15 @@ static AppMessage * _new_deserialize_call(AppMessage * message,
|
|||
char const * data, const size_t size, size_t pos);
|
||||
static AppMessage * _new_deserialize_id(AppMessage * message, char const * data,
|
||||
const size_t size, size_t * pos);
|
||||
static AppMessage * _new_deserialize_status_get(AppMessage * message,
|
||||
char const * data, const size_t size, size_t pos);
|
||||
|
||||
AppMessage * appmessage_new_deserialize(Buffer * buffer)
|
||||
{
|
||||
AppMessage * message;
|
||||
char const * data = buffer_get_data(buffer);
|
||||
size_t size = buffer_get_size(buffer);
|
||||
size_t pos = 0;
|
||||
size_t pos;
|
||||
size_t s;
|
||||
Variable * v;
|
||||
uint8_t u8;
|
||||
|
@ -230,15 +232,12 @@ AppMessage * appmessage_new_deserialize(Buffer * buffer)
|
|||
if((message = object_new(sizeof(*message))) == NULL)
|
||||
return NULL;
|
||||
s = size;
|
||||
if((v = variable_new_deserialize_type(VT_UINT8, &s, &data[pos]))
|
||||
== NULL)
|
||||
if((v = variable_new_deserialize_type(VT_UINT8, &s, &data[0])) == NULL)
|
||||
{
|
||||
object_delete(message);
|
||||
return NULL;
|
||||
}
|
||||
pos += s;
|
||||
size -= s;
|
||||
/* XXX may fail */
|
||||
pos = s;
|
||||
variable_get_as(v, VT_UINT8, &u8);
|
||||
variable_delete(v);
|
||||
switch((message->type = u8))
|
||||
|
@ -271,7 +270,9 @@ static AppMessage * _new_deserialize_call(AppMessage * message,
|
|||
size_t s;
|
||||
Variable * v;
|
||||
size_t i;
|
||||
AppMessageCallArgument * p;
|
||||
uint8_t direction;
|
||||
uint8_t type;
|
||||
AppMessageCallArgument * arg;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||
|
@ -295,36 +296,71 @@ static AppMessage * _new_deserialize_call(AppMessage * message,
|
|||
variable_get_as(v, VT_STRING, &message->t.call.method);
|
||||
variable_delete(v);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__,
|
||||
fprintf(stderr, "DEBUG: %s() method=\"%s\"\n", __func__,
|
||||
message->t.call.method);
|
||||
#endif
|
||||
/* deserialize the arguments */
|
||||
for(i = 0; pos < size; i++)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() %lu\n", __func__, i);
|
||||
fprintf(stderr, "DEBUG: %s() arg=%zu\n", __func__, i);
|
||||
#endif
|
||||
if((p = realloc(message->t.call.args, sizeof(*p) * (i + 1)))
|
||||
if((arg = realloc(message->t.call.args, sizeof(*arg) * (i + 1)))
|
||||
== NULL)
|
||||
{
|
||||
error_set_code(-errno, "%s", strerror(errno));
|
||||
appmessage_delete(message);
|
||||
return NULL;
|
||||
}
|
||||
message->t.call.args = p;
|
||||
message->t.call.args = arg;
|
||||
arg = &message->t.call.args[i];
|
||||
s = size - pos;
|
||||
if((v = variable_new_deserialize(&s, &data[pos])) == NULL)
|
||||
/* obtain the direction */
|
||||
if((v = variable_new_deserialize_type(VT_UINT8, &s, &data[pos]))
|
||||
== NULL)
|
||||
{
|
||||
appmessage_delete(message);
|
||||
return NULL;
|
||||
}
|
||||
variable_get_as(v, VT_UINT8, &direction);
|
||||
variable_delete(v);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() arg=%zu direction=%u\n", __func__,
|
||||
i, direction);
|
||||
#endif
|
||||
pos += s;
|
||||
s = size - pos;
|
||||
if(direction == AMCD_OUT)
|
||||
{
|
||||
/* obtain the type */
|
||||
if((v = variable_new_deserialize_type(VT_UINT8, &s,
|
||||
&data[pos])) == NULL)
|
||||
{
|
||||
appmessage_delete(message);
|
||||
return NULL;
|
||||
}
|
||||
variable_get_as(v, VT_UINT8, &type);
|
||||
variable_delete(v);
|
||||
pos += s;
|
||||
s = size - pos;
|
||||
arg->arg = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((v = variable_new_deserialize(&s, &data[pos]))
|
||||
== NULL)
|
||||
{
|
||||
appmessage_delete(message);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() %lu (%u)\n", __func__, i,
|
||||
variable_get_type(v));
|
||||
fprintf(stderr, "DEBUG: %s() arg=%zu type=%u\n",
|
||||
__func__, i, variable_get_type(v));
|
||||
#endif
|
||||
pos += s;
|
||||
message->t.call.args[i].direction = AMCD_IN; /* XXX */
|
||||
message->t.call.args[i].arg = v;
|
||||
arg->arg = v;
|
||||
}
|
||||
arg->direction = direction;
|
||||
message->t.call.args_cnt = i + 1;
|
||||
}
|
||||
return message;
|
||||
|
@ -380,6 +416,7 @@ static void _delete_call(AppMessage * message)
|
|||
size_t i;
|
||||
|
||||
for(i = 0; i < message->t.call.args_cnt; i++)
|
||||
if(message->t.call.args[i].arg != NULL)
|
||||
variable_delete(message->t.call.args[i].arg);
|
||||
free(message->t.call.args);
|
||||
string_delete(message->t.call.method);
|
||||
|
@ -423,8 +460,16 @@ static int _serialize_acknowledgement(AppMessage * message, Buffer * buffer,
|
|||
Buffer * b);
|
||||
static int _serialize_append(Buffer * buffer, Buffer * b);
|
||||
static int _serialize_call(AppMessage * message, Buffer * buffer, Buffer * b);
|
||||
static int _serialize_id(AppMessage * message, Buffer * buffer, Buffer * b);
|
||||
static int _serialize_type(AppMessage * message, Buffer * buffer, Buffer * b);
|
||||
static int _serialize_call_arg_direction(Buffer * buffer, Buffer * b,
|
||||
AppMessageCallArgument * arg);
|
||||
static int _serialize_call_arg_type(Buffer * buffer, Buffer * b,
|
||||
AppMessageCallArgument * arg);
|
||||
static int _serialize_call_method(Buffer * buffer, Buffer * b,
|
||||
String const * method);
|
||||
static int _serialize_message_id(AppMessage * message, Buffer * buffer,
|
||||
Buffer * b);
|
||||
static int _serialize_message_type(AppMessage * message, Buffer * buffer,
|
||||
Buffer * b);
|
||||
|
||||
int appmessage_serialize(AppMessage * message, Buffer * buffer)
|
||||
{
|
||||
|
@ -434,7 +479,7 @@ int appmessage_serialize(AppMessage * message, Buffer * buffer)
|
|||
return -1;
|
||||
/* reset the output buffer */
|
||||
buffer_set_size(buffer, 0);
|
||||
if(_serialize_type(message, buffer, b) != 0)
|
||||
if(_serialize_message_type(message, buffer, b) != 0)
|
||||
return -1;
|
||||
switch(message->type)
|
||||
{
|
||||
|
@ -452,7 +497,7 @@ int appmessage_serialize(AppMessage * message, Buffer * buffer)
|
|||
static int _serialize_acknowledgement(AppMessage * message, Buffer * buffer,
|
||||
Buffer * b)
|
||||
{
|
||||
return _serialize_id(message, buffer, b);
|
||||
return _serialize_message_id(message, buffer, b);
|
||||
}
|
||||
|
||||
static int _serialize_append(Buffer * buffer, Buffer * b)
|
||||
|
@ -463,24 +508,28 @@ static int _serialize_append(Buffer * buffer, Buffer * b)
|
|||
|
||||
static int _serialize_call(AppMessage * message, Buffer * buffer, Buffer * b)
|
||||
{
|
||||
int ret;
|
||||
Variable * v;
|
||||
size_t i;
|
||||
AppMessageCallArgument * arg;
|
||||
|
||||
if(_serialize_id(message, buffer, b) != 0)
|
||||
if(_serialize_message_id(message, buffer, b) != 0)
|
||||
return -1;
|
||||
if((v = variable_new(VT_STRING, message->t.call.method)) == NULL)
|
||||
if(_serialize_call_method(buffer, b, message->t.call.method) != 0)
|
||||
return -1;
|
||||
ret = (variable_serialize(v, b, 0) == 0
|
||||
&& _serialize_append(buffer, b) == 0) ? 0 : -1;
|
||||
variable_delete(v);
|
||||
if(ret != 0)
|
||||
return ret;
|
||||
for(i = 0; i < message->t.call.args_cnt; i++)
|
||||
{
|
||||
if(message->t.call.args[i].direction == AMCD_OUT)
|
||||
continue;
|
||||
if(variable_serialize(message->t.call.args[i].arg, b, 1) != 0
|
||||
arg = &message->t.call.args[i];
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() arg=%zu direction=%u\n", __func__,
|
||||
i, arg->direction);
|
||||
#endif
|
||||
if(_serialize_call_arg_direction(buffer, b, arg) != 0)
|
||||
break;
|
||||
if(arg->direction == AMCD_OUT)
|
||||
{
|
||||
if(_serialize_call_arg_type(buffer, b, arg) != 0)
|
||||
break;
|
||||
}
|
||||
else if(variable_serialize(arg->arg, b, true) != 0
|
||||
|| _serialize_append(buffer, b) != 0)
|
||||
break;
|
||||
}
|
||||
|
@ -488,12 +537,63 @@ static int _serialize_call(AppMessage * message, Buffer * buffer, Buffer * b)
|
|||
return (i == message->t.call.args_cnt) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int _serialize_id(AppMessage * message, Buffer * buffer, Buffer * b)
|
||||
static int _serialize_call_arg_direction(Buffer * buffer, Buffer * b,
|
||||
AppMessageCallArgument * arg)
|
||||
{
|
||||
int ret = 0;
|
||||
Variable * v;
|
||||
|
||||
if((v = variable_new(VT_UINT8, arg->direction)) == NULL)
|
||||
return -1;
|
||||
if(variable_serialize(v, b, false) != 0
|
||||
|| _serialize_append(buffer, b) != 0)
|
||||
ret = -1;
|
||||
variable_delete(v);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _serialize_call_arg_type(Buffer * buffer, Buffer * b,
|
||||
AppMessageCallArgument * arg)
|
||||
{
|
||||
int ret = 0;
|
||||
VariableType type;
|
||||
Variable * v;
|
||||
|
||||
type = variable_get_type(arg->arg);
|
||||
if((v = variable_new(VT_UINT8, type)) == NULL)
|
||||
return -1;
|
||||
if(variable_serialize(v, b, false) != 0
|
||||
|| _serialize_append(buffer, b) != 0)
|
||||
ret = -1;
|
||||
variable_delete(v);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _serialize_call_method(Buffer * buffer, Buffer * b,
|
||||
String const * method)
|
||||
{
|
||||
int ret = 0;
|
||||
Variable * v;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, method);
|
||||
#endif
|
||||
if((v = variable_new(VT_STRING, method)) == NULL)
|
||||
return -1;
|
||||
if(variable_serialize(v, b, 0) != 0
|
||||
|| _serialize_append(buffer, b) != 0)
|
||||
ret = -1;
|
||||
variable_delete(v);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _serialize_message_id(AppMessage * message, Buffer * buffer,
|
||||
Buffer * b)
|
||||
{
|
||||
int ret;
|
||||
Variable * v;
|
||||
|
||||
if((v = variable_new(VT_UINT32, &message->id)) == NULL)
|
||||
if((v = variable_new(VT_UINT32, message->id)) == NULL)
|
||||
return -1;
|
||||
ret = (variable_serialize(v, b, 0) == 0
|
||||
&& _serialize_append(buffer, b) == 0) ? 0 : -1;
|
||||
|
@ -501,12 +601,13 @@ static int _serialize_id(AppMessage * message, Buffer * buffer, Buffer * b)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int _serialize_type(AppMessage * message, Buffer * buffer, Buffer * b)
|
||||
static int _serialize_message_type(AppMessage * message, Buffer * buffer,
|
||||
Buffer * b)
|
||||
{
|
||||
int ret;
|
||||
Variable * v;
|
||||
|
||||
if((v = variable_new(VT_UINT8, &message->type)) == NULL)
|
||||
if((v = variable_new(VT_UINT8, message->type)) == NULL)
|
||||
return -1;
|
||||
ret = (variable_serialize(v, b, 0) == 0
|
||||
&& _serialize_append(buffer, b) == 0) ? 0 : -1;
|
||||
|
|
|
@ -183,9 +183,8 @@ static int _helper_message_call(AppServer * appserver, AppTransport * transport,
|
|||
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);
|
||||
client, result, method, 0, NULL);
|
||||
if(result != NULL)
|
||||
variable_delete(result);
|
||||
return ret;
|
||||
|
|
|
@ -79,6 +79,8 @@ static void _apptransport_helper_client_delete(AppTransport * transport,
|
|||
|
||||
static int _apptransport_helper_client_receive(AppTransport * transport,
|
||||
AppTransportClient * client, AppMessage * message);
|
||||
static int _apptransport_helper_receive(AppTransport * transport,
|
||||
AppMessage * message);
|
||||
|
||||
|
||||
/* protected */
|
||||
|
@ -198,8 +200,8 @@ AppTransport * apptransport_new_plugin(AppTransportMode mode,
|
|||
AppTransport * apptransport;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s(%u, \"%s\", \"%s\", %p)\n", __func__, mode,
|
||||
plugin, name, (void *)event);
|
||||
fprintf(stderr, "DEBUG: %s(%u, %p, \"%s\", %p)\n", __func__, mode,
|
||||
(void *)plugin, name, (void *)event);
|
||||
#endif
|
||||
/* check the arguments */
|
||||
if(plugin == NULL)
|
||||
|
@ -225,9 +227,8 @@ AppTransport * apptransport_new_plugin(AppTransportMode mode,
|
|||
/* load the transport plug-in */
|
||||
apptransport->plugin = plugin;
|
||||
if(apptransport->name == NULL
|
||||
|| (apptransport->definition = plugin_lookup(
|
||||
apptransport->plugin, "transport"))
|
||||
== NULL
|
||||
|| (apptransport->definition = plugin_lookup(plugin,
|
||||
"transport")) == NULL
|
||||
|| apptransport->definition->init == NULL
|
||||
|| apptransport->definition->destroy == NULL
|
||||
|| (apptransport->tplugin
|
||||
|
@ -253,6 +254,8 @@ static void _new_plugin_helper(AppTransport * apptransport,
|
|||
= _apptransport_helper_client_delete;
|
||||
apptransport->thelper.client_receive
|
||||
= _apptransport_helper_client_receive;
|
||||
apptransport->thelper.receive
|
||||
= _apptransport_helper_receive;
|
||||
}
|
||||
|
||||
|
||||
|
@ -331,11 +334,11 @@ String * apptransport_lookup(char const * app)
|
|||
|
||||
/* apptransport_client_send */
|
||||
int apptransport_client_send(AppTransport * transport, AppMessage * message,
|
||||
int acknowledge)
|
||||
AppTransportFlags flags)
|
||||
{
|
||||
if(transport->mode == ATM_CLIENT
|
||||
&& appmessage_get_type(message) == AMT_CALL
|
||||
&& acknowledge != 0)
|
||||
&& (flags & ATF_ACKNOWLEDGE) != 0)
|
||||
/* FIXME will wrap around after 2^32-1 acknowledgements */
|
||||
appmessage_set_id(message, ++transport->id);
|
||||
return transport->definition->client_send(transport->tplugin, message);
|
||||
|
@ -461,3 +464,16 @@ static int _apptransport_helper_client_receive(AppTransport * transport,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* apptransport_helper_receive */
|
||||
static int _apptransport_helper_receive(AppTransport * transport,
|
||||
AppMessage * message)
|
||||
{
|
||||
if(transport->mode != ATM_CLIENT)
|
||||
/* XXX improve the error message */
|
||||
return -error_set_code(1, "Not a client");
|
||||
transport->helper.message(transport->helper.data, transport, NULL,
|
||||
message);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* $Id$ */
|
||||
/* Copyright (c) 2012-2015 Pierre Pronchery <khorben@defora.org> */
|
||||
/* Copyright (c) 2012-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
|
||||
|
@ -26,6 +26,10 @@
|
|||
/* AppTransport */
|
||||
/* protected */
|
||||
/* types */
|
||||
typedef unsigned int AppTransportFlags;
|
||||
# define ATF_ACKNOWLEDGE 0x1
|
||||
# define ATF_SYNC 0x2
|
||||
|
||||
typedef struct _AppTransportHelper
|
||||
{
|
||||
void * data;
|
||||
|
@ -57,7 +61,7 @@ String * apptransport_lookup(char const * app);
|
|||
|
||||
/* ATM_CLIENT */
|
||||
int apptransport_client_send(AppTransport * transport, AppMessage * message,
|
||||
int acknowledge);
|
||||
AppTransportFlags flags);
|
||||
|
||||
/* ATM_SERVER */
|
||||
int apptransport_server_register(AppTransport * transport, char const * app,
|
||||
|
|
|
@ -118,6 +118,7 @@ static int _tcp_error(char const * message);
|
|||
|
||||
/* servers */
|
||||
static int _tcp_server_add_client(TCP * tcp, TCPSocket * client);
|
||||
static int _tcp_server_remove_client(TCP * tcp, TCPSocket * client);
|
||||
|
||||
/* sockets */
|
||||
static int _tcp_socket_init(TCPSocket * tcpsocket, int domain, int flags,
|
||||
|
@ -378,7 +379,8 @@ static int _tcp_client_send(TCP * tcp, AppMessage * message)
|
|||
if((buffer = buffer_new(0, NULL)) == NULL)
|
||||
return -1;
|
||||
if((ret = appmessage_serialize(message, buffer)) == 0
|
||||
&& (ret = _tcp_socket_queue(&tcp->u.client, buffer)) == 0)
|
||||
&& (ret = _tcp_socket_queue(&tcp->u.client,
|
||||
buffer)) == 0)
|
||||
event_loop(tcp->helper->event);
|
||||
buffer_delete(buffer);
|
||||
return ret;
|
||||
|
@ -462,6 +464,25 @@ static int _tcp_server_add_client(TCP * tcp, TCPSocket * client)
|
|||
}
|
||||
|
||||
|
||||
/* tcp_server_remove_client */
|
||||
static int _tcp_server_remove_client(TCP * tcp, TCPSocket * client)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < tcp->u.server.clients_cnt; i++)
|
||||
if(tcp->u.server.clients[i] == client)
|
||||
break;
|
||||
if(i == tcp->u.server.clients_cnt)
|
||||
return -1;
|
||||
tcp->u.server.clients[i] = NULL;
|
||||
_tcp_socket_delete(client);
|
||||
for(i = tcp->u.server.clients_cnt;
|
||||
i > 0 && tcp->u.server.clients[i - 1] == NULL;)
|
||||
tcp->u.server.clients_cnt = --i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* sockets */
|
||||
/* tcp_socket_init */
|
||||
static int _tcp_socket_init(TCPSocket * tcpsocket, int domain, int flags,
|
||||
|
@ -709,7 +730,8 @@ static int _tcp_callback_connect(int fd, TCP * tcp)
|
|||
|
||||
|
||||
/* tcp_socket_callback_read */
|
||||
static AppMessage * _socket_callback_message(TCPSocket * tcpsocket);
|
||||
static int _socket_callback_message(TCPSocket * tcpsocket,
|
||||
AppMessage ** message);
|
||||
static void _socket_callback_read_client(TCPSocket * tcpsocket,
|
||||
AppMessage * message);
|
||||
static void _socket_callback_read_server(TCPSocket * tcpsocket,
|
||||
|
@ -719,6 +741,7 @@ static int _socket_callback_recv(TCPSocket * tcpsocket);
|
|||
static int _tcp_socket_callback_read(int fd, TCPSocket * tcpsocket)
|
||||
{
|
||||
AppMessage * message;
|
||||
int res;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s(%d)\n", __func__, fd);
|
||||
|
@ -728,7 +751,7 @@ static int _tcp_socket_callback_read(int fd, TCPSocket * tcpsocket)
|
|||
return -1;
|
||||
if(_socket_callback_recv(tcpsocket) != 0)
|
||||
return -1;
|
||||
while((message = _socket_callback_message(tcpsocket)) != NULL)
|
||||
while((res = _socket_callback_message(tcpsocket, &message)) > 0)
|
||||
{
|
||||
switch(tcpsocket->tcp->mode)
|
||||
{
|
||||
|
@ -743,32 +766,54 @@ static int _tcp_socket_callback_read(int fd, TCPSocket * tcpsocket)
|
|||
}
|
||||
appmessage_delete(message);
|
||||
}
|
||||
if(res < 0)
|
||||
{
|
||||
_tcp_server_remove_client(tcpsocket->tcp, tcpsocket);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static AppMessage * _socket_callback_message(TCPSocket * tcpsocket)
|
||||
static int _socket_callback_message(TCPSocket * tcpsocket,
|
||||
AppMessage ** message)
|
||||
{
|
||||
AppMessage * message = NULL;
|
||||
int ret = 0;
|
||||
size_t size;
|
||||
Variable * variable;
|
||||
Buffer * buffer;
|
||||
uint32_t u32;
|
||||
|
||||
size = tcpsocket->bufin_cnt;
|
||||
/* XXX assumes the serialized size is sizeof(u32) */
|
||||
if((size = tcpsocket->bufin_cnt) < sizeof(u32))
|
||||
return 0;
|
||||
/* obtain the message size */
|
||||
if((variable = variable_new_deserialize_type(VT_UINT32, &size,
|
||||
tcpsocket->bufin)) == NULL)
|
||||
return -1;
|
||||
variable_get_as(variable, VT_UINT32, &u32);
|
||||
variable_delete(variable);
|
||||
/* verify the message size */
|
||||
if(u32 > APPMESSAGE_MAX_SIZE)
|
||||
return -error_set_code(E2BIG, "Message too big (%#x)", u32);
|
||||
/* XXX assumes the serialized size is u32 */
|
||||
if(u32 > tcpsocket->bufin_cnt)
|
||||
return 0;
|
||||
/* deserialize the data as a buffer (containing a message) */
|
||||
size = tcpsocket->bufin_cnt;
|
||||
if((variable = variable_new_deserialize_type(VT_BUFFER, &size,
|
||||
tcpsocket->bufin)) == NULL)
|
||||
/* XXX assumes not enough data was available */
|
||||
return NULL;
|
||||
return -1;
|
||||
tcpsocket->bufin_cnt -= size;
|
||||
memmove(tcpsocket->bufin, &tcpsocket->bufin[size],
|
||||
tcpsocket->bufin_cnt);
|
||||
if((variable_get_as(variable, VT_BUFFER, &buffer)) == 0)
|
||||
{
|
||||
message = appmessage_new_deserialize(buffer);
|
||||
*message = appmessage_new_deserialize(buffer);
|
||||
buffer_delete(buffer);
|
||||
ret = (*message != NULL) ? 1 : -1;
|
||||
}
|
||||
variable_delete(variable);
|
||||
return message;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _socket_callback_read_client(TCPSocket * tcpsocket,
|
||||
|
|
Loading…
Reference in New Issue
Block a user