Code

proto: Let unmarshal functions return the number of bytes processed.
[sysdb.git] / src / utils / proto.c
index beaa07e98397f18876f27952ab38ed83ff673638..9cdc21603283e6a8e6a33e5dcc2b59a800429a3f 100644 (file)
@@ -30,6 +30,7 @@
 #endif
 
 #include "core/data.h"
+#include "core/store.h"
 #include "core/time.h"
 #include "utils/error.h"
 #include "utils/proto.h"
  * return the number of bytes that would have been written if enough space had
  * been available. */
 
+static ssize_t
+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));
        }
@@ -73,8 +84,8 @@ marshal_double(char *buf, size_t buf_len, double v)
        assert(sizeof(v) == sizeof(t));
        memcpy(&t, &v, sizeof(v));
 #if IEEE754_DOUBLE_BYTE_ORDER != IEEE754_DOUBLE_BIG_ENDIAN
-       t = (((int64_t)ntohl((int32_t)t)) << 32)
-               + ((int64_t)ntohl((int32_t)(t >> 32)));
+       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));
@@ -91,7 +102,7 @@ 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);
        }
@@ -102,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
  */
@@ -133,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;
@@ -238,36 +267,151 @@ 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_int32(buf, buf_len);
+       n = sdb_proto_unmarshal_int32(buf, buf_len, &tmp);
        if (code)
                *code = tmp;
-       tmp = sdb_proto_unmarshal_int32(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_int32(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);
+       if (v)
+               *v = ntohl(n);
+       return sizeof(n);
 } /* sdb_proto_unmarshal_int32 */
 
 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */