diff options
Diffstat (limited to 'protocols/Steam/src')
-rw-r--r-- | protocols/Steam/src/protobuf-c/protobuf-c-text.c | 501 | ||||
-rw-r--r-- | protocols/Steam/src/protobuf-c/protobuf-c-text.cpp | 388 | ||||
-rw-r--r-- | protocols/Steam/src/protobuf-c/protobuf-c-text.h | 213 | ||||
-rw-r--r-- | protocols/Steam/src/stdafx.h | 6 | ||||
-rw-r--r-- | protocols/Steam/src/steam_ws.cpp | 4 |
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); |