aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxutil/marshal.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/libxutil/marshal.c')
-rw-r--r--tools/libxutil/marshal.c207
1 files changed, 207 insertions, 0 deletions
diff --git a/tools/libxutil/marshal.c b/tools/libxutil/marshal.c
new file mode 100644
index 0000000000..21691d4412
--- /dev/null
+++ b/tools/libxutil/marshal.c
@@ -0,0 +1,207 @@
+#include <errno.h>
+#include "sys_net.h"
+#include "allocate.h"
+#include "marshal.h"
+
+#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
+#define wprintf(fmt, args...) IOStream_print(iostderr, "[WARN] %s" fmt, __FUNCTION__, ##args)
+#define iprintf(fmt, args...) IOStream_print(iostdout, "[INFO] %s" fmt, __FUNCTION__, ##args)
+#define eprintf(fmt, args...) IOStream_print(iostderr, "[ERROR] %s" fmt, __FUNCTION__, ##args)
+
+
+#define ARRAY_SIZE(ary) (sizeof(ary)/sizeof((ary)[0]))
+
+/* Messages are coded as msgid followed by message fields.
+ * Initial message on any channel is hello - so can check version
+ * compatibility.
+ *
+ * char* -> uint16_t:n <n bytes>
+ * ints/uints go as suitable number of bytes (e.g. uint16_t is 2 bytes).
+ * optional fields go as '1' <val> or '0' (the 0/1 is 1 byte).
+ * lists go as ('1' <elt>)* '0'
+ */
+
+int marshal_flush(IOStream *io){
+ int err = 0;
+ err = IOStream_flush(io);
+ return err;
+}
+
+int marshal_bytes(IOStream *io, void *s, uint32_t s_n){
+ int err = 0;
+ int n;
+ n = IOStream_write(io, s, s_n);
+ if(n < 0){
+ err = n;
+ } else if (n < s_n){
+ wprintf("> Wanted %d, got %d\n", s_n, n);
+ err = -EIO;
+ }
+ return err;
+}
+
+int unmarshal_bytes(IOStream *io, void *s, uint32_t s_n){
+ int err = 0;
+ int n;
+ //dprintf("> s_n=%d\n", s_n);
+ n = IOStream_read(io, s, s_n);
+ //dprintf("> n=%d\n", n);
+ if(n < 0){
+ err = n;
+ } else if(n < s_n){
+ wprintf("> Wanted %d, got %d\n", s_n, n);
+ err = -EIO;
+ }
+ //dprintf("< err=%d\n", err);
+ return err;
+}
+
+int marshal_uint8(IOStream *io, uint8_t x){
+ return marshal_bytes(io, &x, sizeof(x));
+}
+
+int unmarshal_uint8(IOStream *io, uint8_t *x){
+ return unmarshal_bytes(io, x, sizeof(*x));
+}
+
+int marshal_uint16(IOStream *io, uint16_t x){
+ x = htons(x);
+ return marshal_bytes(io, &x, sizeof(x));
+}
+
+int unmarshal_uint16(IOStream *io, uint16_t *x){
+ int err = 0;
+ err = unmarshal_bytes(io, x, sizeof(*x));
+ *x = ntohs(*x);
+ return err;
+}
+
+int marshal_int32(IOStream *io, int32_t x){
+ int err = 0;
+ //dprintf("> x=%d\n", x);
+ x = htonl(x);
+ err = marshal_bytes(io, &x, sizeof(x));
+ //dprintf("< err=%d\n", err);
+ return err;
+}
+
+int unmarshal_int32(IOStream *io, int32_t *x){
+ int err = 0;
+ //dprintf(">\n");
+ err = unmarshal_bytes(io, x, sizeof(*x));
+ *x = ntohl(*x);
+ //dprintf("< err=%d x=%d\n", err, *x);
+ return err;
+}
+
+int marshal_uint32(IOStream *io, uint32_t x){
+ int err = 0;
+ //dprintf("> x=%u\n", x);
+ x = htonl(x);
+ err = marshal_bytes(io, &x, sizeof(x));
+ //dprintf("< err=%d\n", err);
+ return err;
+}
+
+int unmarshal_uint32(IOStream *io, uint32_t *x){
+ int err = 0;
+ //dprintf(">\n");
+ err = unmarshal_bytes(io, x, sizeof(*x));
+ *x = ntohl(*x);
+ //dprintf("< err=%d x=%u\n", err, *x);
+ return err;
+}
+
+int marshal_uint64(IOStream *io, uint64_t x){
+ int err;
+ err = marshal_uint32(io, (uint32_t) ((x >> 32) & 0xffffffff));
+ if(err) goto exit;
+ err = marshal_uint32(io, (uint32_t) ( x & 0xffffffff));
+ exit:
+ return err;
+}
+
+int unmarshal_uint64(IOStream *io, uint64_t *x){
+ int err = 0;
+ uint32_t hi, lo;
+ err = unmarshal_uint32(io, &hi);
+ if(err) goto exit;
+ err = unmarshal_uint32(io, &lo);
+ *x = (((uint64_t) hi) << 32) | lo;
+ exit:
+ return err;
+}
+
+int marshal_net16(IOStream *io, net16_t x){
+ return marshal_bytes(io, &x, sizeof(x));
+}
+
+int unmarshal_net16(IOStream *io, net16_t *x){
+ int err = 0;
+ err = unmarshal_bytes(io, x, sizeof(*x));
+ return err;
+}
+
+int marshal_net32(IOStream *io, net32_t x){
+ return marshal_bytes(io, &x, sizeof(x));
+}
+
+int unmarshal_net32(IOStream *io, net32_t *x){
+ int err = 0;
+ err = unmarshal_bytes(io, x, sizeof(*x));
+ return err;
+}
+
+int marshal_string(IOStream *io, char *s, uint32_t s_n){
+ int err;
+ //dprintf("> s=%s\n", s);
+ err = marshal_uint32(io, s_n);
+ if(err) goto exit;
+ err = marshal_bytes(io, s, s_n);
+ exit:
+ //dprintf("< err=%d\n", err);
+ return err;
+}
+
+int unmarshal_string(IOStream *io, char *s, uint32_t s_n){
+ int err = 0, val_n = 0;
+ //dprintf(">\n");
+ err = unmarshal_uint32(io, &val_n);
+ if(err) goto exit;
+ if(val_n >= s_n){
+ err = -EINVAL;
+ goto exit;
+ }
+ err = unmarshal_bytes(io, s, val_n);
+ if(err) goto exit;
+ s[val_n] = '\0';
+ exit:
+ //dprintf("< err=%d s=%s\n", err, s);
+ return err;
+}
+
+int unmarshal_new_string(IOStream *io, char **s, uint32_t *s_n){
+ int err = 0, val_n = 0;
+ char *val = NULL;
+ //dprintf(">\n");
+ err = unmarshal_uint32(io, &val_n);
+ if(err) goto exit;
+ val = allocate(val_n + 1);
+ if(!val){
+ err = -ENOMEM;
+ goto exit;
+ }
+ err = unmarshal_bytes(io, val, val_n);
+ if(err) goto exit;
+ val[val_n] = '\0';
+ exit:
+ if(err){
+ if(val) deallocate(val);
+ val = NULL;
+ val_n = 0;
+ }
+ *s = val;
+ if(s_n) *s_n = val_n;
+ //dprintf("< err=%d s=%s\n", err, *s);
+ return err;
+}