ecore_con: add an intermediate Efl.Net.Server.Ip

This commit is contained in:
Cedric BAIL 2017-09-29 14:12:03 -07:00
parent f73d794132
commit b7049e8c43
14 changed files with 142 additions and 204 deletions

View File

@ -16,6 +16,7 @@ ecore_con_eolian_files = \
lib/ecore_con/efl_net_server.eo \
lib/ecore_con/efl_net_server_simple.eo \
lib/ecore_con/efl_net_server_fd.eo \
lib/ecore_con/efl_net_server_ip.eo \
lib/ecore_con/efl_net_server_tcp.eo \
lib/ecore_con/efl_net_server_udp.eo \
lib/ecore_con/efl_net_server_udp_client.eo \
@ -108,6 +109,7 @@ lib/ecore_con/efl_net_dialer_websocket.c \
lib/ecore_con/efl_net_server.c \
lib/ecore_con/efl_net_server_simple.c \
lib/ecore_con/efl_net_server_fd.c \
lib/ecore_con/efl_net_server_ip.c \
lib/ecore_con/efl_net_server_tcp.c \
lib/ecore_con/efl_net_server_udp.c \
lib/ecore_con/efl_net_server_udp_client.c \

View File

@ -425,7 +425,7 @@ _server_serving(void *data EINA_UNUSED, const Efl_Event *event)
fprintf(stderr,
"TCP options:\n"
" - IPv6 only: %u\n",
efl_net_server_tcp_ipv6_only_get(event->object));
efl_net_server_ip_ipv6_only_get(event->object));
}
else if (efl_class_get(event->object) == EFL_NET_SERVER_UDP_CLASS)
{
@ -439,7 +439,7 @@ _server_serving(void *data EINA_UNUSED, const Efl_Event *event)
" - multicast TTL: %u\n"
" - multicast loopback: %u\n"
" - multicast groups:\n",
efl_net_server_udp_ipv6_only_get(event->object),
efl_net_server_ip_ipv6_only_get(event->object),
efl_net_server_udp_dont_route_get(event->object),
efl_net_server_udp_multicast_time_to_live_get(event->object),
efl_net_server_udp_multicast_loopback_get(event->object));
@ -651,7 +651,7 @@ main(int argc, char **argv)
if (cls == EFL_NET_SERVER_TCP_CLASS)
{
efl_net_server_tcp_ipv6_only_set(server, ipv6_only);
efl_net_server_ip_ipv6_only_set(server, ipv6_only);
efl_net_server_fd_reuse_address_set(server, EINA_TRUE); /* optional, but nice for testing */
efl_net_server_fd_reuse_port_set(server, EINA_TRUE); /* optional, but nice for testing... not secure unless you know what you're doing */
@ -661,7 +661,7 @@ main(int argc, char **argv)
{
const Eina_List *lst;
efl_net_server_udp_ipv6_only_set(server, ipv6_only);
efl_net_server_ip_ipv6_only_set(server, ipv6_only);
efl_net_server_udp_dont_route_set(server, udp_dont_route);
efl_net_server_udp_multicast_time_to_live_set(server, udp_mcast_ttl);

View File

@ -229,7 +229,7 @@ _server_serving(void *data EINA_UNUSED, const Efl_Event *event)
fprintf(stderr,
"TCP options:\n"
" - IPv6 only: %u\n",
efl_net_server_tcp_ipv6_only_get(event->object));
efl_net_server_ip_ipv6_only_get(event->object));
}
else if (efl_class_get(event->object) == EFL_NET_SERVER_UDP_CLASS)
{
@ -243,7 +243,7 @@ _server_serving(void *data EINA_UNUSED, const Efl_Event *event)
" - multicast TTL: %u\n"
" - multicast loopback: %u\n"
" - multicast groups:\n",
efl_net_server_udp_ipv6_only_get(event->object),
efl_net_server_ip_ipv6_only_get(event->object),
efl_net_server_udp_dont_route_get(event->object),
efl_net_server_udp_multicast_time_to_live_get(event->object),
efl_net_server_udp_multicast_loopback_get(event->object));
@ -459,7 +459,7 @@ main(int argc, char **argv)
if (cls == EFL_NET_SERVER_TCP_CLASS)
{
efl_net_server_tcp_ipv6_only_set(server, ipv6_only);
efl_net_server_ip_ipv6_only_set(server, ipv6_only);
efl_net_server_fd_reuse_address_set(server, EINA_TRUE); /* optional, but nice for testing */
efl_net_server_fd_reuse_port_set(server, EINA_TRUE); /* optional, but nice for testing... not secure unless you know what you're doing */
@ -469,7 +469,7 @@ main(int argc, char **argv)
{
const Eina_List *lst;
efl_net_server_udp_ipv6_only_set(server, ipv6_only);
efl_net_server_ip_ipv6_only_set(server, ipv6_only);
efl_net_server_udp_dont_route_set(server, udp_dont_route);
efl_net_server_udp_multicast_time_to_live_set(server, udp_mcast_ttl);

View File

@ -311,7 +311,7 @@ main(int argc, char **argv)
eina_iterator_free(it);
server = efl_add(EFL_NET_SERVER_TCP_CLASS, ecore_main_loop_get(), /* it's mandatory to use a main loop provider as the server parent */
efl_net_server_tcp_ipv6_only_set(efl_added, EINA_FALSE), /* optional, but helps testing IPv4 on IPv6 servers */
efl_net_server_ip_ipv6_only_set(efl_added, EINA_FALSE), /* optional, but helps testing IPv4 on IPv6 servers */
efl_net_server_fd_reuse_address_set(efl_added, EINA_TRUE), /* optional, but nice for testing */
efl_net_server_fd_reuse_port_set(efl_added, EINA_TRUE), /* optional, but nice for testing... not secure unless you know what you're doing */
efl_event_callback_array_add(efl_added, server_cbs(), NULL)); /* mandatory to have "client,add" in order to be useful */

View File

@ -13,6 +13,8 @@
#include "efl_net_socket_fd.eo.h"
#include "efl_net_server_fd.eo.h"
#include "efl_net_server_ip.eo.h"
#include "efl_net_socket_tcp.eo.h"
#include "efl_net_dialer_tcp.eo.h"
#include "efl_net_server_tcp.eo.h"

View File

@ -1515,12 +1515,12 @@ _ecore_con_server_server_set(Ecore_Con_Server *svr, Eo *server)
if (efl_isa(inner_server, EFL_NET_SERVER_TCP_CLASS))
{
/* old ecore_con did not map ipv4 to ipv6... */
efl_net_server_tcp_ipv6_only_set(inner_server, EINA_TRUE);
efl_net_server_ip_ipv6_only_set(inner_server, EINA_TRUE);
}
else if (efl_isa(inner_server, EFL_NET_SERVER_UDP_CLASS))
{
/* old ecore_con did not map ipv4 to ipv6... */
efl_net_server_udp_ipv6_only_set(inner_server, EINA_TRUE);
efl_net_server_ip_ipv6_only_set(inner_server, EINA_TRUE);
svr->want_mcast = type == ECORE_CON_REMOTE_MCAST;
}
else if (efl_isa(inner_server, EFL_NET_SERVER_SSL_CLASS))

View File

@ -0,0 +1,82 @@
#define EFL_NET_SERVER_FD_PROTECTED 1
#define EFL_NET_SERVER_PROTECTED 1
#define EFL_LOOP_FD_PROTECTED 1
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "Ecore.h"
#include "Ecore_Con.h"
#include "ecore_con_private.h"
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_TCP_H
# include <netinet/tcp.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef _WIN32
# include <Evil.h>
#endif
#define MY_CLASS EFL_NET_SERVER_IP_CLASS
typedef struct _Efl_Net_Server_Ip_Data
{
Eina_Bool ipv6_only;
} Efl_Net_Server_Ip_Data;
EOLIAN Efl_Object *
_efl_net_server_ip_efl_object_constructor(Eo *o, Efl_Net_Server_Ip_Data *pd)
{
pd->ipv6_only = 0xff;
return efl_constructor(efl_super(o, MY_CLASS));
}
EOLIAN void
_efl_net_server_ip_ipv6_only_set(Eo *o, Efl_Net_Server_Ip_Data *pd, Eina_Bool ipv6_only)
{
#ifdef IPV6_V6ONLY
SOCKET fd = efl_loop_fd_get(o);
#ifdef _WIN32
DWORD value = ipv6_only;
int valuelen;
#else
int value = ipv6_only;
socklen_t valuelen;
#endif
#endif
#ifdef IPV6_V6ONLY
if (fd == INVALID_SOCKET) return;
if (efl_net_server_fd_family_get(o) != AF_INET6) return;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&value, sizeof(value)) != 0)
{
ERR("could not set socket=" SOCKET_FMT " IPV6_V6ONLY=%d: %s", fd, (int)value, eina_error_msg_get(efl_net_socket_error_get()));
}
valuelen = sizeof(value);
if (getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&value, &valuelen) != 0)
{
WRN("getsockopt(" SOCKET_FMT ", IPPROTO_IPV6, IPV6_V6ONLY): %s", fd, eina_error_msg_get(efl_net_socket_error_get()));
return ;
}
pd->ipv6_only = !!value;
#endif
}
EOLIAN Eina_Bool
_efl_net_server_ip_ipv6_only_get(Eo *o EINA_UNUSED, Efl_Net_Server_Ip_Data *pd)
{
return pd->ipv6_only;
}
#include "efl_net_server_ip.eo.c"

