forked from enlightenment/efl
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.
This commit is contained in:
parent
83cbcf7cb5
commit
afdbe897a0
|
@ -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)
|
||||
if (efl_net_ip_port_parse_split(host, port, &want_addr))
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue