summaryrefslogtreecommitdiff
path: root/protocols/Steam/src
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Steam/src')
-rw-r--r--protocols/Steam/src/protobuf-c/protobuf-c-text.c501
-rw-r--r--protocols/Steam/src/protobuf-c/protobuf-c-text.cpp388
-rw-r--r--protocols/Steam/src/protobuf-c/protobuf-c-text.h213
-rw-r--r--protocols/Steam/src/stdafx.h6
-rw-r--r--protocols/Steam/src/steam_ws.cpp4
5 files changed, 390 insertions, 722 deletions
diff --git a/protocols/Steam/src/protobuf-c/protobuf-c-text.c b/protocols/Steam/src/protobuf-c/protobuf-c-text.c
deleted file mode 100644
index 7c7f82001b..0000000000
--- a/protocols/Steam/src/protobuf-c/protobuf-c-text.c
+++ /dev/null
@@ -1,501 +0,0 @@
-/** \file
- * Routines to generate text format protobufs.
- *
- * This file contains the internal support functions as well as the
- * exported functions which are used to generate text format protobufs
- * from C protobuf data types.
- *
- * \author Kevin Lyda <kevin@ie.suberic.net>
- * \date March 2014
- */
-
-#include <sys/types.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include "protobuf-c.h"
-#include "protobuf-c-text.h"
-#include "protobuf-c-util.h"
-
-/** A dynamic string struct.
- *
- * Used to track additions to a growing string and memory allocation
- * errors that occur in processing
- */
-typedef struct _ReturnString {
- int malloc_err; /**< Set to 1 when there's been a malloc error. */
- int allocated; /**< Size of allocated string. */
- int pos; /**< Current end of the string. */
- char *s; /**< The string. */
-} ReturnString;
-
-/** Append a string to the ReturnString.
- *
- * Append the string built from \c format and its args to the \c rs
- * string. Note that \c malloc_err is checked and if it's true,
- * this function won't do anything.
- *
- * \param[in,out] rs The string to append to.
- * \param[in] guess A guess at the number of chars being added.
- * \param[in] allocator allocator functions.
- * \param[in] format Printf-style format string.
- * \param[in] ... Variable number of args for \c format.
- */
-
-static void
-rs_append(ReturnString *rs, int guess,
- ProtobufCAllocator *allocator,
- const char *format, ...)
-{
- va_list args;
- int added;
-
- if (rs->malloc_err) {
- return;
- }
-
- if (rs->allocated - rs->pos < guess * 2) {
- char *tmp;
-
- tmp = PBC_ALLOC(rs->allocated + guess * 2);
- if (!tmp) {
- PBC_FREE(rs->s);
- rs->s = NULL;
- rs->malloc_err = 1;
- return;
- }
- memcpy(tmp, rs->s, rs->allocated);
- PBC_FREE(rs->s);
- rs->s = tmp;
- rs->allocated += guess * 2;
- }
- va_start(args, format);
- added = vsnprintf(rs->s + rs->pos, rs->allocated - rs->pos, format, args);
- va_end(args);
- rs->pos += added;
- return;
-}
-
-/** @} */ /* End of utility group. */
-
-
-/** \defgroup generate Functions to generate text format proto bufs
- * \ingroup internal
- * @{
- */
-
-/** Escape string.
- *
- * Add escape characters to strings for problematic characters.
- *
- * \param[in] src The unescaped string to process.
- * \param[in] len Length of \c src. Note that \c src might have ASCII
- * \c NULs so strlen() isn't good enough here.
- * \param[in] allocator allocator functions.
- * \return The fully escaped string, or \c NULL if there has been an
- * allocation error.
- */
-static char *
-esc_str(char *src, int len, ProtobufCAllocator *allocator)
-{
- int i, escapes = 0, dst_len = 0;
- unsigned char *dst;
-
- for (i = 0; i < len; i++) {
- if (!isprint(src[i])) {
- escapes++;
- }
- }
- dst = PBC_ALLOC((escapes * 4) + ((len - escapes) * 2) + 1);
- if (!dst) {
- return NULL;
- }
-
- for (i = 0; i < len; i++) {
- switch (src[i]) {
- /* Special cases. */
- case '\'':
- dst[dst_len++] = '\\';
- dst[dst_len++] = '\'';
- break;
- case '\"':
- dst[dst_len++] = '\\';
- dst[dst_len++] = '\"';
- break;
- case '\\':
- dst[dst_len++] = '\\';
- dst[dst_len++] = '\\';
- break;
- case '\n':
- dst[dst_len++] = '\\';
- dst[dst_len++] = 'n';
- break;
- case '\r':
- dst[dst_len++] = '\\';
- dst[dst_len++] = 'r';
- break;
- case '\t':
- dst[dst_len++] = '\\';
- dst[dst_len++] = 't';
- break;
-
- /* Escape with octal if !isprint. */
- default:
- if (!isprint(src[i])) {
- dst_len += sprintf(dst + dst_len, "\\%03o", src[i]);
- } else {
- dst[dst_len++] = src[i];
- }
- break;
- }
- }
- dst[dst_len] = '\0';
-
- return dst;
-}
-
-/** Internal function to back API function.
- *
- * Has a few extra params to better enable recursion. This function gets
- * called for each nested message as the \c ProtobufCMessage struct is
- * traversed.
- *
- * \param[in,out] rs The string being built up for the text format protobuf.
- * \param[in] level Indent level - increments in 2's.
- * \param[in] m The \c ProtobufCMessage being serialised.
- * \param[in] d The descriptor for the \c ProtobufCMessage.
- * \param[in] allocator allocator functions.
- */
-static void
-protobuf_c_text_to_string_internal(ReturnString *rs,
- int level,
- ProtobufCMessage *m,
- const ProtobufCMessageDescriptor *d,
- ProtobufCAllocator *allocator)
-{
- int i;
- size_t j, quantifier_offset;
- double float_var;
- const ProtobufCFieldDescriptor *f;
- ProtobufCEnumDescriptor *enumd;
- const ProtobufCEnumValue *enumv;
-
- f = d->fields;
- for (i = 0; i < d->n_fields; i++) {
- if (rs->malloc_err) {
- /* If there's been a malloc error, go die. */
- return;
- }
-
- /* Decide if something needs to be done for this field. */
- switch (f[i].label) {
- case PROTOBUF_C_LABEL_OPTIONAL:
- if (f[i].type == PROTOBUF_C_TYPE_STRING) {
- if (!STRUCT_MEMBER(char *, m, f[i].offset)
- || (STRUCT_MEMBER(char *, m, f[i].offset)
- == (char *)f[i].default_value)) {
- continue;
- }
- } else if (f[i].type == PROTOBUF_C_TYPE_MESSAGE) {
- if (!STRUCT_MEMBER(char *, m, f[i].offset)) {
- continue;
- }
- } else {
- if (!STRUCT_MEMBER(protobuf_c_boolean, m, f[i].quantifier_offset)) {
- continue;
- }
- }
- break;
- case PROTOBUF_C_LABEL_REPEATED:
- if (!STRUCT_MEMBER(size_t, m, f[i].quantifier_offset)) {
- continue;
- }
- break;
- }
-
- quantifier_offset = STRUCT_MEMBER(size_t, m, f[i].quantifier_offset);
- /* Field exists and has data, dump it. */
- switch (f[i].type) {
- case PROTOBUF_C_TYPE_INT32:
- case PROTOBUF_C_TYPE_UINT32:
- case PROTOBUF_C_TYPE_FIXED32:
- if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
- for (j = 0; j < quantifier_offset; j++) {
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %u\n",
- level, "", f[i].name,
- STRUCT_MEMBER(uint32_t *, m, f[i].offset)[j]);
- }
- } else {
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %u\n",
- level, "", f[i].name,
- STRUCT_MEMBER(uint32_t, m, f[i].offset));
- }
- break;
- case PROTOBUF_C_TYPE_SINT32:
- case PROTOBUF_C_TYPE_SFIXED32:
- if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
- for (j = 0; j < quantifier_offset; j++) {
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %d\n",
- level, "", f[i].name,
- STRUCT_MEMBER(int32_t *, m, f[i].offset)[j]);
- }
- } else {
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %d\n",
- level, "", f[i].name,
- STRUCT_MEMBER(int32_t, m, f[i].offset));
- }
- break;
- case PROTOBUF_C_TYPE_INT64:
- case PROTOBUF_C_TYPE_UINT64:
- case PROTOBUF_C_TYPE_FIXED64:
- if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
- for (j = 0; j < quantifier_offset; j++) {
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %lu\n",
- level, "", f[i].name,
- STRUCT_MEMBER(uint64_t *, m, f[i].offset)[j]);
- }
- } else {
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %lu\n",
- level, "", f[i].name,
- STRUCT_MEMBER(uint64_t, m, f[i].offset));
- }
- break;
- case PROTOBUF_C_TYPE_SINT64:
- case PROTOBUF_C_TYPE_SFIXED64:
- if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
- for (j = 0; j < quantifier_offset; j++) {
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %ld\n",
- level, "", f[i].name,
- STRUCT_MEMBER(int64_t *, m, f[i].offset)[j]);
- }
- } else {
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %ld\n",
- level, "", f[i].name,
- STRUCT_MEMBER(int64_t, m, f[i].offset));
- }
- break;
- case PROTOBUF_C_TYPE_FLOAT:
- if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
- for (j = 0; j < quantifier_offset; j++) {
- float_var = STRUCT_MEMBER(float *, m, f[i].offset)[j];
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %g\n",
- level, "", f[i].name,
- float_var);
- }
- } else {
- float_var = STRUCT_MEMBER(float, m, f[i].offset);
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %g\n",
- level, "", f[i].name,
- float_var);
- }
- break;
- case PROTOBUF_C_TYPE_DOUBLE:
- if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
- for (j = 0; j < quantifier_offset; j++) {
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %g\n",
- level, "", f[i].name,
- STRUCT_MEMBER(double *, m, f[i].offset)[j]);
- }
- } else {
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %g\n",
- level, "", f[i].name,
- STRUCT_MEMBER(double, m, f[i].offset));
- }
- break;
- case PROTOBUF_C_TYPE_BOOL:
- if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
- for (j = 0; j < quantifier_offset; j++) {
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %s\n",
- level, "", f[i].name,
- STRUCT_MEMBER(protobuf_c_boolean *, m, f[i].offset)[j]?
- "true": "false");
- }
- } else {
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %s\n",
- level, "", f[i].name,
- STRUCT_MEMBER(protobuf_c_boolean, m, f[i].offset)?
- "true": "false");
- }
- break;
- case PROTOBUF_C_TYPE_ENUM:
- enumd = (ProtobufCEnumDescriptor *)f[i].descriptor;
- if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
- for (j = 0; j < quantifier_offset; j++) {
- enumv = protobuf_c_enum_descriptor_get_value(
- enumd, STRUCT_MEMBER(int *, m, f[i].offset)[j]);
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %s\n",
- level, "", f[i].name,
- enumv? enumv->name: "unknown");
- }
- } else {
- enumv = protobuf_c_enum_descriptor_get_value(
- enumd, STRUCT_MEMBER(int, m, f[i].offset));
- rs_append(rs, level + strlen(f[i].name) + 20,
- allocator,
- "%*s%s: %s\n",
- level, "", f[i].name,
- enumv? enumv->name: "unknown");
- }
- break;
- case PROTOBUF_C_TYPE_STRING:
- if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
- for (j = 0; j < quantifier_offset; j++) {
- unsigned char *escaped;
-
- escaped = esc_str(
- STRUCT_MEMBER(unsigned char **, m, f[i].offset)[j],
- strlen(STRUCT_MEMBER(unsigned char **, m, f[i].offset)[j]),
- allocator);
- if (!escaped) {
- PBC_FREE(rs->s);
- rs->s = NULL;
- rs->malloc_err = 1;
- return;
- }
- rs_append(rs, level + strlen(f[i].name) + strlen(escaped) + 10,
- allocator,
- "%*s%s: \"%s\"\n", level, "", f[i].name, escaped);
- PBC_FREE(escaped);
- }
- } else {
- unsigned char *escaped;
-
- escaped = esc_str(STRUCT_MEMBER(unsigned char *, m, f[i].offset),
- strlen(STRUCT_MEMBER(unsigned char *, m, f[i].offset)),
- allocator);
- if (!escaped) {
- PBC_FREE(rs->s);
- rs->s = NULL;
- rs->malloc_err = 1;
- return;
- }
- rs_append(rs, level + strlen(f[i].name) + strlen(escaped) + 10,
- allocator,
- "%*s%s: \"%s\"\n", level, "", f[i].name, escaped);
- PBC_FREE(escaped);
- }
- break;
- case PROTOBUF_C_TYPE_BYTES:
- if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
- for (j = 0; j < quantifier_offset; j++) {
- unsigned char *escaped;
-
- escaped = esc_str(
- STRUCT_MEMBER(ProtobufCBinaryData *, m, f[i].offset)[j].data,
- STRUCT_MEMBER(ProtobufCBinaryData *, m, f[i].offset)[j].len,
- allocator);
- if (!escaped) {
- PBC_FREE(rs->s);
- rs->s = NULL;
- rs->malloc_err = 1;
- return;
- }
- rs_append(rs, level + strlen(f[i].name) + strlen(escaped) + 10,
- allocator,
- "%*s%s: \"%s\"\n", level, "", f[i].name, escaped);
- PBC_FREE(escaped);
- }
- } else {
- unsigned char *escaped;
-
- escaped = esc_str(
- STRUCT_MEMBER(ProtobufCBinaryData, m, f[i].offset).data,
- STRUCT_MEMBER(ProtobufCBinaryData, m, f[i].offset).len,
- allocator);
- if (!escaped) {
- PBC_FREE(rs->s);
- rs->s = NULL;
- rs->malloc_err = 1;
- return;
- }
- rs_append(rs, level + strlen(f[i].name) + strlen(escaped) + 10,
- allocator,
- "%*s%s: \"%s\"\n", level, "", f[i].name, escaped);
- PBC_FREE(escaped);
- }
- break;
-
- case PROTOBUF_C_TYPE_MESSAGE:
- if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
- for (j = 0;
- j < STRUCT_MEMBER(size_t, m, f[i].quantifier_offset);
- j++) {
- rs_append(rs, level + strlen(f[i].name) + 10,
- allocator,
- "%*s%s {\n", level, "", f[i].name);
- protobuf_c_text_to_string_internal(rs, level + 2,
- STRUCT_MEMBER(ProtobufCMessage **, m, f[i].offset)[j],
- (ProtobufCMessageDescriptor *)f[i].descriptor,
- allocator);
- rs_append(rs, level + 10,
- allocator,
- "%*s}\n", level, "");
- }
- } else {
- rs_append(rs, level + strlen(f[i].name) + 10,
- allocator,
- "%*s%s {\n", level, "", f[i].name);
- protobuf_c_text_to_string_internal(rs, level + 2,
- STRUCT_MEMBER(ProtobufCMessage *, m, f[i].offset),
- (ProtobufCMessageDescriptor *)f[i].descriptor,
- allocator);
- rs_append(rs, level + 10,
- allocator,
- "%*s}\n", level, "");
- }
- break;
- default:
- PBC_FREE(rs->s);
- rs->s = NULL;
- return;
- break;
- }
-
- }
-}
-
-/** @} */ /* End of generate group. */
-
-/* See .h file for API docs. */
-
-char *
-protobuf_c_text_to_string(const ProtobufCMessage *m,
- ProtobufCAllocator *allocator)
-{
- ReturnString rs = { 0, 0, 0, NULL };
-
- protobuf_c_text_to_string_internal(&rs, 0, m, m->descriptor, allocator);
-
- return rs.s;
-}
diff --git a/protocols/Steam/src/protobuf-c/protobuf-c-text.cpp b/protocols/Steam/src/protobuf-c/protobuf-c-text.cpp
new file mode 100644
index 0000000000..c0438b6ac8
--- /dev/null
+++ b/protocols/Steam/src/protobuf-c/protobuf-c-text.cpp
@@ -0,0 +1,388 @@
+/** \file
+ * Routines to generate text format protobufs.
+ *
+ * This file contains the internal support functions as well as the
+ * exported functions which are used to generate text format protobufs
+ * from C protobuf data types.
+ *
+ * \author Kevin Lyda <kevin@ie.suberic.net>
+ * \date March 2014
+ */
+
+#include "../stdafx.h"
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "protobuf-c.h"
+#include "protobuf-c-util.h"
+
+ /** Append a string to the ReturnString.
+ *
+ * Append the string built from \c format and its args to the \c rs
+ * string. Note that \c malloc_err is checked and if it's true,
+ * this function won't do anything.
+ *
+ * \param[in,out] rs The string to append to.
+ * \param[in] guess A guess at the number of chars being added.
+ * \param[in] allocator allocator functions.
+ * \param[in] format Printf-style format string.
+ * \param[in] ... Variable number of args for \c format.
+ */
+
+ /** \defgroup generate Functions to generate text format proto bufs
+ * \ingroup internal
+ * @{
+ */
+
+ /** Escape string.
+ *
+ * Add escape characters to strings for problematic characters.
+ *
+ * \param[in] src The unescaped string to process.
+ * \param[in] len Length of \c src. Note that \c src might have ASCII
+ * \c NULs so strlen() isn't good enough here.
+ * \param[in] allocator allocator functions.
+ * \return The fully escaped string, or \c NULL if there has been an
+ * allocation error.
+ */
+static char *
+esc_str(const char *src, size_t len)
+{
+ size_t escapes = 0, dst_len = 0;
+
+ for (size_t i = 0; i < len; i++) {
+ if (!isprint(src[i])) {
+ escapes++;
+ }
+ }
+
+ char *dst = (char *)malloc((escapes * 4) + ((len - escapes) * 2) + 1);
+ if (!dst) {
+ return NULL;
+ }
+
+ for (size_t i = 0; i < len; i++) {
+ switch (src[i]) {
+ /* Special cases. */
+ case '\'':
+ dst[dst_len++] = '\\';
+ dst[dst_len++] = '\'';
+ break;
+ case '\"':
+ dst[dst_len++] = '\\';
+ dst[dst_len++] = '\"';
+ break;
+ case '\\':
+ dst[dst_len++] = '\\';
+ dst[dst_len++] = '\\';
+ break;
+ case '\n':
+ dst[dst_len++] = '\\';
+ dst[dst_len++] = 'n';
+ break;
+ case '\r':
+ dst[dst_len++] = '\\';
+ dst[dst_len++] = 'r';
+ break;
+ case '\t':
+ dst[dst_len++] = '\\';
+ dst[dst_len++] = 't';
+ break;
+
+ /* Escape with octal if !isprint. */
+ default:
+ if (!isprint(src[i])) {
+ dst_len += sprintf(dst + dst_len, "\\%03o", src[i]);
+ }
+ else {
+ dst[dst_len++] = src[i];
+ }
+ break;
+ }
+ }
+ dst[dst_len] = '\0';
+
+ return dst;
+}
+
+/** Internal function to back API function.
+ *
+ * Has a few extra params to better enable recursion. This function gets
+ * called for each nested message as the \c ProtobufCMessage struct is
+ * traversed.
+ *
+ * \param[in,out] rs The string being built up for the text format protobuf.
+ * \param[in] level Indent level - increments in 2's.
+ * \param[in] m The \c ProtobufCMessage being serialised.
+ * \param[in] d The descriptor for the \c ProtobufCMessage.
+ * \param[in] allocator allocator functions.
+ */
+static void protobuf_c_text_to_string_internal(
+ CMStringA &str,
+ int level,
+ const ProtobufCMessage *m,
+ const ProtobufCMessageDescriptor *d)
+{
+ size_t j, quantifier_offset;
+ double float_var;
+ const ProtobufCFieldDescriptor *f;
+ ProtobufCEnumDescriptor *enumd;
+ const ProtobufCEnumValue *enumv;
+
+ f = d->fields;
+ for (unsigned i = 0; i < d->n_fields; i++) {
+ /* Decide if something needs to be done for this field. */
+ switch (f[i].label) {
+ case PROTOBUF_C_LABEL_OPTIONAL:
+ if (f[i].type == PROTOBUF_C_TYPE_STRING) {
+ if (!STRUCT_MEMBER(char *, m, f[i].offset)
+ || (STRUCT_MEMBER(char *, m, f[i].offset)
+ == (char *)f[i].default_value)) {
+ continue;
+ }
+ }
+ else if (f[i].type == PROTOBUF_C_TYPE_MESSAGE) {
+ if (!STRUCT_MEMBER(char *, m, f[i].offset)) {
+ continue;
+ }
+ }
+ else {
+ if (!STRUCT_MEMBER(protobuf_c_boolean, m, f[i].quantifier_offset)) {
+ continue;
+ }
+ }
+ break;
+ case PROTOBUF_C_LABEL_REPEATED:
+ if (!STRUCT_MEMBER(size_t, m, f[i].quantifier_offset)) {
+ continue;
+ }
+ break;
+ }
+
+ quantifier_offset = STRUCT_MEMBER(size_t, m, f[i].quantifier_offset);
+ /* Field exists and has data, dump it. */
+ switch (f[i].type) {
+ case PROTOBUF_C_TYPE_INT32:
+ case PROTOBUF_C_TYPE_UINT32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
+ for (j = 0; j < quantifier_offset; j++) {
+ str.AppendFormat(
+ "%*s%s: %u\n",
+ level, "", f[i].name,
+ STRUCT_MEMBER(uint32_t *, m, f[i].offset)[j]);
+ }
+ }
+ else {
+ str.AppendFormat(
+ "%*s%s: %u\n",
+ level, "", f[i].name,
+ STRUCT_MEMBER(uint32_t, m, f[i].offset));
+ }
+ break;
+ case PROTOBUF_C_TYPE_SINT32:
+ case PROTOBUF_C_TYPE_SFIXED32:
+ if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
+ for (j = 0; j < quantifier_offset; j++) {
+ str.AppendFormat(
+ "%*s%s: %d\n",
+ level, "", f[i].name,
+ STRUCT_MEMBER(int32_t *, m, f[i].offset)[j]);
+ }
+ }
+ else {
+ str.AppendFormat(
+ "%*s%s: %d\n",
+ level, "", f[i].name,
+ STRUCT_MEMBER(int32_t, m, f[i].offset));
+ }
+ break;
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
+ for (j = 0; j < quantifier_offset; j++) {
+ str.AppendFormat(
+ "%*s%s: %lu\n",
+ level, "", f[i].name,
+ STRUCT_MEMBER(uint64_t *, m, f[i].offset)[j]);
+ }
+ }
+ else {
+ str.AppendFormat(
+ "%*s%s: %lu\n",
+ level, "", f[i].name,
+ STRUCT_MEMBER(uint64_t, m, f[i].offset));
+ }
+ break;
+ case PROTOBUF_C_TYPE_SINT64:
+ case PROTOBUF_C_TYPE_SFIXED64:
+ if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
+ for (j = 0; j < quantifier_offset; j++) {
+ str.AppendFormat(
+ "%*s%s: %ld\n",
+ level, "", f[i].name,
+ STRUCT_MEMBER(int64_t *, m, f[i].offset)[j]);
+ }
+ }
+ else {
+ str.AppendFormat(
+ "%*s%s: %ld\n",
+ level, "", f[i].name,
+ STRUCT_MEMBER(int64_t, m, f[i].offset));
+ }
+ break;
+ case PROTOBUF_C_TYPE_FLOAT:
+ if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
+ for (j = 0; j < quantifier_offset; j++) {
+ float_var = STRUCT_MEMBER(float *, m, f[i].offset)[j];
+ str.AppendFormat(
+ "%*s%s: %g\n",
+ level, "", f[i].name,
+ float_var);
+ }
+ }
+ else {
+ float_var = STRUCT_MEMBER(float, m, f[i].offset);
+ str.AppendFormat(
+ "%*s%s: %g\n",
+ level, "", f[i].name,
+ float_var);
+ }
+ break;
+ case PROTOBUF_C_TYPE_DOUBLE:
+ if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
+ for (j = 0; j < quantifier_offset; j++) {
+ str.AppendFormat(
+ "%*s%s: %g\n",
+ level, "", f[i].name,
+ STRUCT_MEMBER(double *, m, f[i].offset)[j]);
+ }
+ }
+ else {
+ str.AppendFormat(
+ "%*s%s: %g\n",
+ level, "", f[i].name,
+ STRUCT_MEMBER(double, m, f[i].offset));
+ }
+ break;
+ case PROTOBUF_C_TYPE_BOOL:
+ if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
+ for (j = 0; j < quantifier_offset; j++) {
+ str.AppendFormat(
+ "%*s%s: %s\n",
+ level, "", f[i].name,
+ STRUCT_MEMBER(protobuf_c_boolean *, m, f[i].offset)[j] ?
+ "true" : "false");
+ }
+ }
+ else {
+ str.AppendFormat(
+ "%*s%s: %s\n",
+ level, "", f[i].name,
+ STRUCT_MEMBER(protobuf_c_boolean, m, f[i].offset) ?
+ "true" : "false");
+ }
+ break;
+ case PROTOBUF_C_TYPE_ENUM:
+ enumd = (ProtobufCEnumDescriptor *)f[i].descriptor;
+ if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
+ for (j = 0; j < quantifier_offset; j++) {
+ enumv = protobuf_c_enum_descriptor_get_value(
+ enumd, STRUCT_MEMBER(int *, m, f[i].offset)[j]);
+ str.AppendFormat(
+ "%*s%s: %s\n",
+ level, "", f[i].name,
+ enumv ? enumv->name : "unknown");
+ }
+ }
+ else {
+ enumv = protobuf_c_enum_descriptor_get_value(
+ enumd, STRUCT_MEMBER(int, m, f[i].offset));
+ str.AppendFormat(
+ "%*s%s: %s\n",
+ level, "", f[i].name,
+ enumv ? enumv->name : "unknown");
+ }
+ break;
+ case PROTOBUF_C_TYPE_STRING:
+ if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
+ for (j = 0; j < quantifier_offset; j++) {
+ char *escaped = esc_str(
+ STRUCT_MEMBER(char **, m, f[i].offset)[j],
+ strlen(STRUCT_MEMBER(char **, m, f[i].offset)[j]));
+ str.AppendFormat("%*s%s: \"%s\"\n", level, "", f[i].name, escaped);
+ free(escaped);
+ }
+ }
+ else {
+ char *escaped = esc_str(STRUCT_MEMBER(char *, m, f[i].offset),
+ strlen(STRUCT_MEMBER(char *, m, f[i].offset)));
+ str.AppendFormat("%*s%s: \"%s\"\n", level, "", f[i].name, escaped);
+ free(escaped);
+ }
+ break;
+ case PROTOBUF_C_TYPE_BYTES:
+ if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
+ for (j = 0; j < quantifier_offset; j++) {
+ auto *member = STRUCT_MEMBER(ProtobufCBinaryData *, m, f[i].offset);
+ char *p = (char *)malloc(member->len * 2 + 1);
+ bin2hex(member->data, member->len, p);
+ str.AppendFormat("%*s%s: \"%s\"\n", level, "", f[i].name, p);
+ free(p);
+ }
+ }
+ else {
+ auto member = STRUCT_MEMBER(ProtobufCBinaryData, m, f[i].offset);
+ char *p = (char *)malloc(member.len * 2 + 1);
+ bin2hex(member.data, member.len, p);
+ str.AppendFormat("%*s%s: \"%s\"\n", level, "", f[i].name, p);
+ free(p);
+ }
+ break;
+
+ case PROTOBUF_C_TYPE_MESSAGE:
+ if (f[i].label == PROTOBUF_C_LABEL_REPEATED) {
+ for (j = 0;
+ j < STRUCT_MEMBER(size_t, m, f[i].quantifier_offset);
+ j++) {
+ str.AppendFormat("%*s%s {\n", level, "", f[i].name);
+ protobuf_c_text_to_string_internal(str, level + 2,
+ STRUCT_MEMBER(ProtobufCMessage **, m, f[i].offset)[j],
+ (ProtobufCMessageDescriptor *)f[i].descriptor);
+ str.AppendFormat("%*s}\n", level, "");
+ }
+ }
+ else {
+ str.AppendFormat("%*s%s {\n", level, "", f[i].name);
+ protobuf_c_text_to_string_internal(str, level + 2,
+ STRUCT_MEMBER(ProtobufCMessage *, m, f[i].offset),
+ (ProtobufCMessageDescriptor *)f[i].descriptor);
+ str.AppendFormat("%*s}\n", level, "");
+ }
+ break;
+
+ default:
+ return;
+ }
+ }
+}
+
+/** @} */ /* End of generate group. */
+
+/* See .h file for API docs. */
+
+CMStringA protobuf_c_text_to_string(const ProtobufCMessage &msg)
+{
+ CMStringA ret;
+
+ ret.AppendFormat("%s {\n", msg.descriptor->c_name);
+ protobuf_c_text_to_string_internal(ret, 1, &msg, msg.descriptor);
+ ret.Append("}\n");
+
+ return ret;
+}
diff --git a/protocols/Steam/src/protobuf-c/protobuf-c-text.h b/protocols/Steam/src/protobuf-c/protobuf-c-text.h
deleted file mode 100644
index d921b21d08..0000000000
--- a/protocols/Steam/src/protobuf-c/protobuf-c-text.h
+++ /dev/null
@@ -1,213 +0,0 @@
-#ifndef PROTOBUF_C_TEXT_H
-#define PROTOBUF_C_TEXT_H
-
-/*
- * \file
- * Library header file.
- * This is the header file for the text format protobuf routines.
- * It contains declarations of all functions and data types exported by
- * the library.
- *
- * \author Kevin Lyda <kevin@ie.suberic.net>
- * \date March 2014
- *
- */
-
-/** \mainpage
- *
- * \section description Description
- *
- * Google protobufs are an efficient way to serialise and deserialise
- * data to send across the wire or to store on disk. The Google compiler
- * and related libraries provide implementations for C++, Java and Python.
- * A very simple message definition language is used to generate parsers
- * and generators for this binary format.
- *
- * The Protobuf compiler and library for C provide access to this
- * technology from within C code.
- *
- * Besides the efficient binary protobuf format there is also a text mode
- * format which is accessible to code generated by the Google protobuf
- * compiler. While the text format has limitations - namely that it lacks
- * some of the back/forwards-compatibility features of the binary format -
- * it can be a useful debugging tool and a strict but human readable config
- * file format.
- *
- * The C protobuf implementation is very minimal and lacks this feature.
- * This library supplements \c libprotobuf-c and provides functions to
- * generate and consume text format protobuf. They will work fine with
- * any \c ProtobufCMessage subtype generated by the \c protoc-c
- * compiler.
- *
- * \sa
- * - Google Protobufs: https://code.google.com/p/protobuf/
- * - Protobuf docs:
- * https://developers.google.com/protocol-buffers/docs/overview
- * - Notes on protobuf compatibility:
- * https://developers.google.com/protocol-buffers/docs/proto#updating
- * - Protobuf for C code: https://github.com/protobuf-c/protobuf-c
- * - Protobuf for C docs:
- * https://github.com/protobuf-c/protobuf-c/wiki
- * - Protobuf for C RPC library code:
- * https://github.com/protobuf-c/protobuf-c-rpc
- * - Protobuf for C text format code:
- * https://github.com/protobuf-c/protobuf-c-text
- * - Protobuf for C text format
- * <a href=coverage/index.html>test coverage</a>
- *
- * \section example Examples
- *
- * Both examples use this \c .proto definition:
- * \verbatim
-message Ponycopter {
- optional string hair_colour = 1;
- optional uint32 rotors = 2;
- optional uint32 awesomeness = 3;
-}
-\endverbatim
- *
- * \b Generating
- *
- * \verbatim
-#include <protobuf-c/protobuf-c.h>
-#include "ponycopter.pb-c.h"
-
-int main(int argc, char *argv[]) {
- int len;
- char *pc_bin, *pc_text;
- Ponycopter *pc;
-
- pc_bin = read_a_blob(argv[1], &len);
- pc = ponycopter__unpack(NULL, len, pc_bin);
- pc_text = protobuf_c_text_to_string((ProtobufCMessage *)pc, NULL);
- printf("Ponycopter: %s\n", pc_text);
-}
-\endverbatim
- *
- * \b Parsing
- *
- * \verbatim
-#include <protobuf-c/protobuf-c.h>
-#include "ponycopter.pb-c.h"
-
-int main(int argc, char *argv[]) {
- ProtobufCTextError tf_res;
- Ponycopter *pc;
-
- pc = (Ponycopter *)protobuf_c_text_from_file(
- &ponycopter__descriptor, argv[1], &tf_res, NULL);
-}
-\endverbatim
- */
-
-#include <stdio.h> /* for the FILE * data type. */
-#include "protobuf-c.h"
-
-/** \defgroup api Public API for text format protobufs
- *
- * These functions supplement the generated code from \c protoc-c to
- * allow you to import and export \c ProtobufCMessage structures
- * from/to the protobuf text mode serialisation.
- *
- * These will work with any code generated from \c protoc-c.
- * @{
- */
-
-/** Structure for reporting API errors.
- *
- * Provides feedback on the success of an API call. Generally if an
- * API call fails it will return \c NULL. More detail on why it failed
- * can be found in the parameter with this type.
- */
-typedef struct _ProtobufCTextError {
- int *error; /**< Error code. 0 for success, >0 for failure. */
- char *error_txt; /**< String with error message. */
- int complete; /**< Reports whether the message is complete
- (if supported):
- - -1: Required field check wasn't performed - this
- happens if your libprotobuf-c is too old.
- - 0: The message was incomplete.
- - >0: Message has all required fields set. */
-} ProtobufCTextError;
-
-/** Convert a \c ProtobufCMessage to a string.
- *
- * Given a \c ProtobufCMessage serialise it as a text format protobuf.
- *
- * \param[in] m The \c ProtobufCMessage to be serialised.
- * \param[in] allocator This is the same \c ProtobufCAllocator type used
- * by the \c libprotobuf-c library. You can set it
- * to \c NULL to accept \c protobuf_c_default_allocator -
- * the default allocator.
- * \return The string with the text format serialised \c ProtobufCMessage.
- * On failure it will return \c NULL. On success, the resulting value
- * be freed by you with the \c allocator you provided. If you didn't
- * provide an allocator technically you should do:
- * \code
- * protobuf_c_default_allocator.free(
- * protobuf_c_default_allocator.allocator_data, retval);
- * \endcode
- * Though technically \c free(retval); is probably sufficient.
- */
-extern char *protobuf_c_text_to_string(const ProtobufCMessage *m,
- ProtobufCAllocator *allocator);
-
-/** Import a text format protobuf from a string into a \c ProtobufCMessage.
- *
- * Given a string containing a text format protobuf, parse it and return
- * the corresponding \c ProtobufCMessage struct. On failure, \c NULL is
- * returned and \c result is updated with why.
- *
- * The resulting \c ProtobufCMessage should be freed with
- * \c protobuf_c_message_free_unpacked() or the generated
- * \c ..._free_upacked() function. Either is fine, but that's how the
- * memory should be freed.
- *
- * \param[in] descriptor The descriptor from the generated code.
- * \param[in] msg The string containing the text format protobuf.
- * \param[out] result This structure contains information on any error
- * that halted processing.
- * \param[in] allocator This is the same \c ProtobufCAllocator type used
- * by the \c libprotobuf-c library. You can set it
- * to \c NULL to accept \c protobuf_c_default_allocator -
- * the default allocator.
- * \return The resulting \c ProtobufCMessage . It returns \c NULL on error.
- * Check \c result->complete to make sure the message is valid.
- */
-extern ProtobufCMessage *protobuf_c_text_from_string(
- const ProtobufCMessageDescriptor *descriptor,
- char *msg,
- ProtobufCTextError *result,
- ProtobufCAllocator *allocator);
-
-/** Import a text format protobuf from a \c FILE into a \c ProtobufCMessage.
- *
- * Given a \c FILE containing a text format protobuf, parse it and return
- * the corresponding \c ProtobufCMessage struct. On failure, \c NULL is
- * returned and \c result is updated with why.
- *
- * The resulting \c ProtobufCMessage should be freed with
- * \c protobuf_c_message_free_unpacked() or the generated
- * \c ..._free_upacked() function. Either is fine, but that's how the
- * memory should be freed.
- *
- * \param[in] descriptor The descriptor from the generated code.
- * \param[in] msg_file The \c FILE containing the text format protobuf.
- * \param[out] result This structure contains information on any error
- * that halted processing.
- * \param[in] allocator This is the same \c ProtobufCAllocator type used
- * by the \c libprotobuf-c library. You can set it
- * to \c NULL to accept \c protobuf_c_default_allocator -
- * the default allocator.
- * \return The resulting \c ProtobufCMessage . It returns \c NULL on error.
- * Check \c result->complete to make sure the message is valid.
- */
-extern ProtobufCMessage *protobuf_c_text_from_file(
- const ProtobufCMessageDescriptor *descriptor,
- FILE *msg_file,
- ProtobufCTextError *result,
- ProtobufCAllocator *allocator);
-
-/** @} */ /* End of API group. */
-
-#endif /* PROTOBUF_C_TEXT_H */
diff --git a/protocols/Steam/src/stdafx.h b/protocols/Steam/src/stdafx.h
index 11cdbe7e49..d14388ef70 100644
--- a/protocols/Steam/src/stdafx.h
+++ b/protocols/Steam/src/stdafx.h
@@ -44,11 +44,6 @@
#include "protobuf-c/steammessages_friendmessages.steamclient.pb-c.h"
#include "proto.h"
-extern "C"
-{
- #include "protobuf-c/protobuf-c-text.h"
-}
-
#define MODULE "Steam"
#define DB_KEY_LASTMSGTS "LastMessageTS"
@@ -73,6 +68,7 @@ extern HANDLE hExtraXStatus;
#define now() time(0)
int64_t getRandomInt();
+CMStringA protobuf_c_text_to_string(const ProtobufCMessage &msg);
#include "steam_dialogs.h"
diff --git a/protocols/Steam/src/steam_ws.cpp b/protocols/Steam/src/steam_ws.cpp
index b84baf95e8..bbf8a5b7a0 100644
--- a/protocols/Steam/src/steam_ws.cpp
+++ b/protocols/Steam/src/steam_ws.cpp
@@ -207,9 +207,7 @@ void CSteamProto::WSSend(EMsg msgType, const ProtobufCppMessage &msg)
void CSteamProto::WSSendHeader(EMsg msgType, const CMsgProtoBufHeader &hdr, const ProtobufCppMessage &msg)
{
- auto *pszText = protobuf_c_text_to_string(&msg, 0);
- debugLogA("Message sent: %s\r\n%s", msg.descriptor->c_name, pszText);
- free(pszText);
+ debugLogA("Message sent:\n%s", protobuf_c_text_to_string(msg).c_str());
uint32_t hdrLen = (uint32_t)protobuf_c_message_get_packed_size(&hdr);
MBinBuffer hdrbuf(hdrLen);