View File

@ -0,0 +1,38 @@
class Efl.Net.Server.Ip (Efl.Net.Server.Fd) {
[[An IP server.
@since 1.20
]]
methods {
@property ipv6_only {
[[Whenever IPv6 listen address will accept only same-family clients or will allow IPv4 to connect as well.
Since Linux 2.4.21, Windows Vista and MacOS X these
control whenever a server that did bind to an IPv6
address will accept only IPv6 clients or will also
accept IPv4 by automatically converting them in an IPv6
address, allowing a single socket to handle both
protocols.
If an IPv6 address was used in @Efl.Net.Server.address,
this property is $false and an IPv4 connects, then an
address such as [::ffff:IPv4]:PORT will be used, such as
[::ffff:192.168.0.2]:1234, where the IPv4 address can be
extracted.
If an IPv4 address was used in @Efl.Net.Server.address,
this has no effect.
Systems can configure their default value, usually true
(allows only IPv6 clients).
]]
values {
ipv6_only: bool; [[If $true the server will only accept IPv6 clients, $false otherwise]]
}
}
}
implements {
Efl.Object.constructor;
}
}

View File

@ -284,13 +284,13 @@ _efl_net_server_ssl_reuse_port_get(Eo *o EINA_UNUSED, Efl_Net_Server_Ssl_Data *p
EOLIAN void
_efl_net_server_ssl_ipv6_only_set(Eo *o EINA_UNUSED, Efl_Net_Server_Ssl_Data *pd, Eina_Bool ipv6_only)
{
efl_net_server_tcp_ipv6_only_set(pd->server, ipv6_only);
efl_net_server_ip_ipv6_only_set(pd->server, ipv6_only);
}
EOLIAN Eina_Bool
_efl_net_server_ssl_ipv6_only_get(Eo *o EINA_UNUSED, Efl_Net_Server_Ssl_Data *pd)
{
return efl_net_server_tcp_ipv6_only_get(pd->server);
return efl_net_server_ip_ipv6_only_get(pd->server);
}

View File

@ -32,16 +32,8 @@
typedef struct _Efl_Net_Server_Tcp_Data
{
Ecore_Thread *resolver;
Eina_Bool ipv6_only;
} Efl_Net_Server_Tcp_Data;
EOLIAN Efl_Object *
_efl_net_server_tcp_efl_object_constructor(Eo *o, Efl_Net_Server_Tcp_Data *pd)
{
pd->ipv6_only = 0xff;
return efl_constructor(efl_super(o, MY_CLASS));
}
EOLIAN void
_efl_net_server_tcp_efl_object_destructor(Eo *o, Efl_Net_Server_Tcp_Data *pd)
{
@ -80,10 +72,7 @@ _efl_net_server_tcp_resolved_bind(Eo *o, Efl_Net_Server_Tcp_Data *pd, const stru
/* apply pending value BEFORE bind() */
if (addr->ai_family == AF_INET6)
{
if (pd->ipv6_only == 0xff)
efl_net_server_tcp_ipv6_only_get(o); /* fetch & sync */
else
efl_net_server_tcp_ipv6_only_set(o, pd->ipv6_only);
efl_net_server_ip_ipv6_only_set(o, efl_net_server_ip_ipv6_only_get(o));
}
r = bind(fd, addr->ai_addr, addrlen);
@ -293,61 +282,4 @@ _efl_net_server_tcp_efl_net_server_fd_client_reject(Eo *o, Efl_Net_Server_Tcp_Da
efl_event_callback_call(o, EFL_NET_SERVER_EVENT_CLIENT_REJECTED, str);
}
EOLIAN void
_efl_net_server_tcp_ipv6_only_set(Eo *o, Efl_Net_Server_Tcp_Data *pd, Eina_Bool ipv6_only)
{
#ifdef IPV6_V6ONLY
Eina_Bool old = pd->ipv6_only;
SOCKET fd = efl_loop_fd_get(o);
#ifdef _WIN32
DWORD value = ipv6_only;
#else
int value = ipv6_only;
#endif
#endif
pd->ipv6_only = ipv6_only;
#ifdef IPV6_V6ONLY
if (fd == INVALID_SOCKET) return;
if (efl_net_server_fd_family_get(o) != AF_INET6) return;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&value, sizeof(value)) != 0)
{
ERR("could not set socket=" SOCKET_FMT " IPV6_V6ONLY=%d: %s", fd, (int)value, eina_error_msg_get(efl_net_socket_error_get()));
pd->ipv6_only = old;
}
#endif
}
EOLIAN Eina_Bool
_efl_net_server_tcp_ipv6_only_get(Eo *o EINA_UNUSED, Efl_Net_Server_Tcp_Data *pd)
{
#ifdef IPV6_V6ONLY
SOCKET fd = efl_loop_fd_get(o);
#ifdef _WIN32
DWORD value = 0;
int valuelen;
#else
int value = 0;
socklen_t valuelen;
#endif
if (fd == INVALID_SOCKET) goto end;
if (efl_net_server_fd_family_get(o) != AF_INET6) goto end;
valuelen = sizeof(value);
if (getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&value, &valuelen) != 0)
{
WRN("getsockopt(" SOCKET_FMT ", IPPROTO_IPV6, IPV6_V6ONLY): %s", fd, eina_error_msg_get(efl_net_socket_error_get()));
goto end;
}
pd->ipv6_only = !!value;
end:
#endif
return pd->ipv6_only;
}
#include "efl_net_server_tcp.eo.c"

View File

@ -1,40 +1,10 @@
class Efl.Net.Server.Tcp (Efl.Net.Server.Fd) {
class Efl.Net.Server.Tcp (Efl.Net.Server.Ip) {
[[A TCP server.
@since 1.19
]]
methods {
@property ipv6_only {
[[Whenever IPv6 listen address will accept only same-family clients or will allow IPv4 to connect as well.
Since Linux 2.4.21, Windows Vista and MacOS X these
control whenever a server that did bind to an IPv6
address will accept only IPv6 clients or will also
accept IPv4 by automatically converting them in an IPv6
address, allowing a single socket to handle both
protocols.
If an IPv6 address was used in @Efl.Net.Server.address,
this property is $false and an IPv4 connects, then an
address such as [::ffff:IPv4]:PORT will be used, such as
[::ffff:192.168.0.2]:1234, where the IPv4 address can be
extracted.
If an IPv4 address was used in @Efl.Net.Server.address,
this has no effect.
Systems can configure their default value, usually true
(allows only IPv6 clients).
]]
values {
ipv6_only: bool; [[If $true the server will only accept IPv6 clients, $false otherwise]]
}
}
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;
Efl.Net.Server.serve;
Efl.Net.Server.Fd.client_add;

View File

@ -42,14 +42,12 @@ typedef struct _Efl_Net_Server_Udp_Data
Eina_Bool loopback;
Eina_Bool ttl_set;
} multicast;
Eina_Bool ipv6_only;
Eina_Bool dont_route;
} Efl_Net_Server_Udp_Data;
EOLIAN Efl_Object *
_efl_net_server_udp_efl_object_constructor(Eo *o, Efl_Net_Server_Udp_Data *pd)
{
pd->ipv6_only = 0xff;
pd->clients = eina_hash_string_superfast_new(NULL);
pd->multicast.ttl = 1;
pd->multicast.ttl_set = EINA_FALSE;
@ -111,10 +109,7 @@ _efl_net_server_udp_resolved_bind(Eo *o, Efl_Net_Server_Udp_Data *pd, const stru
/* apply pending value BEFORE bind() */
if (addr->ai_family == AF_INET6)
{
if (pd->ipv6_only == 0xff)
efl_net_server_udp_ipv6_only_get(o); /* fetch & sync */
else
efl_net_server_udp_ipv6_only_set(o, pd->ipv6_only);
efl_net_server_ip_ipv6_only_set(o, efl_net_server_ip_ipv6_only_get(o));
}
efl_net_server_udp_dont_route_set(o, pd->dont_route);
@ -403,62 +398,6 @@ _efl_net_server_udp_efl_net_server_fd_process_incoming_data(Eo *o, Efl_Net_Serve
_efl_net_server_udp_client_feed(client, slice);
}
EOLIAN void
_efl_net_server_udp_ipv6_only_set(Eo *o, Efl_Net_Server_Udp_Data *pd, Eina_Bool ipv6_only)
{
#ifdef IPV6_V6ONLY
Eina_Bool old = pd->ipv6_only;
SOCKET fd = efl_loop_fd_get(o);
#ifdef _WIN32
DWORD value = ipv6_only;
#else
int value = ipv6_only;
#endif
#endif
pd->ipv6_only = ipv6_only;
#ifdef IPV6_V6ONLY
if (fd == INVALID_SOCKET) return;
if (efl_net_server_fd_family_get(o) != AF_INET6) return;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&value, sizeof(value)) != 0)
{
ERR("could not set socket=" SOCKET_FMT " IPV6_V6ONLY=%d: %s", fd, (int)value, eina_error_msg_get(efl_net_socket_error_get()));
pd->ipv6_only = old;
}
#endif
}
EOLIAN Eina_Bool
_efl_net_server_udp_ipv6_only_get(Eo *o EINA_UNUSED, Efl_Net_Server_Udp_Data *pd)
{
#ifdef IPV6_V6ONLY
SOCKET fd = efl_loop_fd_get(o);
#ifdef _WIN32
DWORD value = 0;
int valuelen;
#else
int value = 0;
socklen_t valuelen;
#endif
if (fd == INVALID_SOCKET) goto end;
if (efl_net_server_fd_family_get(o) != AF_INET6) goto end;
valuelen = sizeof(value);
if (getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&value, &valuelen) != 0)
{
WRN("getsockopt(" SOCKET_FMT ", IPPROTO_IPV6, IPV6_V6ONLY): %s", fd, eina_error_msg_get(efl_net_socket_error_get()));
goto end;
}
pd->ipv6_only = !!value;
end:
#endif
return pd->ipv6_only;
}
EOLIAN static Eina_Bool
_efl_net_server_udp_dont_route_set(Eo *o, Efl_Net_Server_Udp_Data *pd, Eina_Bool dont_route)
{

View File

@ -1,37 +1,10 @@
class Efl.Net.Server.Udp (Efl.Net.Server.Fd) {
class Efl.Net.Server.Udp (Efl.Net.Server.Ip) {
[[A UDP server.
@since 1.19
]]
methods {
@property ipv6_only {
[[Whenever IPv6 listen address will accept only same-family clients or will allow IPv4 to connect as well.
Since Linux 2.4.21, Windows Vista and MacOS X these
control whenever a server that did bind to an IPv6
address will accept only IPv6 clients or will also
accept IPv4 by automatically converting them in an IPv6
address, allowing a single socket to handle both
protocols.
If an IPv6 address was used in @Efl.Net.Server.address,
this property is $false and an IPv4 connects, then an
address such as [::ffff:IPv4]:PORT will be used, such as
[::ffff:192.168.0.2]:1234, where the IPv4 address can be
extracted.
If an IPv4 address was used in @Efl.Net.Server.address,
this has no effect.
Systems can configure their default value, usually true
(allows only IPv6 clients).
]]
values {
ipv6_only: bool; [[If $true the server will only accept IPv6 clients, $false otherwise]]
}
}
@property dont_route {
[[Avoids sent UDP packets being routed by a gateway, limiting them to the local network.

View File

@ -488,7 +488,7 @@ ecore_ipc_server_add(Ecore_Ipc_Type type, const char *name, int port, const void
if (efl_isa(svr->server, EFL_NET_SERVER_TCP_CLASS))
{
/* old ecore_con did not map ipv4 to ipv6... */
efl_net_server_tcp_ipv6_only_set(svr->server, EINA_TRUE);
efl_net_server_ip_ipv6_only_set(svr->server, EINA_TRUE);
}
else if (efl_isa(svr->server, EFL_NET_SERVER_SSL_CLASS))
{