Getting closer to functional UDP calls
This commit is contained in:
parent
3017f213fe
commit
727a33b6eb
1
Makefile
1
Makefile
|
@ -60,6 +60,7 @@ dist:
|
||||||
$(PACKAGE)-$(VERSION)/src/transport/udp4.c \
|
$(PACKAGE)-$(VERSION)/src/transport/udp4.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/transport/udp6.c \
|
$(PACKAGE)-$(VERSION)/src/transport/udp6.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/transport/Makefile \
|
$(PACKAGE)-$(VERSION)/src/transport/Makefile \
|
||||||
|
$(PACKAGE)-$(VERSION)/src/transport/common.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/transport/project.conf \
|
$(PACKAGE)-$(VERSION)/src/transport/project.conf \
|
||||||
$(PACKAGE)-$(VERSION)/tests/appmessage.c \
|
$(PACKAGE)-$(VERSION)/tests/appmessage.c \
|
||||||
$(PACKAGE)-$(VERSION)/tests/transport.c \
|
$(PACKAGE)-$(VERSION)/tests/transport.c \
|
||||||
|
|
|
@ -68,25 +68,25 @@ udp6_LDFLAGS = $(LDFLAGSF) $(LDFLAGS)
|
||||||
udp6.so: $(udp6_OBJS)
|
udp6.so: $(udp6_OBJS)
|
||||||
$(CCSHARED) -o udp6.so $(udp6_OBJS) $(udp6_LDFLAGS)
|
$(CCSHARED) -o udp6.so $(udp6_OBJS) $(udp6_LDFLAGS)
|
||||||
|
|
||||||
tcp.o: tcp.c
|
tcp.o: tcp.c common.c
|
||||||
$(CC) $(tcp_CFLAGS) -c tcp.c
|
$(CC) $(tcp_CFLAGS) -c tcp.c
|
||||||
|
|
||||||
tcp4.o: tcp4.c tcp.c
|
tcp4.o: tcp4.c tcp.c common.c
|
||||||
$(CC) $(tcp4_CFLAGS) -c tcp4.c
|
$(CC) $(tcp4_CFLAGS) -c tcp4.c
|
||||||
|
|
||||||
tcp6.o: tcp6.c tcp.c
|
tcp6.o: tcp6.c tcp.c common.c
|
||||||
$(CC) $(tcp6_CFLAGS) -c tcp6.c
|
$(CC) $(tcp6_CFLAGS) -c tcp6.c
|
||||||
|
|
||||||
template.o: template.c
|
template.o: template.c
|
||||||
$(CC) $(template_CFLAGS) -c template.c
|
$(CC) $(template_CFLAGS) -c template.c
|
||||||
|
|
||||||
udp.o: udp.c
|
udp.o: udp.c common.c
|
||||||
$(CC) $(udp_CFLAGS) -c udp.c
|
$(CC) $(udp_CFLAGS) -c udp.c
|
||||||
|
|
||||||
udp4.o: udp4.c udp.c
|
udp4.o: udp4.c udp.c common.c
|
||||||
$(CC) $(udp4_CFLAGS) -c udp4.c
|
$(CC) $(udp4_CFLAGS) -c udp4.c
|
||||||
|
|
||||||
udp6.o: udp6.c udp.c
|
udp6.o: udp6.c udp.c common.c
|
||||||
$(CC) $(udp6_CFLAGS) -c udp6.c
|
$(CC) $(udp6_CFLAGS) -c udp6.c
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
62
src/transport/common.c
Normal file
62
src/transport/common.c
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2014 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/>. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* init_address */
|
||||||
|
static int _init_address(Class * instance, char const * name, int domain)
|
||||||
|
{
|
||||||
|
char sep = ':';
|
||||||
|
char * p;
|
||||||
|
char * q;
|
||||||
|
char * r;
|
||||||
|
long l;
|
||||||
|
struct addrinfo hints;
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
/* guess the port separator */
|
||||||
|
if((q = strchr(name, ':')) != NULL && strchr(++q, ':') != NULL)
|
||||||
|
sep = '.';
|
||||||
|
/* obtain the name */
|
||||||
|
if((p = strdup(name)) == NULL)
|
||||||
|
return -error_set_code(1, "%s", strerror(errno));
|
||||||
|
/* obtain the port number */
|
||||||
|
if((q = strrchr(p, sep)) == NULL)
|
||||||
|
l = -error_set_code(1, "%s", strerror(EINVAL));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*(q++) = '\0';
|
||||||
|
l = strtol(q, &r, 10);
|
||||||
|
if(q[0] == '\0' || *r != '\0')
|
||||||
|
l = -error_set_code(1, "%s", strerror(EINVAL));
|
||||||
|
}
|
||||||
|
/* FIXME perform this asynchronously */
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = domain;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
if(l >= 0)
|
||||||
|
res = getaddrinfo(p, q, &hints, &instance->ai);
|
||||||
|
free(p);
|
||||||
|
/* check for errors */
|
||||||
|
if(res != 0)
|
||||||
|
{
|
||||||
|
error_set_code(1, "%s", gai_strerror(res));
|
||||||
|
if(instance->ai != NULL)
|
||||||
|
freeaddrinfo(instance->ai);
|
||||||
|
instance->ai = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return (instance->ai != NULL) ? 0 : -1;
|
||||||
|
}
|
|
@ -4,20 +4,23 @@ cppflags=
|
||||||
cflags_force=-W -fPIC `pkg-config --cflags libSystem`
|
cflags_force=-W -fPIC `pkg-config --cflags libSystem`
|
||||||
cflags=-Wall -g -O2 -pedantic
|
cflags=-Wall -g -O2 -pedantic
|
||||||
ldflags_force=`pkg-config --cflags libSystem`
|
ldflags_force=`pkg-config --cflags libSystem`
|
||||||
dist=Makefile
|
dist=Makefile,common.c
|
||||||
|
|
||||||
[tcp]
|
[tcp]
|
||||||
type=plugin
|
type=plugin
|
||||||
sources=tcp.c
|
sources=tcp.c
|
||||||
install=$(LIBDIR)/App/transport
|
install=$(LIBDIR)/App/transport
|
||||||
|
|
||||||
|
[tcp.c]
|
||||||
|
depends=common.c
|
||||||
|
|
||||||
[tcp4]
|
[tcp4]
|
||||||
type=plugin
|
type=plugin
|
||||||
sources=tcp4.c
|
sources=tcp4.c
|
||||||
install=$(LIBDIR)/App/transport
|
install=$(LIBDIR)/App/transport
|
||||||
|
|
||||||
[tcp4.c]
|
[tcp4.c]
|
||||||
depends=tcp.c
|
depends=tcp.c,common.c
|
||||||
|
|
||||||
[tcp6]
|
[tcp6]
|
||||||
type=plugin
|
type=plugin
|
||||||
|
@ -25,7 +28,7 @@ sources=tcp6.c
|
||||||
install=$(LIBDIR)/App/transport
|
install=$(LIBDIR)/App/transport
|
||||||
|
|
||||||
[tcp6.c]
|
[tcp6.c]
|
||||||
depends=tcp.c
|
depends=tcp.c,common.c
|
||||||
|
|
||||||
[template]
|
[template]
|
||||||
type=plugin
|
type=plugin
|
||||||
|
@ -36,13 +39,16 @@ type=plugin
|
||||||
sources=udp.c
|
sources=udp.c
|
||||||
install=$(LIBDIR)/App/transport
|
install=$(LIBDIR)/App/transport
|
||||||
|
|
||||||
|
[udp.c]
|
||||||
|
depends=common.c
|
||||||
|
|
||||||
[udp4]
|
[udp4]
|
||||||
type=plugin
|
type=plugin
|
||||||
sources=udp4.c
|
sources=udp4.c
|
||||||
install=$(LIBDIR)/App/transport
|
install=$(LIBDIR)/App/transport
|
||||||
|
|
||||||
[udp4.c]
|
[udp4.c]
|
||||||
depends=udp.c
|
depends=udp.c,common.c
|
||||||
|
|
||||||
[udp6]
|
[udp6]
|
||||||
type=plugin
|
type=plugin
|
||||||
|
@ -50,4 +56,4 @@ sources=udp6.c
|
||||||
install=$(LIBDIR)/App/transport
|
install=$(LIBDIR)/App/transport
|
||||||
|
|
||||||
[udp6.c]
|
[udp6.c]
|
||||||
depends=udp.c
|
depends=udp.c,common.c
|
||||||
|
|
|
@ -98,6 +98,9 @@ struct _AppTransportPlugin
|
||||||
/* constants */
|
/* constants */
|
||||||
#define INC 1024
|
#define INC 1024
|
||||||
|
|
||||||
|
#define Class TCP
|
||||||
|
#include "common.c"
|
||||||
|
|
||||||
|
|
||||||
/* protected */
|
/* protected */
|
||||||
/* prototypes */
|
/* prototypes */
|
||||||
|
@ -191,51 +194,6 @@ static TCP * _tcp_init(AppTransportPluginHelper * helper,
|
||||||
return tcp;
|
return tcp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _init_address(TCP * tcp, char const * name, int domain)
|
|
||||||
{
|
|
||||||
char sep = ':';
|
|
||||||
char * p;
|
|
||||||
char * q;
|
|
||||||
char * r;
|
|
||||||
long l;
|
|
||||||
struct addrinfo hints;
|
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
/* guess the port separator */
|
|
||||||
if((q = strchr(name, ':')) != NULL && strchr(++q, ':') != NULL)
|
|
||||||
sep = '.';
|
|
||||||
/* obtain the name */
|
|
||||||
if((p = strdup(name)) == NULL)
|
|
||||||
return -error_set_code(1, "%s", strerror(errno));
|
|
||||||
/* obtain the port number */
|
|
||||||
if((q = strrchr(p, sep)) == NULL)
|
|
||||||
l = -error_set_code(1, "%s", strerror(EINVAL));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*(q++) = '\0';
|
|
||||||
l = strtol(q, &r, 10);
|
|
||||||
if(q[0] == '\0' || *r != '\0')
|
|
||||||
l = -error_set_code(1, "%s", strerror(EINVAL));
|
|
||||||
}
|
|
||||||
/* FIXME perform this asynchronously */
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
|
||||||
hints.ai_family = domain;
|
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
|
||||||
if(l >= 0)
|
|
||||||
res = getaddrinfo(p, q, &hints, &tcp->ai);
|
|
||||||
free(p);
|
|
||||||
/* check for errors */
|
|
||||||
if(res != 0)
|
|
||||||
{
|
|
||||||
error_set_code(1, "%s", gai_strerror(res));
|
|
||||||
if(tcp->ai != NULL)
|
|
||||||
freeaddrinfo(tcp->ai);
|
|
||||||
tcp->ai = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return (tcp->ai != NULL) ? 0 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _init_client(TCP * tcp, char const * name)
|
static int _init_client(TCP * tcp, char const * name)
|
||||||
{
|
{
|
||||||
struct addrinfo * aip;
|
struct addrinfo * aip;
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
# include <netdb.h>
|
# include <netdb.h>
|
||||||
#endif
|
#endif
|
||||||
#include <System.h>
|
#include <System.h>
|
||||||
|
#include "App/appmessage.h"
|
||||||
#include "App/apptransport.h"
|
#include "App/apptransport.h"
|
||||||
|
|
||||||
/* portability */
|
/* portability */
|
||||||
|
@ -51,6 +52,14 @@
|
||||||
/* types */
|
/* types */
|
||||||
typedef struct _AppTransportPlugin UDP;
|
typedef struct _AppTransportPlugin UDP;
|
||||||
|
|
||||||
|
typedef struct _UDPClient
|
||||||
|
{
|
||||||
|
AppTransportClient * client;
|
||||||
|
|
||||||
|
struct sockaddr * sa;
|
||||||
|
socklen_t sa_len;
|
||||||
|
} UDPClient;
|
||||||
|
|
||||||
typedef struct _UDPMessage
|
typedef struct _UDPMessage
|
||||||
{
|
{
|
||||||
char * buffer;
|
char * buffer;
|
||||||
|
@ -66,11 +75,24 @@ struct _AppTransportPlugin
|
||||||
struct addrinfo * ai;
|
struct addrinfo * ai;
|
||||||
struct addrinfo * aip;
|
struct addrinfo * aip;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/* for servers */
|
||||||
|
UDPClient ** clients;
|
||||||
|
size_t clients_cnt;
|
||||||
|
} server;
|
||||||
|
} u;
|
||||||
|
|
||||||
/* output queue */
|
/* output queue */
|
||||||
UDPMessage * messages;
|
UDPMessage * messages;
|
||||||
size_t messages_cnt;
|
size_t messages_cnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define Class UDP
|
||||||
|
#include "common.c"
|
||||||
|
|
||||||
|
|
||||||
/* protected */
|
/* protected */
|
||||||
/* prototypes */
|
/* prototypes */
|
||||||
|
@ -84,6 +106,10 @@ static int _udp_send(UDP * udp, AppMessage * message, int acknowledge);
|
||||||
/* useful */
|
/* useful */
|
||||||
static int _udp_error(char const * message, int code);
|
static int _udp_error(char const * message, int code);
|
||||||
|
|
||||||
|
/* clients */
|
||||||
|
static int _udp_client_init(UDPClient * client, struct sockaddr * sa,
|
||||||
|
socklen_t sa_len, UDP * udp);
|
||||||
|
|
||||||
/* callbacks */
|
/* callbacks */
|
||||||
static int _udp_callback_read(int fd, UDP * udp);
|
static int _udp_callback_read(int fd, UDP * udp);
|
||||||
|
|
||||||
|
@ -145,53 +171,9 @@ static UDP * _udp_init(AppTransportPluginHelper * helper,
|
||||||
return udp;
|
return udp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _init_address(UDP * udp, char const * name, int domain)
|
|
||||||
{
|
|
||||||
char sep = ':';
|
|
||||||
char * p;
|
|
||||||
char * q;
|
|
||||||
char * r;
|
|
||||||
long l;
|
|
||||||
struct addrinfo hints;
|
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
/* guess the port separator */
|
|
||||||
if((q = strchr(name, ':')) != NULL && strchr(++q, ':') != NULL)
|
|
||||||
sep = '.';
|
|
||||||
/* obtain the name */
|
|
||||||
if((p = strdup(name)) == NULL)
|
|
||||||
return -error_set_code(1, "%s", strerror(errno));
|
|
||||||
/* obtain the port number */
|
|
||||||
if((q = strrchr(p, sep)) == NULL)
|
|
||||||
l = -error_set_code(1, "%s", strerror(EINVAL));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*(q++) = '\0';
|
|
||||||
l = strtol(q, &r, 10);
|
|
||||||
if(q[0] == '\0' || *r != '\0')
|
|
||||||
l = -error_set_code(1, "%s", strerror(EINVAL));
|
|
||||||
}
|
|
||||||
/* FIXME perform this asynchronously */
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
|
||||||
hints.ai_family = domain;
|
|
||||||
hints.ai_socktype = SOCK_DGRAM;
|
|
||||||
if(l >= 0)
|
|
||||||
res = getaddrinfo(p, q, &hints, &udp->ai);
|
|
||||||
free(p);
|
|
||||||
/* check for errors */
|
|
||||||
if(res != 0)
|
|
||||||
{
|
|
||||||
error_set_code(1, "%s", gai_strerror(res));
|
|
||||||
if(udp->ai != NULL)
|
|
||||||
freeaddrinfo(udp->ai);
|
|
||||||
udp->ai = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return (udp->ai != NULL) ? 0 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _init_client(UDP * udp, char const * name)
|
static int _init_client(UDP * udp, char const * name)
|
||||||
{
|
{
|
||||||
|
memset(&udp->u, 0, sizeof(udp->u));
|
||||||
/* obtain the remote address */
|
/* obtain the remote address */
|
||||||
if(_init_address(udp, name, UDP_FAMILY) != 0)
|
if(_init_address(udp, name, UDP_FAMILY) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -200,14 +182,6 @@ static int _init_client(UDP * udp, char const * name)
|
||||||
/* create the socket */
|
/* create the socket */
|
||||||
if(_init_socket(udp, udp->aip->ai_family) != 0)
|
if(_init_socket(udp, udp->aip->ai_family) != 0)
|
||||||
continue;
|
continue;
|
||||||
/* accept incoming messages */
|
|
||||||
if(bind(udp->fd, udp->aip->ai_addr, udp->aip->ai_addrlen) != 0)
|
|
||||||
{
|
|
||||||
_udp_error("bind", 1);
|
|
||||||
close(udp->fd);
|
|
||||||
udp->fd = -1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* listen for incoming messages */
|
/* listen for incoming messages */
|
||||||
event_register_io_read(udp->helper->event, udp->fd,
|
event_register_io_read(udp->helper->event, udp->fd,
|
||||||
(EventIOFunc)_udp_callback_read, udp);
|
(EventIOFunc)_udp_callback_read, udp);
|
||||||
|
@ -224,6 +198,8 @@ static int _init_client(UDP * udp, char const * name)
|
||||||
|
|
||||||
static int _init_server(UDP * udp, char const * name)
|
static int _init_server(UDP * udp, char const * name)
|
||||||
{
|
{
|
||||||
|
udp->u.server.clients = NULL;
|
||||||
|
udp->u.server.clients_cnt = 0;
|
||||||
/* obtain the local address */
|
/* obtain the local address */
|
||||||
if(_init_address(udp, name, UDP_FAMILY) != 0)
|
if(_init_address(udp, name, UDP_FAMILY) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -232,6 +208,14 @@ static int _init_server(UDP * udp, char const * name)
|
||||||
/* create the socket */
|
/* create the socket */
|
||||||
if(_init_socket(udp, udp->aip->ai_family) != 0)
|
if(_init_socket(udp, udp->aip->ai_family) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
/* accept incoming messages */
|
||||||
|
if(bind(udp->fd, udp->aip->ai_addr, udp->aip->ai_addrlen) != 0)
|
||||||
|
{
|
||||||
|
_udp_error("bind", 1);
|
||||||
|
close(udp->fd);
|
||||||
|
udp->fd = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
/* listen for incoming messages */
|
/* listen for incoming messages */
|
||||||
event_register_io_read(udp->helper->event, udp->fd,
|
event_register_io_read(udp->helper->event, udp->fd,
|
||||||
(EventIOFunc)_udp_callback_read, udp);
|
(EventIOFunc)_udp_callback_read, udp);
|
||||||
|
@ -266,8 +250,18 @@ static int _init_socket(UDP * udp, int domain)
|
||||||
|
|
||||||
|
|
||||||
/* udp_destroy */
|
/* udp_destroy */
|
||||||
|
static void _destroy_server(UDP * udp);
|
||||||
|
|
||||||
static void _udp_destroy(UDP * udp)
|
static void _udp_destroy(UDP * udp)
|
||||||
{
|
{
|
||||||
|
switch(udp->mode)
|
||||||
|
{
|
||||||
|
case ATM_CLIENT:
|
||||||
|
break;
|
||||||
|
case ATM_SERVER:
|
||||||
|
_destroy_server(udp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if(udp->fd >= 0)
|
if(udp->fd >= 0)
|
||||||
close(udp->fd);
|
close(udp->fd);
|
||||||
free(udp->messages);
|
free(udp->messages);
|
||||||
|
@ -276,31 +270,57 @@ static void _udp_destroy(UDP * udp)
|
||||||
object_delete(udp);
|
object_delete(udp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _destroy_server(UDP * udp)
|
||||||
|
{
|
||||||
|
AppTransportPluginHelper * helper = udp->helper;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for(i = 0; i < udp->u.server.clients_cnt; i++)
|
||||||
|
{
|
||||||
|
helper->client_delete(helper->transport,
|
||||||
|
udp->u.server.clients[i]->client);
|
||||||
|
free(udp->u.server.clients[i]->sa);
|
||||||
|
free(udp->u.server.clients[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* udp_send */
|
/* udp_send */
|
||||||
static int _udp_send(UDP * udp, AppMessage * message, int acknowledge)
|
static int _udp_send(UDP * udp, AppMessage * message, int acknowledge)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
Buffer * buffer;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
struct sockaddr_in * sa;
|
struct sockaddr_in * sa;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(udp->mode != ATM_CLIENT)
|
if(udp->mode != ATM_CLIENT)
|
||||||
return -error_set_code(1, "%s", "Not a client");
|
return -error_set_code(1, "%s", "Not a client");
|
||||||
|
/* FIXME confirm the message will be consistent and readable */
|
||||||
|
if((buffer = buffer_new(0, NULL)) == NULL)
|
||||||
|
return -1;
|
||||||
|
if(appmessage_serialize(message, buffer) != 0)
|
||||||
|
{
|
||||||
|
buffer_delete(buffer);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(udp->aip->ai_family == AF_INET)
|
if(udp->aip->ai_family == AF_INET)
|
||||||
{
|
{
|
||||||
sa = (struct sockaddr_in *)udp->aip->ai_addr;
|
sa = (struct sockaddr_in *)udp->aip->ai_addr;
|
||||||
fprintf(stderr, "DEBUG: %s() %s (%s:%u)\n", __func__,
|
fprintf(stderr, "DEBUG: %s() %s (%s:%u) size=%lu\n", __func__,
|
||||||
"sendto()", inet_ntoa(sa->sin_addr),
|
"sendto()", inet_ntoa(sa->sin_addr),
|
||||||
ntohs(sa->sin_port));
|
ntohs(sa->sin_port), buffer_get_size(buffer));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fprintf(stderr, "DEBUG: %s() %s %d\n", __func__,
|
fprintf(stderr, "DEBUG: %s() %s family=%d size=%lu\n", __func__,
|
||||||
"sendto()", udp->aip->ai_family);
|
"sendto()", udp->aip->ai_family,
|
||||||
|
buffer_get_size(buffer));
|
||||||
#endif
|
#endif
|
||||||
/* FIXME really implement */
|
ret = sendto(udp->fd, buffer_get_data(buffer), buffer_get_size(buffer),
|
||||||
return sendto(udp->fd, NULL, 0, 0, udp->aip->ai_addr,
|
0, udp->aip->ai_addr, udp->aip->ai_addrlen);
|
||||||
udp->aip->ai_addrlen);
|
buffer_delete(buffer);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -313,14 +333,42 @@ static int _udp_error(char const * message, int code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* clients */
|
||||||
|
/* udp_client_init */
|
||||||
|
static int _udp_client_init(UDPClient * client, struct sockaddr * sa,
|
||||||
|
socklen_t sa_len, UDP * udp)
|
||||||
|
{
|
||||||
|
AppTransportPluginHelper * helper = udp->helper;
|
||||||
|
|
||||||
|
if((client->sa = malloc(sa_len)) == NULL)
|
||||||
|
return -1;
|
||||||
|
if((client->client = helper->client_new(helper->transport)) == NULL)
|
||||||
|
{
|
||||||
|
free(client->sa);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(client->sa, sa, sa_len);
|
||||||
|
client->sa_len = sa_len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* callbacks */
|
/* callbacks */
|
||||||
/* udp_callback_read */
|
/* udp_callback_read */
|
||||||
|
static void _callback_read_client(UDP * udp, struct sockaddr * sa,
|
||||||
|
socklen_t sa_len, AppMessage * message);
|
||||||
|
static void _callback_read_server(UDP * udp, struct sockaddr * sa,
|
||||||
|
socklen_t sa_len, AppMessage * message);
|
||||||
|
|
||||||
static int _udp_callback_read(int fd, UDP * udp)
|
static int _udp_callback_read(int fd, UDP * udp)
|
||||||
{
|
{
|
||||||
char buf[65536];
|
char buf[65536];
|
||||||
ssize_t ssize;
|
ssize_t ssize;
|
||||||
struct sockaddr * sa;
|
struct sockaddr * sa;
|
||||||
socklen_t sa_len = udp->aip->ai_addrlen;
|
socklen_t sa_len = udp->aip->ai_addrlen;
|
||||||
|
size_t size;
|
||||||
|
Buffer * buffer;
|
||||||
|
AppMessage * message = NULL;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "DEBUG: %s(%d)\n", __func__, fd);
|
fprintf(stderr, "DEBUG: %s(%d)\n", __func__, fd);
|
||||||
|
@ -339,18 +387,81 @@ static int _udp_callback_read(int fd, UDP * udp)
|
||||||
udp->fd = -1;
|
udp->fd = -1;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if(ssize == 0)
|
|
||||||
{
|
|
||||||
/* FIXME really implement */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* FIXME really implement */
|
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "DEBUG: %s() received message (%ld)\n", __func__,
|
fprintf(stderr, "DEBUG: %s() ssize=%ld\n", __func__, ssize);
|
||||||
ssize);
|
|
||||||
#endif
|
#endif
|
||||||
|
size = ssize;
|
||||||
|
if((buffer = buffer_new(ssize, buf)) == NULL)
|
||||||
|
{
|
||||||
free(sa);
|
free(sa);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
message = appmessage_new_deserialize(buffer);
|
||||||
|
buffer_delete(buffer);
|
||||||
|
if(message == NULL)
|
||||||
|
{
|
||||||
|
/* FIXME report error */
|
||||||
|
free(sa);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
switch(udp->mode)
|
||||||
|
{
|
||||||
|
case ATM_CLIENT:
|
||||||
|
_callback_read_client(udp, sa, sa_len, message);
|
||||||
|
break;
|
||||||
|
case ATM_SERVER:
|
||||||
|
_callback_read_server(udp, sa, sa_len, message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
appmessage_delete(message);
|
||||||
|
free(sa);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _callback_read_client(UDP * udp, struct sockaddr * sa,
|
||||||
|
socklen_t sa_len, AppMessage * message)
|
||||||
|
{
|
||||||
|
/* FIXME implement */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _callback_read_server(UDP * udp, struct sockaddr * sa,
|
||||||
|
socklen_t sa_len, AppMessage * message)
|
||||||
|
{
|
||||||
|
AppTransportPluginHelper * helper = udp->helper;
|
||||||
|
size_t i;
|
||||||
|
UDPClient ** p;
|
||||||
|
AppTransportClient * client;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||||
|
#endif
|
||||||
|
for(i = 0; i < udp->u.server.clients_cnt; i++)
|
||||||
|
if(udp->u.server.clients[i]->sa_len == sa_len
|
||||||
|
&& memcmp(udp->u.server.clients[i]->sa, sa,
|
||||||
|
sa_len) == 0)
|
||||||
|
break;
|
||||||
|
if(i == udp->u.server.clients_cnt)
|
||||||
|
{
|
||||||
|
if((p = realloc(udp->u.server.clients, sizeof(*p) * (i + 1)))
|
||||||
|
== NULL)
|
||||||
|
/* FIXME report error */
|
||||||
|
return;
|
||||||
|
udp->u.server.clients = p;
|
||||||
|
if((udp->u.server.clients[i] = malloc(sizeof(*p))) == NULL)
|
||||||
|
/* FIXME report error */
|
||||||
|
return;
|
||||||
|
if(_udp_client_init(udp->u.server.clients[i], sa, sa_len, udp)
|
||||||
|
!= 0)
|
||||||
|
{
|
||||||
|
/* FIXME report error */
|
||||||
|
free(p[i]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
udp->u.server.clients_cnt++;
|
||||||
|
}
|
||||||
|
client = udp->u.server.clients[i]->client;
|
||||||
|
helper->client_receive(helper->transport, client, message);
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s() received message\n", __func__);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user