X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Futils%2Fproto.c;h=9cdc21603283e6a8e6a33e5dcc2b59a800429a3f;hp=cb88887d1f1313cd0797dcf9a5fbec9c63404277;hb=d25f3c59b5cf5387acd4e6d1467ce9efffa40f9a;hpb=895a5695294975c87e1695f41be997fbeac85563 diff --git a/src/utils/proto.c b/src/utils/proto.c index cb88887..9cdc216 100644 --- a/src/utils/proto.c +++ b/src/utils/proto.c @@ -25,14 +25,20 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_CONFIG_H +# include "config.h" +#endif + #include "core/data.h" +#include "core/store.h" #include "core/time.h" #include "utils/error.h" #include "utils/proto.h" -#include +#include #include +#include #include #include @@ -49,39 +55,54 @@ * been available. */ static ssize_t -marshal_int(char *buf, size_t buf_len, int64_t v) +marshal_int32(char *buf, size_t buf_len, uint32_t v) +{ + if (buf_len >= sizeof(v)) { + v = htonl(v); + memcpy(buf, &v, sizeof(v)); + } + return sizeof(v); +} /* marshal_int32 */ + +static ssize_t +marshal_int64(char *buf, size_t buf_len, int64_t v) { if (buf_len >= sizeof(v)) { #if __BYTE_ORDER != __BIG_ENDIAN - v = (((int64_t)ntohl((int32_t)v)) << 32) - + ((int64_t)ntohl((int32_t)(v >> 32))); + v = (((int64_t)htonl((int32_t)v)) << 32) + + ((int64_t)htonl((int32_t)(v >> 32))); #endif memcpy(buf, &v, sizeof(v)); } return sizeof(v); -} /* marshal_int */ +} /* marshal_int64 */ static ssize_t -marshal_double(char __attribute__((unused)) *buf, - size_t __attribute__((unused)) buf_len, - double __attribute__((unused)) v) +marshal_double(char *buf, size_t buf_len, double v) { - /* XXX: find a good network representation */ - errno = ENOTSUP; - return -1; + uint64_t t = 0; + assert(sizeof(v) == sizeof(t)); + memcpy(&t, &v, sizeof(v)); +#if IEEE754_DOUBLE_BYTE_ORDER != IEEE754_DOUBLE_BIG_ENDIAN + t = (((int64_t)htonl((int32_t)t)) << 32) + + ((int64_t)htonl((int32_t)(t >> 32))); +#endif + if (buf_len >= sizeof(t)) + memcpy(buf, &t, sizeof(t)); + return sizeof(t); } /* marshal_double */ static ssize_t marshal_datetime(char *buf, size_t buf_len, sdb_time_t v) { - return marshal_int(buf, buf_len, (int64_t)v); + return marshal_int64(buf, buf_len, (int64_t)v); } /* marshal_datetime */ static ssize_t marshal_binary(char *buf, size_t buf_len, size_t len, const unsigned char *v) { uint32_t tmp = htonl((uint32_t)len); - if (buf_len >= len) { + if (buf_len >= sizeof(tmp) + len) { memcpy(buf, &tmp, sizeof(tmp)); memcpy(buf + sizeof(tmp), v, len); } @@ -92,10 +113,28 @@ static ssize_t marshal_string(char *buf, size_t buf_len, const char *v) { /* The actual string including the terminating null byte. */ - return marshal_binary(buf, buf_len, - strlen(v) + 1, (const unsigned char *)v); + size_t len = strlen(v) + 1; + if (buf_len >= len) + memcpy(buf, v, len); + return len; } /* marshal_string */ +#define OBJ_HEADER_LEN (sizeof(uint32_t) + sizeof(sdb_time_t)) +static ssize_t +marshal_obj_header(char *buf, size_t buf_len, + int type, sdb_time_t last_update) +{ + ssize_t n; + + if (buf_len < OBJ_HEADER_LEN) + return OBJ_HEADER_LEN; + + n = marshal_int32(buf, buf_len, (uint32_t)type); + buf += n; buf_len -= n; + marshal_datetime(buf, buf_len, last_update); + return OBJ_HEADER_LEN; +} /* marshal_obj_header */ + /* * public API */ @@ -123,7 +162,7 @@ sdb_proto_marshal(char *buf, size_t buf_len, uint32_t code, } /* sdb_proto_marshal */ ssize_t -sdb_proto_marshal_data(char *buf, size_t buf_len, sdb_data_t *datum) +sdb_proto_marshal_data(char *buf, size_t buf_len, const sdb_data_t *datum) { ssize_t len = 0, n = 0; uint32_t tmp; @@ -144,7 +183,7 @@ sdb_proto_marshal_data(char *buf, size_t buf_len, sdb_data_t *datum) return len; if (datum->type == SDB_TYPE_INTEGER) - n = marshal_int(buf, buf_len, datum->data.integer); + n = marshal_int64(buf, buf_len, datum->data.integer); else if (datum->type == SDB_TYPE_DECIMAL) n = marshal_double(buf, buf_len, datum->data.decimal); else if (datum->type == SDB_TYPE_STRING) @@ -154,6 +193,8 @@ sdb_proto_marshal_data(char *buf, size_t buf_len, sdb_data_t *datum) else if (datum->type == SDB_TYPE_BINARY) n = marshal_binary(buf, buf_len, datum->data.binary.length, datum->data.binary.datum); + else if (datum->type == SDB_TYPE_REGEX) + n = marshal_string(buf, buf_len, datum->data.re.raw); if (n < 0) return n; @@ -180,7 +221,7 @@ sdb_proto_marshal_data(char *buf, size_t buf_len, sdb_data_t *datum) for (i = 0; i < datum->data.array.length; ++i) { if (type == SDB_TYPE_INTEGER) { int64_t *v = datum->data.array.values; - n = marshal_int(buf, buf_len, v[i]); + n = marshal_int64(buf, buf_len, v[i]); } else if (type == SDB_TYPE_DECIMAL) { double *v = datum->data.array.values; @@ -190,8 +231,26 @@ sdb_proto_marshal_data(char *buf, size_t buf_len, sdb_data_t *datum) char **v = datum->data.array.values; n = marshal_string(buf, buf_len, v[i]); } + else if (type == SDB_TYPE_DATETIME) { + sdb_time_t *v = datum->data.array.values; + n = marshal_datetime(buf, buf_len, v[i]); + } + else if (type == SDB_TYPE_BINARY) { + struct { + size_t length; + unsigned char *datum; + } *v = datum->data.array.values; + n = marshal_binary(buf, buf_len, v[i].length, v[i].datum); + } + else if (type == SDB_TYPE_REGEX) { + struct { + char *raw; + regex_t regex; + } *v = datum->data.array.values; + n = marshal_string(buf, buf_len, v[i].raw); + } else { - errno = ENOTSUP; + errno = EINVAL; return -1; } @@ -208,37 +267,152 @@ sdb_proto_marshal_data(char *buf, size_t buf_len, sdb_data_t *datum) return len; } /* sdb_proto_marshal_data */ -int +ssize_t +sdb_proto_marshal_host(char *buf, size_t buf_len, + const sdb_proto_host_t *host) +{ + size_t len; + ssize_t n; + + if ((! host) || (! host->name)) + return -1; + + len = OBJ_HEADER_LEN + strlen(host->name) + 1; + if (buf_len < len) + return len; + + n = marshal_obj_header(buf, buf_len, SDB_HOST, host->last_update); + buf += n; buf_len -= n; + marshal_string(buf, buf_len, host->name); + return len; +} /* sdb_proto_marshal_host */ + +ssize_t +sdb_proto_marshal_service(char *buf, size_t buf_len, + const sdb_proto_service_t *svc) +{ + size_t len; + ssize_t n; + + if ((! svc) || (! svc->hostname) || (! svc->name)) + return -1; + + len = OBJ_HEADER_LEN + strlen(svc->hostname) + strlen(svc->name) + 2; + if (buf_len < len) + return len; + + n = marshal_obj_header(buf, buf_len, SDB_SERVICE, svc->last_update); + buf += n; buf_len -= n; + n = marshal_string(buf, buf_len, svc->hostname); + buf += n; buf_len -= n; + marshal_string(buf, buf_len, svc->name); + return len; +} /* sdb_proto_marshal_service */ + +ssize_t +sdb_proto_marshal_metric(char *buf, size_t buf_len, + const sdb_proto_metric_t *metric) +{ + size_t len; + ssize_t n; + + if ((! metric) || (! metric->hostname) || (! metric->name)) + return -1; + + len = OBJ_HEADER_LEN + strlen(metric->hostname) + strlen(metric->name) + 2; + if (metric->store_type && metric->store_id) + len += strlen(metric->store_type) + strlen(metric->store_id) + 2; + if (buf_len < len) + return len; + + n = marshal_obj_header(buf, buf_len, SDB_METRIC, metric->last_update); + buf += n; buf_len -= n; + n = marshal_string(buf, buf_len, metric->hostname); + buf += n; buf_len -= n; + n = marshal_string(buf, buf_len, metric->name); + buf += n; buf_len -= n; + if (metric->store_type && metric->store_id) { + n = marshal_string(buf, buf_len, metric->store_type); + buf += n; buf_len -= n; + marshal_string(buf, buf_len, metric->store_id); + } + return len; +} /* sdb_proto_marshal_metric */ + +ssize_t +sdb_proto_marshal_attribute(char *buf, size_t buf_len, + const sdb_proto_attribute_t *attr) +{ + size_t len; + ssize_t n; + + if ((! attr) || (! attr->parent) || (! attr->key) || (! attr->value) + || ((attr->parent_type != SDB_HOST) && (! attr->hostname)) + || ((attr->parent_type != SDB_HOST) + && (attr->parent_type != SDB_SERVICE) + && (attr->parent_type != SDB_METRIC))) + return -1; + + n = sdb_proto_marshal_data(NULL, 0, attr->value); + if (n < 0) + return -1; + + len = OBJ_HEADER_LEN + + strlen(attr->parent) + strlen(attr->key) + 2 + (size_t)n; + if (attr->parent_type != SDB_HOST) + len += strlen(attr->hostname) + 1; + if (buf_len < len) + return len; + + n = marshal_obj_header(buf, buf_len, + attr->parent_type | SDB_ATTRIBUTE, attr->last_update); + buf += n; buf_len -= n; + if (attr->parent_type != SDB_HOST) { + n = marshal_string(buf, buf_len, attr->hostname); + buf += n; buf_len -= n; + } + n = marshal_string(buf, buf_len, attr->parent); + buf += n; buf_len -= n; + n = marshal_string(buf, buf_len, attr->key); + buf += n; buf_len -= n; + sdb_proto_marshal_data(buf, buf_len, attr->value); + return len; +} /* sdb_proto_marshal_attribute */ + +ssize_t sdb_proto_unmarshal_header(const char *buf, size_t buf_len, uint32_t *code, uint32_t *msg_len) { uint32_t tmp; + ssize_t n; if (buf_len < 2 * sizeof(uint32_t)) return -1; - tmp = sdb_proto_unmarshal_int(buf, buf_len); + n = sdb_proto_unmarshal_int32(buf, buf_len, &tmp); if (code) *code = tmp; - tmp = sdb_proto_unmarshal_int(buf + sizeof(uint32_t), - buf_len - sizeof(uint32_t)); + buf += n; buf_len -= n; + sdb_proto_unmarshal_int32(buf, buf_len, &tmp); if (msg_len) *msg_len = tmp; - return 0; + return 2 * sizeof(uint32_t); } /* sdb_proto_unmarshal_header */ -uint32_t -sdb_proto_unmarshal_int(const char *buf, size_t buf_len) +ssize_t +sdb_proto_unmarshal_int32(const char *buf, size_t buf_len, uint32_t *v) { uint32_t n; /* not enough data to read */ if (buf_len < sizeof(n)) - return UINT32_MAX; + return -1; memcpy(&n, buf, sizeof(n)); - return ntohl(n); -} /* sdb_proto_unmarshal_int */ + if (v) + *v = ntohl(n); + return sizeof(n); +} /* sdb_proto_unmarshal_int32 */ /* vim: set tw=78 sw=4 ts=4 noexpandtab : */