As preparation for eliminating the use of the XDR library,
introduce helpers for (de)serializing XDR types from/to
the virNetMessage object.
In contrast to the XDR APIs, when encoding data our helpers
can dynamically resize the virNetMessage buffer. Our decode
helpers also exhibit delayed error reporting, so that callers
can deserialize a bunch of data and check for errors once at
the end.
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
src/rpc/virnetmessage.c | 704 ++++++++++++++++++++++++++++++++++++++++
src/rpc/virnetmessage.h | 88 +++++
2 files changed, 792 insertions(+)
diff --git a/src/rpc/virnetmessage.c b/src/rpc/virnetmessage.c
index c9698fb263..df9a1aea71 100644
--- a/src/rpc/virnetmessage.c
+++ b/src/rpc/virnetmessage.c
@@ -593,3 +593,707 @@ int virNetMessageAddFD(virNetMessage *msg,
VIR_FORCE_CLOSE(newfd);
return -1;
}
+
+static void virNetMessageEncodePrealloc(virNetMessage *msg, size_t len)
+{
+ if ((msg->bufferLength - msg->bufferOffset) > len)
+ return;
+
+ /*
+ * Over allocate by 64kb, since we'll almost certainly
+ * have more fields written soon
+ */
+ msg->bufferLength += len + (1024 * 64);
+ msg->buffer = g_realloc_n(msg->buffer, 1, msg->bufferLength);
+}
+
+static bool virNetMessageDecodePending(virNetMessage *msg, size_t len)
+{
+ if ((msg->bufferLength - msg->bufferOffset) < len) {
+ msg->decodeErrno = ENOSPC;
+ }
+
+ /* Always return msg->decodeErrno, even if we didn't set it,
+ * because we allow multiple decode calls to be run without
+ * the caller checking for errors
+ */
+ return msg->decodeErrno == 0;
+}
+
+#define VIR_NET_MESSAGE_ENCODE_UINT32 \
+ uint32_t p = htonl((uint32_t)v); \
+ virNetMessageEncodePrealloc(msg, sizeof(uint32_t)); \
+ memcpy(msg->buffer + msg->bufferOffset, &p, sizeof(p)); \
+ msg->bufferOffset += sizeof(p)
+
+#define VIR_NET_MESSAGE_DECODE_UINT32(t) \
+ uint32_t p; \
+ if (!virNetMessageDecodePending(msg, sizeof(uint32_t))) \
+ return; \
+ memcpy(&p, msg->buffer + msg->bufferOffset, sizeof(p)); \
+ msg->bufferOffset += sizeof(p); \
+ *v = (t)ntohl((uint32_t)p);
+
+#define VIR_NET_MESSAGE_ENCODE_UINT64 \
+ uint32_t p[2] = { \
+ htonl((uint32_t)(((uint64_t)v >> 32) & 0xffffffff)), \
+ htonl((uint32_t)((uint64_t)v & 0xffffffff)), \
+ }; \
+ virNetMessageEncodePrealloc(msg, sizeof(uint64_t)); \
+ memcpy(msg->buffer + msg->bufferOffset, p, sizeof(p)); \
+ msg->bufferOffset += sizeof(p)
+
+#define VIR_NET_MESSAGE_DECODE_UINT64(t) \
+ uint32_t p[2]; \
+ if (!virNetMessageDecodePending(msg, sizeof(uint64_t))) \
+ return; \
+ memcpy(&p, msg->buffer + msg->bufferOffset, sizeof(p)); \
+ msg->bufferOffset += sizeof(p); \
+ *v = (t)((((uint64_t)ntohl(p[0])) << 32) + ntohl(p[1]));
+
+
+void virNetMessageEncodeInt8(virNetMessage *msg, int8_t v)
+{
+ VIR_NET_MESSAGE_ENCODE_UINT32;
+}
+
+void virNetMessageDecodeInt8(virNetMessage *msg, int8_t *v)
+{
+ VIR_NET_MESSAGE_DECODE_UINT32(int8_t);
+}
+
+void virNetMessageEncodeUInt8(virNetMessage *msg, uint8_t v)
+{
+ VIR_NET_MESSAGE_ENCODE_UINT32;
+}
+
+void virNetMessageDecodeUInt8(virNetMessage *msg, uint8_t *v)
+{
+ VIR_NET_MESSAGE_DECODE_UINT32(uint8_t);
+}
+
+void virNetMessageEncodeInt16(virNetMessage *msg, int16_t v)
+{
+ VIR_NET_MESSAGE_ENCODE_UINT32;
+}
+
+void virNetMessageDecodeInt16(virNetMessage *msg, int16_t *v)
+{
+ VIR_NET_MESSAGE_DECODE_UINT32(int16_t);
+}
+
+void virNetMessageEncodeUInt16(virNetMessage *msg, uint16_t v)
+{
+ VIR_NET_MESSAGE_ENCODE_UINT32;
+}
+
+void virNetMessageDecodeUInt16(virNetMessage *msg, uint16_t *v)
+{
+ VIR_NET_MESSAGE_DECODE_UINT32(uint16_t);
+}
+
+void virNetMessageEncodeInt32(virNetMessage *msg, int32_t v)
+{
+ VIR_NET_MESSAGE_ENCODE_UINT32;
+}
+
+void virNetMessageDecodeInt32(virNetMessage *msg, int32_t *v)
+{
+ VIR_NET_MESSAGE_DECODE_UINT32(int32_t);
+}
+
+void virNetMessageEncodeUInt32(virNetMessage *msg, uint32_t v)
+{
+ VIR_NET_MESSAGE_ENCODE_UINT32;
+}
+
+void virNetMessageDecodeUInt32(virNetMessage *msg, uint32_t *v)
+{
+ VIR_NET_MESSAGE_DECODE_UINT32(uint32_t);
+}
+
+void virNetMessageEncodeInt64(virNetMessage *msg, int64_t v)
+{
+ VIR_NET_MESSAGE_ENCODE_UINT64;
+}
+
+void virNetMessageDecodeInt64(virNetMessage *msg, int64_t *v)
+{
+ VIR_NET_MESSAGE_DECODE_UINT64(int64_t);
+}
+
+void virNetMessageEncodeUInt64(virNetMessage *msg, uint64_t v)
+{
+ VIR_NET_MESSAGE_ENCODE_UINT64;
+}
+
+void virNetMessageDecodeUInt64(virNetMessage *msg, uint64_t *v)
+{
+ VIR_NET_MESSAGE_DECODE_UINT64(uint64_t);
+}
+
+G_STATIC_ASSERT(sizeof(float) == sizeof(uint32_t));
+void virNetMessageEncodeFloat(virNetMessage *msg, float v)
+{
+ VIR_NET_MESSAGE_ENCODE_UINT32;
+}
+
+void virNetMessageDecodeFloat(virNetMessage *msg, float *v)
+{
+ VIR_NET_MESSAGE_DECODE_UINT32(float);
+}
+
+G_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
+void virNetMessageEncodeDouble(virNetMessage *msg, double v)
+{
+ /* XXXX check I'm doing byte order right here */
+ VIR_NET_MESSAGE_ENCODE_UINT64;
+}
+
+void virNetMessageDecodeDouble(virNetMessage *msg, double *v)
+{
+ /* XXXX check I'm doing byte order right here */
+ VIR_NET_MESSAGE_DECODE_UINT64(double);
+}
+
+void virNetMessageEncodeBool(virNetMessage *msg, bool v)
+{
+ uint32_t p = htonl(v ? 1 : 0);
+ virNetMessageEncodePrealloc(msg, sizeof(p));
+ memcpy(msg->buffer + msg->bufferOffset, &p, sizeof(p));
+ msg->bufferOffset += sizeof(p);
+}
+
+void virNetMessageDecodeBool(virNetMessage *msg, bool *v)
+{
+ uint32_t p;
+ if (!virNetMessageDecodePending(msg, sizeof(uint32_t)))
+ return;
+ memcpy(&p, msg->buffer + msg->bufferOffset, sizeof(p));
+ msg->bufferOffset += sizeof(p);
+ *v = ntohl((uint32_t)p) == 1 ? true : false;
+}
+
+#define VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32 \
+ do { \
+ g_assert(len < (G_MAXUINT32 - 1)); \
+ g_assert((G_MAXSIZE / sizeof(uint32_t)) > len); \
+ virNetMessageEncodePrealloc(msg, sizeof(uint32_t) * len); \
+ while (len) { \
+ uint32_t p = htonl((uint32_t)*v); \
+ memcpy(msg->buffer + msg->bufferOffset, &p, sizeof(p)); \
+ msg->bufferOffset += sizeof(p); \
+ v++; \
+ len--; \
+ } \
+ } while (0)
+
+#define VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(t) \
+ do { \
+ t *vp; \
+ g_assert(len < (G_MAXUINT32 - 1)); \
+ g_assert((G_MAXSIZE / sizeof(uint32_t)) > len); \
+ if (!virNetMessageDecodePending(msg, sizeof(uint32_t) * len)) \
+ return; \
+ *v = vp = g_new0(t, len); \
+ while (len) { \
+ uint32_t p; \
+ memcpy(&p, msg->buffer + msg->bufferOffset, sizeof(p)); \
+ msg->bufferOffset += sizeof(p); \
+ *vp = (t)ntohl(p); \
+ vp++; \
+ len--; \
+ } \
+ } while (0)
+
+#define VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT64 \
+ do { \
+ g_assert(len < (G_MAXUINT32 - 1)); \
+ g_assert((G_MAXSIZE / sizeof(uint64_t)) > len); \
+ virNetMessageEncodePrealloc(msg, sizeof(uint32_t) * len); \
+ while (len) { \
+ uint32_t p[2] = { \
+ htonl((uint32_t)(((uint64_t)*v >> 32) & 0xffffffff)), \
+ htonl((uint32_t)((uint64_t)*v & 0xffffffff)), \
+ }; \
+ memcpy(msg->buffer + msg->bufferOffset, p, sizeof(p)); \
+ msg->bufferOffset += sizeof(p); \
+ v++; \
+ len--; \
+ } \
+ } while (0)
+
+#define VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT64(t) \
+ do { \
+ t *vp; \
+ g_assert(len < (G_MAXUINT32 - 1)); \
+ g_assert((G_MAXSIZE / sizeof(uint64_t)) > len); \
+ if (!virNetMessageDecodePending(msg, sizeof(uint64_t) * len)) \
+ return; \
+ *v = vp = g_new0(t, len); \
+ while (len) { \
+ uint32_t p[2]; \
+ memcpy(p, msg->buffer + msg->bufferOffset, sizeof(p)); \
+ msg->bufferOffset += sizeof(p); \
+ *vp = (t)((((uint64_t)ntohl(p[0])) << 32) + ntohl(p[1])); \
+ vp++; \
+ len--; \
+ } \
+ } while (0)
+
+void virNetMessageEncodeInt8FixedArray(virNetMessage *msg, int8_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32;
+}
+
+void virNetMessageDecodeInt8FixedArray(virNetMessage *msg, int8_t **v, size_t len)
+{
+ VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(int8_t);
+}
+
+void virNetMessageEncodeUInt8FixedArray(virNetMessage *msg, uint8_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32;
+}
+
+void virNetMessageDecodeUInt8FixedArray(virNetMessage *msg, uint8_t **v, size_t len)
+{
+ VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(uint8_t);
+}
+
+void virNetMessageEncodeInt16FixedArray(virNetMessage *msg, int16_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32;
+}
+
+void virNetMessageDecodeInt16FixedArray(virNetMessage *msg, int16_t **v, size_t len)
+{
+ VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(int16_t);
+}
+
+void virNetMessageEncodeUInt16FixedArray(virNetMessage *msg, uint16_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32;
+}
+
+void virNetMessageDecodeUInt16FixedArray(virNetMessage *msg, uint16_t **v, size_t len)
+{
+ VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(uint16_t);
+}
+
+void virNetMessageEncodeInt32FixedArray(virNetMessage *msg, int32_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32;
+}
+
+void virNetMessageDecodeInt32FixedArray(virNetMessage *msg, int32_t **v, size_t len)
+{
+ VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(int32_t);
+}
+
+void virNetMessageEncodeUInt32FixedArray(virNetMessage *msg, uint32_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32;
+}
+
+void virNetMessageDecodeUInt32FixedArray(virNetMessage *msg, uint32_t **v, size_t len)
+{
+ VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(uint32_t);
+}
+
+void virNetMessageEncodeInt64FixedArray(virNetMessage *msg, int64_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT64;
+}
+
+void virNetMessageDecodeInt64FixedArray(virNetMessage *msg, int64_t **v, size_t len)
+{
+ VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT64(int64_t);
+}
+
+void virNetMessageEncodeUInt64FixedArray(virNetMessage *msg, uint64_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT64;
+}
+
+void virNetMessageDecodeUInt64FixedArray(virNetMessage *msg, uint64_t **v, size_t len)
+{
+ VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT64(uint64_t);
+}
+
+void virNetMessageEncodeFloatFixedArray(virNetMessage *msg, float *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32;
+}
+
+void virNetMessageDecodeFloatFixedArray(virNetMessage *msg, float **v, size_t len)
+{
+ VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(float);
+}
+
+void virNetMessageEncodeDoubleFixedArray(virNetMessage *msg, double *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT64;
+}
+
+void virNetMessageDecodeDoubleFixedArray(virNetMessage *msg, double **v, size_t len)
+{
+ VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT64(double);
+}
+
+#define VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32 \
+ do { \
+ uint32_t lenp = htonl(len); \
+ g_assert(len < (G_MAXUINT32 - 1)); \
+ g_assert(((G_MAXSIZE - sizeof(uint32_t))/ sizeof(uint32_t)) > len); \
+ virNetMessageEncodePrealloc(msg, sizeof(uint32_t) + (sizeof(uint32_t) * len)); \
+ memcpy(msg->buffer + msg->bufferOffset, &lenp, sizeof(lenp)); \
+ msg->bufferOffset += sizeof(lenp); \
+ while (len) { \
+ uint32_t p = htonl((uint32_t)*v); \
+ memcpy(msg->buffer + msg->bufferOffset, &p, sizeof(p)); \
+ msg->bufferOffset += sizeof(p); \
+ v++; \
+ len--; \
+ } \
+ } while (0)
+
+#define VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(t) \
+ do { \
+ t *vp; \
+ uint32_t lentmp; \
+ virNetMessageDecodeUInt32(msg, &lentmp); \
+ if (msg->decodeErrno != 0) { \
+ return; \
+ } \
+ if (lentmp > maxlen) { \
+ msg->decodeErrno = EFBIG; \
+ return; \
+ } \
+ g_assert(lentmp < (G_MAXUINT32 - 1)); \
+ /* g_assert((G_MAXSIZE / sizeof(uint32_t)) > lentmp);*/ \
+ if (!virNetMessageDecodePending(msg, sizeof(uint32_t) * lentmp)) \
+ return; \
+ *v = vp = g_new0(t, lentmp); \
+ *len = lentmp; \
+ while (lentmp) { \
+ uint32_t p; \
+ memcpy(&p, msg->buffer + msg->bufferOffset, sizeof(p)); \
+ msg->bufferOffset += sizeof(p); \
+ *vp = (t)ntohl(p); \
+ vp++; \
+ lentmp--; \
+ } \
+ } while (0)
+
+#define VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT64 \
+ do { \
+ uint32_t lenp = htonl(len); \
+ g_assert(len < (G_MAXUINT32 - 1)); \
+ g_assert(((G_MAXSIZE - sizeof(uint32_t))/ sizeof(uint64_t)) > len); \
+ virNetMessageEncodePrealloc(msg, sizeof(uint32_t) + (sizeof(uint64_t) * len)); \
+ memcpy(msg->buffer + msg->bufferOffset, &lenp, sizeof(lenp)); \
+ msg->bufferOffset += sizeof(lenp); \
+ while (len) { \
+ uint32_t p[2] = { \
+ htonl((uint32_t)(((uint64_t)*v >> 32) & 0xffffffff)), \
+ htonl((uint32_t)((uint64_t)*v & 0xffffffff)), \
+ }; \
+ memcpy(msg->buffer + msg->bufferOffset, p, sizeof(p)); \
+ msg->bufferOffset += sizeof(p); \
+ v++; \
+ len--; \
+ } \
+ } while (0)
+
+#define VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT64(t) \
+ do { \
+ t *vp; \
+ uint32_t lentmp; \
+ virNetMessageDecodeUInt32(msg, &lentmp); \
+ if (msg->decodeErrno != 0) { \
+ return; \
+ } \
+ if (lentmp > maxlen) { \
+ msg->decodeErrno = EFBIG; \
+ return; \
+ } \
+ g_assert(lentmp < (G_MAXUINT32 - 1)); \
+ /* g_assert((G_MAXSIZE / sizeof(uint32_t)) > lentmp);*/ \
+ if (!virNetMessageDecodePending(msg, sizeof(uint32_t) * lentmp)) \
+ return; \
+ *v = vp = g_new0(t, lentmp); \
+ *len = lentmp; \
+ while (lentmp) { \
+ uint32_t p[2]; \
+ memcpy(p, msg->buffer + msg->bufferOffset, sizeof(p)); \
+ msg->bufferOffset += sizeof(p); \
+ *vp = (t)((((uint64_t)ntohl(p[0])) << 32) + ntohl(p[1])); \
+ vp++; \
+ lentmp--; \
+ } \
+ } while (0)
+
+
+void virNetMessageEncodeInt8DynArray(virNetMessage *msg, int8_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32;
+}
+
+void virNetMessageDecodeInt8DynArray(virNetMessage *msg, size_t maxlen, int8_t **v,
size_t *len)
+{
+ VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(int8_t);
+}
+
+void virNetMessageEncodeUInt8DynArray(virNetMessage *msg, uint8_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32;
+}
+
+void virNetMessageDecodeUInt8DynArray(virNetMessage *msg, size_t maxlen, uint8_t **v,
size_t *len)
+{
+ VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(uint8_t);
+}
+
+void virNetMessageEncodeInt16DynArray(virNetMessage *msg, int16_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32;
+}
+
+void virNetMessageDecodeInt16DynArray(virNetMessage *msg, size_t maxlen, int16_t **v,
size_t *len)
+{
+ VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(int16_t);
+}
+
+void virNetMessageEncodeUInt16DynArray(virNetMessage *msg, uint16_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32;
+}
+
+void virNetMessageDecodeUInt16DynArray(virNetMessage *msg, size_t maxlen, uint16_t **v,
size_t *len)
+{
+ VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(uint16_t);
+}
+
+void virNetMessageEncodeInt32DynArray(virNetMessage *msg, int32_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32;
+}
+
+void virNetMessageDecodeInt32DynArray(virNetMessage *msg, size_t maxlen, int32_t **v,
size_t *len)
+{
+ VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(int32_t);
+}
+
+void virNetMessageEncodeUInt32DynArray(virNetMessage *msg, uint32_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32;
+}
+
+void virNetMessageDecodeUInt32DynArray(virNetMessage *msg, size_t maxlen, uint32_t **v,
size_t *len)
+{
+ VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(uint32_t);
+}
+
+void virNetMessageEncodeInt64DynArray(virNetMessage *msg, int64_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT64;
+}
+
+void virNetMessageDecodeInt64DynArray(virNetMessage *msg, size_t maxlen, int64_t **v,
size_t *len)
+{
+ VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT64(int64_t);
+}
+
+void virNetMessageEncodeUInt64DynArray(virNetMessage *msg, uint64_t *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT64;
+}
+
+void virNetMessageDecodeUInt64DynArray(virNetMessage *msg, size_t maxlen, uint64_t **v,
size_t *len)
+{
+ VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT64(uint64_t);
+}
+
+void virNetMessageEncodeFloatDynArray(virNetMessage *msg, float *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32;
+}
+
+void virNetMessageDecodeFloatDynArray(virNetMessage *msg, size_t maxlen, float **v,
size_t *len)
+{
+ VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(float);
+}
+
+void virNetMessageEncodeDoubleDynArray(virNetMessage *msg, double *v, size_t len)
+{
+ VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT64;
+}
+
+void virNetMessageDecodeDoubleDynArray(virNetMessage *msg, size_t maxlen, double **v,
size_t *len)
+{
+ VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT64(double);
+}
+
+void virNetMessageEncodeString(virNetMessage *msg, char *v)
+{
+ virNetMessageEncodeOpaqueDynArray(msg, (uint8_t *)v, strlen(v));
+}
+
+void virNetMessageDecodeString(virNetMessage *msg, size_t maxlen, char **v)
+{
+ size_t len;
+ virNetMessageDecodeOpaqueDynArray(msg, maxlen, (uint8_t **)v, &len);
+}
+
+void virNetMessageEncodeOpaqueFixedArray(virNetMessage *msg, uint8_t *v, size_t len)
+{
+ size_t pad = 4 - (len % 4);
+
+ g_assert(len < (G_MAXUINT32 - 1));
+ g_assert((G_MAXSIZE - len) > pad);
+
+ virNetMessageEncodePrealloc(msg, len + pad);
+ memcpy(msg->buffer + msg->bufferOffset, v, len);
+ msg->bufferOffset += len;
+ memset(msg->buffer + msg->bufferOffset, 0, pad);
+ msg->bufferOffset += pad;
+}
+
+void virNetMessageDecodeOpaqueFixedArray(virNetMessage *msg, uint8_t **v, size_t len)
+{
+ size_t pad = 4 - (len % 4);
+
+ g_assert(len < (G_MAXUINT32 - 1));
+ g_assert((G_MAXSIZE - len) > pad);
+
+ if (!virNetMessageDecodePending(msg, len + pad))
+ return;
+
+ memcpy(*v, msg->buffer + msg->bufferOffset, len);
+ msg->bufferOffset += len + pad;
+}
+
+void virNetMessageEncodeOpaqueDynArray(virNetMessage *msg, uint8_t *v, size_t len)
+{
+ uint32_t lenp = htonl(len);
+ size_t pad = 4 - (len % 4);
+
+ g_assert(len < (G_MAXUINT32 - 1));
+ g_assert((G_MAXSIZE - len) > (pad + 4));
+
+ virNetMessageEncodePrealloc(msg, len + pad + sizeof(lenp));
+ memcpy(msg->buffer + msg->bufferOffset, &lenp, sizeof(lenp));
+ msg->bufferOffset += sizeof(lenp);
+ memcpy(msg->buffer + msg->bufferOffset, v, len);
+ msg->bufferOffset += len;
+ memset(msg->buffer + msg->bufferOffset, 0, pad);
+ msg->bufferOffset += pad;
+}
+
+void virNetMessageDecodeOpaqueDynArray(virNetMessage *msg, size_t maxlen, uint8_t **v,
size_t *len)
+{
+ uint32_t lentmp;
+ size_t pad;
+
+ g_assert(maxlen < (G_MAXUINT32 - 1));
+
+ virNetMessageDecodeUInt32(msg, &lentmp);
+ if (msg->decodeErrno != 0)
+ return;
+
+ if (lentmp > maxlen) {
+ msg->decodeErrno = EFBIG;
+ return;
+ }
+
+ pad = 4 - (lentmp % 4);
+
+ if ((G_MAXSIZE - lentmp) <= pad) {
+ msg->decodeErrno = EFBIG;
+ return;
+ }
+
+ if (!virNetMessageDecodePending(msg, lentmp + pad))
+ return;
+
+ *v = g_new0(uint8_t, lentmp);
+ *len = lentmp;
+ memcpy(*v, msg->buffer + msg->bufferOffset, lentmp);
+ msg->bufferOffset += lentmp + pad;
+}
+
+
+void virNetMessageEncodeAnyFixedArray(virNetMessage *msg, void *v, size_t len, size_t
size,
+ virNetMessageEncoder encoder)
+{
+ char *vp = v;
+ while (len) {
+ encoder(msg, vp);
+ vp += size;
+ len--;
+ }
+}
+
+void virNetMessageDecodeAnyFixedArray(virNetMessage *msg, void **v, size_t len, size_t
size,
+ virNetMessageDecoder decoder)
+{
+ char *val = g_malloc0_n(size, len);
+ *v = val;
+ while (len) {
+ decoder(msg, (void **)&val);
+ val += size;
+ len--;
+ }
+}
+
+void virNetMessageEncodeAnyDynArray(virNetMessage *msg, void *v, size_t len, size_t
size,
+ virNetMessageEncoder encoder)
+{
+ char *vp = v;
+ uint32_t lenp = htonl(len);
+ g_assert(len < (G_MAXUINT32 - 1));
+ g_assert(((G_MAXSIZE - sizeof(uint32_t))/size) > len);
+ virNetMessageEncodePrealloc(msg, sizeof(uint32_t));
+ memcpy(msg->buffer + msg->bufferOffset, &lenp, sizeof(lenp));
+ msg->bufferOffset += sizeof(lenp);
+ while (len) {
+ encoder(msg, vp);
+ vp += size;
+ len--;
+ }
+}
+
+void virNetMessageDecodeAnyDynArray(virNetMessage *msg, size_t maxlen, size_t size,
+ virNetMessageDecoder decoder, void **v, size_t *len)
+{
+ uint32_t lentmp;
+ char *vp;
+ virNetMessageDecodeUInt32(msg, &lentmp);
+ if (msg->decodeErrno != 0) {
+ return;
+ }
+ if (lentmp > maxlen) {
+ msg->decodeErrno = EFBIG;
+ return;
+ }
+ g_assert(lentmp < (G_MAXUINT32 - 1));
+ /* g_assert((G_MAXSIZE / size) > lentmp);*/
+ *v = vp = g_malloc0_n(lentmp, size);
+ *len = lentmp;
+ while (lentmp) {
+ decoder(msg, (void**)&vp);
+ vp += size;
+ lentmp--;
+ }
+}
+
+int virNetMessageHasDecodeError(virNetMessage *msg)
+{
+ if (msg->decodeErrno) {
+ virReportSystemError(msg->decodeErrno, "%s",
+ _("Message terminated unexpectedly"));
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/rpc/virnetmessage.h b/src/rpc/virnetmessage.h
index 849674fa53..264ddd3c05 100644
--- a/src/rpc/virnetmessage.h
+++ b/src/rpc/virnetmessage.h
@@ -20,6 +20,7 @@
#pragma once
+#include <rpc/rpc.h>
#include "virnetprotocol.h"
typedef struct _virNetMessage virNetMessage;
@@ -28,6 +29,7 @@ typedef void (*virNetMessageFreeCallback)(virNetMessage *msg, void
*opaque);
struct _virNetMessage {
bool tracked;
+ int decodeErrno;
char *buffer; /* Initially VIR_NET_MESSAGE_INITIAL + VIR_NET_MESSAGE_LEN_MAX */
/* Maximum VIR_NET_MESSAGE_MAX + VIR_NET_MESSAGE_LEN_MAX */
@@ -94,3 +96,89 @@ int virNetMessageDupFD(virNetMessage *msg,
int virNetMessageAddFD(virNetMessage *msg,
int fd);
+
+void virNetMessageEncodeInt8(virNetMessage *msg, int8_t v);
+void virNetMessageDecodeInt8(virNetMessage *msg, int8_t *v);
+void virNetMessageEncodeUInt8(virNetMessage *msg, uint8_t v);
+void virNetMessageDecodeUInt8(virNetMessage *msg, uint8_t *v);
+void virNetMessageEncodeInt16(virNetMessage *msg, int16_t v);
+void virNetMessageDecodeInt16(virNetMessage *msg, int16_t *v);
+void virNetMessageEncodeUInt16(virNetMessage *msg, uint16_t v);
+void virNetMessageDecodeUInt16(virNetMessage *msg, uint16_t *v);
+void virNetMessageEncodeInt32(virNetMessage *msg, int32_t v);
+void virNetMessageDecodeInt32(virNetMessage *msg, int32_t *v);
+void virNetMessageEncodeUInt32(virNetMessage *msg, uint32_t v);
+void virNetMessageDecodeUInt32(virNetMessage *msg, uint32_t *v);
+void virNetMessageEncodeInt64(virNetMessage *msg, int64_t v);
+void virNetMessageDecodeInt64(virNetMessage *msg, int64_t *v);
+void virNetMessageEncodeUInt64(virNetMessage *msg, uint64_t v);
+void virNetMessageDecodeUInt64(virNetMessage *msg, uint64_t *v);
+
+void virNetMessageEncodeFloat(virNetMessage *msg, float v);
+void virNetMessageDecodeFloat(virNetMessage *msg, float *v);
+void virNetMessageEncodeDouble(virNetMessage *msg, double v);
+void virNetMessageDecodeDouble(virNetMessage *msg, double *v);
+void virNetMessageEncodeBool(virNetMessage *msg, bool v);
+void virNetMessageDecodeBool(virNetMessage *msg, bool *v);
+
+void virNetMessageEncodeInt8FixedArray(virNetMessage *msg, int8_t *v, size_t len);
+void virNetMessageDecodeInt8FixedArray(virNetMessage *msg, int8_t **v, size_t len);
+void virNetMessageEncodeUInt8FixedArray(virNetMessage *msg, uint8_t *v, size_t len);
+void virNetMessageDecodeUInt8FixedArray(virNetMessage *msg, uint8_t **v, size_t len);
+void virNetMessageEncodeInt16FixedArray(virNetMessage *msg, int16_t *v, size_t len);
+void virNetMessageDecodeInt16FixedArray(virNetMessage *msg, int16_t **v, size_t len);
+void virNetMessageEncodeUInt16FixedArray(virNetMessage *msg, uint16_t *v, size_t len);
+void virNetMessageDecodeUInt16FixedArray(virNetMessage *msg, uint16_t **v, size_t len);
+void virNetMessageEncodeInt32FixedArray(virNetMessage *msg, int32_t *v, size_t len);
+void virNetMessageDecodeInt32FixedArray(virNetMessage *msg, int32_t **v, size_t len);
+void virNetMessageEncodeUInt32FixedArray(virNetMessage *msg, uint32_t *v, size_t len);
+void virNetMessageDecodeUInt32FixedArray(virNetMessage *msg, uint32_t **v, size_t len);
+void virNetMessageEncodeInt64FixedArray(virNetMessage *msg, int64_t *v, size_t len);
+void virNetMessageDecodeInt64FixedArray(virNetMessage *msg, int64_t **v, size_t len);
+void virNetMessageEncodeUInt64FixedArray(virNetMessage *msg, uint64_t *v, size_t len);
+void virNetMessageDecodeUInt64FixedArray(virNetMessage *msg, uint64_t **v, size_t len);
+void virNetMessageEncodeFloatFixedArray(virNetMessage *msg, float *v, size_t len);
+void virNetMessageDecodeFloatFixedArray(virNetMessage *msg, float **v, size_t len);
+void virNetMessageEncodeDoubleFixedArray(virNetMessage *msg, double *v, size_t len);
+void virNetMessageDecodeDoubleFixedArray(virNetMessage *msg, double **v, size_t len);
+
+void virNetMessageEncodeInt8DynArray(virNetMessage *msg, int8_t *v, size_t len);
+void virNetMessageDecodeInt8DynArray(virNetMessage *msg, size_t maxlen, int8_t **v,
size_t *len);
+void virNetMessageEncodeUInt8DynArray(virNetMessage *msg, uint8_t *v, size_t len);
+void virNetMessageDecodeUInt8DynArray(virNetMessage *msg, size_t maxlen, uint8_t **v,
size_t *len);
+void virNetMessageEncodeInt16DynArray(virNetMessage *msg, int16_t *v, size_t len);
+void virNetMessageDecodeInt16DynArray(virNetMessage *msg, size_t maxlen, int16_t **v,
size_t *len);
+void virNetMessageEncodeUInt16DynArray(virNetMessage *msg, uint16_t *v, size_t len);
+void virNetMessageDecodeUInt16DynArray(virNetMessage *msg, size_t maxlen, uint16_t **v,
size_t *len);
+void virNetMessageEncodeInt32DynArray(virNetMessage *msg, int32_t *v, size_t len);
+void virNetMessageDecodeInt32DynArray(virNetMessage *msg, size_t maxlen, int32_t **v,
size_t *len);
+void virNetMessageEncodeUInt32DynArray(virNetMessage *msg, uint32_t *v, size_t len);
+void virNetMessageDecodeUInt32DynArray(virNetMessage *msg, size_t maxlen, uint32_t **v,
size_t *len);
+void virNetMessageEncodeInt64DynArray(virNetMessage *msg, int64_t *v, size_t len);
+void virNetMessageDecodeInt64DynArray(virNetMessage *msg, size_t maxlen, int64_t **v,
size_t *len);
+void virNetMessageEncodeUInt64DynArray(virNetMessage *msg, uint64_t *v, size_t len);
+void virNetMessageDecodeUInt64DynArray(virNetMessage *msg, size_t maxlen, uint64_t **v,
size_t *len);
+void virNetMessageEncodeFloatDynArray(virNetMessage *msg, float *v, size_t len);
+void virNetMessageDecodeFloatDynArray(virNetMessage *msg, size_t maxlen, float **v,
size_t *len);
+void virNetMessageEncodeDoubleDynArray(virNetMessage *msg, double *v, size_t len);
+void virNetMessageDecodeDoubleDynArray(virNetMessage *msg, size_t maxlen, double **v,
size_t *len);
+
+void virNetMessageEncodeString(virNetMessage *msg, char *v);
+void virNetMessageDecodeString(virNetMessage *msg, size_t maxlen, char **v);
+void virNetMessageEncodeOpaqueFixedArray(virNetMessage *msg, uint8_t *v, size_t len);
+void virNetMessageDecodeOpaqueFixedArray(virNetMessage *msg, uint8_t **v, size_t len);
+void virNetMessageEncodeOpaqueDynArray(virNetMessage *msg, uint8_t *v, size_t len);
+void virNetMessageDecodeOpaqueDynArray(virNetMessage *msg, size_t maxlen, uint8_t **v,
size_t *len);
+
+typedef void (*virNetMessageEncoder)(virNetMessage *msg, void *v);
+typedef void (*virNetMessageDecoder)(virNetMessage *msg, void **v);
+void virNetMessageEncodeAnyFixedArray(virNetMessage *msg, void *v, size_t len, size_t
size,
+ virNetMessageEncoder encoder);
+void virNetMessageDecodeAnyFixedArray(virNetMessage *msg, void **v, size_t len, size_t
size,
+ virNetMessageDecoder decoder);
+void virNetMessageEncodeAnyDynArray(virNetMessage *msg, void *v, size_t len, size_t
size,
+ virNetMessageEncoder encoder);
+void virNetMessageDecodeAnyDynArray(virNetMessage *msg, size_t maxlen, size_t size,
+ virNetMessageDecoder decoder, void **v, size_t
*len);
+
+int virNetMessageHasDecodeError(virNetMessage *msg);
--
2.39.1