|
|
|
#include "first.h"
|
|
|
|
|
|
|
|
#include "sock_addr_cache.h"
|
|
|
|
|
|
|
|
#include "sys-socket.h"
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "buffer.h"
|
|
|
|
#include "sock_addr.h"
|
|
|
|
|
|
|
|
|
|
|
|
int sock_addr_cache_inet_ntop_copy_buffer(buffer * const restrict b, const sock_addr * const restrict saddr)
|
|
|
|
{
|
|
|
|
#define NTOP_CACHE_MAX 4
|
|
|
|
static int ndx4;
|
|
|
|
static struct { struct in_addr ipv4; } ntop4_cache[NTOP_CACHE_MAX];
|
|
|
|
static struct { char s[INET_ADDRSTRLEN+1]; } ntop4_strs[NTOP_CACHE_MAX];
|
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
static int ndx6;
|
|
|
|
static struct { struct in6_addr ipv6; } ntop6_cache[NTOP_CACHE_MAX];
|
|
|
|
static struct { char s[INET6_ADDRSTRLEN+1]; } ntop6_strs[NTOP_CACHE_MAX];
|
|
|
|
#endif
|
|
|
|
switch (saddr->plain.sa_family) {
|
|
|
|
case AF_INET:
|
|
|
|
for (int i = 0; i < NTOP_CACHE_MAX; ++i) {
|
|
|
|
if (ntop4_cache[i].ipv4.s_addr == saddr->ipv4.sin_addr.s_addr) {
|
|
|
|
buffer_copy_string(b, ntop4_strs[i].s);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
case AF_INET6:
|
|
|
|
for (int i = 0; i < NTOP_CACHE_MAX; ++i) {
|
|
|
|
if (0 == memcmp(ntop6_cache[i].ipv6.s6_addr,
|
|
|
|
saddr->ipv6.sin6_addr.s6_addr, 16)) {
|
|
|
|
buffer_copy_string(b, ntop6_strs[i].s);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (0 != sock_addr_inet_ntop_copy_buffer(b, saddr)) {
|
[multiple] reduce redundant NULL buffer checks
This commit is a large set of code changes and results in removal of
hundreds, perhaps thousands, of CPU instructions, a portion of which
are on hot code paths.
Most (buffer *) used by lighttpd are not NULL, especially since buffers
were inlined into numerous larger structs such as request_st and chunk.
In the small number of instances where that is not the case, a NULL
check is often performed earlier in a function where that buffer is
later used with a buffer_* func. In the handful of cases that remained,
a NULL check was added, e.g. with r->http_host and r->conf.server_tag.
- check for empty strings at config time and set value to NULL if blank
string will be ignored at runtime; at runtime, simple pointer check
for NULL can be used to check for a value that has been set and is not
blank ("")
- use buffer_is_blank() instead of buffer_string_is_empty(),
and use buffer_is_unset() instead of buffer_is_empty(),
where buffer is known not to be NULL so that NULL check can be skipped
- use buffer_clen() instead of buffer_string_length() when buffer is
known not to be NULL (to avoid NULL check at runtime)
- use buffer_truncate() instead of buffer_string_set_length() to
truncate string, and use buffer_extend() to extend
Examples where buffer known not to be NULL:
- cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL
(though we might set it to NULL if buffer_is_blank(cpv->v.b))
- address of buffer is arg (&foo)
(compiler optimizer detects this in most, but not all, cases)
- buffer is checked for NULL earlier in func
- buffer is accessed in same scope without a NULL check (e.g. b->ptr)
internal behavior change:
callers must not pass a NULL buffer to some funcs.
- buffer_init_buffer() requires non-null args
- buffer_copy_buffer() requires non-null args
- buffer_append_string_buffer() requires non-null args
- buffer_string_space() requires non-null arg
1 year ago
|
|
|
buffer_blank(b);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (saddr->plain.sa_family) {
|
|
|
|
case AF_INET:
|
|
|
|
ntop4_cache[ndx4].ipv4.s_addr = saddr->ipv4.sin_addr.s_addr;
|
[multiple] reduce redundant NULL buffer checks
This commit is a large set of code changes and results in removal of
hundreds, perhaps thousands, of CPU instructions, a portion of which
are on hot code paths.
Most (buffer *) used by lighttpd are not NULL, especially since buffers
were inlined into numerous larger structs such as request_st and chunk.
In the small number of instances where that is not the case, a NULL
check is often performed earlier in a function where that buffer is
later used with a buffer_* func. In the handful of cases that remained,
a NULL check was added, e.g. with r->http_host and r->conf.server_tag.
- check for empty strings at config time and set value to NULL if blank
string will be ignored at runtime; at runtime, simple pointer check
for NULL can be used to check for a value that has been set and is not
blank ("")
- use buffer_is_blank() instead of buffer_string_is_empty(),
and use buffer_is_unset() instead of buffer_is_empty(),
where buffer is known not to be NULL so that NULL check can be skipped
- use buffer_clen() instead of buffer_string_length() when buffer is
known not to be NULL (to avoid NULL check at runtime)
- use buffer_truncate() instead of buffer_string_set_length() to
truncate string, and use buffer_extend() to extend
Examples where buffer known not to be NULL:
- cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL
(though we might set it to NULL if buffer_is_blank(cpv->v.b))
- address of buffer is arg (&foo)
(compiler optimizer detects this in most, but not all, cases)
- buffer is checked for NULL earlier in func
- buffer is accessed in same scope without a NULL check (e.g. b->ptr)
internal behavior change:
callers must not pass a NULL buffer to some funcs.
- buffer_init_buffer() requires non-null args
- buffer_copy_buffer() requires non-null args
- buffer_append_string_buffer() requires non-null args
- buffer_string_space() requires non-null arg
1 year ago
|
|
|
memcpy(ntop4_strs+ndx4, b->ptr, buffer_clen(b)+1);
|
|
|
|
if (++ndx4 == NTOP_CACHE_MAX) ndx4 = 0;
|
|
|
|
break;
|
|
|
|
#ifdef HAVE_IPV6
|
|
|
|
case AF_INET6:
|
|
|
|
memcpy(ntop6_cache[ndx6].ipv6.s6_addr,saddr->ipv6.sin6_addr.s6_addr,16);
|
[multiple] reduce redundant NULL buffer checks
This commit is a large set of code changes and results in removal of
hundreds, perhaps thousands, of CPU instructions, a portion of which
are on hot code paths.
Most (buffer *) used by lighttpd are not NULL, especially since buffers
were inlined into numerous larger structs such as request_st and chunk.
In the small number of instances where that is not the case, a NULL
check is often performed earlier in a function where that buffer is
later used with a buffer_* func. In the handful of cases that remained,
a NULL check was added, e.g. with r->http_host and r->conf.server_tag.
- check for empty strings at config time and set value to NULL if blank
string will be ignored at runtime; at runtime, simple pointer check
for NULL can be used to check for a value that has been set and is not
blank ("")
- use buffer_is_blank() instead of buffer_string_is_empty(),
and use buffer_is_unset() instead of buffer_is_empty(),
where buffer is known not to be NULL so that NULL check can be skipped
- use buffer_clen() instead of buffer_string_length() when buffer is
known not to be NULL (to avoid NULL check at runtime)
- use buffer_truncate() instead of buffer_string_set_length() to
truncate string, and use buffer_extend() to extend
Examples where buffer known not to be NULL:
- cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL
(though we might set it to NULL if buffer_is_blank(cpv->v.b))
- address of buffer is arg (&foo)
(compiler optimizer detects this in most, but not all, cases)
- buffer is checked for NULL earlier in func
- buffer is accessed in same scope without a NULL check (e.g. b->ptr)
internal behavior change:
callers must not pass a NULL buffer to some funcs.
- buffer_init_buffer() requires non-null args
- buffer_copy_buffer() requires non-null args
- buffer_append_string_buffer() requires non-null args
- buffer_string_space() requires non-null arg
1 year ago
|
|
|
memcpy(ntop6_strs+ndx6, b->ptr, buffer_clen(b)+1);
|
|
|
|
if (++ndx6 == NTOP_CACHE_MAX) ndx6 = 0;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|