{
ECORE_GETOPT_STORE_BOOL('r', "read-after-write", "Do a read after writes are done."),
ECORE_GETOPT_STORE_BOOL('c', "cork", "use UDP_CORK around messages to generate a single datagram."),
+ ECORE_GETOPT_STORE_BOOL('R', "dont-route", "Do not route packets via a gateway."),
ECORE_GETOPT_STORE_DOUBLE('t', "connect-timeout", "timeout in seconds for the connection phase"),
ECORE_GETOPT_VERSION('V', "version"),
ECORE_GETOPT_COPYRIGHT('C', "copyright"),
char *address = NULL;
Eina_Bool cork = EINA_FALSE;
Eina_Bool do_read = EINA_FALSE;
+ Eina_Bool dont_route = EINA_FALSE;
Eina_Bool quit_option = EINA_FALSE;
double timeout_dial = 30.0;
Ecore_Getopt_Value values[] = {
ECORE_GETOPT_VALUE_BOOL(do_read),
ECORE_GETOPT_VALUE_BOOL(cork),
+ ECORE_GETOPT_VALUE_BOOL(dont_route),
ECORE_GETOPT_VALUE_DOUBLE(timeout_dial),
/* standard block to provide version, copyright, license and help */
dialer = efl_add(EFL_NET_DIALER_UDP_CLASS, loop,
efl_name_set(efl_added, "dialer"),
efl_net_socket_udp_cork_set(efl_added, cork),
+ efl_net_socket_udp_dont_route_set(efl_added, dont_route),
efl_net_dialer_timeout_dial_set(efl_added, timeout_dial),
efl_event_callback_array_add(efl_added, dialer_cbs(), NULL));
{
fprintf(stderr, "INFO: serving at %s\n",
efl_net_server_address_get(event->object));
+
+ if (efl_class_get(event->object) == EFL_NET_SERVER_TCP_CLASS)
+ {
+ fprintf(stderr,
+ "TCP options:\n"
+ " - IPv6 only: %u\n",
+ efl_net_server_tcp_ipv6_only_get(event->object));
+ }
+ else if (efl_class_get(event->object) == EFL_NET_SERVER_UDP_CLASS)
+ {
+ fprintf(stderr,
+ "UDP options:\n"
+ " - IPv6 only: %u\n"
+ " - don't route: %u\n",
+ efl_net_server_udp_ipv6_only_get(event->object),
+ efl_net_server_udp_dont_route_get(event->object));
+ }
}
EFL_CALLBACKS_ARRAY_DEFINE(server_cbs,
ECORE_GETOPT_LICENSE('L', "license"),
ECORE_GETOPT_HELP('h', "help"),
+ ECORE_GETOPT_CATEGORY("udp", "UDP options"),
+ ECORE_GETOPT_STORE_BOOL(0, "udp-dont-route",
+ "If true, datagrams won't be routed using a gateway, being restricted to the local network."),
+
ECORE_GETOPT_CHOICE_METAVAR(0, NULL, "The server protocol.", "protocol",
protocols),
ECORE_GETOPT_STORE_METAVAR_STR(0, NULL,
"The server address to listen, such as "
"IPv4:PORT, [IPv6]:PORT, Unix socket path...",
"address"),
+
ECORE_GETOPT_SENTINEL
}
};
unsigned int clients_limit = 0;
Eina_Bool clients_reject_excess = EINA_FALSE;
Eina_Bool ipv6_only = EINA_TRUE;
+ Eina_Bool udp_dont_route = EINA_FALSE;
Eina_Bool quit_option = EINA_FALSE;
Ecore_Getopt_Value values[] = {
ECORE_GETOPT_VALUE_BOOL(echo),
ECORE_GETOPT_VALUE_BOOL(quit_option), /* -L/--license quits */
ECORE_GETOPT_VALUE_BOOL(quit_option), /* -h/--help quits */
+ ECORE_GETOPT_VALUE_BOOL(quit_option), /* category: udp */
+ ECORE_GETOPT_VALUE_BOOL(udp_dont_route),
+
/* positional argument */
ECORE_GETOPT_VALUE_STR(protocol),
ECORE_GETOPT_VALUE_STR(address),
goto end;
}
+ if (!protocol)
+ {
+ fputs("ERROR: missing protocol.\n", stderr);
+ retval = EXIT_FAILURE;
+ goto end;
+ }
+
if (strcmp(protocol, "tcp") == 0) cls = EFL_NET_SERVER_TCP_CLASS;
else if (strcmp(protocol, "udp") == 0) cls = EFL_NET_SERVER_UDP_CLASS;
else
if (cls == EFL_NET_SERVER_TCP_CLASS)
efl_net_server_tcp_ipv6_only_set(server, ipv6_only);
else if (cls == EFL_NET_SERVER_UDP_CLASS)
- efl_net_server_udp_ipv6_only_set(server, ipv6_only);
+ {
+ efl_net_server_udp_ipv6_only_set(server, ipv6_only);
+ efl_net_server_udp_dont_route_set(server, udp_dont_route);
+ }
/* an explicit call to efl_net_server_serve() after the object is
* constructed allows for more complex setup, such as interacting
Ecore_Thread *resolver;
Eina_Hash *clients; /* addr (string) -> client (Efl.Net.Server.Udp.Client) */
Eina_Bool ipv6_only;
+ Eina_Bool dont_route;
} Efl_Net_Server_Udp_Data;
EOLIAN Efl_Object *
efl_net_server_udp_ipv6_only_set(o, pd->ipv6_only);
}
+ efl_net_server_udp_dont_route_set(o, pd->dont_route);
+
r = bind(fd, addr->ai_addr, addrlen);
if (r < 0)
{
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)
+{
+ Eina_Bool old = pd->dont_route;
+ int fd = efl_loop_fd_get(o);
+#ifdef _WIN32
+ DWORD value = dont_route;
+#else
+ int value = dont_route;
+#endif
+
+ pd->dont_route = dont_route;
+
+ if (fd < 0) return EINA_TRUE;
+
+ if (setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &value, sizeof(value)) != 0)
+ {
+ Eina_Error err = efl_net_socket_error_get();
+ ERR("setsockopt(%d, SOL_SOCKET, SO_DONTROUTE, %u): %s", fd, dont_route, eina_error_msg_get(err));
+ pd->dont_route = old;
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+EOLIAN static Eina_Bool
+_efl_net_server_udp_dont_route_get(Eo *o, Efl_Net_Server_Udp_Data *pd)
+{
+ int fd = efl_loop_fd_get(o);
+#ifdef _WIN32
+ DWORD value;
+#else
+ int value;
+#endif
+ socklen_t valuelen;
+
+ if (fd < 0) return pd->dont_route;
+
+ /* if there is a fd, always query it directly as it may be modified
+ * elsewhere by nasty users.
+ */
+ valuelen = sizeof(value);
+ if (getsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &value, &valuelen) != 0)
+ {
+ Eina_Error err = efl_net_socket_error_get();
+ ERR("getsockopt(%d, SOL_SOCKET, SO_DONTROUTE): %s", fd, eina_error_msg_get(err));
+ return EINA_FALSE;
+ }
+
+ pd->dont_route = !!value; /* sync */
+ return pd->dont_route;
+}
+
+
#include "efl_net_server_udp.eo.c"
ipv6_only: bool;
}
}
+
+ @property dont_route {
+ [[Avoid sent UDP packets being routed by a gateway, limiting them to the local network.
+
+ This will use SO_DONTROUTE option to avoid gateways
+ routing sent packets to outside of local network. It's
+ useful for some protocols that only want local area to
+ be affected.
+ ]]
+ get { }
+ set {
+ return: bool (false); [[$true on success]]
+ }
+ values {
+ dont_route: bool;
+ }
+ }
}
implements {
typedef struct _Efl_Net_Socket_Udp_Data
{
Eina_Bool cork;
+ Eina_Bool dont_route;
} Efl_Net_Socket_Udp_Data;
EOLIAN static void
/* apply postponed values */
efl_net_socket_udp_cork_set(o, pd->cork);
+ efl_net_socket_udp_dont_route_set(o, pd->dont_route);
family = efl_net_socket_fd_family_get(o);
if (family == AF_UNSPEC) return;
return pd->cork;
}
+EOLIAN static Eina_Bool
+_efl_net_socket_udp_dont_route_set(Eo *o, Efl_Net_Socket_Udp_Data *pd, Eina_Bool dont_route)
+{
+ Eina_Bool old = pd->dont_route;
+ int fd = efl_loop_fd_get(o);
+#ifdef _WIN32
+ DWORD value = dont_route;
+#else
+ int value = dont_route;
+#endif
+
+ pd->dont_route = dont_route;
+
+ if (fd < 0) return EINA_TRUE;
+
+ if (setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &value, sizeof(value)) != 0)
+ {
+ Eina_Error err = efl_net_socket_error_get();
+ ERR("setsockopt(%d, SOL_SOCKET, SO_DONTROUTE, %u): %s", fd, dont_route, eina_error_msg_get(err));
+ pd->dont_route = old;
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+EOLIAN static Eina_Bool
+_efl_net_socket_udp_dont_route_get(Eo *o, Efl_Net_Socket_Udp_Data *pd)
+{
+ int fd = efl_loop_fd_get(o);
+#ifdef _WIN32
+ DWORD value;
+#else
+ int value;
+#endif
+ socklen_t valuelen;
+
+ if (fd < 0) return pd->dont_route;
+
+ /* if there is a fd, always query it directly as it may be modified
+ * elsewhere by nasty users.
+ */
+ valuelen = sizeof(value);
+ if (getsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &value, &valuelen) != 0)
+ {
+ Eina_Error err = efl_net_socket_error_get();
+ ERR("getsockopt(%d, SOL_SOCKET, SO_DONTROUTE): %s", fd, eina_error_msg_get(err));
+ return EINA_FALSE;
+ }
+
+ pd->dont_route = !!value; /* sync */
+ return pd->dont_route;
+}
+
#include "efl_net_socket_udp.eo.c"
cork: bool;
}
}
+
+ @property dont_route {
+ [[Avoid sent UDP packets being routed by a gateway, limiting them to the local network.
+
+ This will use SO_DONTROUTE option to avoid gateways
+ routing sent packets to outside of local network. It's
+ useful for some protocols that only want local area to
+ be affected.
+ ]]
+ get { }
+ set {
+ return: bool (false); [[$true on success]]
+ }
+ values {
+ dont_route: bool;
+ }
+ }
}
implements {