Merge pull request #258 from wtoorop/devel/_vfixed_gbuffers

A special bit for the snprintf style modus operandi of fixed gldns gbuffer's
This commit is contained in:
wtoorop 2017-02-16 10:51:20 +01:00 committed by GitHub
commit 17a5a5db92
9 changed files with 81 additions and 56 deletions

View File

@ -1131,7 +1131,6 @@ AH_BOTTOM([
# ifndef FD_SETSIZE
# define FD_SETSIZE 1024
# endif
# define PRIsz "%Iu"
#else
# define PRIsz "%zu"
@ -1171,8 +1170,6 @@ AH_BOTTOM([
#define FD_SET_T
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -1227,6 +1224,12 @@ int inet_pton(int af, const char* src, void* dst);
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
#endif
#ifdef USE_WINSOCK
static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *format, va_list ap)
{ int r = vsnprintf(str, size, format, ap); return r == -1 ? _vscprintf(format, ap) : r; }
# define vsnprintf _gldns_custom_vsnprintf
#endif
#ifdef __cplusplus
}
#endif

View File

@ -1354,7 +1354,7 @@ getdns_context_create_with_extended_memory_functions(
result->suffixes = no_suffixes;
result->suffixes_len = sizeof(no_suffixes);
gldns_buffer_init_frm_data(&gbuf, result->trust_anchors_spc
gldns_buffer_init_vfixed_frm_data(&gbuf, result->trust_anchors_spc
, sizeof(result->trust_anchors_spc));
if (!_getdns_parse_ta_file(NULL, &gbuf)) {
@ -2333,7 +2333,7 @@ getdns_context_set_suffix(getdns_context *context, getdns_list *value)
context->suffixes_len = sizeof(no_suffixes);
return GETDNS_RETURN_GOOD;
}
gldns_buffer_init_frm_data(&gbuf, buf_spc, sizeof(buf_spc));
gldns_buffer_init_vfixed_frm_data(&gbuf, buf_spc, sizeof(buf_spc));
for (;;) {
for ( i = 0
; !(r = getdns_list_get_bindata(value, i, &bindata))

View File

@ -297,7 +297,7 @@ getdns_rr_dict2wire_scan(
return GETDNS_RETURN_INVALID_PARAMETER;
gldns_buffer_init_frm_data(&gbuf, *wire, *wire_sz);
gldns_buffer_init_vfixed_frm_data(&gbuf, *wire, *wire_sz);
if ((r = _getdns_rr_dict2wire(rr_dict, &gbuf)))
return r;
@ -447,7 +447,7 @@ getdns_rr_dict2str_scan(
if (!rr_dict || !str || !*str || !str_len)
return GETDNS_RETURN_INVALID_PARAMETER;
gldns_buffer_init_frm_data(&gbuf, buf, sizeof(buf_spc));
gldns_buffer_init_vfixed_frm_data(&gbuf, buf, sizeof(buf_spc));
r = _getdns_rr_dict2wire(rr_dict, &gbuf);
if (gldns_buffer_position(&gbuf) > sizeof(buf_spc)) {
if (!(buf = GETDNS_XMALLOC(
@ -960,7 +960,7 @@ getdns_msg_dict2wire_scan(
if (!msg_dict || !wire || !wire_sz || (!*wire && *wire_sz))
return GETDNS_RETURN_INVALID_PARAMETER;
gldns_buffer_init_frm_data(&gbuf, *wire, *wire_sz);
gldns_buffer_init_vfixed_frm_data(&gbuf, *wire, *wire_sz);
if ((r = _getdns_msg_dict2wire_buf(msg_dict, &gbuf)))
return r;
@ -1036,7 +1036,7 @@ getdns_msg_dict2str_scan(
if (!msg_dict || !str || !*str || !str_len)
return GETDNS_RETURN_INVALID_PARAMETER;
gldns_buffer_init_frm_data(&gbuf, buf, sizeof(buf_spc));
gldns_buffer_init_vfixed_frm_data(&gbuf, buf, sizeof(buf_spc));
r = _getdns_msg_dict2wire_buf(msg_dict, &gbuf);
if (gldns_buffer_position(&gbuf) > sizeof(buf_spc)) {
if (!(buf = GETDNS_XMALLOC(

View File

@ -1186,7 +1186,7 @@ getdns_pretty_snprint_dict(char *str, size_t size, const getdns_dict *dict)
if (!dict) return -1;
gldns_buffer_init_frm_data(&buf, str, size);
gldns_buffer_init_vfixed_frm_data(&buf, str, size);
return getdns_pp_dict(&buf, 0, dict, 0) < 0
? -1 : (int)gldns_buffer_position(&buf);
}
@ -1220,7 +1220,7 @@ getdns_pretty_snprint_list(char *str, size_t size, const getdns_list *list)
if (!list) return -1;
gldns_buffer_init_frm_data(&buf, str, size);
gldns_buffer_init_vfixed_frm_data(&buf, str, size);
return getdns_pp_list(&buf, 0, list, 0, 0) < 0
? -1 : (int)gldns_buffer_position(&buf);
}
@ -1255,7 +1255,7 @@ getdns_snprint_json_dict(
if (!dict) return -1;
gldns_buffer_init_frm_data(&buf, str, size);
gldns_buffer_init_vfixed_frm_data(&buf, str, size);
return getdns_pp_dict(&buf, 0, dict, pretty ? 1 : 2) < 0
? -1 : (int)gldns_buffer_position(&buf);
}
@ -1290,7 +1290,7 @@ getdns_snprint_json_list(
if (!list) return -1;
gldns_buffer_init_frm_data(&buf, str, size);
gldns_buffer_init_vfixed_frm_data(&buf, str, size);
return getdns_pp_list(&buf, 0, list, 0, pretty ? 1 : 2) < 0
? -1 : (int)gldns_buffer_position(&buf);
}

View File

@ -33,6 +33,7 @@ gldns_buffer_new(size_t capacity)
buffer->_position = 0;
buffer->_limit = buffer->_capacity = capacity;
buffer->_fixed = 0;
buffer->_vfixed = 0;
buffer->_status_err = 0;
gldns_buffer_invariant(buffer);
@ -48,6 +49,7 @@ gldns_buffer_new_frm_data(gldns_buffer *buffer, void *data, size_t size)
buffer->_position = 0;
buffer->_limit = buffer->_capacity = size;
buffer->_fixed = 0;
buffer->_vfixed = 0;
buffer->_data = malloc(size);
if(!buffer->_data) {
buffer->_status_err = 1;
@ -66,6 +68,17 @@ gldns_buffer_init_frm_data(gldns_buffer *buffer, void *data, size_t size)
buffer->_data = data;
buffer->_capacity = buffer->_limit = size;
buffer->_fixed = 1;
buffer->_vfixed = 0;
}
void
gldns_buffer_init_vfixed_frm_data(gldns_buffer *buffer, void *data, size_t size)
{
memset(buffer, 0, sizeof(*buffer));
buffer->_data = data;
buffer->_capacity = buffer->_limit = size;
buffer->_fixed = 1;
buffer->_vfixed = 1;
}
int
@ -120,20 +133,19 @@ gldns_buffer_printf(gldns_buffer *buffer, const char *format, ...)
remaining = gldns_buffer_remaining(buffer);
va_start(args, format);
written = _gldns_vsnprintf((char*)gldns_buffer_current(buffer),
remaining, format, args);
written = vsnprintf((char *) gldns_buffer_current(buffer), remaining,
format, args);
va_end(args);
if (written == -1) {
buffer->_status_err = 1;
return -1;
} else if (!buffer->_fixed && (size_t) written >= remaining) {
} else if (!buffer->_vfixed && (size_t) written >= remaining) {
if (!gldns_buffer_reserve(buffer, (size_t) written + 1)) {
buffer->_status_err = 1;
return -1;
}
va_start(args, format);
written = _gldns_vsnprintf(
(char *) gldns_buffer_current(buffer),
written = vsnprintf((char *) gldns_buffer_current(buffer),
gldns_buffer_remaining(buffer), format, args);
va_end(args);
if (written == -1) {

View File

@ -27,21 +27,6 @@ extern "C" {
# endif
#endif
#ifndef USE_WINSOCK
#define _gldns_vsnprintf vsnprintf
#else
/* Unlike Linux and BSD, vsnprintf on Windows returns -1 on overflow.
* Here it is redefined to always return the amount printed
* if enough space had been available.
*/
INLINE int
_gldns_vsnprintf(char *str, size_t size, const char *format, va_list ap)
{
int r = vsnprintf(str, size, format, ap);
return r == -1 ? _vscprintf(format, ap) : r;
}
#endif
/*
* Copy data allowing for unaligned accesses in network byte order
* (big endian).
@ -145,6 +130,17 @@ struct gldns_buffer
/** If the buffer is fixed it cannot be resized */
unsigned _fixed : 1;
/** If the buffer is vfixed, no more than capacity bytes willl be
* written to _data, however the _position counter will be updated
* with the amount that would have been written in consecutive
* writes. This allows for a modus operandi in which a sequence is
* written on a fixed capacity buffer (perhaps with _data on stack).
* When everything could be written, then the _data is immediately
* usable, if not, then a buffer could be allocated sized precisely
* to fit the data for a second attempt.
*/
unsigned _vfixed : 1;
/** The current state of the buffer. If writing to the buffer fails
* for any reason, this value is changed. This way, you can perform
* multiple writes in sequence and check for success afterwards. */
@ -162,9 +158,9 @@ INLINE void
gldns_buffer_invariant(gldns_buffer *buffer)
{
assert(buffer != NULL);
assert(buffer->_position <= buffer->_limit || buffer->_fixed);
assert(buffer->_position <= buffer->_limit || buffer->_vfixed);
assert(buffer->_limit <= buffer->_capacity);
assert(buffer->_data != NULL || (buffer->_capacity == 0 && buffer->_fixed));
assert(buffer->_data != NULL || (buffer->_vfixed && buffer->_capacity == 0));
}
#endif
@ -196,6 +192,19 @@ void gldns_buffer_new_frm_data(gldns_buffer *buffer, void *data, size_t size);
*/
void gldns_buffer_init_frm_data(gldns_buffer *buffer, void *data, size_t size);
/**
* Setup a buffer with the data pointed to. No data copied, no memory allocs.
* The buffer is "virtually" fixed. Writes beyond size (the capacity) will
* only update position, but no data will be written beyond capacity. This
* allows to determine how big the buffer should have been to contain all the
* written data, by looking at the position with gldns_buffer_position(),
* similarly to the return value of POSIX's snprintf.
* \param[in] buffer pointer to the buffer to put the data in
* \param[in] data the data to encapsulate in the buffer
* \param[in] size the size of the data
*/
void gldns_buffer_init_vfixed_frm_data(gldns_buffer *buffer, void *data, size_t size);
/**
* clears the buffer and make it ready for writing. The buffer's limit
* is set to the capacity and the position is set to 0.
@ -259,7 +268,7 @@ gldns_buffer_position(gldns_buffer *buffer)
INLINE void
gldns_buffer_set_position(gldns_buffer *buffer, size_t mark)
{
assert(mark <= buffer->_limit || buffer->_fixed);
assert(mark <= buffer->_limit || buffer->_vfixed);
buffer->_position = mark;
}
@ -273,7 +282,7 @@ gldns_buffer_set_position(gldns_buffer *buffer, size_t mark)
INLINE void
gldns_buffer_skip(gldns_buffer *buffer, ssize_t count)
{
assert(buffer->_position + count <= buffer->_limit || buffer->_fixed);
assert(buffer->_position + count <= buffer->_limit || buffer->_vfixed);
buffer->_position += count;
}
@ -345,7 +354,7 @@ int gldns_buffer_reserve(gldns_buffer *buffer, size_t amount);
INLINE uint8_t *
gldns_buffer_at(const gldns_buffer *buffer, size_t at)
{
assert(at <= buffer->_limit || buffer->_fixed);
assert(at <= buffer->_limit || buffer->_vfixed);
return buffer->_data + at;
}
@ -395,6 +404,7 @@ INLINE size_t
gldns_buffer_remaining_at(gldns_buffer *buffer, size_t at)
{
gldns_buffer_invariant(buffer);
assert(at <= buffer->_limit || buffer->_vfixed);
return at < buffer->_limit ? buffer->_limit - at : 0;
}
@ -447,7 +457,7 @@ gldns_buffer_available(gldns_buffer *buffer, size_t count)
INLINE void
gldns_buffer_write_at(gldns_buffer *buffer, size_t at, const void *data, size_t count)
{
if (!buffer->_fixed)
if (!buffer->_vfixed)
assert(gldns_buffer_available_at(buffer, at, count));
else if (gldns_buffer_remaining_at(buffer, at) == 0)
return;
@ -504,7 +514,7 @@ gldns_buffer_write_string(gldns_buffer *buffer, const char *str)
INLINE void
gldns_buffer_write_u8_at(gldns_buffer *buffer, size_t at, uint8_t data)
{
if (buffer->_fixed && at + sizeof(data) > buffer->_limit) return;
if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return;
assert(gldns_buffer_available_at(buffer, at, sizeof(data)));
buffer->_data[at] = data;
}
@ -530,7 +540,7 @@ gldns_buffer_write_u8(gldns_buffer *buffer, uint8_t data)
INLINE void
gldns_buffer_write_u16_at(gldns_buffer *buffer, size_t at, uint16_t data)
{
if (buffer->_fixed && at + sizeof(data) > buffer->_limit) return;
if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return;
assert(gldns_buffer_available_at(buffer, at, sizeof(data)));
gldns_write_uint16(buffer->_data + at, data);
}
@ -556,7 +566,7 @@ gldns_buffer_write_u16(gldns_buffer *buffer, uint16_t data)
INLINE void
gldns_buffer_write_u32_at(gldns_buffer *buffer, size_t at, uint32_t data)
{
if (buffer->_fixed && at + sizeof(data) > buffer->_limit) return;
if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return;
assert(gldns_buffer_available_at(buffer, at, sizeof(data)));
gldns_write_uint32(buffer->_data + at, data);
}
@ -570,7 +580,7 @@ gldns_buffer_write_u32_at(gldns_buffer *buffer, size_t at, uint32_t data)
INLINE void
gldns_buffer_write_u48_at(gldns_buffer *buffer, size_t at, uint64_t data)
{
if (buffer->_fixed && at + 6 > buffer->_limit) return;
if (buffer->_vfixed && at + 6 > buffer->_limit) return;
assert(gldns_buffer_available_at(buffer, at, 6));
gldns_write_uint48(buffer->_data + at, data);
}

View File

@ -279,7 +279,7 @@ int gldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
int gldns_str_vprint(char** str, size_t* slen, const char* format, va_list args)
{
int w = _gldns_vsnprintf(*str, *slen, format, args);
int w = vsnprintf(*str, *slen, format, args);
if(w < 0) {
/* error in printout */
return 0;

View File

@ -383,7 +383,7 @@ _getdns_network_req_add_tsig(getdns_network_req *req)
#endif
tsig_info = _getdns_get_tsig_info(upstream->tsig_alg);
gldns_buffer_init_frm_data(&gbuf, req->response, MAXIMUM_TSIG_SPACE);
gldns_buffer_init_vfixed_frm_data(&gbuf, req->response, MAXIMUM_TSIG_SPACE);
gldns_buffer_write(&gbuf,
upstream->tsig_dname, upstream->tsig_dname_len); /* Name */
gldns_buffer_write_u16(&gbuf, GETDNS_RRCLASS_ANY); /* Class */

View File

@ -1510,7 +1510,7 @@ uint8_t *_getdns_list2wire(
gldns_buffer gbuf;
size_t sz;
gldns_buffer_init_frm_data(&gbuf, buf, *buf_len);
gldns_buffer_init_vfixed_frm_data(&gbuf, buf, *buf_len);
_getdns_list2wire_buf(&gbuf, l);
if ((sz = gldns_buffer_position(&gbuf)) <= *buf_len) {
@ -1531,7 +1531,7 @@ uint8_t *_getdns_reply2wire(
gldns_buffer gbuf;
size_t sz;
gldns_buffer_init_frm_data(&gbuf, buf, *buf_len);
gldns_buffer_init_vfixed_frm_data(&gbuf, buf, *buf_len);
_getdns_reply2wire_buf(&gbuf, r);
if ((sz = gldns_buffer_position(&gbuf)) <= *buf_len) {