summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-12-09 11:42:17 -0200
committerGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-12-09 13:47:04 -0200
commitafdbe897a0cc46a3ae945110e83323d40c1ecc8e (patch)
tree5d39ac20ccb2ca10a02ac4c9fbea20d6fa3df6d6
parent83cbcf7cb534b3e2690a0f151e5fa490144f3822 (diff)
downloadefl-afdbe897a0cc46a3ae945110e83323d40c1ecc8e.tar.gz
efl_net: optimize serving of IP addresses.
If we can parse the IP using inet_pton() and the port, there is no reason to call getaddrinfo() in a thread. This is required since ecore_con_suite (for ecore_con-over-efl_net) will assume the server is running as soon as it's created.
-rw-r--r--src/lib/ecore_con/ecore_con.c113
-rw-r--r--src/lib/ecore_con/ecore_con_private.h2
-rw-r--r--src/lib/ecore_con/efl_net_server_tcp.c29
-rw-r--r--src/lib/ecore_con/efl_net_server_udp.c28
4 files changed, 115 insertions, 57 deletions
diff --git a/src/lib/ecore_con/ecore_con.c b/src/lib/ecore_con/ecore_con.c
index 7b613715cc..84f639d85f 100644
--- a/src/lib/ecore_con/ecore_con.c
+++ b/src/lib/ecore_con/ecore_con.c
@@ -3085,6 +3085,69 @@ efl_net_unix_fmt(char *buf, size_t buflen, SOCKET fd, const struct sockaddr_un *
}
#endif
+/* The reverse of efl_net_ip_port_fmt().
+ *
+ * If was parsed, then returns EINA_TRUE, otherwise use getaddrinfo()
+ * or efl_net_ip_resolve_async_new().
+ */
+Eina_Bool
+efl_net_ip_port_parse(const char *address, struct sockaddr_storage *storage)
+{
+ char *str;
+ const char *host, *port;
+ Eina_Bool ret;
+
+ str = strdup(address);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(str, EINA_FALSE);
+ if (!efl_net_ip_port_split(str, &host, &port))
+ {
+ ERR("invalid IP:PORT address: %s", address);
+ ret = EINA_FALSE;
+ }
+ else
+ ret = efl_net_ip_port_parse_split(host, port, storage);
+
+ free(str);
+ return ret;
+}
+
+Eina_Bool
+efl_net_ip_port_parse_split(const char *host, const char *port, struct sockaddr_storage *storage)
+{
+ int x;
+ char *endptr;
+ unsigned long p;
+
+ if (!port) port = "0";
+
+ if (strchr(host, ':')) storage->ss_family = AF_INET6;
+ else storage->ss_family = AF_INET;
+
+ errno = 0;
+ p = strtoul(port, &endptr, 10);
+ if ((errno) || (endptr == port) || (*endptr != '\0')) return EINA_FALSE;
+ else if (p > UINT16_MAX)
+ {
+ ERR("invalid port number %lu (out of range)", p);
+ return EINA_FALSE;
+ }
+
+ if (storage->ss_family == AF_INET6)
+ {
+ struct sockaddr_in6 *a = (struct sockaddr_in6 *)storage;
+ a->sin6_port = htons(p);
+ x = inet_pton(AF_INET6, host, &a->sin6_addr);
+ }
+ else
+ {
+ struct sockaddr_in *a = (struct sockaddr_in *)storage;
+ a->sin_port = htons(p);
+ x = inet_pton(AF_INET, host, &a->sin_addr);
+ }
+
+ return x == 1;
+}
+
Eina_Bool
efl_net_ip_port_fmt(char *buf, size_t buflen, const struct sockaddr *addr)
{
@@ -3262,62 +3325,20 @@ efl_net_ip_socket_activate_check(const char *address, int family, int type, Eina
}
if (!port) port = "0";
- if ((family == AF_UNSPEC) && (strchr(host, ':'))) family = AF_INET6;
-
- if (family == AF_INET6)
- {
- struct sockaddr_in6 *a = (struct sockaddr_in6 *)&want_addr;
- x = inet_pton(AF_INET6, host, &a->sin6_addr);
- }
- else
- {
- struct sockaddr_in *a = (struct sockaddr_in *)&want_addr;
- x = inet_pton(AF_INET, host, &a->sin_addr);
- }
-
- /* FAST PATH: numbers were provided */
- if (x == 1)
+ if (efl_net_ip_port_parse_split(host, port, &want_addr))
{
- char *endptr;
- unsigned long p;
Eina_Bool matches;
- want_addr.ss_family = family;
if (want_addr.ss_family != sock_addr.ss_family)
{
ERR("socket " SOCKET_FMT " family=%d differs from wanted %d", fd, sock_addr.ss_family, want_addr.ss_family);
free(str);
return EINVAL;
}
-
- errno = 0;
- p = strtoul(port, &endptr, 10);
- if ((errno) || (endptr == port) || (*endptr != '\0'))
- {
- ERR("invalid port number '%s'", port);
- free(str);
- return EINVAL;
- }
- else if (p > UINT16_MAX)
- {
- ERR("invalid port number %lu (out of range)", p);
- free(str);
- return ERANGE;
- }
-
- if (family == AF_INET6)
- {
- struct sockaddr_in6 *a = (struct sockaddr_in6 *)&want_addr;
- a->sin6_port = htons(p);
- matches = memcmp(a, &sock_addr, sizeof(*a)) == 0;
- }
+ else if (want_addr.ss_family == AF_INET6)
+ matches = memcmp(&want_addr, &sock_addr, sizeof(struct sockaddr_in6)) == 0;
else
- {
- struct sockaddr_in *a = (struct sockaddr_in *)&want_addr;
- x = inet_pton(AF_INET, host, &a->sin_addr);
- a->sin_port = htons(p);
- matches = memcmp(a, &sock_addr, sizeof(*a)) == 0;
- }
+ matches = memcmp(&want_addr, &sock_addr, sizeof(struct sockaddr_in)) == 0;
if (!matches)
{
diff --git a/src/lib/ecore_con/ecore_con_private.h b/src/lib/ecore_con/ecore_con_private.h
index bf70f64292..9db016b003 100644
--- a/src/lib/ecore_con/ecore_con_private.h
+++ b/src/lib/ecore_con/ecore_con_private.h
@@ -447,6 +447,8 @@ void _efl_net_socket_udp_init(Eo *o, const struct sockaddr *addr, socklen_t addr
#ifndef _WIN32
Eina_Bool efl_net_unix_fmt(char *buf, size_t buflen, SOCKET fd, const struct sockaddr_un *addr, socklen_t addrlen);
#endif
+Eina_Bool efl_net_ip_port_parse(const char *address, struct sockaddr_storage *storage);
+Eina_Bool efl_net_ip_port_parse_split(const char *host, const char *port, struct sockaddr_storage *storage);
Eina_Bool efl_net_ip_port_fmt(char *buf, size_t buflen, const struct sockaddr *addr);
#ifdef HAVE_SYSTEMD
diff --git a/src/lib/ecore_con/efl_net_server_tcp.c b/src/lib/ecore_con/efl_net_server_tcp.c
index bdb081233e..93d502416c 100644
--- a/src/lib/ecore_con/efl_net_server_tcp.c
+++ b/src/lib/ecore_con/efl_net_server_tcp.c
@@ -223,6 +223,8 @@ _efl_net_server_tcp_efl_net_server_serve(Eo *o, Efl_Net_Server_Tcp_Data *pd, con
.ai_family = AF_UNSPEC,
.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED,
};
+ struct sockaddr_storage ss;
+ Eina_Error err;
EINA_SAFETY_ON_NULL_RETURN_VAL(address, EINVAL);
@@ -233,13 +235,28 @@ _efl_net_server_tcp_efl_net_server_serve(Eo *o, Efl_Net_Server_Tcp_Data *pd, con
return EINVAL;
}
if (!port) port = "0";
- if (strchr(host, ':')) hints.ai_family = AF_INET6;
- pd->resolver = efl_net_ip_resolve_async_new(host, port, &hints,
- _efl_net_server_tcp_resolved, o);
- free(str);
- EINA_SAFETY_ON_NULL_RETURN_VAL(pd->resolver, EINVAL);
- return 0;
+ if (efl_net_ip_port_parse_split(host, port, &ss))
+ {
+ struct addrinfo ai = hints;
+
+ ai.ai_family = ss.ss_family;
+ ai.ai_addr = (struct sockaddr *)&ss;
+ ai.ai_addrlen = ss.ss_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
+
+ err = _efl_net_server_tcp_resolved_bind(o, pd, &ai);
+ free(str);
+ }
+ else
+ {
+ pd->resolver = efl_net_ip_resolve_async_new(host, port, &hints,
+ _efl_net_server_tcp_resolved, o);
+ free(str);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd->resolver, EINVAL);
+ err = 0;
+ }
+
+ return err;
}
static void
diff --git a/src/lib/ecore_con/efl_net_server_udp.c b/src/lib/ecore_con/efl_net_server_udp.c
index 4b297939ae..27928e02cd 100644
--- a/src/lib/ecore_con/efl_net_server_udp.c
+++ b/src/lib/ecore_con/efl_net_server_udp.c
@@ -259,6 +259,8 @@ _efl_net_server_udp_efl_net_server_serve(Eo *o, Efl_Net_Server_Udp_Data *pd, con
.ai_family = AF_UNSPEC,
.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED,
};
+ struct sockaddr_storage ss;
+ Eina_Error err;
EINA_SAFETY_ON_NULL_RETURN_VAL(address, EINVAL);
@@ -271,11 +273,27 @@ _efl_net_server_udp_efl_net_server_serve(Eo *o, Efl_Net_Server_Udp_Data *pd, con
if (!port) port = "0";
if (strchr(host, ':')) hints.ai_family = AF_INET6;
- pd->resolver = efl_net_ip_resolve_async_new(host, port, &hints,
- _efl_net_server_udp_resolved, o);
- free(str);
- EINA_SAFETY_ON_NULL_RETURN_VAL(pd->resolver, EINVAL);
- return 0;
+ if (efl_net_ip_port_parse_split(host, port, &ss))
+ {
+ struct addrinfo ai = hints;
+
+ ai.ai_family = ss.ss_family;
+ ai.ai_addr = (struct sockaddr *)&ss;
+ ai.ai_addrlen = ss.ss_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
+
+ err = _efl_net_server_udp_resolved_bind(o, pd, &ai);
+ free(str);
+ }
+ else
+ {
+ pd->resolver = efl_net_ip_resolve_async_new(host, port, &hints,
+ _efl_net_server_udp_resolved, o);
+ free(str);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pd->resolver, EINVAL);
+ err = 0;
+ }
+
+ return err;
}
static void