Attempt to really re-implement the AppClient
This is still very messy... :(
This commit is contained in:
parent
607c9b00f3
commit
688d40c1ad
|
@ -18,6 +18,7 @@
|
|||
#ifndef LIBAPP_APP_APPCLIENT_H
|
||||
# define LIBAPP_APP_APPCLIENT_H
|
||||
|
||||
# include <stdarg.h>
|
||||
# include <stdint.h>
|
||||
# include <System/event.h>
|
||||
# include <System/variable.h>
|
||||
|
@ -42,7 +43,13 @@ AppStatus * appclient_get_status(AppClient * appclient);
|
|||
/* useful */
|
||||
int appclient_call(AppClient * appclient,
|
||||
void ** result, char const * method, ...);
|
||||
int appclient_callv(AppClient * appclient,
|
||||
void ** result, char const * method, va_list args);
|
||||
int appclient_call_variable(AppClient * appclient,
|
||||
Variable * result, char const * method, ...);
|
||||
int appclient_call_variables(AppClient * appclient,
|
||||
Variable * result, char const * method, Variable ** args);
|
||||
int appclient_call_variablev(AppClient * appclient,
|
||||
Variable * result, char const * method, va_list args);
|
||||
|
||||
#endif /* !LIBAPP_APP_APPCLIENT_H */
|
||||
|
|
|
@ -83,6 +83,9 @@ AppClient * appclient_new_event(App * self, char const * app,
|
|||
|| appclient->event == NULL)
|
||||
{
|
||||
appclient_delete(appclient);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() => NULL\n", __func__);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
|
@ -131,34 +134,73 @@ int appclient_call(AppClient * appclient,
|
|||
va_list ap;
|
||||
|
||||
va_start(ap, method);
|
||||
ret = appinterface_callv(appclient->interface, appclient->app, result,
|
||||
method, ap);
|
||||
ret = appclient_callv(appclient, result, method, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* appclient_callv */
|
||||
int appclient_callv(AppClient * appclient,
|
||||
void ** result, char const * method, va_list args)
|
||||
{
|
||||
int ret;
|
||||
AppMessage * message;
|
||||
|
||||
if((message = appinterface_messagev(appclient->interface, method, args))
|
||||
== NULL)
|
||||
return -1;
|
||||
/* FIXME obtain the answer (AICD_{,IN}OUT) */
|
||||
ret = apptransport_client_send(appclient->transport, message, 1);
|
||||
appmessage_delete(message);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* appclient_call_variable */
|
||||
int appclient_call_variable(AppClient * appclient,
|
||||
Variable * result, char const * method, ...)
|
||||
{
|
||||
int ret;
|
||||
size_t cnt;
|
||||
size_t i;
|
||||
va_list ap;
|
||||
Variable ** argv;
|
||||
|
||||
if(appinterface_get_args_count(appclient->interface, &cnt, method) != 0)
|
||||
return -1;
|
||||
if((argv = malloc(sizeof(*argv) * cnt)) == NULL)
|
||||
return error_set_code(-errno, "%s", strerror(errno));
|
||||
va_start(ap, method);
|
||||
for(i = 0; i < cnt; i++)
|
||||
argv[i] = va_arg(ap, Variable *);
|
||||
ret = appclient_call_variablev(appclient, result, method, ap);
|
||||
va_end(ap);
|
||||
ret = appinterface_call_variablev(appclient->interface, appclient->app,
|
||||
result, method, cnt, argv);
|
||||
free(argv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* appclient_call_variables */
|
||||
int appclient_call_variables(AppClient * appclient,
|
||||
Variable * result, char const * method, Variable ** args)
|
||||
{
|
||||
int ret;
|
||||
AppMessage * message;
|
||||
|
||||
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);
|
||||
appmessage_delete(message);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* appclient_call_variablev */
|
||||
int appclient_call_variablev(AppClient * appclient,
|
||||
Variable * result, char const * method, va_list args)
|
||||
{
|
||||
int ret;
|
||||
AppMessage * message;
|
||||
|
||||
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);
|
||||
appmessage_delete(message);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <errno.h>
|
||||
#include <System.h>
|
||||
#include <System/Marshall.h>
|
||||
#include "App/appmessage.h"
|
||||
#include "App/appserver.h"
|
||||
#include "appstatus.h"
|
||||
#include "appinterface.h"
|
||||
|
@ -161,8 +162,12 @@ static AppInterfaceCall * _appinterface_get_call(AppInterface * appinterface,
|
|||
char const * method);
|
||||
|
||||
/* useful */
|
||||
static Variable ** _appinterface_argv(AppInterfaceCall * call, va_list args);
|
||||
static void _appinterface_argv_free(Variable ** argv, size_t argc);
|
||||
static int _appinterface_call(App * app, Variable * result,
|
||||
AppInterfaceCall * call, size_t argc, Variable ** argv);
|
||||
static AppMessage * _appinterface_message(AppInterfaceCall * call,
|
||||
size_t argc, Variable ** argv);
|
||||
|
||||
|
||||
/* functions */
|
||||
|
@ -513,8 +518,125 @@ int appinterface_callv(AppInterface * appinterface, App * app, void ** result,
|
|||
int ret = 0;
|
||||
AppInterfaceCall * call;
|
||||
Variable * r;
|
||||
size_t argc;
|
||||
Variable ** argv;
|
||||
|
||||
if((call = _appinterface_get_call(appinterface, method)) == NULL)
|
||||
return -1;
|
||||
if(call->type.type == VT_NULL)
|
||||
r = NULL;
|
||||
else if((r = variable_new(call->type.type, NULL)) == NULL)
|
||||
return -1;
|
||||
if((argv = _appinterface_argv(call, args)) == NULL)
|
||||
{
|
||||
if(r != NULL)
|
||||
variable_delete(r);
|
||||
return -1;
|
||||
}
|
||||
if(ret == 0)
|
||||
ret = _appinterface_call(app, r, call, call->args_cnt, argv);
|
||||
if(r != NULL)
|
||||
{
|
||||
if(ret == 0 && result != NULL)
|
||||
/* XXX return 0 anyway? */
|
||||
ret = variable_get_as(r, call->type.type, *result);
|
||||
variable_delete(r);
|
||||
}
|
||||
/* FIXME also implement AICD_{,IN}OUT */
|
||||
_appinterface_argv_free(argv, call->args_cnt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* appinterface_call_variablev */
|
||||
int appinterface_call_variablev(AppInterface * appinterface, App * app,
|
||||
Variable * result, char const * method,
|
||||
size_t argc, Variable ** argv)
|
||||
{
|
||||
AppInterfaceCall * call;
|
||||
|
||||
if((call = _appinterface_get_call(appinterface, method)) == NULL)
|
||||
return -1;
|
||||
return _appinterface_call(app, result, call, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
/* appinterface_messagev */
|
||||
AppMessage * appinterface_messagev(AppInterface * appinterface,
|
||||
char const * method, va_list args)
|
||||
{
|
||||
AppInterfaceCall * call;
|
||||
Variable ** argv;
|
||||
AppMessage * message;
|
||||
|
||||
if((call = _appinterface_get_call(appinterface, method)) == NULL)
|
||||
return NULL;
|
||||
if((argv = _appinterface_argv(call, args)) == NULL)
|
||||
return NULL;
|
||||
message = _appinterface_message(call, call->args_cnt, argv);
|
||||
_appinterface_argv_free(argv, call->args_cnt);
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
/* appinterface_message_variables */
|
||||
AppMessage * appinterface_message_variables(AppInterface * appinterface,
|
||||
char const * method, Variable ** args)
|
||||
{
|
||||
AppInterfaceCall * call;
|
||||
|
||||
if((call = _appinterface_get_call(appinterface, method)) == NULL)
|
||||
return NULL;
|
||||
return _appinterface_message(call, call->args_cnt, args);
|
||||
}
|
||||
|
||||
|
||||
/* appinterface_message_variablev */
|
||||
AppMessage * appinterface_message_variablev(AppInterface * appinterface,
|
||||
char const * method, va_list args)
|
||||
{
|
||||
AppInterfaceCall * call;
|
||||
Variable ** argv;
|
||||
size_t i;
|
||||
AppMessage * message;
|
||||
|
||||
if((call = _appinterface_get_call(appinterface, method)) == NULL)
|
||||
return NULL;
|
||||
if(call->args_cnt == 0)
|
||||
argv = NULL;
|
||||
else if((argv = malloc(sizeof(*argv) * call->args_cnt)) == NULL)
|
||||
/* XXX report error */
|
||||
return NULL;
|
||||
for(i = 0; i < call->args_cnt; i++)
|
||||
argv[i] = va_arg(args, Variable *);
|
||||
message = _appinterface_message(call, call->args_cnt, argv);
|
||||
free(argv);
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
/* private */
|
||||
/* accessors */
|
||||
/* appinterface_get_call */
|
||||
static AppInterfaceCall * _appinterface_get_call(AppInterface * appinterface,
|
||||
String const * method)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < appinterface->calls_cnt; i++)
|
||||
if(string_compare(appinterface->calls[i].name, method) == 0)
|
||||
return &appinterface->calls[i];
|
||||
error_set_code(1, "%s%s%s%s", "Unknown call \"", method,
|
||||
"\" for interface ", appinterface->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* useful */
|
||||
/* appinterface_argv */
|
||||
static Variable ** _appinterface_argv(AppInterfaceCall * call, va_list args)
|
||||
{
|
||||
Variable ** argv;
|
||||
size_t argc;
|
||||
union
|
||||
{
|
||||
bool b;
|
||||
|
@ -533,18 +655,9 @@ int appinterface_callv(AppInterface * appinterface, App * app, void ** result,
|
|||
} u;
|
||||
void * p;
|
||||
|
||||
if((call = _appinterface_get_call(appinterface, method)) == NULL)
|
||||
return -1;
|
||||
if(call->type.type == VT_NULL)
|
||||
r = NULL;
|
||||
else if((r = variable_new(call->type.type, NULL)) == NULL)
|
||||
return -1;
|
||||
if((argv = malloc(sizeof(*argv) * (call->args_cnt))) == NULL)
|
||||
{
|
||||
if(r != NULL)
|
||||
variable_delete(r);
|
||||
return -1;
|
||||
}
|
||||
/* XXX set the error */
|
||||
return NULL;
|
||||
for(argc = 0; argc < call->args_cnt; argc++)
|
||||
{
|
||||
/* FIXME also implement AICD_{,IN}OUT */
|
||||
|
@ -610,50 +723,26 @@ int appinterface_callv(AppInterface * appinterface, App * app, void ** result,
|
|||
argv[argc] = (p != NULL)
|
||||
? variable_new(call->args[argc].type, p) : NULL;
|
||||
if(p == NULL || argv[argc] == NULL)
|
||||
ret = -1;
|
||||
{
|
||||
_appinterface_argv_free(argv, argc);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if(ret == 0)
|
||||
ret = _appinterface_call(app, r, call, argc, argv);
|
||||
if(ret == 0 && result != NULL)
|
||||
/* XXX return 0 anyway? */
|
||||
ret = variable_get_as(r, call->type.type, *result);
|
||||
if(r != NULL)
|
||||
variable_delete(r);
|
||||
return ret;
|
||||
return argv;
|
||||
}
|
||||
|
||||
|
||||
/* appinterface_call_variablev */
|
||||
int appinterface_call_variablev(AppInterface * appinterface, App * app,
|
||||
Variable * result, char const * method,
|
||||
size_t argc, Variable ** argv)
|
||||
{
|
||||
AppInterfaceCall * call;
|
||||
|
||||
if((call = _appinterface_get_call(appinterface, method)) == NULL)
|
||||
return -1;
|
||||
return _appinterface_call(app, result, call, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
/* private */
|
||||
/* accessors */
|
||||
/* appinterface_get_call */
|
||||
static AppInterfaceCall * _appinterface_get_call(AppInterface * appinterface,
|
||||
String const * method)
|
||||
/* appinterface_argv_free */
|
||||
static void _appinterface_argv_free(Variable ** argv, size_t argc)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < appinterface->calls_cnt; i++)
|
||||
if(string_compare(appinterface->calls[i].name, method) == 0)
|
||||
return &appinterface->calls[i];
|
||||
error_set_code(1, "%s%s%s%s", "Unknown call \"", method,
|
||||
"\" for interface ", appinterface->name);
|
||||
return NULL;
|
||||
for(i = 0; i < argc; i++)
|
||||
variable_delete(argv[argc]);
|
||||
free(argv);
|
||||
}
|
||||
|
||||
|
||||
/* useful */
|
||||
/* appinterface_call */
|
||||
static int _appinterface_call(App * app, Variable * result,
|
||||
AppInterfaceCall * call, size_t argc, Variable ** argv)
|
||||
|
@ -663,8 +752,10 @@ static int _appinterface_call(App * app, Variable * result,
|
|||
size_t i;
|
||||
|
||||
if(argc != call->args_cnt)
|
||||
/* XXX set the error */
|
||||
return -1;
|
||||
if((p = malloc(sizeof(*p) * (argc + 1))) == NULL)
|
||||
/* XXX set the error */
|
||||
return -1;
|
||||
/* XXX really is a VT_POINTER (void *) */
|
||||
if((p[0] = variable_new(VT_BUFFER, app)) == NULL)
|
||||
|
@ -679,3 +770,31 @@ static int _appinterface_call(App * app, Variable * result,
|
|||
free(p);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* appinterface_message */
|
||||
static AppMessage * _appinterface_message(AppInterfaceCall * call,
|
||||
size_t argc, Variable ** argv)
|
||||
{
|
||||
AppMessage * message;
|
||||
AppMessageCallArgument * args;
|
||||
size_t i;
|
||||
|
||||
if(argc != call->args_cnt)
|
||||
/* XXX set the error */
|
||||
return NULL;
|
||||
if(argc == 0)
|
||||
args = NULL;
|
||||
else if((args = malloc(sizeof(*args) * argc)) == NULL)
|
||||
/* XXX set the error */
|
||||
return NULL;
|
||||
else
|
||||
for(i = 0; i < argc; i++)
|
||||
{
|
||||
args[i].direction = call->args[i].direction;
|
||||
args[i].arg = argv[i];
|
||||
}
|
||||
message = appmessage_new_call(call->name, args, argc);
|
||||
free(args);
|
||||
return message;
|
||||
}
|
||||
|
|
|
@ -51,4 +51,11 @@ int appinterface_call_variablev(AppInterface * appinterface, App * app,
|
|||
Variable * result, char const * method,
|
||||
size_t argc, Variable ** argv);
|
||||
|
||||
AppMessage * appinterface_messagev(AppInterface * appinterface,
|
||||
char const * method, va_list args);
|
||||
AppMessage * appinterface_message_variables(AppInterface * appinterface,
|
||||
char const * method, Variable ** args);
|
||||
AppMessage * appinterface_message_variablev(AppInterface * appinterface,
|
||||
char const * method, va_list args);
|
||||
|
||||
#endif /* !LIBAPP_APPINTERFACE_H */
|
||||
|
|
|
@ -408,7 +408,16 @@ 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;
|
||||
if(name != NULL)
|
||||
{
|
||||
if((client->name = string_new(name)) == NULL)
|
||||
{
|
||||
object_delete(client);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
client->name = NULL;
|
||||
return client;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,9 +109,9 @@ static TCP * _tcp_init(AppTransportPluginHelper * helper, AppTransportMode mode,
|
|||
char const * name);
|
||||
static void _tcp_destroy(TCP * tcp);
|
||||
|
||||
static int _tcp_client_send(TCP * tcp, AppTransportClient * client,
|
||||
static int _tcp_client_send(TCP * tcp, AppMessage * message);
|
||||
static int _tcp_server_send(TCP * tcp, AppTransportClient * client,
|
||||
AppMessage * message);
|
||||
static int _tcp_send(TCP * tcp, AppMessage * message);
|
||||
|
||||
/* useful */
|
||||
static int _tcp_error(char const * message);
|
||||
|
@ -120,7 +120,8 @@ static int _tcp_error(char const * message);
|
|||
static int _tcp_server_add_client(TCP * tcp, TCPSocket * client);
|
||||
|
||||
/* sockets */
|
||||
static int _tcp_socket_init(TCPSocket * tcpsocket, int domain, TCP * tcp);
|
||||
static int _tcp_socket_init(TCPSocket * tcpsocket, int domain, int flags,
|
||||
TCP * tcp);
|
||||
static void _tcp_socket_init_fd(TCPSocket * tcpsocket, TCP * tcp, int fd,
|
||||
struct sockaddr * sa, socklen_t sa_len);
|
||||
static TCPSocket * _tcp_socket_new_fd(TCP * tcp, int fd, struct sockaddr * sa,
|
||||
|
@ -146,8 +147,8 @@ AppTransportPluginDefinition transport =
|
|||
NULL,
|
||||
_tcp_init,
|
||||
_tcp_destroy,
|
||||
_tcp_send,
|
||||
_tcp_client_send
|
||||
_tcp_client_send,
|
||||
_tcp_server_send
|
||||
};
|
||||
|
||||
|
||||
|
@ -214,19 +215,20 @@ static int _init_client(TCP * tcp, char const * name, int domain)
|
|||
{
|
||||
tcp->u.client.fd = -1;
|
||||
/* initialize the client socket */
|
||||
if(_tcp_socket_init(&tcp->u.client, aip->ai_family, tcp) != 0)
|
||||
if(_tcp_socket_init(&tcp->u.client, aip->ai_family, O_NONBLOCK,
|
||||
tcp) != 0)
|
||||
continue;
|
||||
#ifdef DEBUG
|
||||
if(aip->ai_family == AF_INET)
|
||||
{
|
||||
sa = (struct sockaddr_in *)aip->ai_addr;
|
||||
fprintf(stderr, "DEBUG: %s() %s (%s:%u)\n", __func__,
|
||||
"connect()", inet_ntoa(sa->sin_addr),
|
||||
fprintf(stderr, "DEBUG: %s() connect(%s:%u)\n", __func__,
|
||||
inet_ntoa(sa->sin_addr),
|
||||
ntohs(sa->sin_port));
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "DEBUG: %s() %s %d\n", __func__,
|
||||
"connect()", aip->ai_family);
|
||||
fprintf(stderr, "DEBUG: %s() connect(%d)\n", __func__,
|
||||
aip->ai_family);
|
||||
#endif
|
||||
if(connect(tcp->u.client.fd, aip->ai_addr, aip->ai_addrlen)
|
||||
!= 0)
|
||||
|
@ -242,14 +244,25 @@ static int _init_client(TCP * tcp, char const * name, int domain)
|
|||
tcp->u.client.fd,
|
||||
(EventIOFunc)_tcp_callback_connect,
|
||||
tcp);
|
||||
event_loop(tcp->helper->event);
|
||||
}
|
||||
else
|
||||
/* listen for any incoming message */
|
||||
event_register_io_read(tcp->helper->event,
|
||||
tcp->u.client.fd,
|
||||
(EventIOFunc)_tcp_socket_callback_read,
|
||||
&tcp->u.client);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() connect() => 0\n", __func__);
|
||||
#endif
|
||||
tcp->ai_addrlen = aip->ai_addrlen;
|
||||
/* listen for any incoming message */
|
||||
event_register_io_read(tcp->helper->event, tcp->u.client.fd,
|
||||
(EventIOFunc)_tcp_socket_callback_read,
|
||||
&tcp->u.client);
|
||||
/* write pending messages if any */
|
||||
if(tcp->u.client.bufout_cnt > 0)
|
||||
{
|
||||
event_register_io_write(tcp->helper->event,
|
||||
tcp->u.client.fd,
|
||||
(EventIOFunc)_tcp_socket_callback_write,
|
||||
&tcp->u.client);
|
||||
event_loop(tcp->helper->event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
freeaddrinfo(tcp->ai);
|
||||
|
@ -272,7 +285,8 @@ static int _init_server(TCP * tcp, char const * name, int domain)
|
|||
for(aip = tcp->ai; aip != NULL; aip = aip->ai_next)
|
||||
{
|
||||
/* create the socket */
|
||||
if(_tcp_socket_init(&tcpsocket, aip->ai_family, tcp) != 0)
|
||||
if(_tcp_socket_init(&tcpsocket, aip->ai_family, O_NONBLOCK,
|
||||
tcp) != 0)
|
||||
continue;
|
||||
/* XXX ugly */
|
||||
tcp->u.server.fd = tcpsocket.fd;
|
||||
|
@ -358,7 +372,26 @@ static void _destroy_server(TCP * tcp)
|
|||
|
||||
|
||||
/* tcp_client_send */
|
||||
static int _tcp_client_send(TCP * tcp, AppTransportClient * client,
|
||||
static int _tcp_client_send(TCP * tcp, AppMessage * message)
|
||||
{
|
||||
int ret;
|
||||
Buffer * buffer;
|
||||
|
||||
if(tcp->mode != ATM_CLIENT)
|
||||
return -error_set_code(1, "%s", "Not a client");
|
||||
/* send the 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)
|
||||
event_loop(tcp->helper->event);
|
||||
buffer_delete(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* tcp_server_send */
|
||||
static int _tcp_server_send(TCP * tcp, AppTransportClient * client,
|
||||
AppMessage * message)
|
||||
{
|
||||
size_t i;
|
||||
|
@ -389,27 +422,6 @@ static int _tcp_client_send(TCP * tcp, AppTransportClient * client,
|
|||
}
|
||||
|
||||
|
||||
/* tcp_send */
|
||||
static int _tcp_send(TCP * tcp, AppMessage * message)
|
||||
{
|
||||
Buffer * buffer;
|
||||
|
||||
if(tcp->mode != ATM_CLIENT)
|
||||
return -error_set_code(1, "%s", "Not a client");
|
||||
/* send the message */
|
||||
if((buffer = buffer_new(0, NULL)) == NULL)
|
||||
return -1;
|
||||
if(appmessage_serialize(message, buffer) != 0
|
||||
|| _tcp_socket_queue(&tcp->u.client, buffer) != 0)
|
||||
{
|
||||
buffer_delete(buffer);
|
||||
return -1;
|
||||
}
|
||||
buffer_delete(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* useful */
|
||||
/* tcp_error */
|
||||
static int _tcp_error(char const * message)
|
||||
|
@ -457,23 +469,27 @@ static int _tcp_server_add_client(TCP * tcp, TCPSocket * client)
|
|||
|
||||
/* sockets */
|
||||
/* tcp_socket_init */
|
||||
static int _tcp_socket_init(TCPSocket * tcpsocket, int domain, TCP * tcp)
|
||||
static int _tcp_socket_init(TCPSocket * tcpsocket, int domain, int flags,
|
||||
TCP * tcp)
|
||||
{
|
||||
int flags;
|
||||
int f;
|
||||
|
||||
if((tcpsocket->fd = socket(domain, SOCK_STREAM, 0)) < 0)
|
||||
return -_tcp_error("socket");
|
||||
_tcp_socket_init_fd(tcpsocket, tcp, tcpsocket->fd, NULL, 0);
|
||||
/* set the socket as non-blocking */
|
||||
if((flags = fcntl(tcpsocket->fd, F_GETFL)) == -1)
|
||||
return -_tcp_error("fcntl");
|
||||
if((flags & O_NONBLOCK) == 0)
|
||||
if(fcntl(tcpsocket->fd, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||
/* set the socket flags */
|
||||
if(flags != 0)
|
||||
{
|
||||
if((f = fcntl(tcpsocket->fd, F_GETFL)) == -1)
|
||||
return -_tcp_error("fcntl");
|
||||
if((f & flags) != flags)
|
||||
if(fcntl(tcpsocket->fd, F_SETFL, f | flags) == -1)
|
||||
return -_tcp_error("fcntl");
|
||||
}
|
||||
#ifdef TCP_NODELAY
|
||||
/* do not wait before sending any traffic */
|
||||
flags = 1;
|
||||
setsockopt(fd, SOL_SOCKET, TCP_NODELAY, &flags, sizeof(flags));
|
||||
f = 1;
|
||||
setsockopt(fd, SOL_SOCKET, TCP_NODELAY, &f, sizeof(f));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -652,8 +668,8 @@ static int _accept_client(TCP * tcp, int fd, struct sockaddr * sa,
|
|||
/* tcp_callback_connect */
|
||||
static int _tcp_callback_connect(int fd, TCP * tcp)
|
||||
{
|
||||
int res;
|
||||
socklen_t s = sizeof(res);
|
||||
int ret;
|
||||
socklen_t s = sizeof(ret);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s(%d)\n", __func__, fd);
|
||||
|
@ -662,7 +678,7 @@ static int _tcp_callback_connect(int fd, TCP * tcp)
|
|||
if(tcp->u.client.fd != fd)
|
||||
return -1;
|
||||
/* obtain the connection status */
|
||||
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &res, &s) != 0)
|
||||
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &s) != 0)
|
||||
{
|
||||
error_set_code(-errno, "%s: %s", "getsockopt", strerror(errno));
|
||||
close(fd);
|
||||
|
@ -671,33 +687,28 @@ static int _tcp_callback_connect(int fd, TCP * tcp)
|
|||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() %s\n", __func__, strerror(errno));
|
||||
#endif
|
||||
return -1;
|
||||
ret = -1;
|
||||
}
|
||||
if(res != 0)
|
||||
else if(ret != 0)
|
||||
{
|
||||
/* the connection failed */
|
||||
error_set_code(-res, "%s: %s", "connect", strerror(res));
|
||||
error_set_code(-ret, "%s: %s", "connect", strerror(ret));
|
||||
close(fd);
|
||||
tcp->u.client.fd = -1;
|
||||
/* FIXME report error */
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() %s\n", __func__, strerror(res));
|
||||
fprintf(stderr, "DEBUG: %s() %s\n", __func__, strerror(ret));
|
||||
#endif
|
||||
return -1;
|
||||
ret = -1;
|
||||
}
|
||||
/* listen for any incoming message */
|
||||
event_register_io_read(tcp->helper->event, fd,
|
||||
(EventIOFunc)_tcp_socket_callback_read,
|
||||
&tcp->u.client);
|
||||
/* write pending messages if any */
|
||||
if(tcp->u.client.bufout_cnt > 0)
|
||||
{
|
||||
event_register_io_write(tcp->helper->event, fd,
|
||||
(EventIOFunc)_tcp_socket_callback_write,
|
||||
&tcp->u.client);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
else
|
||||
/* deregister this callback */
|
||||
ret = 1;
|
||||
event_loop_quit(tcp->helper->event);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() => %d\n", __func__, ret);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -850,6 +861,9 @@ static int _tcp_socket_callback_write(int fd, TCPSocket * tcpsocket)
|
|||
tcpsocket->bufout_cnt -= ssize;
|
||||
/* unregister the callback if there is nothing left to write */
|
||||
if(tcpsocket->bufout_cnt == 0)
|
||||
{
|
||||
event_loop_quit(tcpsocket->tcp->helper->event);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user