Mumble 1.2.x compatible server. Kind of working, at least in server loopback mode.
authorfatbob313 <martin@fatbob.nu>
Sat, 19 Dec 2009 23:38:19 +0000 (23:38 +0000)
committerfatbob313 <martin@fatbob.nu>
Sat, 19 Dec 2009 23:38:19 +0000 (23:38 +0000)
Lots of protocol related changes, most notably the use of protobuf-c for network messages.

16 files changed:
src/Makefile
src/Mumble.pb-c.c [new file with mode: 0644]
src/Mumble.pb-c.h [new file with mode: 0644]
src/client.c
src/client.h
src/google/protobuf-c/Makefile [new file with mode: 0644]
src/google/protobuf-c/protobuf-c-data-buffer.c [new file with mode: 0644]
src/google/protobuf-c/protobuf-c-data-buffer.h [new file with mode: 0644]
src/google/protobuf-c/protobuf-c-private.h [new file with mode: 0644]
src/google/protobuf-c/protobuf-c.c [new file with mode: 0644]
src/google/protobuf-c/protobuf-c.h [new file with mode: 0644]
src/messagehandler.c
src/messages.c
src/messages.h
src/pds.c
src/pds.h

index e66f475ec9e31f5fe5f89f3d0c88f76e841ea4a0..02addaff9f6bd511dd6db298aa7db82a575b3939 100644 (file)
@@ -1,18 +1,24 @@
 # build helloworld executable when user executes "make" 
 
-SRCS:=client.c main.c messages.c pds.c server.c ssl.c log.c conf.c crypt.c timer.c messagehandler.c channel.c
+SRCS:=client.c main.c messages.c pds.c server.c ssl.c log.c conf.c crypt.c \
+       timer.c messagehandler.c channel.c Mumble.pb-c.c
+
 OBJS:=$(patsubst %.c, %.o, $(SRCS))
-CFLAGS:=$(CFLAGS) -Wall -Os -g
-LDFLAGS:=$(LDFLAGS) -lcrypto -lssl -lconfig
+CFLAGS:=$(CFLAGS) -I. -Wall -g -DDEBUG
+LDFLAGS:=$(LDFLAGS) -L/data/export/proj/protobuf/lib -lcrypto -lssl -lconfig
+
+umurmurd:google/protobuf-c/libprotobuf_c.a depend.mak $(OBJS)  
+       $(CC) $(LDFLAGS) $(OBJS) google/protobuf-c/libprotobuf_c.a -o umurmurd
 
-umurmurd:$(OBJS) depend.mak
-       $(CC) $(LDFLAGS) $(OBJS) -o umurmurd
+google/protobuf-c/libprotobuf_c.a:
+       $(MAKE) -C google/protobuf-c/
 
 # remove object files and executable when user executes "make clean"
 clean:
-       rm *.o umurmurd 
+       $(MAKE) -C google/protobuf-c/ clean
+       rm -f *.o umurmurd 
 
-all: umurmur
+all: umurmurd
 
 $(OBJS): Makefile
 
diff --git a/src/Mumble.pb-c.c b/src/Mumble.pb-c.c
new file mode 100644 (file)
index 0000000..d0bbec9
--- /dev/null
@@ -0,0 +1,3175 @@
+/* Generated by the protocol buffer compiler.  DO NOT EDIT! */
+
+#include "Mumble.pb-c.h"
+void   mumble_proto__version__init
+                     (MumbleProto__Version         *message)
+{
+  static MumbleProto__Version init_value = MUMBLE_PROTO__VERSION__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__version__get_packed_size
+                     (const MumbleProto__Version *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__version__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__version__pack
+                     (const MumbleProto__Version *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__version__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__version__pack_to_buffer
+                     (const MumbleProto__Version *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__version__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__Version *
+       mumble_proto__version__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__Version *)
+     protobuf_c_message_unpack (&mumble_proto__version__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__version__free_unpacked
+                     (MumbleProto__Version *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__version__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__udptunnel__init
+                     (MumbleProto__UDPTunnel         *message)
+{
+  static MumbleProto__UDPTunnel init_value = MUMBLE_PROTO__UDPTUNNEL__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__udptunnel__get_packed_size
+                     (const MumbleProto__UDPTunnel *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__udptunnel__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__udptunnel__pack
+                     (const MumbleProto__UDPTunnel *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__udptunnel__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__udptunnel__pack_to_buffer
+                     (const MumbleProto__UDPTunnel *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__udptunnel__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__UDPTunnel *
+       mumble_proto__udptunnel__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__UDPTunnel *)
+     protobuf_c_message_unpack (&mumble_proto__udptunnel__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__udptunnel__free_unpacked
+                     (MumbleProto__UDPTunnel *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__udptunnel__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__authenticate__init
+                     (MumbleProto__Authenticate         *message)
+{
+  static MumbleProto__Authenticate init_value = MUMBLE_PROTO__AUTHENTICATE__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__authenticate__get_packed_size
+                     (const MumbleProto__Authenticate *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__authenticate__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__authenticate__pack
+                     (const MumbleProto__Authenticate *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__authenticate__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__authenticate__pack_to_buffer
+                     (const MumbleProto__Authenticate *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__authenticate__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__Authenticate *
+       mumble_proto__authenticate__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__Authenticate *)
+     protobuf_c_message_unpack (&mumble_proto__authenticate__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__authenticate__free_unpacked
+                     (MumbleProto__Authenticate *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__authenticate__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__ping__init
+                     (MumbleProto__Ping         *message)
+{
+  static MumbleProto__Ping init_value = MUMBLE_PROTO__PING__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__ping__get_packed_size
+                     (const MumbleProto__Ping *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__ping__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__ping__pack
+                     (const MumbleProto__Ping *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__ping__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__ping__pack_to_buffer
+                     (const MumbleProto__Ping *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__ping__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__Ping *
+       mumble_proto__ping__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__Ping *)
+     protobuf_c_message_unpack (&mumble_proto__ping__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__ping__free_unpacked
+                     (MumbleProto__Ping *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__ping__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__reject__init
+                     (MumbleProto__Reject         *message)
+{
+  static MumbleProto__Reject init_value = MUMBLE_PROTO__REJECT__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__reject__get_packed_size
+                     (const MumbleProto__Reject *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__reject__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__reject__pack
+                     (const MumbleProto__Reject *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__reject__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__reject__pack_to_buffer
+                     (const MumbleProto__Reject *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__reject__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__Reject *
+       mumble_proto__reject__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__Reject *)
+     protobuf_c_message_unpack (&mumble_proto__reject__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__reject__free_unpacked
+                     (MumbleProto__Reject *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__reject__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__server_sync__init
+                     (MumbleProto__ServerSync         *message)
+{
+  static MumbleProto__ServerSync init_value = MUMBLE_PROTO__SERVER_SYNC__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__server_sync__get_packed_size
+                     (const MumbleProto__ServerSync *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__server_sync__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__server_sync__pack
+                     (const MumbleProto__ServerSync *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__server_sync__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__server_sync__pack_to_buffer
+                     (const MumbleProto__ServerSync *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__server_sync__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__ServerSync *
+       mumble_proto__server_sync__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__ServerSync *)
+     protobuf_c_message_unpack (&mumble_proto__server_sync__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__server_sync__free_unpacked
+                     (MumbleProto__ServerSync *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__server_sync__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__channel_remove__init
+                     (MumbleProto__ChannelRemove         *message)
+{
+  static MumbleProto__ChannelRemove init_value = MUMBLE_PROTO__CHANNEL_REMOVE__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__channel_remove__get_packed_size
+                     (const MumbleProto__ChannelRemove *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__channel_remove__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__channel_remove__pack
+                     (const MumbleProto__ChannelRemove *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__channel_remove__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__channel_remove__pack_to_buffer
+                     (const MumbleProto__ChannelRemove *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__channel_remove__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__ChannelRemove *
+       mumble_proto__channel_remove__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__ChannelRemove *)
+     protobuf_c_message_unpack (&mumble_proto__channel_remove__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__channel_remove__free_unpacked
+                     (MumbleProto__ChannelRemove *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__channel_remove__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__channel_state__init
+                     (MumbleProto__ChannelState         *message)
+{
+  static MumbleProto__ChannelState init_value = MUMBLE_PROTO__CHANNEL_STATE__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__channel_state__get_packed_size
+                     (const MumbleProto__ChannelState *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__channel_state__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__channel_state__pack
+                     (const MumbleProto__ChannelState *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__channel_state__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__channel_state__pack_to_buffer
+                     (const MumbleProto__ChannelState *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__channel_state__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__ChannelState *
+       mumble_proto__channel_state__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__ChannelState *)
+     protobuf_c_message_unpack (&mumble_proto__channel_state__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__channel_state__free_unpacked
+                     (MumbleProto__ChannelState *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__channel_state__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__user_remove__init
+                     (MumbleProto__UserRemove         *message)
+{
+  static MumbleProto__UserRemove init_value = MUMBLE_PROTO__USER_REMOVE__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__user_remove__get_packed_size
+                     (const MumbleProto__UserRemove *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__user_remove__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__user_remove__pack
+                     (const MumbleProto__UserRemove *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__user_remove__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__user_remove__pack_to_buffer
+                     (const MumbleProto__UserRemove *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__user_remove__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__UserRemove *
+       mumble_proto__user_remove__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__UserRemove *)
+     protobuf_c_message_unpack (&mumble_proto__user_remove__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__user_remove__free_unpacked
+                     (MumbleProto__UserRemove *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__user_remove__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__user_state__init
+                     (MumbleProto__UserState         *message)
+{
+  static MumbleProto__UserState init_value = MUMBLE_PROTO__USER_STATE__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__user_state__get_packed_size
+                     (const MumbleProto__UserState *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__user_state__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__user_state__pack
+                     (const MumbleProto__UserState *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__user_state__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__user_state__pack_to_buffer
+                     (const MumbleProto__UserState *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__user_state__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__UserState *
+       mumble_proto__user_state__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__UserState *)
+     protobuf_c_message_unpack (&mumble_proto__user_state__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__user_state__free_unpacked
+                     (MumbleProto__UserState *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__user_state__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__ban_list__init
+                     (MumbleProto__BanList         *message)
+{
+  static MumbleProto__BanList init_value = MUMBLE_PROTO__BAN_LIST__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__ban_list__get_packed_size
+                     (const MumbleProto__BanList *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__ban_list__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__ban_list__pack
+                     (const MumbleProto__BanList *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__ban_list__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__ban_list__pack_to_buffer
+                     (const MumbleProto__BanList *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__ban_list__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__BanList *
+       mumble_proto__ban_list__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__BanList *)
+     protobuf_c_message_unpack (&mumble_proto__ban_list__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__ban_list__free_unpacked
+                     (MumbleProto__BanList *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__ban_list__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__text_message__init
+                     (MumbleProto__TextMessage         *message)
+{
+  static MumbleProto__TextMessage init_value = MUMBLE_PROTO__TEXT_MESSAGE__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__text_message__get_packed_size
+                     (const MumbleProto__TextMessage *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__text_message__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__text_message__pack
+                     (const MumbleProto__TextMessage *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__text_message__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__text_message__pack_to_buffer
+                     (const MumbleProto__TextMessage *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__text_message__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__TextMessage *
+       mumble_proto__text_message__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__TextMessage *)
+     protobuf_c_message_unpack (&mumble_proto__text_message__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__text_message__free_unpacked
+                     (MumbleProto__TextMessage *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__text_message__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__permission_denied__init
+                     (MumbleProto__PermissionDenied         *message)
+{
+  static MumbleProto__PermissionDenied init_value = MUMBLE_PROTO__PERMISSION_DENIED__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__permission_denied__get_packed_size
+                     (const MumbleProto__PermissionDenied *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__permission_denied__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__permission_denied__pack
+                     (const MumbleProto__PermissionDenied *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__permission_denied__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__permission_denied__pack_to_buffer
+                     (const MumbleProto__PermissionDenied *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__permission_denied__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__PermissionDenied *
+       mumble_proto__permission_denied__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__PermissionDenied *)
+     protobuf_c_message_unpack (&mumble_proto__permission_denied__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__permission_denied__free_unpacked
+                     (MumbleProto__PermissionDenied *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__permission_denied__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__acl__init
+                     (MumbleProto__ACL         *message)
+{
+  static MumbleProto__ACL init_value = MUMBLE_PROTO__ACL__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__acl__get_packed_size
+                     (const MumbleProto__ACL *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__acl__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__acl__pack
+                     (const MumbleProto__ACL *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__acl__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__acl__pack_to_buffer
+                     (const MumbleProto__ACL *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__acl__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__ACL *
+       mumble_proto__acl__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__ACL *)
+     protobuf_c_message_unpack (&mumble_proto__acl__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__acl__free_unpacked
+                     (MumbleProto__ACL *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__acl__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__query_users__init
+                     (MumbleProto__QueryUsers         *message)
+{
+  static MumbleProto__QueryUsers init_value = MUMBLE_PROTO__QUERY_USERS__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__query_users__get_packed_size
+                     (const MumbleProto__QueryUsers *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__query_users__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__query_users__pack
+                     (const MumbleProto__QueryUsers *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__query_users__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__query_users__pack_to_buffer
+                     (const MumbleProto__QueryUsers *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__query_users__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__QueryUsers *
+       mumble_proto__query_users__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__QueryUsers *)
+     protobuf_c_message_unpack (&mumble_proto__query_users__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__query_users__free_unpacked
+                     (MumbleProto__QueryUsers *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__query_users__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__crypt_setup__init
+                     (MumbleProto__CryptSetup         *message)
+{
+  static MumbleProto__CryptSetup init_value = MUMBLE_PROTO__CRYPT_SETUP__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__crypt_setup__get_packed_size
+                     (const MumbleProto__CryptSetup *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__crypt_setup__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__crypt_setup__pack
+                     (const MumbleProto__CryptSetup *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__crypt_setup__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__crypt_setup__pack_to_buffer
+                     (const MumbleProto__CryptSetup *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__crypt_setup__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__CryptSetup *
+       mumble_proto__crypt_setup__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__CryptSetup *)
+     protobuf_c_message_unpack (&mumble_proto__crypt_setup__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__crypt_setup__free_unpacked
+                     (MumbleProto__CryptSetup *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__crypt_setup__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__context_action_add__init
+                     (MumbleProto__ContextActionAdd         *message)
+{
+  static MumbleProto__ContextActionAdd init_value = MUMBLE_PROTO__CONTEXT_ACTION_ADD__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__context_action_add__get_packed_size
+                     (const MumbleProto__ContextActionAdd *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__context_action_add__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__context_action_add__pack
+                     (const MumbleProto__ContextActionAdd *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__context_action_add__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__context_action_add__pack_to_buffer
+                     (const MumbleProto__ContextActionAdd *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__context_action_add__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__ContextActionAdd *
+       mumble_proto__context_action_add__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__ContextActionAdd *)
+     protobuf_c_message_unpack (&mumble_proto__context_action_add__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__context_action_add__free_unpacked
+                     (MumbleProto__ContextActionAdd *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__context_action_add__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__context_action__init
+                     (MumbleProto__ContextAction         *message)
+{
+  static MumbleProto__ContextAction init_value = MUMBLE_PROTO__CONTEXT_ACTION__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__context_action__get_packed_size
+                     (const MumbleProto__ContextAction *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__context_action__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__context_action__pack
+                     (const MumbleProto__ContextAction *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__context_action__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__context_action__pack_to_buffer
+                     (const MumbleProto__ContextAction *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__context_action__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__ContextAction *
+       mumble_proto__context_action__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__ContextAction *)
+     protobuf_c_message_unpack (&mumble_proto__context_action__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__context_action__free_unpacked
+                     (MumbleProto__ContextAction *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__context_action__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__user_list__init
+                     (MumbleProto__UserList         *message)
+{
+  static MumbleProto__UserList init_value = MUMBLE_PROTO__USER_LIST__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__user_list__get_packed_size
+                     (const MumbleProto__UserList *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__user_list__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__user_list__pack
+                     (const MumbleProto__UserList *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__user_list__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__user_list__pack_to_buffer
+                     (const MumbleProto__UserList *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__user_list__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__UserList *
+       mumble_proto__user_list__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__UserList *)
+     protobuf_c_message_unpack (&mumble_proto__user_list__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__user_list__free_unpacked
+                     (MumbleProto__UserList *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__user_list__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__voice_target__init
+                     (MumbleProto__VoiceTarget         *message)
+{
+  static MumbleProto__VoiceTarget init_value = MUMBLE_PROTO__VOICE_TARGET__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__voice_target__get_packed_size
+                     (const MumbleProto__VoiceTarget *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__voice_target__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__voice_target__pack
+                     (const MumbleProto__VoiceTarget *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__voice_target__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__voice_target__pack_to_buffer
+                     (const MumbleProto__VoiceTarget *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__voice_target__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__VoiceTarget *
+       mumble_proto__voice_target__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__VoiceTarget *)
+     protobuf_c_message_unpack (&mumble_proto__voice_target__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__voice_target__free_unpacked
+                     (MumbleProto__VoiceTarget *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__voice_target__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__permission_query__init
+                     (MumbleProto__PermissionQuery         *message)
+{
+  static MumbleProto__PermissionQuery init_value = MUMBLE_PROTO__PERMISSION_QUERY__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__permission_query__get_packed_size
+                     (const MumbleProto__PermissionQuery *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__permission_query__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__permission_query__pack
+                     (const MumbleProto__PermissionQuery *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__permission_query__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__permission_query__pack_to_buffer
+                     (const MumbleProto__PermissionQuery *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__permission_query__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__PermissionQuery *
+       mumble_proto__permission_query__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__PermissionQuery *)
+     protobuf_c_message_unpack (&mumble_proto__permission_query__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__permission_query__free_unpacked
+                     (MumbleProto__PermissionQuery *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__permission_query__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void   mumble_proto__codec_version__init
+                     (MumbleProto__CodecVersion         *message)
+{
+  static MumbleProto__CodecVersion init_value = MUMBLE_PROTO__CODEC_VERSION__INIT;
+  *message = init_value;
+}
+size_t mumble_proto__codec_version__get_packed_size
+                     (const MumbleProto__CodecVersion *message)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__codec_version__descriptor);
+  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t mumble_proto__codec_version__pack
+                     (const MumbleProto__CodecVersion *message,
+                      uint8_t       *out)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__codec_version__descriptor);
+  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t mumble_proto__codec_version__pack_to_buffer
+                     (const MumbleProto__CodecVersion *message,
+                      ProtobufCBuffer *buffer)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__codec_version__descriptor);
+  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+MumbleProto__CodecVersion *
+       mumble_proto__codec_version__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data)
+{
+  return (MumbleProto__CodecVersion *)
+     protobuf_c_message_unpack (&mumble_proto__codec_version__descriptor,
+                                allocator, len, data);
+}
+void   mumble_proto__codec_version__free_unpacked
+                     (MumbleProto__CodecVersion *message,
+                      ProtobufCAllocator *allocator)
+{
+  PROTOBUF_C_ASSERT (message->base.descriptor == &mumble_proto__codec_version__descriptor);
+  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+static const ProtobufCFieldDescriptor mumble_proto__version__field_descriptors[4] =
+{
+  {
+    "version",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__Version, has_version),
+    PROTOBUF_C_OFFSETOF(MumbleProto__Version, version),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "release",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__Version, release),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "os",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__Version, os),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "os_version",
+    4,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__Version, os_version),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__version__field_indices_by_name[] = {
+  2,   /* field[2] = os */
+  3,   /* field[3] = os_version */
+  1,   /* field[1] = release */
+  0,   /* field[0] = version */
+};
+static const ProtobufCIntRange mumble_proto__version__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 4 }
+};
+const ProtobufCMessageDescriptor mumble_proto__version__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.Version",
+  "Version",
+  "MumbleProto__Version",
+  "MumbleProto",
+  sizeof(MumbleProto__Version),
+  4,
+  mumble_proto__version__field_descriptors,
+  mumble_proto__version__field_indices_by_name,
+  1,  mumble_proto__version__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__udptunnel__field_descriptors[1] =
+{
+  {
+    "packet",
+    1,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_BYTES,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__UDPTunnel, packet),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__udptunnel__field_indices_by_name[] = {
+  0,   /* field[0] = packet */
+};
+static const ProtobufCIntRange mumble_proto__udptunnel__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 1 }
+};
+const ProtobufCMessageDescriptor mumble_proto__udptunnel__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.UDPTunnel",
+  "UDPTunnel",
+  "MumbleProto__UDPTunnel",
+  "MumbleProto",
+  sizeof(MumbleProto__UDPTunnel),
+  1,
+  mumble_proto__udptunnel__field_descriptors,
+  mumble_proto__udptunnel__field_indices_by_name,
+  1,  mumble_proto__udptunnel__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__authenticate__field_descriptors[4] =
+{
+  {
+    "username",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__Authenticate, username),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "password",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__Authenticate, password),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "tokens",
+    3,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_STRING,
+    PROTOBUF_C_OFFSETOF(MumbleProto__Authenticate, n_tokens),
+    PROTOBUF_C_OFFSETOF(MumbleProto__Authenticate, tokens),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "celt_versions",
+    4,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_INT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__Authenticate, n_celt_versions),
+    PROTOBUF_C_OFFSETOF(MumbleProto__Authenticate, celt_versions),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__authenticate__field_indices_by_name[] = {
+  3,   /* field[3] = celt_versions */
+  1,   /* field[1] = password */
+  2,   /* field[2] = tokens */
+  0,   /* field[0] = username */
+};
+static const ProtobufCIntRange mumble_proto__authenticate__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 4 }
+};
+const ProtobufCMessageDescriptor mumble_proto__authenticate__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.Authenticate",
+  "Authenticate",
+  "MumbleProto__Authenticate",
+  "MumbleProto",
+  sizeof(MumbleProto__Authenticate),
+  4,
+  mumble_proto__authenticate__field_descriptors,
+  mumble_proto__authenticate__field_indices_by_name,
+  1,  mumble_proto__authenticate__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__ping__field_descriptors[11] =
+{
+  {
+    "timestamp",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT64,
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, has_timestamp),
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, timestamp),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "good",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, has_good),
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, good),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "late",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, has_late),
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, late),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "lost",
+    4,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, has_lost),
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, lost),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "resync",
+    5,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, has_resync),
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, resync),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "udp_packets",
+    6,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, has_udp_packets),
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, udp_packets),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "tcp_packets",
+    7,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, has_tcp_packets),
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, tcp_packets),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "udp_ping_avg",
+    8,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_FLOAT,
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, has_udp_ping_avg),
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, udp_ping_avg),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "udp_ping_var",
+    9,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_FLOAT,
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, has_udp_ping_var),
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, udp_ping_var),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "tcp_ping_avg",
+    10,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_FLOAT,
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, has_tcp_ping_avg),
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, tcp_ping_avg),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "tcp_ping_var",
+    11,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_FLOAT,
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, has_tcp_ping_var),
+    PROTOBUF_C_OFFSETOF(MumbleProto__Ping, tcp_ping_var),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__ping__field_indices_by_name[] = {
+  1,   /* field[1] = good */
+  2,   /* field[2] = late */
+  3,   /* field[3] = lost */
+  4,   /* field[4] = resync */
+  6,   /* field[6] = tcp_packets */
+  9,   /* field[9] = tcp_ping_avg */
+  10,   /* field[10] = tcp_ping_var */
+  0,   /* field[0] = timestamp */
+  5,   /* field[5] = udp_packets */
+  7,   /* field[7] = udp_ping_avg */
+  8,   /* field[8] = udp_ping_var */
+};
+static const ProtobufCIntRange mumble_proto__ping__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 11 }
+};
+const ProtobufCMessageDescriptor mumble_proto__ping__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.Ping",
+  "Ping",
+  "MumbleProto__Ping",
+  "MumbleProto",
+  sizeof(MumbleProto__Ping),
+  11,
+  mumble_proto__ping__field_descriptors,
+  mumble_proto__ping__field_indices_by_name,
+  1,  mumble_proto__ping__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+const ProtobufCEnumValue mumble_proto__reject__reject_type__enum_values_by_number[8] =
+{
+  { "None", "MUMBLE_PROTO__REJECT__REJECT_TYPE__NONE", 0 },
+  { "WrongVersion", "MUMBLE_PROTO__REJECT__REJECT_TYPE__WRONGVERSION", 1 },
+  { "InvalidUsername", "MUMBLE_PROTO__REJECT__REJECT_TYPE__INVALIDUSERNAME", 2 },
+  { "WrongUserPW", "MUMBLE_PROTO__REJECT__REJECT_TYPE__WRONGUSERPW", 3 },
+  { "WrongServerPW", "MUMBLE_PROTO__REJECT__REJECT_TYPE__WRONGSERVERPW", 4 },
+  { "UsernameInUse", "MUMBLE_PROTO__REJECT__REJECT_TYPE__USERNAMEINUSE", 5 },
+  { "ServerFull", "MUMBLE_PROTO__REJECT__REJECT_TYPE__SERVERFULL", 6 },
+  { "NoCertificate", "MUMBLE_PROTO__REJECT__REJECT_TYPE__NOCERTIFICATE", 7 },
+};
+static const ProtobufCIntRange mumble_proto__reject__reject_type__value_ranges[] = {
+{0, 0},{0, 8}
+};
+const ProtobufCEnumValueIndex mumble_proto__reject__reject_type__enum_values_by_name[8] =
+{
+  { "InvalidUsername", 2 },
+  { "NoCertificate", 7 },
+  { "None", 0 },
+  { "ServerFull", 6 },
+  { "UsernameInUse", 5 },
+  { "WrongServerPW", 4 },
+  { "WrongUserPW", 3 },
+  { "WrongVersion", 1 },
+};
+const ProtobufCEnumDescriptor mumble_proto__reject__reject_type__descriptor =
+{
+  PROTOBUF_C_ENUM_DESCRIPTOR_MAGIC,
+  "MumbleProto.Reject.RejectType",
+  "RejectType",
+  "MumbleProto__Reject__RejectType",
+  "MumbleProto",
+  8,
+  mumble_proto__reject__reject_type__enum_values_by_number,
+  8,
+  mumble_proto__reject__reject_type__enum_values_by_name,
+  1,
+  mumble_proto__reject__reject_type__value_ranges,
+  NULL,NULL,NULL,NULL   /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__reject__field_descriptors[2] =
+{
+  {
+    "type",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_ENUM,
+    PROTOBUF_C_OFFSETOF(MumbleProto__Reject, has_type),
+    PROTOBUF_C_OFFSETOF(MumbleProto__Reject, type),
+    &mumble_proto__reject__reject_type__descriptor,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "reason",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__Reject, reason),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__reject__field_indices_by_name[] = {
+  1,   /* field[1] = reason */
+  0,   /* field[0] = type */
+};
+static const ProtobufCIntRange mumble_proto__reject__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 2 }
+};
+const ProtobufCMessageDescriptor mumble_proto__reject__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.Reject",
+  "Reject",
+  "MumbleProto__Reject",
+  "MumbleProto",
+  sizeof(MumbleProto__Reject),
+  2,
+  mumble_proto__reject__field_descriptors,
+  mumble_proto__reject__field_indices_by_name,
+  1,  mumble_proto__reject__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const protobuf_c_boolean mumble_proto__server_sync__allow_html__default_value = 1;
+static const ProtobufCFieldDescriptor mumble_proto__server_sync__field_descriptors[5] =
+{
+  {
+    "session",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ServerSync, has_session),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ServerSync, session),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "max_bandwidth",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ServerSync, has_max_bandwidth),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ServerSync, max_bandwidth),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "welcome_text",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__ServerSync, welcome_text),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "permissions",
+    4,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT64,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ServerSync, has_permissions),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ServerSync, permissions),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "allow_html",
+    5,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ServerSync, has_allow_html),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ServerSync, allow_html),
+    NULL,
+    &mumble_proto__server_sync__allow_html__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__server_sync__field_indices_by_name[] = {
+  4,   /* field[4] = allow_html */
+  1,   /* field[1] = max_bandwidth */
+  3,   /* field[3] = permissions */
+  0,   /* field[0] = session */
+  2,   /* field[2] = welcome_text */
+};
+static const ProtobufCIntRange mumble_proto__server_sync__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 5 }
+};
+const ProtobufCMessageDescriptor mumble_proto__server_sync__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.ServerSync",
+  "ServerSync",
+  "MumbleProto__ServerSync",
+  "MumbleProto",
+  sizeof(MumbleProto__ServerSync),
+  5,
+  mumble_proto__server_sync__field_descriptors,
+  mumble_proto__server_sync__field_indices_by_name,
+  1,  mumble_proto__server_sync__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__channel_remove__field_descriptors[1] =
+{
+  {
+    "channel_id",
+    1,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_UINT32,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelRemove, channel_id),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__channel_remove__field_indices_by_name[] = {
+  0,   /* field[0] = channel_id */
+};
+static const ProtobufCIntRange mumble_proto__channel_remove__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 1 }
+};
+const ProtobufCMessageDescriptor mumble_proto__channel_remove__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.ChannelRemove",
+  "ChannelRemove",
+  "MumbleProto__ChannelRemove",
+  "MumbleProto",
+  sizeof(MumbleProto__ChannelRemove),
+  1,
+  mumble_proto__channel_remove__field_descriptors,
+  mumble_proto__channel_remove__field_indices_by_name,
+  1,  mumble_proto__channel_remove__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const protobuf_c_boolean mumble_proto__channel_state__temporary__default_value = 0;
+static const int32_t mumble_proto__channel_state__position__default_value = 0;
+static const ProtobufCFieldDescriptor mumble_proto__channel_state__field_descriptors[9] =
+{
+  {
+    "channel_id",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, has_channel_id),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, channel_id),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "parent",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, has_parent),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, parent),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "name",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, name),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "links",
+    4,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, n_links),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, links),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "description",
+    5,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, description),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "links_add",
+    6,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, n_links_add),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, links_add),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "links_remove",
+    7,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, n_links_remove),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, links_remove),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "temporary",
+    8,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, has_temporary),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, temporary),
+    NULL,
+    &mumble_proto__channel_state__temporary__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "position",
+    9,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_INT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, has_position),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ChannelState, position),
+    NULL,
+    &mumble_proto__channel_state__position__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__channel_state__field_indices_by_name[] = {
+  0,   /* field[0] = channel_id */
+  4,   /* field[4] = description */
+  3,   /* field[3] = links */
+  5,   /* field[5] = links_add */
+  6,   /* field[6] = links_remove */
+  2,   /* field[2] = name */
+  1,   /* field[1] = parent */
+  8,   /* field[8] = position */
+  7,   /* field[7] = temporary */
+};
+static const ProtobufCIntRange mumble_proto__channel_state__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 9 }
+};
+const ProtobufCMessageDescriptor mumble_proto__channel_state__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.ChannelState",
+  "ChannelState",
+  "MumbleProto__ChannelState",
+  "MumbleProto",
+  sizeof(MumbleProto__ChannelState),
+  9,
+  mumble_proto__channel_state__field_descriptors,
+  mumble_proto__channel_state__field_indices_by_name,
+  1,  mumble_proto__channel_state__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__user_remove__field_descriptors[4] =
+{
+  {
+    "session",
+    1,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_UINT32,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserRemove, session),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "actor",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserRemove, has_actor),
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserRemove, actor),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "reason",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserRemove, reason),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "ban",
+    4,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserRemove, has_ban),
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserRemove, ban),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__user_remove__field_indices_by_name[] = {
+  1,   /* field[1] = actor */
+  3,   /* field[3] = ban */
+  2,   /* field[2] = reason */
+  0,   /* field[0] = session */
+};
+static const ProtobufCIntRange mumble_proto__user_remove__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 4 }
+};
+const ProtobufCMessageDescriptor mumble_proto__user_remove__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.UserRemove",
+  "UserRemove",
+  "MumbleProto__UserRemove",
+  "MumbleProto",
+  sizeof(MumbleProto__UserRemove),
+  4,
+  mumble_proto__user_remove__field_descriptors,
+  mumble_proto__user_remove__field_indices_by_name,
+  1,  mumble_proto__user_remove__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__user_state__field_descriptors[15] =
+{
+  {
+    "session",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, has_session),
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, session),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "actor",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, has_actor),
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, actor),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "name",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, name),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "user_id",
+    4,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, has_user_id),
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, user_id),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "channel_id",
+    5,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, has_channel_id),
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, channel_id),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "mute",
+    6,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, has_mute),
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, mute),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "deaf",
+    7,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, has_deaf),
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, deaf),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "suppress",
+    8,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, has_suppress),
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, suppress),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "self_mute",
+    9,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, has_self_mute),
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, self_mute),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "self_deaf",
+    10,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, has_self_deaf),
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, self_deaf),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "texture",
+    11,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BYTES,
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, has_texture),
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, texture),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "plugin_context",
+    12,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, plugin_context),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "plugin_identity",
+    13,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, plugin_identity),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "comment",
+    14,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, comment),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "hash",
+    15,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserState, hash),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__user_state__field_indices_by_name[] = {
+  1,   /* field[1] = actor */
+  4,   /* field[4] = channel_id */
+  13,   /* field[13] = comment */
+  6,   /* field[6] = deaf */
+  14,   /* field[14] = hash */
+  5,   /* field[5] = mute */
+  2,   /* field[2] = name */
+  11,   /* field[11] = plugin_context */
+  12,   /* field[12] = plugin_identity */
+  9,   /* field[9] = self_deaf */
+  8,   /* field[8] = self_mute */
+  0,   /* field[0] = session */
+  7,   /* field[7] = suppress */
+  10,   /* field[10] = texture */
+  3,   /* field[3] = user_id */
+};
+static const ProtobufCIntRange mumble_proto__user_state__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 15 }
+};
+const ProtobufCMessageDescriptor mumble_proto__user_state__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.UserState",
+  "UserState",
+  "MumbleProto__UserState",
+  "MumbleProto",
+  sizeof(MumbleProto__UserState),
+  15,
+  mumble_proto__user_state__field_descriptors,
+  mumble_proto__user_state__field_indices_by_name,
+  1,  mumble_proto__user_state__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__ban_list__ban_entry__field_descriptors[7] =
+{
+  {
+    "address",
+    1,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_BYTES,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__BanList__BanEntry, address),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "mask",
+    2,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_UINT32,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__BanList__BanEntry, mask),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "name",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__BanList__BanEntry, name),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "hash",
+    4,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__BanList__BanEntry, hash),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "reason",
+    5,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__BanList__BanEntry, reason),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "start",
+    6,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__BanList__BanEntry, start),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "duration",
+    7,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__BanList__BanEntry, has_duration),
+    PROTOBUF_C_OFFSETOF(MumbleProto__BanList__BanEntry, duration),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__ban_list__ban_entry__field_indices_by_name[] = {
+  0,   /* field[0] = address */
+  6,   /* field[6] = duration */
+  3,   /* field[3] = hash */
+  1,   /* field[1] = mask */
+  2,   /* field[2] = name */
+  4,   /* field[4] = reason */
+  5,   /* field[5] = start */
+};
+static const ProtobufCIntRange mumble_proto__ban_list__ban_entry__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 7 }
+};
+const ProtobufCMessageDescriptor mumble_proto__ban_list__ban_entry__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.BanList.BanEntry",
+  "BanEntry",
+  "MumbleProto__BanList__BanEntry",
+  "MumbleProto",
+  sizeof(MumbleProto__BanList__BanEntry),
+  7,
+  mumble_proto__ban_list__ban_entry__field_descriptors,
+  mumble_proto__ban_list__ban_entry__field_indices_by_name,
+  1,  mumble_proto__ban_list__ban_entry__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const protobuf_c_boolean mumble_proto__ban_list__query__default_value = 0;
+static const ProtobufCFieldDescriptor mumble_proto__ban_list__field_descriptors[2] =
+{
+  {
+    "bans",
+    1,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_MESSAGE,
+    PROTOBUF_C_OFFSETOF(MumbleProto__BanList, n_bans),
+    PROTOBUF_C_OFFSETOF(MumbleProto__BanList, bans),
+    &mumble_proto__ban_list__ban_entry__descriptor,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "query",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__BanList, has_query),
+    PROTOBUF_C_OFFSETOF(MumbleProto__BanList, query),
+    NULL,
+    &mumble_proto__ban_list__query__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__ban_list__field_indices_by_name[] = {
+  0,   /* field[0] = bans */
+  1,   /* field[1] = query */
+};
+static const ProtobufCIntRange mumble_proto__ban_list__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 2 }
+};
+const ProtobufCMessageDescriptor mumble_proto__ban_list__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.BanList",
+  "BanList",
+  "MumbleProto__BanList",
+  "MumbleProto",
+  sizeof(MumbleProto__BanList),
+  2,
+  mumble_proto__ban_list__field_descriptors,
+  mumble_proto__ban_list__field_indices_by_name,
+  1,  mumble_proto__ban_list__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__text_message__field_descriptors[5] =
+{
+  {
+    "actor",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__TextMessage, has_actor),
+    PROTOBUF_C_OFFSETOF(MumbleProto__TextMessage, actor),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "session",
+    2,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__TextMessage, n_session),
+    PROTOBUF_C_OFFSETOF(MumbleProto__TextMessage, session),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "channel_id",
+    3,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__TextMessage, n_channel_id),
+    PROTOBUF_C_OFFSETOF(MumbleProto__TextMessage, channel_id),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "tree_id",
+    4,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__TextMessage, n_tree_id),
+    PROTOBUF_C_OFFSETOF(MumbleProto__TextMessage, tree_id),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "message",
+    5,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__TextMessage, message),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__text_message__field_indices_by_name[] = {
+  0,   /* field[0] = actor */
+  2,   /* field[2] = channel_id */
+  4,   /* field[4] = message */
+  1,   /* field[1] = session */
+  3,   /* field[3] = tree_id */
+};
+static const ProtobufCIntRange mumble_proto__text_message__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 5 }
+};
+const ProtobufCMessageDescriptor mumble_proto__text_message__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.TextMessage",
+  "TextMessage",
+  "MumbleProto__TextMessage",
+  "MumbleProto",
+  sizeof(MumbleProto__TextMessage),
+  5,
+  mumble_proto__text_message__field_descriptors,
+  mumble_proto__text_message__field_indices_by_name,
+  1,  mumble_proto__text_message__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+const ProtobufCEnumValue mumble_proto__permission_denied__deny_type__enum_values_by_number[8] =
+{
+  { "Text", "MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__TEXT", 0 },
+  { "Permission", "MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__PERMISSION", 1 },
+  { "SuperUser", "MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__SUPERUSER", 2 },
+  { "ChannelName", "MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__CHANNELNAME", 3 },
+  { "TextTooLong", "MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__TEXTTOOLONG", 4 },
+  { "H9K", "MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__H9K", 5 },
+  { "TemporaryChannel", "MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__TEMPORARYCHANNEL", 6 },
+  { "MissingCertificate", "MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__MISSINGCERTIFICATE", 7 },
+};
+static const ProtobufCIntRange mumble_proto__permission_denied__deny_type__value_ranges[] = {
+{0, 0},{0, 8}
+};
+const ProtobufCEnumValueIndex mumble_proto__permission_denied__deny_type__enum_values_by_name[8] =
+{
+  { "ChannelName", 3 },
+  { "H9K", 5 },
+  { "MissingCertificate", 7 },
+  { "Permission", 1 },
+  { "SuperUser", 2 },
+  { "TemporaryChannel", 6 },
+  { "Text", 0 },
+  { "TextTooLong", 4 },
+};
+const ProtobufCEnumDescriptor mumble_proto__permission_denied__deny_type__descriptor =
+{
+  PROTOBUF_C_ENUM_DESCRIPTOR_MAGIC,
+  "MumbleProto.PermissionDenied.DenyType",
+  "DenyType",
+  "MumbleProto__PermissionDenied__DenyType",
+  "MumbleProto",
+  8,
+  mumble_proto__permission_denied__deny_type__enum_values_by_number,
+  8,
+  mumble_proto__permission_denied__deny_type__enum_values_by_name,
+  1,
+  mumble_proto__permission_denied__deny_type__value_ranges,
+  NULL,NULL,NULL,NULL   /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__permission_denied__field_descriptors[5] =
+{
+  {
+    "permission",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__PermissionDenied, has_permission),
+    PROTOBUF_C_OFFSETOF(MumbleProto__PermissionDenied, permission),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "channel_id",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__PermissionDenied, has_channel_id),
+    PROTOBUF_C_OFFSETOF(MumbleProto__PermissionDenied, channel_id),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "session",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__PermissionDenied, has_session),
+    PROTOBUF_C_OFFSETOF(MumbleProto__PermissionDenied, session),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "reason",
+    4,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__PermissionDenied, reason),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "type",
+    5,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_ENUM,
+    PROTOBUF_C_OFFSETOF(MumbleProto__PermissionDenied, has_type),
+    PROTOBUF_C_OFFSETOF(MumbleProto__PermissionDenied, type),
+    &mumble_proto__permission_denied__deny_type__descriptor,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__permission_denied__field_indices_by_name[] = {
+  1,   /* field[1] = channel_id */
+  0,   /* field[0] = permission */
+  3,   /* field[3] = reason */
+  2,   /* field[2] = session */
+  4,   /* field[4] = type */
+};
+static const ProtobufCIntRange mumble_proto__permission_denied__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 5 }
+};
+const ProtobufCMessageDescriptor mumble_proto__permission_denied__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.PermissionDenied",
+  "PermissionDenied",
+  "MumbleProto__PermissionDenied",
+  "MumbleProto",
+  sizeof(MumbleProto__PermissionDenied),
+  5,
+  mumble_proto__permission_denied__field_descriptors,
+  mumble_proto__permission_denied__field_indices_by_name,
+  1,  mumble_proto__permission_denied__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const protobuf_c_boolean mumble_proto__acl__chan_group__inherited__default_value = 1;
+static const protobuf_c_boolean mumble_proto__acl__chan_group__inherit__default_value = 1;
+static const protobuf_c_boolean mumble_proto__acl__chan_group__inheritable__default_value = 1;
+static const ProtobufCFieldDescriptor mumble_proto__acl__chan_group__field_descriptors[7] =
+{
+  {
+    "name",
+    1,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanGroup, name),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "inherited",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanGroup, has_inherited),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanGroup, inherited),
+    NULL,
+    &mumble_proto__acl__chan_group__inherited__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "inherit",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanGroup, has_inherit),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanGroup, inherit),
+    NULL,
+    &mumble_proto__acl__chan_group__inherit__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "inheritable",
+    4,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanGroup, has_inheritable),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanGroup, inheritable),
+    NULL,
+    &mumble_proto__acl__chan_group__inheritable__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "add",
+    5,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanGroup, n_add),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanGroup, add),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "remove",
+    6,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanGroup, n_remove),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanGroup, remove),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "inherited_members",
+    7,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanGroup, n_inherited_members),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanGroup, inherited_members),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__acl__chan_group__field_indices_by_name[] = {
+  4,   /* field[4] = add */
+  2,   /* field[2] = inherit */
+  3,   /* field[3] = inheritable */
+  1,   /* field[1] = inherited */
+  6,   /* field[6] = inherited_members */
+  0,   /* field[0] = name */
+  5,   /* field[5] = remove */
+};
+static const ProtobufCIntRange mumble_proto__acl__chan_group__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 7 }
+};
+const ProtobufCMessageDescriptor mumble_proto__acl__chan_group__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.ACL.ChanGroup",
+  "ChanGroup",
+  "MumbleProto__ACL__ChanGroup",
+  "MumbleProto",
+  sizeof(MumbleProto__ACL__ChanGroup),
+  7,
+  mumble_proto__acl__chan_group__field_descriptors,
+  mumble_proto__acl__chan_group__field_indices_by_name,
+  1,  mumble_proto__acl__chan_group__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const protobuf_c_boolean mumble_proto__acl__chan_acl__apply_here__default_value = 1;
+static const protobuf_c_boolean mumble_proto__acl__chan_acl__apply_subs__default_value = 1;
+static const protobuf_c_boolean mumble_proto__acl__chan_acl__inherited__default_value = 1;
+static const ProtobufCFieldDescriptor mumble_proto__acl__chan_acl__field_descriptors[7] =
+{
+  {
+    "apply_here",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanACL, has_apply_here),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanACL, apply_here),
+    NULL,
+    &mumble_proto__acl__chan_acl__apply_here__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "apply_subs",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanACL, has_apply_subs),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanACL, apply_subs),
+    NULL,
+    &mumble_proto__acl__chan_acl__apply_subs__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "inherited",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanACL, has_inherited),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanACL, inherited),
+    NULL,
+    &mumble_proto__acl__chan_acl__inherited__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "user_id",
+    4,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanACL, has_user_id),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanACL, user_id),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "group",
+    5,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanACL, group),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "grant",
+    6,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanACL, has_grant),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanACL, grant),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "deny",
+    7,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanACL, has_deny),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL__ChanACL, deny),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__acl__chan_acl__field_indices_by_name[] = {
+  0,   /* field[0] = apply_here */
+  1,   /* field[1] = apply_subs */
+  6,   /* field[6] = deny */
+  5,   /* field[5] = grant */
+  4,   /* field[4] = group */
+  2,   /* field[2] = inherited */
+  3,   /* field[3] = user_id */
+};
+static const ProtobufCIntRange mumble_proto__acl__chan_acl__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 7 }
+};
+const ProtobufCMessageDescriptor mumble_proto__acl__chan_acl__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.ACL.ChanACL",
+  "ChanACL",
+  "MumbleProto__ACL__ChanACL",
+  "MumbleProto",
+  sizeof(MumbleProto__ACL__ChanACL),
+  7,
+  mumble_proto__acl__chan_acl__field_descriptors,
+  mumble_proto__acl__chan_acl__field_indices_by_name,
+  1,  mumble_proto__acl__chan_acl__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const protobuf_c_boolean mumble_proto__acl__inherit_acls__default_value = 1;
+static const protobuf_c_boolean mumble_proto__acl__query__default_value = 0;
+static const ProtobufCFieldDescriptor mumble_proto__acl__field_descriptors[5] =
+{
+  {
+    "channel_id",
+    1,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_UINT32,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL, channel_id),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "inherit_acls",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL, has_inherit_acls),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL, inherit_acls),
+    NULL,
+    &mumble_proto__acl__inherit_acls__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "groups",
+    3,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_MESSAGE,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL, n_groups),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL, groups),
+    &mumble_proto__acl__chan_group__descriptor,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "acls",
+    4,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_MESSAGE,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL, n_acls),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL, acls),
+    &mumble_proto__acl__chan_acl__descriptor,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "query",
+    5,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL, has_query),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ACL, query),
+    NULL,
+    &mumble_proto__acl__query__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__acl__field_indices_by_name[] = {
+  3,   /* field[3] = acls */
+  0,   /* field[0] = channel_id */
+  2,   /* field[2] = groups */
+  1,   /* field[1] = inherit_acls */
+  4,   /* field[4] = query */
+};
+static const ProtobufCIntRange mumble_proto__acl__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 5 }
+};
+const ProtobufCMessageDescriptor mumble_proto__acl__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.ACL",
+  "ACL",
+  "MumbleProto__ACL",
+  "MumbleProto",
+  sizeof(MumbleProto__ACL),
+  5,
+  mumble_proto__acl__field_descriptors,
+  mumble_proto__acl__field_indices_by_name,
+  1,  mumble_proto__acl__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__query_users__field_descriptors[2] =
+{
+  {
+    "ids",
+    1,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__QueryUsers, n_ids),
+    PROTOBUF_C_OFFSETOF(MumbleProto__QueryUsers, ids),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "names",
+    2,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_STRING,
+    PROTOBUF_C_OFFSETOF(MumbleProto__QueryUsers, n_names),
+    PROTOBUF_C_OFFSETOF(MumbleProto__QueryUsers, names),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__query_users__field_indices_by_name[] = {
+  0,   /* field[0] = ids */
+  1,   /* field[1] = names */
+};
+static const ProtobufCIntRange mumble_proto__query_users__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 2 }
+};
+const ProtobufCMessageDescriptor mumble_proto__query_users__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.QueryUsers",
+  "QueryUsers",
+  "MumbleProto__QueryUsers",
+  "MumbleProto",
+  sizeof(MumbleProto__QueryUsers),
+  2,
+  mumble_proto__query_users__field_descriptors,
+  mumble_proto__query_users__field_indices_by_name,
+  1,  mumble_proto__query_users__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__crypt_setup__field_descriptors[3] =
+{
+  {
+    "key",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BYTES,
+    PROTOBUF_C_OFFSETOF(MumbleProto__CryptSetup, has_key),
+    PROTOBUF_C_OFFSETOF(MumbleProto__CryptSetup, key),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "client_nonce",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BYTES,
+    PROTOBUF_C_OFFSETOF(MumbleProto__CryptSetup, has_client_nonce),
+    PROTOBUF_C_OFFSETOF(MumbleProto__CryptSetup, client_nonce),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "server_nonce",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BYTES,
+    PROTOBUF_C_OFFSETOF(MumbleProto__CryptSetup, has_server_nonce),
+    PROTOBUF_C_OFFSETOF(MumbleProto__CryptSetup, server_nonce),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__crypt_setup__field_indices_by_name[] = {
+  1,   /* field[1] = client_nonce */
+  0,   /* field[0] = key */
+  2,   /* field[2] = server_nonce */
+};
+static const ProtobufCIntRange mumble_proto__crypt_setup__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 3 }
+};
+const ProtobufCMessageDescriptor mumble_proto__crypt_setup__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.CryptSetup",
+  "CryptSetup",
+  "MumbleProto__CryptSetup",
+  "MumbleProto",
+  sizeof(MumbleProto__CryptSetup),
+  3,
+  mumble_proto__crypt_setup__field_descriptors,
+  mumble_proto__crypt_setup__field_indices_by_name,
+  1,  mumble_proto__crypt_setup__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+const ProtobufCEnumValue mumble_proto__context_action_add__context__enum_values_by_number[3] =
+{
+  { "Server", "MUMBLE_PROTO__CONTEXT_ACTION_ADD__CONTEXT__SERVER", 1 },
+  { "Channel", "MUMBLE_PROTO__CONTEXT_ACTION_ADD__CONTEXT__CHANNEL", 2 },
+  { "User", "MUMBLE_PROTO__CONTEXT_ACTION_ADD__CONTEXT__USER", 4 },
+};
+static const ProtobufCIntRange mumble_proto__context_action_add__context__value_ranges[] = {
+{1, 0},{4, 2},{0, 3}
+};
+const ProtobufCEnumValueIndex mumble_proto__context_action_add__context__enum_values_by_name[3] =
+{
+  { "Channel", 1 },
+  { "Server", 0 },
+  { "User", 2 },
+};
+const ProtobufCEnumDescriptor mumble_proto__context_action_add__context__descriptor =
+{
+  PROTOBUF_C_ENUM_DESCRIPTOR_MAGIC,
+  "MumbleProto.ContextActionAdd.Context",
+  "Context",
+  "MumbleProto__ContextActionAdd__Context",
+  "MumbleProto",
+  3,
+  mumble_proto__context_action_add__context__enum_values_by_number,
+  3,
+  mumble_proto__context_action_add__context__enum_values_by_name,
+  2,
+  mumble_proto__context_action_add__context__value_ranges,
+  NULL,NULL,NULL,NULL   /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__context_action_add__field_descriptors[3] =
+{
+  {
+    "action",
+    1,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__ContextActionAdd, action),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "text",
+    2,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__ContextActionAdd, text),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "context",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ContextActionAdd, has_context),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ContextActionAdd, context),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__context_action_add__field_indices_by_name[] = {
+  0,   /* field[0] = action */
+  2,   /* field[2] = context */
+  1,   /* field[1] = text */
+};
+static const ProtobufCIntRange mumble_proto__context_action_add__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 3 }
+};
+const ProtobufCMessageDescriptor mumble_proto__context_action_add__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.ContextActionAdd",
+  "ContextActionAdd",
+  "MumbleProto__ContextActionAdd",
+  "MumbleProto",
+  sizeof(MumbleProto__ContextActionAdd),
+  3,
+  mumble_proto__context_action_add__field_descriptors,
+  mumble_proto__context_action_add__field_indices_by_name,
+  1,  mumble_proto__context_action_add__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__context_action__field_descriptors[3] =
+{
+  {
+    "session",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ContextAction, has_session),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ContextAction, session),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "channel_id",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__ContextAction, has_channel_id),
+    PROTOBUF_C_OFFSETOF(MumbleProto__ContextAction, channel_id),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "action",
+    3,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__ContextAction, action),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__context_action__field_indices_by_name[] = {
+  2,   /* field[2] = action */
+  1,   /* field[1] = channel_id */
+  0,   /* field[0] = session */
+};
+static const ProtobufCIntRange mumble_proto__context_action__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 3 }
+};
+const ProtobufCMessageDescriptor mumble_proto__context_action__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.ContextAction",
+  "ContextAction",
+  "MumbleProto__ContextAction",
+  "MumbleProto",
+  sizeof(MumbleProto__ContextAction),
+  3,
+  mumble_proto__context_action__field_descriptors,
+  mumble_proto__context_action__field_indices_by_name,
+  1,  mumble_proto__context_action__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__user_list__user__field_descriptors[2] =
+{
+  {
+    "user_id",
+    1,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_UINT32,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserList__User, user_id),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "name",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserList__User, name),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__user_list__user__field_indices_by_name[] = {
+  1,   /* field[1] = name */
+  0,   /* field[0] = user_id */
+};
+static const ProtobufCIntRange mumble_proto__user_list__user__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 2 }
+};
+const ProtobufCMessageDescriptor mumble_proto__user_list__user__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.UserList.User",
+  "User",
+  "MumbleProto__UserList__User",
+  "MumbleProto",
+  sizeof(MumbleProto__UserList__User),
+  2,
+  mumble_proto__user_list__user__field_descriptors,
+  mumble_proto__user_list__user__field_indices_by_name,
+  1,  mumble_proto__user_list__user__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__user_list__field_descriptors[1] =
+{
+  {
+    "users",
+    1,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_MESSAGE,
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserList, n_users),
+    PROTOBUF_C_OFFSETOF(MumbleProto__UserList, users),
+    &mumble_proto__user_list__user__descriptor,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__user_list__field_indices_by_name[] = {
+  0,   /* field[0] = users */
+};
+static const ProtobufCIntRange mumble_proto__user_list__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 1 }
+};
+const ProtobufCMessageDescriptor mumble_proto__user_list__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.UserList",
+  "UserList",
+  "MumbleProto__UserList",
+  "MumbleProto",
+  sizeof(MumbleProto__UserList),
+  1,
+  mumble_proto__user_list__field_descriptors,
+  mumble_proto__user_list__field_indices_by_name,
+  1,  mumble_proto__user_list__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const protobuf_c_boolean mumble_proto__voice_target__target__links__default_value = 0;
+static const protobuf_c_boolean mumble_proto__voice_target__target__children__default_value = 0;
+static const ProtobufCFieldDescriptor mumble_proto__voice_target__target__field_descriptors[5] =
+{
+  {
+    "session",
+    1,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__VoiceTarget__Target, n_session),
+    PROTOBUF_C_OFFSETOF(MumbleProto__VoiceTarget__Target, session),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "channel_id",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__VoiceTarget__Target, has_channel_id),
+    PROTOBUF_C_OFFSETOF(MumbleProto__VoiceTarget__Target, channel_id),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "group",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_STRING,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__VoiceTarget__Target, group),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "links",
+    4,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__VoiceTarget__Target, has_links),
+    PROTOBUF_C_OFFSETOF(MumbleProto__VoiceTarget__Target, links),
+    NULL,
+    &mumble_proto__voice_target__target__links__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "children",
+    5,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__VoiceTarget__Target, has_children),
+    PROTOBUF_C_OFFSETOF(MumbleProto__VoiceTarget__Target, children),
+    NULL,
+    &mumble_proto__voice_target__target__children__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__voice_target__target__field_indices_by_name[] = {
+  1,   /* field[1] = channel_id */
+  4,   /* field[4] = children */
+  2,   /* field[2] = group */
+  3,   /* field[3] = links */
+  0,   /* field[0] = session */
+};
+static const ProtobufCIntRange mumble_proto__voice_target__target__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 5 }
+};
+const ProtobufCMessageDescriptor mumble_proto__voice_target__target__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.VoiceTarget.Target",
+  "Target",
+  "MumbleProto__VoiceTarget__Target",
+  "MumbleProto",
+  sizeof(MumbleProto__VoiceTarget__Target),
+  5,
+  mumble_proto__voice_target__target__field_descriptors,
+  mumble_proto__voice_target__target__field_indices_by_name,
+  1,  mumble_proto__voice_target__target__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor mumble_proto__voice_target__field_descriptors[2] =
+{
+  {
+    "id",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__VoiceTarget, has_id),
+    PROTOBUF_C_OFFSETOF(MumbleProto__VoiceTarget, id),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "targets",
+    2,
+    PROTOBUF_C_LABEL_REPEATED,
+    PROTOBUF_C_TYPE_MESSAGE,
+    PROTOBUF_C_OFFSETOF(MumbleProto__VoiceTarget, n_targets),
+    PROTOBUF_C_OFFSETOF(MumbleProto__VoiceTarget, targets),
+    &mumble_proto__voice_target__target__descriptor,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__voice_target__field_indices_by_name[] = {
+  0,   /* field[0] = id */
+  1,   /* field[1] = targets */
+};
+static const ProtobufCIntRange mumble_proto__voice_target__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 2 }
+};
+const ProtobufCMessageDescriptor mumble_proto__voice_target__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.VoiceTarget",
+  "VoiceTarget",
+  "MumbleProto__VoiceTarget",
+  "MumbleProto",
+  sizeof(MumbleProto__VoiceTarget),
+  2,
+  mumble_proto__voice_target__field_descriptors,
+  mumble_proto__voice_target__field_indices_by_name,
+  1,  mumble_proto__voice_target__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const protobuf_c_boolean mumble_proto__permission_query__flush__default_value = 0;
+static const ProtobufCFieldDescriptor mumble_proto__permission_query__field_descriptors[3] =
+{
+  {
+    "channel_id",
+    1,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__PermissionQuery, has_channel_id),
+    PROTOBUF_C_OFFSETOF(MumbleProto__PermissionQuery, channel_id),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "permissions",
+    2,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_UINT32,
+    PROTOBUF_C_OFFSETOF(MumbleProto__PermissionQuery, has_permissions),
+    PROTOBUF_C_OFFSETOF(MumbleProto__PermissionQuery, permissions),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "flush",
+    3,
+    PROTOBUF_C_LABEL_OPTIONAL,
+    PROTOBUF_C_TYPE_BOOL,
+    PROTOBUF_C_OFFSETOF(MumbleProto__PermissionQuery, has_flush),
+    PROTOBUF_C_OFFSETOF(MumbleProto__PermissionQuery, flush),
+    NULL,
+    &mumble_proto__permission_query__flush__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__permission_query__field_indices_by_name[] = {
+  0,   /* field[0] = channel_id */
+  2,   /* field[2] = flush */
+  1,   /* field[1] = permissions */
+};
+static const ProtobufCIntRange mumble_proto__permission_query__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 3 }
+};
+const ProtobufCMessageDescriptor mumble_proto__permission_query__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.PermissionQuery",
+  "PermissionQuery",
+  "MumbleProto__PermissionQuery",
+  "MumbleProto",
+  sizeof(MumbleProto__PermissionQuery),
+  3,
+  mumble_proto__permission_query__field_descriptors,
+  mumble_proto__permission_query__field_indices_by_name,
+  1,  mumble_proto__permission_query__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
+static const protobuf_c_boolean mumble_proto__codec_version__prefer_alpha__default_value = 1;
+static const ProtobufCFieldDescriptor mumble_proto__codec_version__field_descriptors[3] =
+{
+  {
+    "alpha",
+    1,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_INT32,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__CodecVersion, alpha),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "beta",
+    2,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_INT32,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__CodecVersion, beta),
+    NULL,
+    NULL,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+  {
+    "prefer_alpha",
+    3,
+    PROTOBUF_C_LABEL_REQUIRED,
+    PROTOBUF_C_TYPE_BOOL,
+    0,   /* quantifier_offset */
+    PROTOBUF_C_OFFSETOF(MumbleProto__CodecVersion, prefer_alpha),
+    NULL,
+    &mumble_proto__codec_version__prefer_alpha__default_value,
+    NULL,NULL    /* reserved1, reserved2 */
+  },
+};
+static const unsigned mumble_proto__codec_version__field_indices_by_name[] = {
+  0,   /* field[0] = alpha */
+  1,   /* field[1] = beta */
+  2,   /* field[2] = prefer_alpha */
+};
+static const ProtobufCIntRange mumble_proto__codec_version__number_ranges[1 + 1] =
+{
+  { 1, 0 },
+  { 0, 3 }
+};
+const ProtobufCMessageDescriptor mumble_proto__codec_version__descriptor =
+{
+  PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC,
+  "MumbleProto.CodecVersion",
+  "CodecVersion",
+  "MumbleProto__CodecVersion",
+  "MumbleProto",
+  sizeof(MumbleProto__CodecVersion),
+  3,
+  mumble_proto__codec_version__field_descriptors,
+  mumble_proto__codec_version__field_indices_by_name,
+  1,  mumble_proto__codec_version__number_ranges,
+  NULL,NULL,NULL,NULL    /* reserved[1234] */
+};
diff --git a/src/Mumble.pb-c.h b/src/Mumble.pb-c.h
new file mode 100644 (file)
index 0000000..55bad75
--- /dev/null
@@ -0,0 +1,1058 @@
+/* Generated by the protocol buffer compiler.  DO NOT EDIT! */
+
+#ifndef PROTOBUF_C_Mumble_2eproto__INCLUDED
+#define PROTOBUF_C_Mumble_2eproto__INCLUDED
+
+#include <google/protobuf-c/protobuf-c.h>
+
+PROTOBUF_C_BEGIN_DECLS
+
+
+typedef struct _MumbleProto__Version MumbleProto__Version;
+typedef struct _MumbleProto__UDPTunnel MumbleProto__UDPTunnel;
+typedef struct _MumbleProto__Authenticate MumbleProto__Authenticate;
+typedef struct _MumbleProto__Ping MumbleProto__Ping;
+typedef struct _MumbleProto__Reject MumbleProto__Reject;
+typedef struct _MumbleProto__ServerSync MumbleProto__ServerSync;
+typedef struct _MumbleProto__ChannelRemove MumbleProto__ChannelRemove;
+typedef struct _MumbleProto__ChannelState MumbleProto__ChannelState;
+typedef struct _MumbleProto__UserRemove MumbleProto__UserRemove;
+typedef struct _MumbleProto__UserState MumbleProto__UserState;
+typedef struct _MumbleProto__BanList MumbleProto__BanList;
+typedef struct _MumbleProto__BanList__BanEntry MumbleProto__BanList__BanEntry;
+typedef struct _MumbleProto__TextMessage MumbleProto__TextMessage;
+typedef struct _MumbleProto__PermissionDenied MumbleProto__PermissionDenied;
+typedef struct _MumbleProto__ACL MumbleProto__ACL;
+typedef struct _MumbleProto__ACL__ChanGroup MumbleProto__ACL__ChanGroup;
+typedef struct _MumbleProto__ACL__ChanACL MumbleProto__ACL__ChanACL;
+typedef struct _MumbleProto__QueryUsers MumbleProto__QueryUsers;
+typedef struct _MumbleProto__CryptSetup MumbleProto__CryptSetup;
+typedef struct _MumbleProto__ContextActionAdd MumbleProto__ContextActionAdd;
+typedef struct _MumbleProto__ContextAction MumbleProto__ContextAction;
+typedef struct _MumbleProto__UserList MumbleProto__UserList;
+typedef struct _MumbleProto__UserList__User MumbleProto__UserList__User;
+typedef struct _MumbleProto__VoiceTarget MumbleProto__VoiceTarget;
+typedef struct _MumbleProto__VoiceTarget__Target MumbleProto__VoiceTarget__Target;
+typedef struct _MumbleProto__PermissionQuery MumbleProto__PermissionQuery;
+typedef struct _MumbleProto__CodecVersion MumbleProto__CodecVersion;
+
+
+/* --- enums --- */
+
+typedef enum _MumbleProto__Reject__RejectType {
+  MUMBLE_PROTO__REJECT__REJECT_TYPE__None = 0,
+  MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongVersion = 1,
+  MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername = 2,
+  MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongUserPW = 3,
+  MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW = 4,
+  MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse = 5,
+  MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull = 6,
+  MUMBLE_PROTO__REJECT__REJECT_TYPE__NoCertificate = 7
+} MumbleProto__Reject__RejectType;
+typedef enum _MumbleProto__PermissionDenied__DenyType {
+  MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text = 0,
+  MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Permission = 1,
+  MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__SuperUser = 2,
+  MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__ChannelName = 3,
+  MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__TextTooLong = 4,
+  MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__H9K = 5,
+  MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__TemporaryChannel = 6,
+  MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__MissingCertificate = 7
+} MumbleProto__PermissionDenied__DenyType;
+typedef enum _MumbleProto__ContextActionAdd__Context {
+  MUMBLE_PROTO__CONTEXT_ACTION_ADD__CONTEXT__Server = 1,
+  MUMBLE_PROTO__CONTEXT_ACTION_ADD__CONTEXT__Channel = 2,
+  MUMBLE_PROTO__CONTEXT_ACTION_ADD__CONTEXT__User = 4
+} MumbleProto__ContextActionAdd__Context;
+
+/* --- messages --- */
+
+struct  _MumbleProto__Version
+{
+  ProtobufCMessage base;
+  protobuf_c_boolean has_version;
+  uint32_t version;
+  char *release;
+  char *os;
+  char *os_version;
+};
+#define MUMBLE_PROTO__VERSION__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__version__descriptor) \
+    , 0,0, NULL, NULL, NULL }
+
+
+struct  _MumbleProto__UDPTunnel
+{
+  ProtobufCMessage base;
+  ProtobufCBinaryData packet;
+};
+#define MUMBLE_PROTO__UDPTUNNEL__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__udptunnel__descriptor) \
+    , {0,NULL} }
+
+
+struct  _MumbleProto__Authenticate
+{
+  ProtobufCMessage base;
+  char *username;
+  char *password;
+  size_t n_tokens;
+  char **tokens;
+  size_t n_celt_versions;
+  int32_t *celt_versions;
+};
+#define MUMBLE_PROTO__AUTHENTICATE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__authenticate__descriptor) \
+    , NULL, NULL, 0,NULL, 0,NULL }
+
+
+struct  _MumbleProto__Ping
+{
+  ProtobufCMessage base;
+  protobuf_c_boolean has_timestamp;
+  uint64_t timestamp;
+  protobuf_c_boolean has_good;
+  uint32_t good;
+  protobuf_c_boolean has_late;
+  uint32_t late;
+  protobuf_c_boolean has_lost;
+  uint32_t lost;
+  protobuf_c_boolean has_resync;
+  uint32_t resync;
+  protobuf_c_boolean has_udp_packets;
+  uint32_t udp_packets;
+  protobuf_c_boolean has_tcp_packets;
+  uint32_t tcp_packets;
+  protobuf_c_boolean has_udp_ping_avg;
+  float udp_ping_avg;
+  protobuf_c_boolean has_udp_ping_var;
+  float udp_ping_var;
+  protobuf_c_boolean has_tcp_ping_avg;
+  float tcp_ping_avg;
+  protobuf_c_boolean has_tcp_ping_var;
+  float tcp_ping_var;
+};
+#define MUMBLE_PROTO__PING__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__ping__descriptor) \
+    , 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }
+
+
+struct  _MumbleProto__Reject
+{
+  ProtobufCMessage base;
+  protobuf_c_boolean has_type;
+  MumbleProto__Reject__RejectType type;
+  char *reason;
+};
+#define MUMBLE_PROTO__REJECT__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__reject__descriptor) \
+    , 0,0, NULL }
+
+
+struct  _MumbleProto__ServerSync
+{
+  ProtobufCMessage base;
+  protobuf_c_boolean has_session;
+  uint32_t session;
+  protobuf_c_boolean has_max_bandwidth;
+  uint32_t max_bandwidth;
+  char *welcome_text;
+  protobuf_c_boolean has_permissions;
+  uint64_t permissions;
+  protobuf_c_boolean has_allow_html;
+  protobuf_c_boolean allow_html;
+};
+#define MUMBLE_PROTO__SERVER_SYNC__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__server_sync__descriptor) \
+    , 0,0, 0,0, NULL, 0,0, 0,1 }
+
+
+struct  _MumbleProto__ChannelRemove
+{
+  ProtobufCMessage base;
+  uint32_t channel_id;
+};
+#define MUMBLE_PROTO__CHANNEL_REMOVE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__channel_remove__descriptor) \
+    , 0 }
+
+
+struct  _MumbleProto__ChannelState
+{
+  ProtobufCMessage base;
+  protobuf_c_boolean has_channel_id;
+  uint32_t channel_id;
+  protobuf_c_boolean has_parent;
+  uint32_t parent;
+  char *name;
+  size_t n_links;
+  uint32_t *links;
+  char *description;
+  size_t n_links_add;
+  uint32_t *links_add;
+  size_t n_links_remove;
+  uint32_t *links_remove;
+  protobuf_c_boolean has_temporary;
+  protobuf_c_boolean temporary;
+  protobuf_c_boolean has_position;
+  int32_t position;
+};
+#define MUMBLE_PROTO__CHANNEL_STATE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__channel_state__descriptor) \
+    , 0,0, 0,0, NULL, 0,NULL, NULL, 0,NULL, 0,NULL, 0,0, 0,0 }
+
+
+struct  _MumbleProto__UserRemove
+{
+  ProtobufCMessage base;
+  uint32_t session;
+  protobuf_c_boolean has_actor;
+  uint32_t actor;
+  char *reason;
+  protobuf_c_boolean has_ban;
+  protobuf_c_boolean ban;
+};
+#define MUMBLE_PROTO__USER_REMOVE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__user_remove__descriptor) \
+    , 0, 0,0, NULL, 0,0 }
+
+
+struct  _MumbleProto__UserState
+{
+  ProtobufCMessage base;
+  protobuf_c_boolean has_session;
+  uint32_t session;
+  protobuf_c_boolean has_actor;
+  uint32_t actor;
+  char *name;
+  protobuf_c_boolean has_user_id;
+  uint32_t user_id;
+  protobuf_c_boolean has_channel_id;
+  uint32_t channel_id;
+  protobuf_c_boolean has_mute;
+  protobuf_c_boolean mute;
+  protobuf_c_boolean has_deaf;
+  protobuf_c_boolean deaf;
+  protobuf_c_boolean has_suppress;
+  protobuf_c_boolean suppress;
+  protobuf_c_boolean has_self_mute;
+  protobuf_c_boolean self_mute;
+  protobuf_c_boolean has_self_deaf;
+  protobuf_c_boolean self_deaf;
+  protobuf_c_boolean has_texture;
+  ProtobufCBinaryData texture;
+  char *plugin_context;
+  char *plugin_identity;
+  char *comment;
+  char *hash;
+};
+#define MUMBLE_PROTO__USER_STATE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__user_state__descriptor) \
+    , 0,0, 0,0, NULL, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,{0,NULL}, NULL, NULL, NULL, NULL }
+
+
+struct  _MumbleProto__BanList__BanEntry
+{
+  ProtobufCMessage base;
+  ProtobufCBinaryData address;
+  uint32_t mask;
+  char *name;
+  char *hash;
+  char *reason;
+  char *start;
+  protobuf_c_boolean has_duration;
+  uint32_t duration;
+};
+#define MUMBLE_PROTO__BAN_LIST__BAN_ENTRY__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__ban_list__ban_entry__descriptor) \
+    , {0,NULL}, 0, NULL, NULL, NULL, NULL, 0,0 }
+
+
+struct  _MumbleProto__BanList
+{
+  ProtobufCMessage base;
+  size_t n_bans;
+  MumbleProto__BanList__BanEntry **bans;
+  protobuf_c_boolean has_query;
+  protobuf_c_boolean query;
+};
+#define MUMBLE_PROTO__BAN_LIST__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__ban_list__descriptor) \
+    , 0,NULL, 0,0 }
+
+
+struct  _MumbleProto__TextMessage
+{
+  ProtobufCMessage base;
+  protobuf_c_boolean has_actor;
+  uint32_t actor;
+  size_t n_session;
+  uint32_t *session;
+  size_t n_channel_id;
+  uint32_t *channel_id;
+  size_t n_tree_id;
+  uint32_t *tree_id;
+  char *message;
+};
+#define MUMBLE_PROTO__TEXT_MESSAGE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__text_message__descriptor) \
+    , 0,0, 0,NULL, 0,NULL, 0,NULL, NULL }
+
+
+struct  _MumbleProto__PermissionDenied
+{
+  ProtobufCMessage base;
+  protobuf_c_boolean has_permission;
+  uint32_t permission;
+  protobuf_c_boolean has_channel_id;
+  uint32_t channel_id;
+  protobuf_c_boolean has_session;
+  uint32_t session;
+  char *reason;
+  protobuf_c_boolean has_type;
+  MumbleProto__PermissionDenied__DenyType type;
+};
+#define MUMBLE_PROTO__PERMISSION_DENIED__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__permission_denied__descriptor) \
+    , 0,0, 0,0, 0,0, NULL, 0,0 }
+
+
+struct  _MumbleProto__ACL__ChanGroup
+{
+  ProtobufCMessage base;
+  char *name;
+  protobuf_c_boolean has_inherited;
+  protobuf_c_boolean inherited;
+  protobuf_c_boolean has_inherit;
+  protobuf_c_boolean inherit;
+  protobuf_c_boolean has_inheritable;
+  protobuf_c_boolean inheritable;
+  size_t n_add;
+  uint32_t *add;
+  size_t n_remove;
+  uint32_t *remove;
+  size_t n_inherited_members;
+  uint32_t *inherited_members;
+};
+#define MUMBLE_PROTO__ACL__CHAN_GROUP__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__acl__chan_group__descriptor) \
+    , NULL, 0,1, 0,1, 0,1, 0,NULL, 0,NULL, 0,NULL }
+
+
+struct  _MumbleProto__ACL__ChanACL
+{
+  ProtobufCMessage base;
+  protobuf_c_boolean has_apply_here;
+  protobuf_c_boolean apply_here;
+  protobuf_c_boolean has_apply_subs;
+  protobuf_c_boolean apply_subs;
+  protobuf_c_boolean has_inherited;
+  protobuf_c_boolean inherited;
+  protobuf_c_boolean has_user_id;
+  uint32_t user_id;
+  char *group;
+  protobuf_c_boolean has_grant;
+  uint32_t grant;
+  protobuf_c_boolean has_deny;
+  uint32_t deny;
+};
+#define MUMBLE_PROTO__ACL__CHAN_ACL__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__acl__chan_acl__descriptor) \
+    , 0,1, 0,1, 0,1, 0,0, NULL, 0,0, 0,0 }
+
+
+struct  _MumbleProto__ACL
+{
+  ProtobufCMessage base;
+  uint32_t channel_id;
+  protobuf_c_boolean has_inherit_acls;
+  protobuf_c_boolean inherit_acls;
+  size_t n_groups;
+  MumbleProto__ACL__ChanGroup **groups;
+  size_t n_acls;
+  MumbleProto__ACL__ChanACL **acls;
+  protobuf_c_boolean has_query;
+  protobuf_c_boolean query;
+};
+#define MUMBLE_PROTO__ACL__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__acl__descriptor) \
+    , 0, 0,1, 0,NULL, 0,NULL, 0,0 }
+
+
+struct  _MumbleProto__QueryUsers
+{
+  ProtobufCMessage base;
+  size_t n_ids;
+  uint32_t *ids;
+  size_t n_names;
+  char **names;
+};
+#define MUMBLE_PROTO__QUERY_USERS__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__query_users__descriptor) \
+    , 0,NULL, 0,NULL }
+
+
+struct  _MumbleProto__CryptSetup
+{
+  ProtobufCMessage base;
+  protobuf_c_boolean has_key;
+  ProtobufCBinaryData key;
+  protobuf_c_boolean has_client_nonce;
+  ProtobufCBinaryData client_nonce;
+  protobuf_c_boolean has_server_nonce;
+  ProtobufCBinaryData server_nonce;
+};
+#define MUMBLE_PROTO__CRYPT_SETUP__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__crypt_setup__descriptor) \
+    , 0,{0,NULL}, 0,{0,NULL}, 0,{0,NULL} }
+
+
+struct  _MumbleProto__ContextActionAdd
+{
+  ProtobufCMessage base;
+  char *action;
+  char *text;
+  protobuf_c_boolean has_context;
+  uint32_t context;
+};
+#define MUMBLE_PROTO__CONTEXT_ACTION_ADD__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__context_action_add__descriptor) \
+    , NULL, NULL, 0,0 }
+
+
+struct  _MumbleProto__ContextAction
+{
+  ProtobufCMessage base;
+  protobuf_c_boolean has_session;
+  uint32_t session;
+  protobuf_c_boolean has_channel_id;
+  uint32_t channel_id;
+  char *action;
+};
+#define MUMBLE_PROTO__CONTEXT_ACTION__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__context_action__descriptor) \
+    , 0,0, 0,0, NULL }
+
+
+struct  _MumbleProto__UserList__User
+{
+  ProtobufCMessage base;
+  uint32_t user_id;
+  char *name;
+};
+#define MUMBLE_PROTO__USER_LIST__USER__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__user_list__user__descriptor) \
+    , 0, NULL }
+
+
+struct  _MumbleProto__UserList
+{
+  ProtobufCMessage base;
+  size_t n_users;
+  MumbleProto__UserList__User **users;
+};
+#define MUMBLE_PROTO__USER_LIST__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__user_list__descriptor) \
+    , 0,NULL }
+
+
+struct  _MumbleProto__VoiceTarget__Target
+{
+  ProtobufCMessage base;
+  size_t n_session;
+  uint32_t *session;
+  protobuf_c_boolean has_channel_id;
+  uint32_t channel_id;
+  char *group;
+  protobuf_c_boolean has_links;
+  protobuf_c_boolean links;
+  protobuf_c_boolean has_children;
+  protobuf_c_boolean children;
+};
+#define MUMBLE_PROTO__VOICE_TARGET__TARGET__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__voice_target__target__descriptor) \
+    , 0,NULL, 0,0, NULL, 0,0, 0,0 }
+
+
+struct  _MumbleProto__VoiceTarget
+{
+  ProtobufCMessage base;
+  protobuf_c_boolean has_id;
+  uint32_t id;
+  size_t n_targets;
+  MumbleProto__VoiceTarget__Target **targets;
+};
+#define MUMBLE_PROTO__VOICE_TARGET__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__voice_target__descriptor) \
+    , 0,0, 0,NULL }
+
+
+struct  _MumbleProto__PermissionQuery
+{
+  ProtobufCMessage base;
+  protobuf_c_boolean has_channel_id;
+  uint32_t channel_id;
+  protobuf_c_boolean has_permissions;
+  uint32_t permissions;
+  protobuf_c_boolean has_flush;
+  protobuf_c_boolean flush;
+};
+#define MUMBLE_PROTO__PERMISSION_QUERY__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__permission_query__descriptor) \
+    , 0,0, 0,0, 0,0 }
+
+
+struct  _MumbleProto__CodecVersion
+{
+  ProtobufCMessage base;
+  int32_t alpha;
+  int32_t beta;
+  protobuf_c_boolean prefer_alpha;
+};
+#define MUMBLE_PROTO__CODEC_VERSION__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&mumble_proto__codec_version__descriptor) \
+    , 0, 0, 1 }
+
+
+/* MumbleProto__Version methods */
+void   mumble_proto__version__init
+                     (MumbleProto__Version         *message);
+size_t mumble_proto__version__get_packed_size
+                     (const MumbleProto__Version   *message);
+size_t mumble_proto__version__pack
+                     (const MumbleProto__Version   *message,
+                      uint8_t             *out);
+size_t mumble_proto__version__pack_to_buffer
+                     (const MumbleProto__Version   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__Version *
+       mumble_proto__version__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__version__free_unpacked
+                     (MumbleProto__Version *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__UDPTunnel methods */
+void   mumble_proto__udptunnel__init
+                     (MumbleProto__UDPTunnel         *message);
+size_t mumble_proto__udptunnel__get_packed_size
+                     (const MumbleProto__UDPTunnel   *message);
+size_t mumble_proto__udptunnel__pack
+                     (const MumbleProto__UDPTunnel   *message,
+                      uint8_t             *out);
+size_t mumble_proto__udptunnel__pack_to_buffer
+                     (const MumbleProto__UDPTunnel   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__UDPTunnel *
+       mumble_proto__udptunnel__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__udptunnel__free_unpacked
+                     (MumbleProto__UDPTunnel *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__Authenticate methods */
+void   mumble_proto__authenticate__init
+                     (MumbleProto__Authenticate         *message);
+size_t mumble_proto__authenticate__get_packed_size
+                     (const MumbleProto__Authenticate   *message);
+size_t mumble_proto__authenticate__pack
+                     (const MumbleProto__Authenticate   *message,
+                      uint8_t             *out);
+size_t mumble_proto__authenticate__pack_to_buffer
+                     (const MumbleProto__Authenticate   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__Authenticate *
+       mumble_proto__authenticate__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__authenticate__free_unpacked
+                     (MumbleProto__Authenticate *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__Ping methods */
+void   mumble_proto__ping__init
+                     (MumbleProto__Ping         *message);
+size_t mumble_proto__ping__get_packed_size
+                     (const MumbleProto__Ping   *message);
+size_t mumble_proto__ping__pack
+                     (const MumbleProto__Ping   *message,
+                      uint8_t             *out);
+size_t mumble_proto__ping__pack_to_buffer
+                     (const MumbleProto__Ping   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__Ping *
+       mumble_proto__ping__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__ping__free_unpacked
+                     (MumbleProto__Ping *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__Reject methods */
+void   mumble_proto__reject__init
+                     (MumbleProto__Reject         *message);
+size_t mumble_proto__reject__get_packed_size
+                     (const MumbleProto__Reject   *message);
+size_t mumble_proto__reject__pack
+                     (const MumbleProto__Reject   *message,
+                      uint8_t             *out);
+size_t mumble_proto__reject__pack_to_buffer
+                     (const MumbleProto__Reject   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__Reject *
+       mumble_proto__reject__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__reject__free_unpacked
+                     (MumbleProto__Reject *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__ServerSync methods */
+void   mumble_proto__server_sync__init
+                     (MumbleProto__ServerSync         *message);
+size_t mumble_proto__server_sync__get_packed_size
+                     (const MumbleProto__ServerSync   *message);
+size_t mumble_proto__server_sync__pack
+                     (const MumbleProto__ServerSync   *message,
+                      uint8_t             *out);
+size_t mumble_proto__server_sync__pack_to_buffer
+                     (const MumbleProto__ServerSync   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__ServerSync *
+       mumble_proto__server_sync__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__server_sync__free_unpacked
+                     (MumbleProto__ServerSync *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__ChannelRemove methods */
+void   mumble_proto__channel_remove__init
+                     (MumbleProto__ChannelRemove         *message);
+size_t mumble_proto__channel_remove__get_packed_size
+                     (const MumbleProto__ChannelRemove   *message);
+size_t mumble_proto__channel_remove__pack
+                     (const MumbleProto__ChannelRemove   *message,
+                      uint8_t             *out);
+size_t mumble_proto__channel_remove__pack_to_buffer
+                     (const MumbleProto__ChannelRemove   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__ChannelRemove *
+       mumble_proto__channel_remove__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__channel_remove__free_unpacked
+                     (MumbleProto__ChannelRemove *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__ChannelState methods */
+void   mumble_proto__channel_state__init
+                     (MumbleProto__ChannelState         *message);
+size_t mumble_proto__channel_state__get_packed_size
+                     (const MumbleProto__ChannelState   *message);
+size_t mumble_proto__channel_state__pack
+                     (const MumbleProto__ChannelState   *message,
+                      uint8_t             *out);
+size_t mumble_proto__channel_state__pack_to_buffer
+                     (const MumbleProto__ChannelState   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__ChannelState *
+       mumble_proto__channel_state__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__channel_state__free_unpacked
+                     (MumbleProto__ChannelState *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__UserRemove methods */
+void   mumble_proto__user_remove__init
+                     (MumbleProto__UserRemove         *message);
+size_t mumble_proto__user_remove__get_packed_size
+                     (const MumbleProto__UserRemove   *message);
+size_t mumble_proto__user_remove__pack
+                     (const MumbleProto__UserRemove   *message,
+                      uint8_t             *out);
+size_t mumble_proto__user_remove__pack_to_buffer
+                     (const MumbleProto__UserRemove   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__UserRemove *
+       mumble_proto__user_remove__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__user_remove__free_unpacked
+                     (MumbleProto__UserRemove *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__UserState methods */
+void   mumble_proto__user_state__init
+                     (MumbleProto__UserState         *message);
+size_t mumble_proto__user_state__get_packed_size
+                     (const MumbleProto__UserState   *message);
+size_t mumble_proto__user_state__pack
+                     (const MumbleProto__UserState   *message,
+                      uint8_t             *out);
+size_t mumble_proto__user_state__pack_to_buffer
+                     (const MumbleProto__UserState   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__UserState *
+       mumble_proto__user_state__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__user_state__free_unpacked
+                     (MumbleProto__UserState *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__BanList methods */
+void   mumble_proto__ban_list__init
+                     (MumbleProto__BanList         *message);
+size_t mumble_proto__ban_list__get_packed_size
+                     (const MumbleProto__BanList   *message);
+size_t mumble_proto__ban_list__pack
+                     (const MumbleProto__BanList   *message,
+                      uint8_t             *out);
+size_t mumble_proto__ban_list__pack_to_buffer
+                     (const MumbleProto__BanList   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__BanList *
+       mumble_proto__ban_list__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__ban_list__free_unpacked
+                     (MumbleProto__BanList *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__TextMessage methods */
+void   mumble_proto__text_message__init
+                     (MumbleProto__TextMessage         *message);
+size_t mumble_proto__text_message__get_packed_size
+                     (const MumbleProto__TextMessage   *message);
+size_t mumble_proto__text_message__pack
+                     (const MumbleProto__TextMessage   *message,
+                      uint8_t             *out);
+size_t mumble_proto__text_message__pack_to_buffer
+                     (const MumbleProto__TextMessage   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__TextMessage *
+       mumble_proto__text_message__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__text_message__free_unpacked
+                     (MumbleProto__TextMessage *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__PermissionDenied methods */
+void   mumble_proto__permission_denied__init
+                     (MumbleProto__PermissionDenied         *message);
+size_t mumble_proto__permission_denied__get_packed_size
+                     (const MumbleProto__PermissionDenied   *message);
+size_t mumble_proto__permission_denied__pack
+                     (const MumbleProto__PermissionDenied   *message,
+                      uint8_t             *out);
+size_t mumble_proto__permission_denied__pack_to_buffer
+                     (const MumbleProto__PermissionDenied   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__PermissionDenied *
+       mumble_proto__permission_denied__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__permission_denied__free_unpacked
+                     (MumbleProto__PermissionDenied *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__ACL methods */
+void   mumble_proto__acl__init
+                     (MumbleProto__ACL         *message);
+size_t mumble_proto__acl__get_packed_size
+                     (const MumbleProto__ACL   *message);
+size_t mumble_proto__acl__pack
+                     (const MumbleProto__ACL   *message,
+                      uint8_t             *out);
+size_t mumble_proto__acl__pack_to_buffer
+                     (const MumbleProto__ACL   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__ACL *
+       mumble_proto__acl__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__acl__free_unpacked
+                     (MumbleProto__ACL *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__QueryUsers methods */
+void   mumble_proto__query_users__init
+                     (MumbleProto__QueryUsers         *message);
+size_t mumble_proto__query_users__get_packed_size
+                     (const MumbleProto__QueryUsers   *message);
+size_t mumble_proto__query_users__pack
+                     (const MumbleProto__QueryUsers   *message,
+                      uint8_t             *out);
+size_t mumble_proto__query_users__pack_to_buffer
+                     (const MumbleProto__QueryUsers   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__QueryUsers *
+       mumble_proto__query_users__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__query_users__free_unpacked
+                     (MumbleProto__QueryUsers *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__CryptSetup methods */
+void   mumble_proto__crypt_setup__init
+                     (MumbleProto__CryptSetup         *message);
+size_t mumble_proto__crypt_setup__get_packed_size
+                     (const MumbleProto__CryptSetup   *message);
+size_t mumble_proto__crypt_setup__pack
+                     (const MumbleProto__CryptSetup   *message,
+                      uint8_t             *out);
+size_t mumble_proto__crypt_setup__pack_to_buffer
+                     (const MumbleProto__CryptSetup   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__CryptSetup *
+       mumble_proto__crypt_setup__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__crypt_setup__free_unpacked
+                     (MumbleProto__CryptSetup *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__ContextActionAdd methods */
+void   mumble_proto__context_action_add__init
+                     (MumbleProto__ContextActionAdd         *message);
+size_t mumble_proto__context_action_add__get_packed_size
+                     (const MumbleProto__ContextActionAdd   *message);
+size_t mumble_proto__context_action_add__pack
+                     (const MumbleProto__ContextActionAdd   *message,
+                      uint8_t             *out);
+size_t mumble_proto__context_action_add__pack_to_buffer
+                     (const MumbleProto__ContextActionAdd   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__ContextActionAdd *
+       mumble_proto__context_action_add__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__context_action_add__free_unpacked
+                     (MumbleProto__ContextActionAdd *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__ContextAction methods */
+void   mumble_proto__context_action__init
+                     (MumbleProto__ContextAction         *message);
+size_t mumble_proto__context_action__get_packed_size
+                     (const MumbleProto__ContextAction   *message);
+size_t mumble_proto__context_action__pack
+                     (const MumbleProto__ContextAction   *message,
+                      uint8_t             *out);
+size_t mumble_proto__context_action__pack_to_buffer
+                     (const MumbleProto__ContextAction   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__ContextAction *
+       mumble_proto__context_action__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__context_action__free_unpacked
+                     (MumbleProto__ContextAction *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__UserList methods */
+void   mumble_proto__user_list__init
+                     (MumbleProto__UserList         *message);
+size_t mumble_proto__user_list__get_packed_size
+                     (const MumbleProto__UserList   *message);
+size_t mumble_proto__user_list__pack
+                     (const MumbleProto__UserList   *message,
+                      uint8_t             *out);
+size_t mumble_proto__user_list__pack_to_buffer
+                     (const MumbleProto__UserList   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__UserList *
+       mumble_proto__user_list__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__user_list__free_unpacked
+                     (MumbleProto__UserList *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__VoiceTarget methods */
+void   mumble_proto__voice_target__init
+                     (MumbleProto__VoiceTarget         *message);
+size_t mumble_proto__voice_target__get_packed_size
+                     (const MumbleProto__VoiceTarget   *message);
+size_t mumble_proto__voice_target__pack
+                     (const MumbleProto__VoiceTarget   *message,
+                      uint8_t             *out);
+size_t mumble_proto__voice_target__pack_to_buffer
+                     (const MumbleProto__VoiceTarget   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__VoiceTarget *
+       mumble_proto__voice_target__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__voice_target__free_unpacked
+                     (MumbleProto__VoiceTarget *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__PermissionQuery methods */
+void   mumble_proto__permission_query__init
+                     (MumbleProto__PermissionQuery         *message);
+size_t mumble_proto__permission_query__get_packed_size
+                     (const MumbleProto__PermissionQuery   *message);
+size_t mumble_proto__permission_query__pack
+                     (const MumbleProto__PermissionQuery   *message,
+                      uint8_t             *out);
+size_t mumble_proto__permission_query__pack_to_buffer
+                     (const MumbleProto__PermissionQuery   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__PermissionQuery *
+       mumble_proto__permission_query__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__permission_query__free_unpacked
+                     (MumbleProto__PermissionQuery *message,
+                      ProtobufCAllocator *allocator);
+/* MumbleProto__CodecVersion methods */
+void   mumble_proto__codec_version__init
+                     (MumbleProto__CodecVersion         *message);
+size_t mumble_proto__codec_version__get_packed_size
+                     (const MumbleProto__CodecVersion   *message);
+size_t mumble_proto__codec_version__pack
+                     (const MumbleProto__CodecVersion   *message,
+                      uint8_t             *out);
+size_t mumble_proto__codec_version__pack_to_buffer
+                     (const MumbleProto__CodecVersion   *message,
+                      ProtobufCBuffer     *buffer);
+MumbleProto__CodecVersion *
+       mumble_proto__codec_version__unpack
+                     (ProtobufCAllocator  *allocator,
+                      size_t               len,
+                      const uint8_t       *data);
+void   mumble_proto__codec_version__free_unpacked
+                     (MumbleProto__CodecVersion *message,
+                      ProtobufCAllocator *allocator);
+/* --- per-message closures --- */
+
+typedef void (*MumbleProto__Version_Closure)
+                 (const MumbleProto__Version *message,
+                  void *closure_data);
+typedef void (*MumbleProto__UDPTunnel_Closure)
+                 (const MumbleProto__UDPTunnel *message,
+                  void *closure_data);
+typedef void (*MumbleProto__Authenticate_Closure)
+                 (const MumbleProto__Authenticate *message,
+                  void *closure_data);
+typedef void (*MumbleProto__Ping_Closure)
+                 (const MumbleProto__Ping *message,
+                  void *closure_data);
+typedef void (*MumbleProto__Reject_Closure)
+                 (const MumbleProto__Reject *message,
+                  void *closure_data);
+typedef void (*MumbleProto__ServerSync_Closure)
+                 (const MumbleProto__ServerSync *message,
+                  void *closure_data);
+typedef void (*MumbleProto__ChannelRemove_Closure)
+                 (const MumbleProto__ChannelRemove *message,
+                  void *closure_data);
+typedef void (*MumbleProto__ChannelState_Closure)
+                 (const MumbleProto__ChannelState *message,
+                  void *closure_data);
+typedef void (*MumbleProto__UserRemove_Closure)
+                 (const MumbleProto__UserRemove *message,
+                  void *closure_data);
+typedef void (*MumbleProto__UserState_Closure)
+                 (const MumbleProto__UserState *message,
+                  void *closure_data);
+typedef void (*MumbleProto__BanList__BanEntry_Closure)
+                 (const MumbleProto__BanList__BanEntry *message,
+                  void *closure_data);
+typedef void (*MumbleProto__BanList_Closure)
+                 (const MumbleProto__BanList *message,
+                  void *closure_data);
+typedef void (*MumbleProto__TextMessage_Closure)
+                 (const MumbleProto__TextMessage *message,
+                  void *closure_data);
+typedef void (*MumbleProto__PermissionDenied_Closure)
+                 (const MumbleProto__PermissionDenied *message,
+                  void *closure_data);
+typedef void (*MumbleProto__ACL__ChanGroup_Closure)
+                 (const MumbleProto__ACL__ChanGroup *message,
+                  void *closure_data);
+typedef void (*MumbleProto__ACL__ChanACL_Closure)
+                 (const MumbleProto__ACL__ChanACL *message,
+                  void *closure_data);
+typedef void (*MumbleProto__ACL_Closure)
+                 (const MumbleProto__ACL *message,
+                  void *closure_data);
+typedef void (*MumbleProto__QueryUsers_Closure)
+                 (const MumbleProto__QueryUsers *message,
+                  void *closure_data);
+typedef void (*MumbleProto__CryptSetup_Closure)
+                 (const MumbleProto__CryptSetup *message,
+                  void *closure_data);
+typedef void (*MumbleProto__ContextActionAdd_Closure)
+                 (const MumbleProto__ContextActionAdd *message,
+                  void *closure_data);
+typedef void (*MumbleProto__ContextAction_Closure)
+                 (const MumbleProto__ContextAction *message,
+                  void *closure_data);
+typedef void (*MumbleProto__UserList__User_Closure)
+                 (const MumbleProto__UserList__User *message,
+                  void *closure_data);
+typedef void (*MumbleProto__UserList_Closure)
+                 (const MumbleProto__UserList *message,
+                  void *closure_data);
+typedef void (*MumbleProto__VoiceTarget__Target_Closure)
+                 (const MumbleProto__VoiceTarget__Target *message,
+                  void *closure_data);
+typedef void (*MumbleProto__VoiceTarget_Closure)
+                 (const MumbleProto__VoiceTarget *message,
+                  void *closure_data);
+typedef void (*MumbleProto__PermissionQuery_Closure)
+                 (const MumbleProto__PermissionQuery *message,
+                  void *closure_data);
+typedef void (*MumbleProto__CodecVersion_Closure)
+                 (const MumbleProto__CodecVersion *message,
+                  void *closure_data);
+
+/* --- services --- */
+
+
+/* --- descriptors --- */
+
+extern const ProtobufCMessageDescriptor mumble_proto__version__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__udptunnel__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__authenticate__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__ping__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__reject__descriptor;
+extern const ProtobufCEnumDescriptor    mumble_proto__reject__reject_type__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__server_sync__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__channel_remove__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__channel_state__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__user_remove__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__user_state__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__ban_list__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__ban_list__ban_entry__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__text_message__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__permission_denied__descriptor;
+extern const ProtobufCEnumDescriptor    mumble_proto__permission_denied__deny_type__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__acl__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__acl__chan_group__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__acl__chan_acl__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__query_users__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__crypt_setup__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__context_action_add__descriptor;
+extern const ProtobufCEnumDescriptor    mumble_proto__context_action_add__context__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__context_action__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__user_list__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__user_list__user__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__voice_target__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__voice_target__target__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__permission_query__descriptor;
+extern const ProtobufCMessageDescriptor mumble_proto__codec_version__descriptor;
+
+PROTOBUF_C_END_DECLS
+
+
+#endif  /* PROTOBUF_Mumble_2eproto__INCLUDED */
index 74633613b744401636c10eee2c7a3b535d5f5bac..42907117694b60dbe87a1028148af862b3ec3e4f 100644 (file)
 #include "ssl.h"
 #include "messages.h"
 #include "messagehandler.h"
-#include "pds.h"
 #include "conf.h"
 #include "channel.h"
 
-
+/* Version 0.2.0 XXX fixme */
+const uint32_t versionBlob = 1<<16 | 2<<8 | 0;
 
 static int Client_read(client_t *client);
 static int Client_write(client_t *client);
-static int Client_voiceMsg(client_t *client, pds_t *pds);
 static int Client_send_udp(client_t *client, uint8_t *data, int len);
-static void Client_voiceMsg_tunnel(client_t *client, message_t *msg);
+void Client_free(client_t *client);
 
 declare_list(clients);
 static int clientcount; /* = 0 */
@@ -142,8 +141,8 @@ void Client_free(client_t *client)
                         ntohs(client->remote_tcp.sin_port));
 
        if (client->authenticated) {
-               sendmsg = Msg_create(ServerLeave);
-               sendmsg->sessionId = client->sessionId;
+               sendmsg = Msg_create(UserRemove);
+               sendmsg->payload.userRemove->session = client->sessionId;
                Client_send_message_except(client, sendmsg);
        }
        list_iterate_safe(itr, save, &client->txMsgQueue) {
@@ -220,7 +219,7 @@ int Client_read(client_t *client)
        do {
                errno = 0;
                if (!client->msgsize) 
-                       rc = SSL_read(client->ssl, client->rxbuf, 3 - client->rxcount);
+                       rc = SSL_read(client->ssl, client->rxbuf, 6 - client->rxcount);
                else if (client->drainleft > 0)
                        rc = SSL_read(client->ssl, client->rxbuf, client->drainleft > BUFSIZE ? BUFSIZE : client->drainleft);
                else
@@ -231,24 +230,20 @@ int Client_read(client_t *client)
                                client->drainleft -= rc;
                        else {
                                client->rxcount += rc;
-                               if (!client->msgsize && rc >= 3)
-                                       client->msgsize = ((client->rxbuf[0] & 0xff) << 16) |
-                                               ((client->rxbuf[1] & 0xff) << 8) |
-                                               (client->rxbuf[2] & 0xff);
-                               if (client->msgsize > BUFSIZE - 3 && client->drainleft == 0) {
+                               if (!client->msgsize && client->rxcount >= 6) {
+                                       uint32_t *msgLen = (uint32_t *) &client->rxbuf[2];
+                                       client->msgsize = ntohl(*msgLen);
+                               }
+                               if (client->msgsize > BUFSIZE - 6 && client->drainleft == 0) {
                                        Log_warn("Too big message received (%d). Discarding.", client->msgsize);
                                        client->rxcount = client->msgsize = 0;
                                        client->drainleft = client->msgsize;
                                }
-                               else if (client->rxcount == client->msgsize + 3) { /* Got all of the message */
-                                       msg = Msg_networkToMessage(&client->rxbuf[3], client->msgsize);
+                               else if (client->rxcount == client->msgsize + 6) { /* Got all of the message */
+                                       msg = Msg_networkToMessage(client->rxbuf, client->msgsize + 6);
                                        /* pass messsage to handler */
-                                       if (msg) {
-                                               if (msg->messageType == Speex) /* Tunneled voice message */
-                                                       Client_voiceMsg_tunnel(client, msg);
-                                               else 
+                                       if (msg)
                                                        Mh_handle_message(client, msg);
-                                       }
                                        client->rxcount = client->msgsize = 0;
                                }
                        }
@@ -350,23 +345,21 @@ int Client_send_message(client_t *client, message_t *msg)
        }
        if (client->txsize != 0) {
                /* Queue message */
-               if ((client->txQueueCount > 5 &&  msg->messageType == Speex) ||
+               if ((client->txQueueCount > 5 &&  msg->messageType == UDPTunnel) ||
                        client->txQueueCount > 30) {
                        Msg_free(msg);
                        return -1;
                }
                client->txQueueCount++;
                list_add_tail(&msg->node, &client->txMsgQueue);
+               Log_debug("Queueing message");
        } else {
                int len;
                memset(client->txbuf, 0, BUFSIZE);
-               len = Msg_messageToNetwork(msg, &client->txbuf[3], BUFSIZE - 3);
-               doAssert(len < BUFSIZE - 3);
+               len = Msg_messageToNetwork(msg, client->txbuf);
+               doAssert(len < BUFSIZE);
 
-               client->txbuf[0] =  (len >> 16) & 0xff;
-               client->txbuf[1] =  (len >> 8) & 0xff;
-               client->txbuf[2] =  len & 0xff;
-               client->txsize = len + 3;
+               client->txsize = len;
                client->txcount = 0;
                Client_write(client);
                Msg_free(msg);
@@ -428,9 +421,7 @@ static bool_t checkDecrypt(client_t *client, const uint8_t *encrypted, uint8_t *
                        message_t *sendmsg;
                        Timer_restart(&client->cryptState.tLastRequest);
                        
-                       sendmsg = Msg_create(CryptSync);
-                       sendmsg->sessionId = client->sessionId;
-                       sendmsg->payload.cryptSync.empty = true;
+                       sendmsg = Msg_create(CryptSetup);
                        Log_info("Requesting voice channel crypt resync");
                        Client_send_message(client, sendmsg);
                }
@@ -438,6 +429,7 @@ static bool_t checkDecrypt(client_t *client, const uint8_t *encrypted, uint8_t *
        return false;
 }
 
+#define UDP_PACKET_SIZE 1024
 int Client_read_udp()
 {
        int len;
@@ -445,58 +437,59 @@ int Client_read_udp()
        socklen_t fromlen = sizeof(struct sockaddr_in);
        uint64_t key;
        client_t *itr;
-       int msgType = 0;
-       uint32_t sessionId = 0;
-       pds_t *pds;
+       UDPMessageType_t msgType;
        
 #if defined(__LP64__)
-       uint8_t encbuff[512 + 8];
+       uint8_t encbuff[UDP_PACKET_SIZE + 8];
        uint8_t *encrypted = encbuff + 4;
 #else
-       uint8_t encrypted[512];
+       uint8_t encrypted[UDP_PACKET_SIZE];
 #endif
-       uint8_t buffer[512];
+       uint8_t buffer[UDP_PACKET_SIZE];
        
-       len = recvfrom(udpsock, encrypted, 512, MSG_TRUNC, (struct sockaddr *)&from, &fromlen);
+       len = recvfrom(udpsock, encrypted, UDP_PACKET_SIZE, MSG_TRUNC, (struct sockaddr *)&from, &fromlen);
        if (len == 0) {
                return -1;
        } else if (len < 0) {
                return -1;
-       } else if (len < 6) {
+       } else if (len < 5) {
                // 4 bytes crypt header + type + session
                return 0;
-       } else if (len > 512) {
+       } else if (len > UDP_PACKET_SIZE) {
+               return 0;
+       }
+
+       /* Ping packet */
+       if (len == 12 && *encrypted == 0) {
+               uint32_t *ping = (uint32_t *)encrypted;
+               ping[0] = htons(versionBlob);
+               // 1 and 2 will be the timestamp, which we return unmodified.
+               ping[3] = htons((uint32_t)clientcount);
+               ping[4] = htons((uint32_t)getIntConf(MAX_CLIENTS));
+               ping[5] = htons((uint32_t)getIntConf(MAX_BANDWIDTH));
+               
+               sendto(udpsock, encrypted, 6 * sizeof(uint32_t), 0, (struct sockaddr *)&from, fromlen);
                return 0;
        }
        
        key = (((uint64_t)from.sin_addr.s_addr) << 16) ^ from.sin_port;
-       pds = Pds_create(buffer, len - 4);
        itr = NULL;
        
        while (Client_iterate(&itr) != NULL) {
                if (itr->key == key) {
                        if (!checkDecrypt(itr, encrypted, buffer, len))
                                goto out;
-                       msgType = Pds_get_numval(pds);
-                       sessionId = Pds_get_numval(pds);
-                       if (itr->sessionId != sessionId)
-                               goto out;
                        break;
                }
        }       
        if (itr == NULL) { /* Unknown peer */
                while (Client_iterate(&itr) != NULL) {
-                       pds->offset = 0;
                        if (itr->remote_tcp.sin_addr.s_addr == from.sin_addr.s_addr) {
                                if (checkDecrypt(itr, encrypted, buffer, len)) {
-                                       msgType = Pds_get_numval(pds);
-                                       sessionId = Pds_get_numval(pds);
-                                       if (itr->sessionId == sessionId) { /* Found matching client */
-                                               itr->key = key;
-                                               Log_info("New UDP connection from %s port %d sessionId %d", inet_ntoa(from.sin_addr), ntohs(from.sin_port), sessionId);
-                                               memcpy(&itr->remote_udp, &from, sizeof(struct sockaddr_in));
-                                               break;
-                                       }
+                                       itr->key = key;
+                                       Log_info("New UDP connection from %s port %d sessionId %d", inet_ntoa(from.sin_addr), ntohs(from.sin_port), itr->sessionId);
+                                       memcpy(&itr->remote_udp, &from, sizeof(struct sockaddr_in));
+                                       break;
                                }
                                else Log_warn("Bad cryptstate from peer");
                        }
@@ -505,80 +498,81 @@ int Client_read_udp()
        if (itr == NULL) {
                goto out;
        }
-       len -= 4;
-       if (msgType != Speex && msgType != Ping)
-               goto out;
        
-       if (msgType == Ping) {
+       msgType = (UDPMessageType_t)((buffer[0] >> 5) & 0x7);
+       switch (msgType) {
+       case UDPVoiceSpeex:
+       case UDPVoiceCELTAlpha:
+       case UDPVoiceCELTBeta:
+               // u->bUdp = true;
+               Client_voiceMsg(itr, buffer, len);
+               break;
+       case UDPPing:
                Client_send_udp(itr, buffer, len);
+               break;
+       default:
+               Log_debug("Unknown UDP message type from %s port %d", inet_ntoa(from.sin_addr), ntohs(from.sin_port));
+               break;
        }
-       else {
-               Client_voiceMsg(itr, pds);
-       }
-       
 out:
-       Pds_free(pds);
        return 0;
 }
 
-static void Client_voiceMsg_tunnel(client_t *client, message_t *msg)
+/* Handle decrypted voice message */
+int Client_voiceMsg(client_t *client, uint8_t *data, int len)
 {
-       uint8_t buf[512];
-       pds_t *pds = Pds_create(buf, 512);
+       uint8_t buffer[UDP_PACKET_SIZE];
+       pds_t *pdi = Pds_create(data + 1, len - 1);
+       pds_t *pds = Pds_create(buffer + 1, UDP_PACKET_SIZE - 1);
+       unsigned int type = data[0] & 0xe0;
+       unsigned int target = data[0] & 0x1f;
+       unsigned int poslen, counter;
+       int offset, packetsize;
 
-       Pds_add_numval(pds, msg->messageType);
-       Pds_add_numval(pds, msg->sessionId);
-       Pds_add_numval(pds, msg->payload.speex.seq);
-       Pds_append_data_nosize(pds, msg->payload.speex.data, msg->payload.speex.size);
-       
-       Msg_free(msg);
-       
-       if (!pds->bOk)
-               Log_warn("Large Speex message from TCP"); /* XXX - pds resize? */
-       pds->maxsize = pds->offset;
-       Client_voiceMsg(client, pds);
-       
-       Pds_free(pds);
-}
-
-static int Client_voiceMsg(client_t *client, pds_t *pds)
-{
-       int seq, flags, msgType, sessionId, packetsize;
        channel_t *ch = (channel_t *)client->channel;
        struct dlist *itr;
        
        if (!client->authenticated || client->mute)
                return 0;
-
        
-       pds->offset = 0;
-       msgType = Pds_get_numval(pds);
-       sessionId = Pds_get_numval(pds);
-       seq = Pds_get_numval(pds);
-       flags = Pds_get_numval(pds);
-
-       packetsize = 20 + 8 + 4 + pds->maxsize - pds->offset;
+       packetsize = 20 + 8 + 4 + len;
        if (client->availableBandwidth - packetsize < 0)
                return 0; /* Discard */
-       
        client->availableBandwidth -= packetsize;
        
-       pds->offset = 0;
+       counter = Pds_get_numval(pdi); /* Seems like this... */
+       do {
+               counter = Pds_next8(pdi);
+               offset = Pds_skip(pdi, counter & 0x7f);
+       } while ((counter & 0x80) && offset > 0);
+
+       poslen = pdi->maxsize - pdi->offset; /* XXX - Add stripping of positional audio */
        
-       if (flags & LoopBack) {
-               Client_send_udp(client, pds->data, pds->maxsize);
-               return 0;
-       }
-       if (ch == NULL)
-               return 0;
+       Pds_add_numval(pds, client->sessionId);
+       Pds_append_data_nosize(pds, data + 1, len - 1);
        
-       list_iterate(itr, &ch->clients) {
-               client_t *c;
-               c = list_get_entry(itr, client_t, chan_node);
-               if (c != client && !c->deaf) {
-                       Client_send_udp(c, pds->data, pds->maxsize);
+       if (target & 0x1f) { /* Loopback */
+               buffer[0] = (uint8_t) type;
+               Client_send_udp(client, buffer, pds->offset + 1);
+       }
+       else if (target == 0) { /* regular channel speech */
+               buffer[0] = (uint8_t) type;
+               
+               if (ch == NULL)
+                       return 0;
+               
+               list_iterate(itr, &ch->clients) {
+                       client_t *c;
+                       c = list_get_entry(itr, client_t, chan_node);
+                       if (c != client && !c->deaf) {
+                               Client_send_udp(c, buffer, pds->offset + 1);
+                       }
                }
        }
+       /* XXX - Add targeted whisper here */
+       Pds_free(pds);
+       Pds_free(pdi);
+       
        return 0;
 }
 
@@ -586,7 +580,6 @@ static int Client_voiceMsg(client_t *client, pds_t *pds)
 static int Client_send_udp(client_t *client, uint8_t *data, int len)
 {
        uint8_t *buf, *mbuf;
-       message_t *sendmsg;
 
        if (client->remote_udp.sin_port != 0 && CryptState_isValid(&client->cryptState)) {
 #if defined(__LP64__)
@@ -604,26 +597,14 @@ static int Client_send_udp(client_t *client, uint8_t *data, int len)
                
                free(mbuf);
        } else {
-               pds_t *pds = Pds_create(data, len);
-               
-               sendmsg = Msg_create(Pds_get_numval(pds));
-               sendmsg->sessionId = Pds_get_numval(pds);
+               message_t *msg;
+               buf = malloc(len);
+               memcpy(buf, data, len);
+               msg = Msg_create(UDPTunnel);
                
-               if (sendmsg->messageType == Speex || sendmsg->messageType == Ping) {
-                       if (sendmsg->messageType == Speex) {
-                               sendmsg->payload.speex.seq = Pds_get_numval(pds);
-                               sendmsg->payload.speex.size = pds->maxsize - pds->offset;
-                               doAssert(pds->maxsize - pds->offset <= SPEEX_DATA_SIZE);
-                               memcpy(sendmsg->payload.speex.data, data + pds->offset, pds->maxsize - pds->offset);
-                       } else { /* Ping */
-                               sendmsg->payload.ping.timestamp = Pds_get_numval(pds);
-                       }
-                       Client_send_message(client, sendmsg);
-               } else {
-                       Log_warn("TCP fallback: Unsupported message type %d", sendmsg->messageType);
-                       Msg_free(sendmsg);
-               }
-               Pds_free(pds);
+               msg->payload.UDPTunnel->packet.data = buf;
+               msg->payload.UDPTunnel->packet.len = len;
+               Client_send_message(client, msg);
        }
        return 0;
 }
index b7460b635fd1d9227ee8a5fc018aa8340beea0c9..b6528ebff8289708eb99e66b361a8c2dba279539 100644 (file)
@@ -46,6 +46,7 @@
 #include "messages.h"
 #include "crypt.h"
 #include "timer.h"
+#include "pds.h"
 
 #define BUFSIZE 2048
 #define UDP_BUFSIZE 512
@@ -94,5 +95,6 @@ client_t *Client_iterate(client_t **client);
 int Client_send_message_except(client_t *client, message_t *msg);
 int Client_read_udp(void);
 void Client_disconnect_all();
+int Client_voiceMsg(client_t *client, uint8_t *data, int len);
 
 #endif
diff --git a/src/google/protobuf-c/Makefile b/src/google/protobuf-c/Makefile
new file mode 100644 (file)
index 0000000..c34f0d1
--- /dev/null
@@ -0,0 +1,11 @@
+PROTOBUF_SRCS:=protobuf-c.c protobuf-c-data-buffer.c
+PROTOBUF_OBJS:=$(patsubst %.c, %.o, $(PROTOBUF_SRCS))
+CFLAGS:=$(CFLAGS) -I. -Wall -g
+
+all: libprotobuf_c.a
+
+libprotobuf_c.a:$(PROTOBUF_OBJS)
+       $(AR) rcs libprotobuf_c.a $(PROTOBUF_OBJS)
+
+clean:
+       rm -f $(PROTOBUF_OBJS) libprotobuf_c.a
diff --git a/src/google/protobuf-c/protobuf-c-data-buffer.c b/src/google/protobuf-c/protobuf-c-data-buffer.c
new file mode 100644 (file)
index 0000000..4ed46ce
--- /dev/null
@@ -0,0 +1,1107 @@
+/* Free blocks to hold around to avoid repeated mallocs... */
+#define MAX_RECYCLED           16
+
+/* Size of allocations to make. */
+#define BUF_CHUNK_SIZE         8192
+
+/* Max fragments in the iovector to writev. */
+#define MAX_FRAGMENTS_TO_WRITE 16
+
+/* This causes fragments not to be transferred from buffer to buffer,
+ * and not to be allocated in pools.  The result is that stack-trace
+ * based debug-allocators work much better with this on.
+ *
+ * On the other hand, this can mask over some abuses (eg stack-based
+ * foreign buffer fragment bugs) so we disable it by default.
+ */ 
+#define GSK_DEBUG_BUFFER_ALLOCATIONS   0
+
+#define BUFFER_RECYCLING                0
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <alloca.h>
+#include "protobuf-c-data-buffer.h"
+
+#undef TRUE
+#define TRUE 1
+#undef FALSE
+#define FALSE 0
+
+#define PROTOBUF_C_FRAGMENT_DATA_SIZE        4096
+#define PROTOBUF_C_FRAGMENT_DATA(frag)     ((uint8_t*)(((ProtobufCDataBufferFragment*)(frag))+1))
+
+/* --- ProtobufCDataBufferFragment implementation --- */
+static inline int 
+protobuf_c_data_buffer_fragment_avail (ProtobufCDataBufferFragment *frag)
+{
+  return PROTOBUF_C_FRAGMENT_DATA_SIZE - frag->buf_start - frag->buf_length;
+}
+static inline uint8_t *
+protobuf_c_data_buffer_fragment_start (ProtobufCDataBufferFragment *frag)
+{
+  return PROTOBUF_C_FRAGMENT_DATA(frag) + frag->buf_start;
+}
+static inline uint8_t *
+protobuf_c_data_buffer_fragment_end (ProtobufCDataBufferFragment *frag)
+{
+  return PROTOBUF_C_FRAGMENT_DATA(frag) + frag->buf_start + frag->buf_length;
+}
+
+/* --- ProtobufCDataBufferFragment recycling --- */
+#if BUFFER_RECYCLING
+static int num_recycled = 0;
+static ProtobufCDataBufferFragment* recycling_stack = 0;
+#endif
+
+static ProtobufCDataBufferFragment *
+new_native_fragment(ProtobufCAllocator *allocator)
+{
+  ProtobufCDataBufferFragment *frag;
+#if !BUFFER_RECYCLING
+  frag = (ProtobufCDataBufferFragment *) allocator->alloc (allocator, BUF_CHUNK_SIZE);
+#else  /* optimized (?) */
+  if (recycling_stack)
+    {
+      frag = recycling_stack;
+      recycling_stack = recycling_stack->next;
+      num_recycled--;
+    }
+  else
+    {
+      frag = (ProtobufCDataBufferFragment *) g_malloc (BUF_CHUNK_SIZE);
+    }
+#endif /* !GSK_DEBUG_BUFFER_ALLOCATIONS */
+  frag->buf_start = frag->buf_length = 0;
+  frag->next = 0;
+  return frag;
+}
+
+#if GSK_DEBUG_BUFFER_ALLOCATIONS || !BUFFER_RECYCLING
+#define recycle(allocator, frag) allocator->free (allocator, frag)
+#else  /* optimized (?) */
+static void
+recycle(ProtobufCDataBufferFragment* frag,
+        ProtobufCAllocator *allocator)
+{
+  frag->next = recycling_stack;
+  recycling_stack = frag;
+  num_recycled++;
+}
+#endif /* !GSK_DEBUG_BUFFER_ALLOCATIONS */
+
+/* --- Global public methods --- */
+/**
+ * protobuf_c_data_buffer_cleanup_recycling_bin:
+ * 
+ * Free unused buffer fragments.  (Normally some are
+ * kept around to reduce strain on the global allocator.)
+ */
+void
+protobuf_c_data_buffer_cleanup_recycling_bin ()
+{
+#if !GSK_DEBUG_BUFFER_ALLOCATIONS && BUFFER_RECYCLING
+  G_LOCK (recycling_stack);
+  while (recycling_stack != NULL)
+    {
+      ProtobufCDataBufferFragment *next;
+      next = recycling_stack->next;
+      g_free (recycling_stack);
+      recycling_stack = next;
+    }
+  num_recycled = 0;
+  G_UNLOCK (recycling_stack);
+#endif
+}
+      
+/* --- Public methods --- */
+/**
+ * protobuf_c_data_buffer_init:
+ * @buffer: buffer to initialize (as empty).
+ *
+ * Construct an empty buffer out of raw memory.
+ * (This is equivalent to filling the buffer with 0s)
+ */
+void
+protobuf_c_data_buffer_init(ProtobufCDataBuffer *buffer,
+                            ProtobufCAllocator *allocator)
+{
+  buffer->first_frag = buffer->last_frag = NULL;
+  buffer->size = 0;
+  buffer->allocator = allocator;
+}
+
+#if defined(GSK_DEBUG) || GSK_DEBUG_BUFFER_ALLOCATIONS
+static inline gboolean
+verify_buffer (const ProtobufCDataBuffer *buffer)
+{
+  const ProtobufCDataBufferFragment *frag;
+  size_t total = 0;
+  for (frag = buffer->first_frag; frag != NULL; frag = frag->next)
+    total += frag->buf_length;
+  return total == buffer->size;
+}
+#define CHECK_INTEGRITY(buffer)        g_assert (verify_buffer (buffer))
+#else
+#define CHECK_INTEGRITY(buffer)
+#endif
+
+/**
+ * protobuf_c_data_buffer_append:
+ * @buffer: the buffer to add data to.  Data is put at the end of the buffer.
+ * @data: binary data to add to the buffer.
+ * @length: length of @data to add to the buffer.
+ *
+ * Append data into the buffer.
+ */
+void
+protobuf_c_data_buffer_append(ProtobufCDataBuffer    *buffer,
+                  const void   *data,
+                 size_t         length)
+{
+  CHECK_INTEGRITY (buffer);
+  buffer->size += length;
+  while (length > 0)
+    {
+      size_t avail;
+      if (!buffer->last_frag)
+       {
+         buffer->last_frag = buffer->first_frag = new_native_fragment (buffer->allocator);
+         avail = protobuf_c_data_buffer_fragment_avail (buffer->last_frag);
+       }
+      else
+       {
+         avail = protobuf_c_data_buffer_fragment_avail (buffer->last_frag);
+         if (avail <= 0)
+           {
+             buffer->last_frag->next = new_native_fragment (buffer->allocator);
+             avail = protobuf_c_data_buffer_fragment_avail (buffer->last_frag);
+             buffer->last_frag = buffer->last_frag->next;
+           }
+       }
+      if (avail > length)
+       avail = length;
+      memcpy (protobuf_c_data_buffer_fragment_end (buffer->last_frag), data, avail);
+      data = (const char *) data + avail;
+      length -= avail;
+      buffer->last_frag->buf_length += avail;
+    }
+  CHECK_INTEGRITY (buffer);
+}
+
+void
+protobuf_c_data_buffer_append_repeated_char (ProtobufCDataBuffer    *buffer, 
+                                 char          character,
+                                 size_t        count)
+{
+  CHECK_INTEGRITY (buffer);
+  buffer->size += count;
+  while (count > 0)
+    {
+      size_t avail;
+      if (!buffer->last_frag)
+       {
+         buffer->last_frag = buffer->first_frag = new_native_fragment (buffer->allocator);
+         avail = protobuf_c_data_buffer_fragment_avail (buffer->last_frag);
+       }
+      else
+       {
+         avail = protobuf_c_data_buffer_fragment_avail (buffer->last_frag);
+         if (avail <= 0)
+           {
+             buffer->last_frag->next = new_native_fragment (buffer->allocator);
+             avail = protobuf_c_data_buffer_fragment_avail (buffer->last_frag);
+             buffer->last_frag = buffer->last_frag->next;
+           }
+       }
+      if (avail > count)
+       avail = count;
+      memset (protobuf_c_data_buffer_fragment_end (buffer->last_frag), character, avail);
+      count -= avail;
+      buffer->last_frag->buf_length += avail;
+    }
+  CHECK_INTEGRITY (buffer);
+}
+
+#if 0
+void
+protobuf_c_data_buffer_append_repeated_data (ProtobufCDataBuffer    *buffer, 
+                                 gconstpointer data_to_repeat,
+                                 gsize         data_length,
+                                 gsize         count)
+{
+  ...
+}
+#endif
+
+/**
+ * protobuf_c_data_buffer_append_string:
+ * @buffer: the buffer to add data to.  Data is put at the end of the buffer.
+ * @string: NUL-terminated string to append to the buffer.
+ *  The NUL is not appended.
+ *
+ * Append a string to the buffer.
+ */
+void
+protobuf_c_data_buffer_append_string(ProtobufCDataBuffer  *buffer,
+                         const char *string)
+{
+  assert (string != NULL);
+  protobuf_c_data_buffer_append (buffer, string, strlen (string));
+}
+
+/**
+ * protobuf_c_data_buffer_append_char:
+ * @buffer: the buffer to add the byte to.
+ * @character: the byte to add to the buffer.
+ *
+ * Append a byte to a buffer.
+ */
+void
+protobuf_c_data_buffer_append_char(ProtobufCDataBuffer *buffer,
+                      char       character)
+{
+  protobuf_c_data_buffer_append (buffer, &character, 1);
+}
+
+/**
+ * protobuf_c_data_buffer_append_string0:
+ * @buffer: the buffer to add data to.  Data is put at the end of the buffer.
+ * @string: NUL-terminated string to append to the buffer;
+ *  NUL is appended.
+ *
+ * Append a NUL-terminated string to the buffer.  The NUL is appended.
+ */
+void
+protobuf_c_data_buffer_append_string0      (ProtobufCDataBuffer    *buffer,
+                               const char   *string)
+{
+  protobuf_c_data_buffer_append (buffer, string, strlen (string) + 1);
+}
+
+/**
+ * protobuf_c_data_buffer_read:
+ * @buffer: the buffer to read data from.
+ * @data: buffer to fill with up to @max_length bytes of data.
+ * @max_length: maximum number of bytes to read.
+ *
+ * Removes up to @max_length data from the beginning of the buffer,
+ * and writes it to @data.  The number of bytes actually read
+ * is returned.
+ *
+ * returns: number of bytes transferred.
+ */
+size_t
+protobuf_c_data_buffer_read(ProtobufCDataBuffer    *buffer,
+                void         *data,
+               size_t         max_length)
+{
+  size_t rv = 0;
+  size_t orig_max_length = max_length;
+  CHECK_INTEGRITY (buffer);
+  while (max_length > 0 && buffer->first_frag)
+    {
+      ProtobufCDataBufferFragment *first = buffer->first_frag;
+      if (first->buf_length <= max_length)
+       {
+         memcpy (data, protobuf_c_data_buffer_fragment_start (first), first->buf_length);
+         rv += first->buf_length;
+         data = (char *) data + first->buf_length;
+         max_length -= first->buf_length;
+         buffer->first_frag = first->next;
+         if (!buffer->first_frag)
+           buffer->last_frag = NULL;
+         recycle (buffer->allocator, first);
+       }
+      else
+       {
+         memcpy (data, protobuf_c_data_buffer_fragment_start (first), max_length);
+         rv += max_length;
+         first->buf_length -= max_length;
+         first->buf_start += max_length;
+         data = (char *) data + max_length;
+         max_length = 0;
+       }
+    }
+  buffer->size -= rv;
+  assert (rv == orig_max_length || buffer->size == 0);
+  CHECK_INTEGRITY (buffer);
+  return rv;
+}
+
+/**
+ * protobuf_c_data_buffer_peek:
+ * @buffer: the buffer to peek data from the front of.
+ *    This buffer is unchanged by the operation.
+ * @data: buffer to fill with up to @max_length bytes of data.
+ * @max_length: maximum number of bytes to peek.
+ *
+ * Copies up to @max_length data from the beginning of the buffer,
+ * and writes it to @data.  The number of bytes actually copied
+ * is returned.
+ *
+ * This function is just like protobuf_c_data_buffer_read() except that the 
+ * data is not removed from the buffer.
+ *
+ * returns: number of bytes copied into data.
+ */
+size_t
+protobuf_c_data_buffer_peek     (const ProtobufCDataBuffer *buffer,
+                     void            *data,
+                    size_t            max_length)
+{
+  int rv = 0;
+  ProtobufCDataBufferFragment *frag = (ProtobufCDataBufferFragment *) buffer->first_frag;
+  CHECK_INTEGRITY (buffer);
+  while (max_length > 0 && frag)
+    {
+      if (frag->buf_length <= max_length)
+       {
+         memcpy (data, protobuf_c_data_buffer_fragment_start (frag), frag->buf_length);
+         rv += frag->buf_length;
+         data = (char *) data + frag->buf_length;
+         max_length -= frag->buf_length;
+         frag = frag->next;
+       }
+      else
+       {
+         memcpy (data, protobuf_c_data_buffer_fragment_start (frag), max_length);
+         rv += max_length;
+         data = (char *) data + max_length;
+         max_length = 0;
+       }
+    }
+  return rv;
+}
+
+/**
+ * protobuf_c_data_buffer_read_line:
+ * @buffer: buffer to read a line from.
+ *
+ * Parse a newline (\n) terminated line from
+ * buffer and return it as a newly allocated string.
+ * The newline is changed to a NUL character.
+ *
+ * If the buffer does not contain a newline, then NULL is returned.
+ *
+ * returns: a newly allocated NUL-terminated string, or NULL.
+ */
+char *
+protobuf_c_data_buffer_read_line(ProtobufCDataBuffer *buffer)
+{
+  int len = 0;
+  char *rv;
+  ProtobufCDataBufferFragment *at;
+  int newline_length;
+  CHECK_INTEGRITY (buffer);
+  for (at = buffer->first_frag; at; at = at->next)
+    {
+      uint8_t *start = protobuf_c_data_buffer_fragment_start (at);
+      uint8_t *got;
+      got = memchr (start, '\n', at->buf_length);
+      if (got)
+       {
+         len += got - start;
+         break;
+       }
+      len += at->buf_length;
+    }
+  if (at == NULL)
+    return NULL;
+  rv = buffer->allocator->alloc (buffer->allocator, len + 1);
+  /* If we found a newline, read it out, truncating
+   * it with NUL before we return from the function... */
+  if (at)
+    newline_length = 1;
+  else
+    newline_length = 0;
+  protobuf_c_data_buffer_read (buffer, rv, len + newline_length);
+  rv[len] = 0;
+  CHECK_INTEGRITY (buffer);
+  return rv;
+}
+
+/**
+ * protobuf_c_data_buffer_parse_string0:
+ * @buffer: buffer to read a line from.
+ *
+ * Parse a NUL-terminated line from
+ * buffer and return it as a newly allocated string.
+ *
+ * If the buffer does not contain a newline, then NULL is returned.
+ *
+ * returns: a newly allocated NUL-terminated string, or NULL.
+ */
+char *
+protobuf_c_data_buffer_parse_string0(ProtobufCDataBuffer *buffer)
+{
+  int index0 = protobuf_c_data_buffer_index_of (buffer, '\0');
+  char *rv;
+  if (index0 < 0)
+    return NULL;
+  rv = buffer->allocator->alloc (buffer->allocator, index0 + 1);
+  protobuf_c_data_buffer_read (buffer, rv, index0 + 1);
+  return rv;
+}
+
+/**
+ * protobuf_c_data_buffer_peek_char:
+ * @buffer: buffer to peek a single byte from.
+ *
+ * Get the first byte in the buffer as a positive or 0 number.
+ * If the buffer is empty, -1 is returned.
+ * The buffer is unchanged.
+ *
+ * returns: an unsigned character or -1.
+ */
+int
+protobuf_c_data_buffer_peek_char(const ProtobufCDataBuffer *buffer)
+{
+  const ProtobufCDataBufferFragment *frag;
+
+  if (buffer->size == 0)
+    return -1;
+
+  for (frag = buffer->first_frag; frag; frag = frag->next)
+    if (frag->buf_length > 0)
+      break;
+  return * protobuf_c_data_buffer_fragment_start ((ProtobufCDataBufferFragment*)frag);
+}
+
+/**
+ * protobuf_c_data_buffer_read_char:
+ * @buffer: buffer to read a single byte from.
+ *
+ * Get the first byte in the buffer as a positive or 0 number,
+ * and remove the character from the buffer.
+ * If the buffer is empty, -1 is returned.
+ *
+ * returns: an unsigned character or -1.
+ */
+int
+protobuf_c_data_buffer_read_char (ProtobufCDataBuffer *buffer)
+{
+  char c;
+  if (protobuf_c_data_buffer_read (buffer, &c, 1) == 0)
+    return -1;
+  return (int) (uint8_t) c;
+}
+
+/**
+ * protobuf_c_data_buffer_discard:
+ * @buffer: the buffer to discard data from.
+ * @max_discard: maximum number of bytes to discard.
+ *
+ * Removes up to @max_discard data from the beginning of the buffer,
+ * and returns the number of bytes actually discarded.
+ *
+ * returns: number of bytes discarded.
+ */
+size_t
+protobuf_c_data_buffer_discard(ProtobufCDataBuffer *buffer,
+                   size_t      max_discard)
+{
+  int rv = 0;
+  CHECK_INTEGRITY (buffer);
+  while (max_discard > 0 && buffer->first_frag)
+    {
+      ProtobufCDataBufferFragment *first = buffer->first_frag;
+      if (first->buf_length <= max_discard)
+       {
+         rv += first->buf_length;
+         max_discard -= first->buf_length;
+         buffer->first_frag = first->next;
+         if (!buffer->first_frag)
+           buffer->last_frag = NULL;
+         recycle (buffer->allocator, first);
+       }
+      else
+       {
+         rv += max_discard;
+         first->buf_length -= max_discard;
+         first->buf_start += max_discard;
+         max_discard = 0;
+       }
+    }
+  buffer->size -= rv;
+  CHECK_INTEGRITY (buffer);
+  return rv;
+}
+
+static inline protobuf_c_boolean
+errno_is_ignorable (int e)
+{
+#ifdef EWOULDBLOCK              /* for windows */
+  if (e == EWOULDBLOCK)
+    return 1;
+#endif
+  return e == EINTR || e == EAGAIN;
+}
+
+/**
+ * protobuf_c_data_buffer_writev:
+ * @read_from: buffer to take data from.
+ * @fd: file-descriptor to write data to.
+ *
+ * Writes as much data as possible to the
+ * given file-descriptor using the writev(2)
+ * function to deal with multiple fragments
+ * efficiently, where available.
+ *
+ * returns: the number of bytes transferred,
+ * or -1 on a write error (consult errno).
+ */
+int
+protobuf_c_data_buffer_writev (ProtobufCDataBuffer       *read_from,
+                  int              fd)
+{
+  int rv;
+  struct iovec *iov;
+  int nfrag, i;
+  ProtobufCDataBufferFragment *frag_at = read_from->first_frag;
+  CHECK_INTEGRITY (read_from);
+  for (nfrag = 0; frag_at != NULL
+#ifdef MAX_FRAGMENTS_TO_WRITE
+       && nfrag < MAX_FRAGMENTS_TO_WRITE
+#endif
+       ; nfrag++)
+    frag_at = frag_at->next;
+  iov = (struct iovec *) alloca (sizeof (struct iovec) * nfrag);
+  frag_at = read_from->first_frag;
+  for (i = 0; i < nfrag; i++)
+    {
+      iov[i].iov_len = frag_at->buf_length;
+      iov[i].iov_base = protobuf_c_data_buffer_fragment_start (frag_at);
+      frag_at = frag_at->next;
+    }
+  rv = writev (fd, iov, nfrag);
+  if (rv < 0 && errno_is_ignorable (errno))
+    return 0;
+  if (rv <= 0)
+    return rv;
+  protobuf_c_data_buffer_discard (read_from, rv);
+  return rv;
+}
+
+/**
+ * protobuf_c_data_buffer_writev_len:
+ * @read_from: buffer to take data from.
+ * @fd: file-descriptor to write data to.
+ * @max_bytes: maximum number of bytes to write.
+ *
+ * Writes up to max_bytes bytes to the
+ * given file-descriptor using the writev(2)
+ * function to deal with multiple fragments
+ * efficiently, where available.
+ *
+ * returns: the number of bytes transferred,
+ * or -1 on a write error (consult errno).
+ */
+#undef MIN
+#define MIN(a,b)   ((a) < (b) ? (a) : (b))
+int
+protobuf_c_data_buffer_writev_len (ProtobufCDataBuffer *read_from,
+                      int        fd,
+                      size_t      max_bytes)
+{
+  int rv;
+  struct iovec *iov;
+  int nfrag, i;
+  size_t bytes;
+  ProtobufCDataBufferFragment *frag_at = read_from->first_frag;
+  CHECK_INTEGRITY (read_from);
+  for (nfrag = 0, bytes = 0; frag_at != NULL && bytes < max_bytes
+#ifdef MAX_FRAGMENTS_TO_WRITE
+       && nfrag < MAX_FRAGMENTS_TO_WRITE
+#endif
+       ; nfrag++)
+    {
+      bytes += frag_at->buf_length;
+      frag_at = frag_at->next;
+    }
+  iov = (struct iovec *) alloca (sizeof (struct iovec) * nfrag);
+  frag_at = read_from->first_frag;
+  for (bytes = max_bytes, i = 0; i < nfrag && bytes > 0; i++)
+    {
+      size_t frag_bytes = MIN (frag_at->buf_length, bytes);
+      iov[i].iov_len = frag_bytes;
+      iov[i].iov_base = protobuf_c_data_buffer_fragment_start (frag_at);
+      frag_at = frag_at->next;
+      bytes -= frag_bytes;
+    }
+  rv = writev (fd, iov, i);
+  if (rv < 0 && errno_is_ignorable (errno))
+    return 0;
+  if (rv <= 0)
+    return rv;
+  protobuf_c_data_buffer_discard (read_from, rv);
+  return rv;
+}
+
+/**
+ * protobuf_c_data_buffer_read_in_fd:
+ * @write_to: buffer to append data to.
+ * @read_from: file-descriptor to read data from.
+ *
+ * Append data into the buffer directly from the
+ * given file-descriptor.
+ *
+ * returns: the number of bytes transferred,
+ * or -1 on a read error (consult errno).
+ */
+/* TODO: zero-copy! */
+int
+protobuf_c_data_buffer_read_in_fd(ProtobufCDataBuffer *write_to,
+                      int        read_from)
+{
+  char buf[8192];
+  int rv = read (read_from, buf, sizeof (buf));
+  if (rv < 0)
+    return rv;
+  protobuf_c_data_buffer_append (write_to, buf, rv);
+  return rv;
+}
+
+/**
+ * protobuf_c_data_buffer_destruct:
+ * @to_destroy: the buffer to empty.
+ *
+ * Remove all fragments from a buffer, leaving it empty.
+ * The buffer is guaranteed to not to be consuming any resources,
+ * but it also is allowed to start using it again.
+ */
+void
+protobuf_c_data_buffer_reset(ProtobufCDataBuffer *to_destroy)
+{
+  ProtobufCDataBufferFragment *at = to_destroy->first_frag;
+  CHECK_INTEGRITY (to_destroy);
+  while (at)
+    {
+      ProtobufCDataBufferFragment *next = at->next;
+      recycle (to_destroy->allocator, at);
+      at = next;
+    }
+  to_destroy->first_frag = to_destroy->last_frag = NULL;
+  to_destroy->size = 0;
+}
+
+void
+protobuf_c_data_buffer_clear(ProtobufCDataBuffer *to_destroy)
+{
+  ProtobufCDataBufferFragment *at = to_destroy->first_frag;
+  CHECK_INTEGRITY (to_destroy);
+  while (at)
+    {
+      ProtobufCDataBufferFragment *next = at->next;
+      recycle (to_destroy->allocator, at);
+      at = next;
+    }
+}
+
+/**
+ * protobuf_c_data_buffer_index_of:
+ * @buffer: buffer to scan.
+ * @char_to_find: a byte to look for.
+ *
+ * Scans for the first instance of the given character.
+ * returns: its index in the buffer, or -1 if the character
+ * is not in the buffer.
+ */
+int
+protobuf_c_data_buffer_index_of(ProtobufCDataBuffer *buffer,
+                    char       char_to_find)
+{
+  ProtobufCDataBufferFragment *at = buffer->first_frag;
+  int rv = 0;
+  while (at)
+    {
+      uint8_t *start = protobuf_c_data_buffer_fragment_start (at);
+      uint8_t *saught = memchr (start, char_to_find, at->buf_length);
+      if (saught)
+       return (saught - start) + rv;
+      else
+       rv += at->buf_length;
+      at = at->next;
+    }
+  return -1;
+}
+
+/**
+ * protobuf_c_data_buffer_str_index_of:
+ * @buffer: buffer to scan.
+ * @str_to_find: a string to look for.
+ *
+ * Scans for the first instance of the given string.
+ * returns: its index in the buffer, or -1 if the string
+ * is not in the buffer.
+ */
+int 
+protobuf_c_data_buffer_str_index_of (ProtobufCDataBuffer *buffer,
+                         const char *str_to_find)
+{
+  ProtobufCDataBufferFragment *frag = buffer->first_frag;
+  size_t rv = 0;
+  for (frag = buffer->first_frag; frag; frag = frag->next)
+    {
+      const uint8_t *frag_at = PROTOBUF_C_FRAGMENT_DATA (frag);
+      size_t frag_rem = frag->buf_length;
+      while (frag_rem > 0)
+        {
+          ProtobufCDataBufferFragment *subfrag;
+          const uint8_t *subfrag_at;
+          size_t subfrag_rem;
+          const char *str_at;
+          if (*frag_at != str_to_find[0])
+            {
+              frag_at++;
+              frag_rem--;
+              rv++;
+              continue;
+            }
+          subfrag = frag;
+          subfrag_at = frag_at + 1;
+          subfrag_rem = frag_rem - 1;
+          str_at = str_to_find + 1;
+          if (*str_at == '\0')
+            return rv;
+          while (subfrag != NULL)
+            {
+              while (subfrag_rem == 0)
+                {
+                  subfrag = subfrag->next;
+                  if (subfrag == NULL)
+                    goto bad_guess;
+                  subfrag_at = protobuf_c_data_buffer_fragment_start (subfrag);
+                  subfrag_rem = subfrag->buf_length;
+                }
+              while (*str_at != '\0' && subfrag_rem != 0)
+                {
+                  if (*str_at++ != *subfrag_at++)
+                    goto bad_guess;
+                  subfrag_rem--;
+                }
+              if (*str_at == '\0')
+                return rv;
+            }
+bad_guess:
+          frag_at++;
+          frag_rem--;
+          rv++;
+        }
+    }
+  return -1;
+}
+
+/**
+ * protobuf_c_data_buffer_drain:
+ * @dst: buffer to add to.
+ * @src: buffer to remove from.
+ *
+ * Transfer all data from @src to @dst,
+ * leaving @src empty.
+ *
+ * returns: the number of bytes transferred.
+ */
+#if GSK_DEBUG_BUFFER_ALLOCATIONS
+size_t
+protobuf_c_data_buffer_drain (ProtobufCDataBuffer *dst,
+                 ProtobufCDataBuffer *src)
+{
+  size_t rv = src->size;
+  ProtobufCDataBufferFragment *frag;
+  CHECK_INTEGRITY (dst);
+  CHECK_INTEGRITY (src);
+  for (frag = src->first_frag; frag; frag = frag->next)
+    protobuf_c_data_buffer_append (dst,
+                       protobuf_c_data_buffer_fragment_start (frag),
+                       frag->buf_length);
+  protobuf_c_data_buffer_discard (src, src->size);
+  CHECK_INTEGRITY (dst);
+  CHECK_INTEGRITY (src);
+  return rv;
+}
+#else  /* optimized */
+size_t
+protobuf_c_data_buffer_drain (ProtobufCDataBuffer *dst,
+                 ProtobufCDataBuffer *src)
+{
+  size_t rv = src->size;
+
+  CHECK_INTEGRITY (dst);
+  CHECK_INTEGRITY (src);
+  if (src->first_frag == NULL)
+    return rv;
+
+  dst->size += src->size;
+
+  if (dst->last_frag != NULL)
+    {
+      dst->last_frag->next = src->first_frag;
+      dst->last_frag = src->last_frag;
+    }
+  else
+    {
+      dst->first_frag = src->first_frag;
+      dst->last_frag = src->last_frag;
+    }
+  src->size = 0;
+  src->first_frag = src->last_frag = NULL;
+  CHECK_INTEGRITY (dst);
+  return rv;
+}
+#endif
+
+/**
+ * protobuf_c_data_buffer_transfer:
+ * @dst: place to copy data into.
+ * @src: place to read data from.
+ * @max_transfer: maximum number of bytes to transfer.
+ *
+ * Transfer data out of @src and into @dst.
+ * Data is removed from @src.  The number of bytes
+ * transferred is returned.
+ *
+ * returns: the number of bytes transferred.
+ */
+#if GSK_DEBUG_BUFFER_ALLOCATIONS
+size_t
+protobuf_c_data_buffer_transfer(ProtobufCDataBuffer *dst,
+                   ProtobufCDataBuffer *src,
+                   size_t max_transfer)
+{
+  size_t rv = 0;
+  ProtobufCDataBufferFragment *frag;
+  CHECK_INTEGRITY (dst);
+  CHECK_INTEGRITY (src);
+  for (frag = src->first_frag; frag && max_transfer > 0; frag = frag->next)
+    {
+      size_t len = frag->buf_length;
+      if (len >= max_transfer)
+        {
+          protobuf_c_data_buffer_append (dst, protobuf_c_data_buffer_fragment_start (frag), max_transfer);
+          rv += max_transfer;
+          break;
+        }
+      else
+        {
+          protobuf_c_data_buffer_append (dst, protobuf_c_data_buffer_fragment_start (frag), len);
+          rv += len;
+          max_transfer -= len;
+        }
+    }
+  protobuf_c_data_buffer_discard (src, rv);
+  CHECK_INTEGRITY (dst);
+  CHECK_INTEGRITY (src);
+  return rv;
+}
+#else  /* optimized */
+size_t
+protobuf_c_data_buffer_transfer(ProtobufCDataBuffer *dst,
+                   ProtobufCDataBuffer *src,
+                   size_t max_transfer)
+{
+  size_t rv = 0;
+  CHECK_INTEGRITY (dst);
+  CHECK_INTEGRITY (src);
+  while (src->first_frag && max_transfer >= src->first_frag->buf_length)
+    {
+      ProtobufCDataBufferFragment *frag = src->first_frag;
+      src->first_frag = frag->next;
+      frag->next = NULL;
+      if (src->first_frag == NULL)
+       src->last_frag = NULL;
+
+      if (dst->last_frag)
+       dst->last_frag->next = frag;
+      else
+       dst->first_frag = frag;
+      dst->last_frag = frag;
+
+      rv += frag->buf_length;
+      max_transfer -= frag->buf_length;
+    }
+  dst->size += rv;
+  if (src->first_frag && max_transfer)
+    {
+      ProtobufCDataBufferFragment *frag = src->first_frag;
+      protobuf_c_data_buffer_append (dst, protobuf_c_data_buffer_fragment_start (frag), max_transfer);
+      frag->buf_start += max_transfer;
+      frag->buf_length -= max_transfer;
+      rv += max_transfer;
+    }
+  src->size -= rv;
+  CHECK_INTEGRITY (dst);
+  CHECK_INTEGRITY (src);
+  return rv;
+}
+#endif /* !GSK_DEBUG_BUFFER_ALLOCATIONS */
+
+#if 0
+/**
+ * protobuf_c_data_buffer_printf:
+ * @buffer: the buffer to append to.
+ * @format: printf-style format string describing what to append to buffer.
+ * @Varargs: values referenced by @format string.
+ *
+ * Append printf-style content to a buffer.
+ */
+void     protobuf_c_data_buffer_printf              (ProtobufCDataBuffer    *buffer,
+                                        const char   *format,
+                                        ...)
+{
+  va_list args;
+  va_start (args, format);
+  protobuf_c_data_buffer_vprintf (buffer, format, args);
+  va_end (args);
+}
+
+/**
+ * protobuf_c_data_buffer_vprintf:
+ * @buffer: the buffer to append to.
+ * @format: printf-style format string describing what to append to buffer.
+ * @args: values referenced by @format string.
+ *
+ * Append printf-style content to a buffer, given a va_list.
+ */
+void     protobuf_c_data_buffer_vprintf             (ProtobufCDataBuffer    *buffer,
+                                        const char   *format,
+                                        va_list       args)
+{
+  gsize size = g_printf_string_upper_bound (format, args);
+  if (size < 1024)
+    {
+      char buf[1024];
+      g_vsnprintf (buf, sizeof (buf), format, args);
+      protobuf_c_data_buffer_append_string (buffer, buf);
+    }
+  else
+    {
+      char *buf = g_strdup_vprintf (format, args);
+      protobuf_c_data_buffer_append_foreign (buffer, buf, strlen (buf), g_free, buf);
+    }
+}
+
+/* --- protobuf_c_data_buffer_polystr_index_of implementation --- */
+/* Test to see if a sequence of buffer fragments
+ * starts with a particular NUL-terminated string.
+ */
+static gboolean
+fragment_n_str(ProtobufCDataBufferFragment   *frag,
+               size_t                frag_index,
+               const char          *string)
+{
+  size_t len = strlen (string);
+  for (;;)
+    {
+      size_t test_len = frag->buf_length - frag_index;
+      if (test_len > len)
+        test_len = len;
+
+      if (memcmp (string,
+                  protobuf_c_data_buffer_fragment_start (frag) + frag_index,
+                  test_len) != 0)
+        return FALSE;
+
+      len -= test_len;
+      string += test_len;
+
+      if (len <= 0)
+        return TRUE;
+      frag_index += test_len;
+      if (frag_index >= frag->buf_length)
+        {
+          frag = frag->next;
+          if (frag == NULL)
+            return FALSE;
+        }
+    }
+}
+
+/**
+ * protobuf_c_data_buffer_polystr_index_of:
+ * @buffer: buffer to scan.
+ * @strings: NULL-terminated set of string.
+ *
+ * Scans for the first instance of any of the strings
+ * in the buffer.
+ *
+ * returns: the index of that instance, or -1 if not found.
+ */
+int     
+protobuf_c_data_buffer_polystr_index_of    (ProtobufCDataBuffer    *buffer,
+                                char        **strings)
+{
+  uint8_t init_char_map[16];
+  int num_strings;
+  int num_bits = 0;
+  int total_index = 0;
+  ProtobufCDataBufferFragment *frag;
+  memset (init_char_map, 0, sizeof (init_char_map));
+  for (num_strings = 0; strings[num_strings] != NULL; num_strings++)
+    {
+      uint8_t c = strings[num_strings][0];
+      uint8_t mask = (1 << (c % 8));
+      uint8_t *rack = init_char_map + (c / 8);
+      if ((*rack & mask) == 0)
+        {
+          *rack |= mask;
+          num_bits++;
+        }
+    }
+  if (num_bits == 0)
+    return 0;
+  for (frag = buffer->first_frag; frag != NULL; frag = frag->next)
+    {
+      const char *frag_start;
+      const char *at;
+      int remaining = frag->buf_length;
+      frag_start = protobuf_c_data_buffer_fragment_start (frag);
+      at = frag_start;
+      while (at != NULL)
+        {
+          const char *start = at;
+          if (num_bits == 1)
+            {
+              at = memchr (start, strings[0][0], remaining);
+              if (at == NULL)
+                remaining = 0;
+              else
+                remaining -= (at - start);
+            }
+          else
+            {
+              while (remaining > 0)
+                {
+                  uint8_t i = (uint8_t) (*at);
+                  if (init_char_map[i / 8] & (1 << (i % 8)))
+                    break;
+                  remaining--;
+                  at++;
+                }
+              if (remaining == 0)
+                at = NULL;
+            }
+
+          if (at == NULL)
+            break;
+
+          /* Now test each of the strings manually. */
+          {
+            char **test;
+            for (test = strings; *test != NULL; test++)
+              {
+                if (fragment_n_str(frag, at - frag_start, *test))
+                  return total_index + (at - frag_start);
+              }
+            at++;
+          }
+        }
+      total_index += frag->buf_length;
+    }
+  return -1;
+}
+#endif
+
diff --git a/src/google/protobuf-c/protobuf-c-data-buffer.h b/src/google/protobuf-c/protobuf-c-data-buffer.h
new file mode 100644 (file)
index 0000000..a4c22e5
--- /dev/null
@@ -0,0 +1,104 @@
+
+#ifndef __PROTOBUF_C_DATA_BUFFER_H_
+#define __PROTOBUF_C_DATA_BUFFER_H_
+
+#include "protobuf-c.h"
+#include <stdarg.h>
+
+
+typedef struct _ProtobufCDataBuffer ProtobufCDataBuffer;
+typedef struct _ProtobufCDataBufferFragment ProtobufCDataBufferFragment;
+
+struct _ProtobufCDataBufferFragment
+{
+  ProtobufCDataBufferFragment *next;
+  unsigned buf_start;  /* offset in buf of valid data */
+  unsigned buf_length; /* length of valid data in buf */
+};
+
+struct _ProtobufCDataBuffer
+{
+  size_t size;
+
+  ProtobufCDataBufferFragment    *first_frag;
+  ProtobufCDataBufferFragment    *last_frag;
+  ProtobufCAllocator *allocator;
+};
+
+void     protobuf_c_data_buffer_init                (ProtobufCDataBuffer       *buffer,
+                                                     ProtobufCAllocator    *allocator);
+void     protobuf_c_data_buffer_clear               (ProtobufCDataBuffer       *buffer);
+void     protobuf_c_data_buffer_reset               (ProtobufCDataBuffer       *buffer);
+
+size_t   protobuf_c_data_buffer_read                (ProtobufCDataBuffer    *buffer,
+                                                     void*      data,
+                                                     size_t         max_length);
+size_t   protobuf_c_data_buffer_peek                (const ProtobufCDataBuffer* buffer,
+                                                     void*      data,
+                                                     size_t        max_length);
+size_t   protobuf_c_data_buffer_discard             (ProtobufCDataBuffer    *buffer,
+                                                     size_t        max_discard);
+char    *protobuf_c_data_buffer_read_line           (ProtobufCDataBuffer    *buffer);
+
+char    *protobuf_c_data_buffer_parse_string0       (ProtobufCDataBuffer    *buffer);
+                        /* Returns first char of buffer, or -1. */
+int      protobuf_c_data_buffer_peek_char           (const ProtobufCDataBuffer *buffer);
+int      protobuf_c_data_buffer_read_char           (ProtobufCDataBuffer    *buffer);
+
+int      protobuf_c_data_buffer_index_of(ProtobufCDataBuffer *buffer,
+                                         char       char_to_find);
+/* 
+ * Appending to the buffer.
+ */
+void     protobuf_c_data_buffer_append              (ProtobufCDataBuffer    *buffer, 
+                                         const void   *data,
+                                         size_t        length);
+void     protobuf_c_data_buffer_append_string       (ProtobufCDataBuffer    *buffer, 
+                                         const char   *string);
+void     protobuf_c_data_buffer_append_char         (ProtobufCDataBuffer    *buffer, 
+                                         char          character);
+void     protobuf_c_data_buffer_append_repeated_char(ProtobufCDataBuffer    *buffer, 
+                                         char          character,
+                                         size_t        count);
+#define protobuf_c_data_buffer_append_zeros(buffer, count) \
+  protobuf_c_data_buffer_append_repeated_char ((buffer), 0, (count))
+
+/* XXX: protobuf_c_data_buffer_append_repeated_data() is UNIMPLEMENTED */
+void     protobuf_c_data_buffer_append_repeated_data(ProtobufCDataBuffer    *buffer, 
+                                         const void   *data_to_repeat,
+                                         size_t        data_length,
+                                         size_t        count);
+
+
+void     protobuf_c_data_buffer_append_string0      (ProtobufCDataBuffer    *buffer,
+                                         const char   *string);
+
+
+/* Take all the contents from src and append
+ * them to dst, leaving src empty.
+ */
+size_t   protobuf_c_data_buffer_drain               (ProtobufCDataBuffer    *dst,
+                                         ProtobufCDataBuffer    *src);
+
+/* Like `drain', but only transfers some of the data. */
+size_t   protobuf_c_data_buffer_transfer            (ProtobufCDataBuffer    *dst,
+                                          ProtobufCDataBuffer    *src,
+                                        size_t        max_transfer);
+
+/* file-descriptor mucking */
+int      protobuf_c_data_buffer_writev              (ProtobufCDataBuffer       *read_from,
+                                         int              fd);
+int      protobuf_c_data_buffer_writev_len          (ProtobufCDataBuffer       *read_from,
+                                         int              fd,
+                                        size_t           max_bytes);
+int      protobuf_c_data_buffer_read_in_fd          (ProtobufCDataBuffer       *write_to,
+                                         int              read_from);
+
+/* This deallocates memory used by the buffer-- you are responsible
+ * for the allocation and deallocation of the ProtobufCDataBuffer itself. */
+void     protobuf_c_data_buffer_destruct            (ProtobufCDataBuffer    *to_destroy);
+
+/* Free all unused buffer fragments. */
+void     protobuf_c_data_buffer_cleanup_recycling_bin ();
+
+#endif
diff --git a/src/google/protobuf-c/protobuf-c-private.h b/src/google/protobuf-c/protobuf-c-private.h
new file mode 100644 (file)
index 0000000..01bbd35
--- /dev/null
@@ -0,0 +1,72 @@
+/* --- protobuf-c-private.h: private structures and functions --- */
+/*
+ * Copyright 2008, Dave Benson.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License
+ * at http://www.apache.org/licenses/LICENSE-2.0 Unless
+ * required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+/* === needs to be declared for the PROTOBUF_C_BUFFER_SIMPLE_INIT macro === */
+
+void protobuf_c_buffer_simple_append (ProtobufCBuffer *buffer,
+                                      size_t           len,
+                                      const unsigned char *data);
+
+/* === stuff which needs to be declared for use in the generated code === */
+
+struct _ProtobufCEnumValueIndex
+{
+  const char *name;
+  unsigned index;               /* into values[] array */
+};
+
+/* IntRange: helper structure for optimizing
+     int => index lookups
+   in the case where the keys are mostly consecutive values,
+   as they presumably are for enums and fields.
+
+   The data structures assumes that the values in the original
+   array are sorted */
+struct _ProtobufCIntRange
+{
+  int start_value;
+  unsigned orig_index;
+  /* NOTE: the number of values in the range can
+     be inferred by looking at the next element's orig_index.
+     a dummy element is added to make this simple */
+};
+
+
+/* === declared for exposition on ProtobufCIntRange === */
+/* note: ranges must have an extra sentinel IntRange at the end whose
+   orig_index is set to the number of actual values in the original array */
+/* returns -1 if no orig_index found */
+int protobuf_c_int_ranges_lookup (unsigned n_ranges,
+                                  ProtobufCIntRange *ranges);
+
+#define PROTOBUF_C_SERVICE_DESCRIPTOR_MAGIC  0x14159bc3
+#define PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC  0x28aaeef9
+#define PROTOBUF_C_ENUM_DESCRIPTOR_MAGIC     0x114315af
+
+/* === behind the scenes on the generated service's __init functions */
+typedef void (*ProtobufCServiceDestroy) (ProtobufCService *service);
+void
+protobuf_c_service_generated_init (ProtobufCService *service,
+                                   const ProtobufCServiceDescriptor *descriptor,
+                                   ProtobufCServiceDestroy destroy);
+
+void 
+protobuf_c_service_invoke_internal(ProtobufCService *service,
+                                  unsigned          method_index,
+                                  const ProtobufCMessage *input,
+                                  ProtobufCClosure  closure,
+                                  void             *closure_data);
diff --git a/src/google/protobuf-c/protobuf-c.c b/src/google/protobuf-c/protobuf-c.c
new file mode 100644 (file)
index 0000000..a7e765d
--- /dev/null
@@ -0,0 +1,1934 @@
+/* --- protobuf-c.c: public protobuf c runtime implementation --- */
+
+/*
+ * Copyright 2008, Dave Benson.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License
+ * at http://www.apache.org/licenses/LICENSE-2.0 Unless
+ * required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* TODO: certain implementations use 32-bit math even for
+   (uint64_size, uint64_pack, parse_uint64) */
+
+/* TODO: get_packed_size and pack seem to use type-prefixed names,
+   whereas parse uses type-suffixed names.  pick one and stick with it.
+      Decision:  go with type-suffixed, since the type (or its instance)
+      is typically the object of the verb.
+   NOTE: perhaps the "parse" methods should be reanemd to "unpack"
+   at the same time.
+ */
+
+#include <stdio.h>                      /* for occasional printf()s */
+#include <stdlib.h>                     /* for abort(), malloc() etc */
+#include <string.h>                     /* for strlen(), memcpy(), memmove() */
+
+#ifndef PRINT_UNPACK_ERRORS
+#define PRINT_UNPACK_ERRORS              1
+#endif
+
+#include "protobuf-c.h"
+
+#define MAX_UINT64_ENCODED_SIZE 10
+
+/* convenience macros */
+#define TMPALLOC(allocator, size) ((allocator)->tmp_alloc ((allocator)->allocator_data, (size)))
+#define FREE(allocator, ptr)   \
+   do { if ((ptr) != NULL) ((allocator)->free ((allocator)->allocator_data, (ptr))); } while(0)
+#define UNALIGNED_ALLOC(allocator, size) ALLOC (allocator, size) /* placeholder */
+#define STRUCT_MEMBER_P(struct_p, struct_offset)   \
+    ((void *) ((uint8_t*) (struct_p) + (struct_offset)))
+#define STRUCT_MEMBER(member_type, struct_p, struct_offset)   \
+    (*(member_type*) STRUCT_MEMBER_P ((struct_p), (struct_offset)))
+#define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset)   \
+    ((member_type*) STRUCT_MEMBER_P ((struct_p), (struct_offset)))
+#define TRUE 1
+#define FALSE 0
+
+static void
+alloc_failed_warning (unsigned size, const char *filename, unsigned line)
+{
+  fprintf (stderr,
+           "WARNING: out-of-memory allocating a block of size %u (%s:%u)\n",
+           size, filename, line);
+}
+
+/* Try to allocate memory, running some special code if it fails. */
+#define DO_ALLOC(dst, allocator, size, fail_code)                           \
+{ size_t da__allocation_size = (size);                                      \
+  if (da__allocation_size == 0)                                             \
+    dst = NULL;                                                             \
+  else if ((dst=((allocator)->alloc ((allocator)->allocator_data,           \
+                                     da__allocation_size))) == NULL)        \
+    {                                                                       \
+      alloc_failed_warning (da__allocation_size, __FILE__, __LINE__);       \
+      fail_code;                                                            \
+    }                                                                       \
+}
+#define DO_UNALIGNED_ALLOC  DO_ALLOC            /* placeholder */
+
+
+
+#define ASSERT_IS_ENUM_DESCRIPTOR(desc) \
+  assert((desc)->magic == PROTOBUF_C_ENUM_DESCRIPTOR_MAGIC)
+#define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \
+  assert((desc)->magic == PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC)
+#define ASSERT_IS_MESSAGE(message) \
+  ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor)
+#define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \
+  assert((desc)->magic == PROTOBUF_C_SERVICE_DESCRIPTOR_MAGIC)
+
+/* --- allocator --- */
+
+static void protobuf_c_out_of_memory_default (void)
+{
+  fprintf (stderr, "Out Of Memory!!!\n");
+  abort ();
+}
+void (*protobuf_c_out_of_memory) (void) = protobuf_c_out_of_memory_default;
+
+static void *system_alloc(void *allocator_data, size_t size)
+{
+  void *rv;
+  (void) allocator_data;
+  if (size == 0)
+    return NULL;
+  rv = malloc (size);
+  if (rv == NULL)
+    protobuf_c_out_of_memory ();
+  return rv;
+}
+
+static void system_free (void *allocator_data, void *data)
+{
+  (void) allocator_data;
+  if (data)
+    free (data);
+}
+
+ProtobufCAllocator protobuf_c_default_allocator =
+{
+  system_alloc,
+  system_free,
+  NULL,
+  8192,
+  NULL
+};
+
+ProtobufCAllocator protobuf_c_system_allocator =
+{
+  system_alloc,
+  system_free,
+  NULL,
+  8192,
+  NULL
+};
+
+/* === buffer-simple === */
+void
+protobuf_c_buffer_simple_append (ProtobufCBuffer *buffer,
+                                 size_t           len,
+                                 const uint8_t   *data)
+{
+  ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer;
+  size_t new_len = simp->len + len;
+  if (new_len > simp->alloced)
+    {
+      size_t new_alloced = simp->alloced * 2;
+      uint8_t *new_data;
+      while (new_alloced < new_len)
+        new_alloced += new_alloced;
+      DO_ALLOC (new_data, &protobuf_c_default_allocator, new_alloced, return);
+      memcpy (new_data, simp->data, simp->len);
+      if (simp->must_free_data)
+        FREE (&protobuf_c_default_allocator, simp->data);
+      else
+        simp->must_free_data = 1;
+      simp->data = new_data;
+      simp->alloced = new_alloced;
+    }
+  memcpy (simp->data + simp->len, data, len);
+  simp->len = new_len;
+}
+
+/* === get_packed_size() === */
+
+/* Return the number of bytes required to store the
+   tag for the field (which includes 3 bits for
+   the wire-type, and a single bit that denotes the end-of-tag. */
+static inline size_t
+get_tag_size (unsigned number)
+{
+  if (number < (1<<4))
+    return 1;
+  else if (number < (1<<11))
+    return 2;
+  else if (number < (1<<18))
+    return 3;
+  else if (number < (1<<25))
+    return 4;
+  else
+    return 5;
+}
+
+/* Return the number of bytes required to store
+   a variable-length unsigned integer that fits in 32-bit uint
+   in base-128 encoding. */
+static inline size_t
+uint32_size (uint32_t v)
+{
+  if (v < (1<<7))
+    return 1;
+  else if (v < (1<<14))
+    return 2;
+  else if (v < (1<<21))
+    return 3;
+  else if (v < (1<<28))
+    return 4;
+  else
+    return 5;
+}
+/* Return the number of bytes required to store
+   a variable-length signed integer that fits in 32-bit int
+   in base-128 encoding. */
+static inline size_t
+int32_size (int32_t v)
+{
+  if (v < 0)
+    return 10;
+  else if (v < (1<<7))
+    return 1;
+  else if (v < (1<<14))
+    return 2;
+  else if (v < (1<<21))
+    return 3;
+  else if (v < (1<<28))
+    return 4;
+  else
+    return 5;
+}
+/* return the zigzag-encoded 32-bit unsigned int from a 32-bit signed int */
+static inline uint32_t
+zigzag32 (int32_t v)
+{
+  if (v < 0)
+    return ((uint32_t)(-v)) * 2 - 1;
+  else
+    return v * 2;
+}
+/* Return the number of bytes required to store
+   a variable-length signed integer that fits in 32-bit int,
+   converted to unsigned via the zig-zag algorithm,
+   then packed using base-128 encoding. */
+static inline size_t
+sint32_size (int32_t v)
+{
+  return uint32_size(zigzag32(v));
+}
+
+/* Return the number of bytes required to store
+   a variable-length unsigned integer that fits in 64-bit uint
+   in base-128 encoding. */
+static inline size_t
+uint64_size (uint64_t v)
+{
+  uint32_t upper_v = (v>>32);
+  if (upper_v == 0)
+    return uint32_size ((uint32_t)v);
+  else if (upper_v < (1<<3))
+    return 5;
+  else if (upper_v < (1<<10))
+    return 6;
+  else if (upper_v < (1<<17))
+    return 7;
+  else if (upper_v < (1<<24))
+    return 8;
+  else if (upper_v < (1U<<31))
+    return 9;
+  else
+    return 10;
+}
+
+/* return the zigzag-encoded 64-bit unsigned int from a 64-bit signed int */
+static inline uint64_t
+zigzag64 (int64_t v)
+{
+  if (v < 0)
+    return ((uint64_t)(-v)) * 2 - 1;
+  else
+    return v * 2;
+}
+
+/* Return the number of bytes required to store
+   a variable-length signed integer that fits in 64-bit int,
+   converted to unsigned via the zig-zag algorithm,
+   then packed using base-128 encoding. */
+static inline size_t
+sint64_size (int64_t v)
+{
+  return uint64_size(zigzag64(v));
+}
+
+/* Get serialized size of a single field in the message,
+   including the space needed by the identifying tag. */
+static size_t
+required_field_get_packed_size (const ProtobufCFieldDescriptor *field,
+                                const void *member)
+{
+  size_t rv = get_tag_size (field->id);
+  switch (field->type)
+    {
+    case PROTOBUF_C_TYPE_SINT32:
+      return rv + sint32_size (*(const int32_t *) member);
+    case PROTOBUF_C_TYPE_INT32:
+      return rv + int32_size (*(const uint32_t *) member);
+    case PROTOBUF_C_TYPE_UINT32:
+      return rv + uint32_size (*(const uint32_t *) member);
+    case PROTOBUF_C_TYPE_SINT64:
+      return rv + sint64_size (*(const int64_t *) member);
+    case PROTOBUF_C_TYPE_INT64:
+    case PROTOBUF_C_TYPE_UINT64:
+      return rv + uint64_size (*(const uint64_t *) member);
+    case PROTOBUF_C_TYPE_SFIXED32:
+    case PROTOBUF_C_TYPE_FIXED32:
+      return rv + 4;
+    case PROTOBUF_C_TYPE_SFIXED64:
+    case PROTOBUF_C_TYPE_FIXED64:
+      return rv + 8;
+    case PROTOBUF_C_TYPE_BOOL:
+      return rv + 1;
+    case PROTOBUF_C_TYPE_FLOAT:
+      return rv + 4;
+    case PROTOBUF_C_TYPE_DOUBLE:
+      return rv + 8;
+    case PROTOBUF_C_TYPE_ENUM:
+      // TODO: is this correct for negative-valued enums?
+      return rv + uint32_size (*(const uint32_t *) member);
+    case PROTOBUF_C_TYPE_STRING:
+      {
+        const char *str = *(char * const *) member;
+        size_t len = str ? strlen (str) : 0;
+        return rv + uint32_size (len) + len;
+      }
+    case PROTOBUF_C_TYPE_BYTES:
+      {
+        size_t len = ((const ProtobufCBinaryData*) member)->len;
+        return rv + uint32_size (len) + len;
+      }
+    //case PROTOBUF_C_TYPE_GROUP:
+    case PROTOBUF_C_TYPE_MESSAGE:
+      {
+        const ProtobufCMessage *msg = * (ProtobufCMessage * const *) member;
+        size_t subrv = msg ? protobuf_c_message_get_packed_size (msg) : 0;
+        return rv + uint32_size (subrv) + subrv;
+      }
+    }
+  PROTOBUF_C_ASSERT_NOT_REACHED ();
+  return 0;
+}
+
+/* Get serialized size of a single optional field in the message,
+   including the space needed by the identifying tag.
+   Returns 0 if the optional field isn't set. */
+static size_t
+optional_field_get_packed_size (const ProtobufCFieldDescriptor *field,
+                                const protobuf_c_boolean *has,
+                                const void *member)
+{
+  if (field->type == PROTOBUF_C_TYPE_MESSAGE
+   || field->type == PROTOBUF_C_TYPE_STRING)
+    {
+      const void *ptr = * (const void * const *) member;
+      if (ptr == NULL
+       || ptr == field->default_value)
+        return 0;
+    }
+  else
+    {
+      if (!*has)
+        return 0;
+    }
+  return required_field_get_packed_size (field, member);
+}
+
+/* Get serialized size of a repeated field in the message,
+   which may consist of any number of values (including 0).
+   Includes the space needed by the identifying tags (as needed). */
+static size_t
+repeated_field_get_packed_size (const ProtobufCFieldDescriptor *field,
+                                size_t count,
+                                const void *member)
+{
+  size_t rv = get_tag_size (field->id) * count;
+  unsigned i;
+  void *array = * (void * const *) member;
+  switch (field->type)
+    {
+    case PROTOBUF_C_TYPE_SINT32:
+      for (i = 0; i < count; i++)
+        rv += sint32_size (((int32_t*)array)[i]);
+      break;
+    case PROTOBUF_C_TYPE_INT32:
+      for (i = 0; i < count; i++)
+        rv += int32_size (((uint32_t*)array)[i]);
+      break;
+    case PROTOBUF_C_TYPE_UINT32:
+    case PROTOBUF_C_TYPE_ENUM:
+      for (i = 0; i < count; i++)
+        rv += uint32_size (((uint32_t*)array)[i]);
+      break;
+    case PROTOBUF_C_TYPE_SINT64:
+      for (i = 0; i < count; i++)
+        rv += sint64_size (((int64_t*)array)[i]);
+      break;
+    case PROTOBUF_C_TYPE_INT64:
+    case PROTOBUF_C_TYPE_UINT64:
+      for (i = 0; i < count; i++)
+        rv += uint64_size (((uint64_t*)array)[i]);
+      break;
+    case PROTOBUF_C_TYPE_SFIXED32:
+    case PROTOBUF_C_TYPE_FIXED32:
+    case PROTOBUF_C_TYPE_FLOAT:
+      rv += 4 * count;
+      break;
+    case PROTOBUF_C_TYPE_SFIXED64:
+    case PROTOBUF_C_TYPE_FIXED64:
+    case PROTOBUF_C_TYPE_DOUBLE:
+      rv += 8 * count;
+      break;
+    case PROTOBUF_C_TYPE_BOOL:
+      rv += count;
+      break;
+    case PROTOBUF_C_TYPE_STRING:
+      for (i = 0; i < count; i++)
+        {
+          size_t len = strlen (((char**) array)[i]);
+          rv += uint32_size (len) + len;
+        }
+      break;
+      
+    case PROTOBUF_C_TYPE_BYTES:
+      for (i = 0; i < count; i++)
+        {
+          size_t len = ((ProtobufCBinaryData*) array)[i].len;
+          rv += uint32_size (len) + len;
+        }
+      break;
+    case PROTOBUF_C_TYPE_MESSAGE:
+      for (i = 0; i < count; i++)
+        {
+          size_t len = protobuf_c_message_get_packed_size (((ProtobufCMessage **) array)[i]);
+          rv += uint32_size (len) + len;
+        }
+      break;
+    //case PROTOBUF_C_TYPE_GROUP:          // NOT SUPPORTED
+    }
+  return rv;
+}
+
+/* Get the packed size of a unknown field (meaning one that
+   is passed through mostly uninterpreted... this is done
+   for forward compatibilty with the addition of new fields). */
+static inline size_t
+unknown_field_get_packed_size (const ProtobufCMessageUnknownField *field)
+{
+  return get_tag_size (field->tag) + field->len;
+}
+
+/* Get the number of bytes that the message will occupy once serialized. */
+size_t
+protobuf_c_message_get_packed_size(const ProtobufCMessage *message)
+{
+  unsigned i;
+  size_t rv = 0;
+  ASSERT_IS_MESSAGE (message);
+  for (i = 0; i < message->descriptor->n_fields; i++)
+    {
+      const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
+      const void *member = ((const char *) message) + field->offset;
+      const void *qmember = ((const char *) message) + field->quantifier_offset;
+
+      if (field->label == PROTOBUF_C_LABEL_REQUIRED)
+        rv += required_field_get_packed_size (field, member);
+      else if (field->label == PROTOBUF_C_LABEL_OPTIONAL)
+        rv += optional_field_get_packed_size (field, qmember, member);
+      else
+        rv += repeated_field_get_packed_size (field, * (const size_t *) qmember, member);
+    }
+  for (i = 0; i < message->n_unknown_fields; i++)
+    rv += unknown_field_get_packed_size (&message->unknown_fields[i]);
+
+  return rv;
+}
+/* === pack() === */
+/* Pack an unsigned 32-bit integer in base-128 encoding, and return the number of bytes needed:
+   this will be 5 or less. */
+static inline size_t
+uint32_pack (uint32_t value, uint8_t *out)
+{
+  unsigned rv = 0;
+  if (value >= 0x80)
+    {
+      out[rv++] = value | 0x80;
+      value >>= 7;
+      if (value >= 0x80)
+        {
+          out[rv++] = value | 0x80;
+          value >>= 7;
+          if (value >= 0x80)
+            {
+              out[rv++] = value | 0x80;
+              value >>= 7;
+              if (value >= 0x80)
+                {
+                  out[rv++] = value | 0x80;
+                  value >>= 7;
+                }
+            }
+        }
+    }
+  /* assert: value<128 */
+  out[rv++] = value;
+  return rv;
+}
+
+/* Pack a 32-bit signed integer, returning the number of bytes needed.
+   Negative numbers are packed as twos-complement 64-bit integers. */
+static inline size_t
+int32_pack (int32_t value, uint8_t *out)
+{
+  if (value < 0)
+    {
+      out[0] = value | 0x80;
+      out[1] = (value>>7) | 0x80;
+      out[2] = (value>>14) | 0x80;
+      out[3] = (value>>21) | 0x80;
+      out[4] = (value>>28) | 0x80;
+      out[5] = out[6] = out[7] = out[8] = 0xff;
+      out[9] = 0x01;
+      return 10;
+    }
+  else
+    return uint32_pack (value, out);
+}
+
+/* Pack a 32-bit integer in zigwag encoding. */
+static inline size_t
+sint32_pack (int32_t value, uint8_t *out)
+{
+  return uint32_pack (zigzag32 (value), out);
+}
+
+/* Pack a 64-bit unsigned integer that fits in a 64-bit uint,
+   using base-128 encoding. */
+static size_t
+uint64_pack (uint64_t value, uint8_t *out)
+{
+  uint32_t hi = value>>32;
+  uint32_t lo = value;
+  unsigned rv;
+  if (hi == 0)
+    return uint32_pack ((uint32_t)lo, out);
+  out[0] = (lo) | 0x80;
+  out[1] = (lo>>7) | 0x80;
+  out[2] = (lo>>14) | 0x80;
+  out[3] = (lo>>21) | 0x80;
+  if (hi < 8)
+    {
+      out[4] = (hi<<4) | (lo>>28);
+      return 5;
+    }
+  else
+    {
+      out[4] = ((hi&7)<<4) | (lo>>28) | 0x80;
+      hi >>= 3;
+    }
+  rv = 5;
+  while (hi >= 128)
+    {
+      out[rv++] = hi | 0x80;
+      hi >>= 7;
+    }
+  out[rv++] = hi;
+  return rv;
+}
+
+/* Pack a 64-bit signed integer in zigzan encoding,
+   return the size of the packed output.
+   (Max returned value is 10) */
+static inline size_t
+sint64_pack (int64_t value, uint8_t *out)
+{
+  return uint64_pack (zigzag64 (value), out);
+}
+
+/* Pack a 32-bit value, little-endian.
+   Used for fixed32, sfixed32, float) */
+static inline size_t
+fixed32_pack (uint32_t value, uint8_t *out)
+{
+#if IS_LITTLE_ENDIAN
+  memcpy (out, &value, 4);
+#else
+  out[0] = value;
+  out[1] = value>>8;
+  out[2] = value>>16;
+  out[3] = value>>24;
+#endif
+  return 4;
+}
+
+static inline size_t
+fixed64_pack (uint64_t value, uint8_t *out)
+{
+#if IS_LITTLE_ENDIAN
+  memcpy (out, &value, 8);
+#else
+  fixed32_pack (value, out);
+  fixed32_pack (value>>32, out+4);
+#endif
+  return 8;
+}
+
+static inline size_t
+boolean_pack (protobuf_c_boolean value, uint8_t *out)
+{
+  *out = value ? 1 : 0;
+  return 1;
+}
+
+static inline size_t
+string_pack (const char * str, uint8_t *out)
+{
+  if (str == NULL)
+    {
+      out[0] = 0;
+      return 1;
+    }
+  else
+    {
+      size_t len = strlen (str);
+      size_t rv = uint32_pack (len, out);
+      memcpy (out + rv, str, len);
+      return rv + len;
+    }
+}
+
+static inline size_t
+binary_data_pack (const ProtobufCBinaryData *bd, uint8_t *out)
+{
+  size_t len = bd->len;
+  size_t rv = uint32_pack (len, out);
+  memcpy (out + rv, bd->data, len);
+  return rv + len;
+}
+
+static inline size_t
+prefixed_message_pack (const ProtobufCMessage *message, uint8_t *out)
+{
+  if (message == NULL)
+    {
+      out[0] = 0;
+      return 1;
+    }
+  else
+    {
+      size_t rv = protobuf_c_message_pack (message, out + 1);
+      uint32_t rv_packed_size = uint32_size (rv);
+      if (rv_packed_size != 1)
+        memmove (out + rv_packed_size, out + 1, rv);
+      return uint32_pack (rv, out) + rv;
+    }
+}
+
+/* wire-type will be added in required_field_pack() */
+static size_t tag_pack (uint32_t id, uint8_t *out)
+{
+  if (id < (1<<(32-3)))
+    return uint32_pack (id<<3, out);
+  else
+    return uint64_pack (((uint64_t)id) << 3, out);
+}
+static size_t
+required_field_pack (const ProtobufCFieldDescriptor *field,
+                     const void *member,
+                     uint8_t *out)
+{
+  size_t rv = tag_pack (field->id, out);
+  switch (field->type)
+    {
+    case PROTOBUF_C_TYPE_SINT32:
+      out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+      return rv + sint32_pack (*(const int32_t *) member, out + rv);
+    case PROTOBUF_C_TYPE_INT32:
+      out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+      return rv + int32_pack (*(const uint32_t *) member, out + rv);
+    case PROTOBUF_C_TYPE_UINT32:
+    case PROTOBUF_C_TYPE_ENUM:
+      out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+      return rv + uint32_pack (*(const uint32_t *) member, out + rv);
+    case PROTOBUF_C_TYPE_SINT64:
+      out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+      return rv + sint64_pack (*(const int64_t *) member, out + rv);
+    case PROTOBUF_C_TYPE_INT64:
+    case PROTOBUF_C_TYPE_UINT64:
+      out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+      return rv + uint64_pack (*(const uint64_t *) member, out + rv);
+    case PROTOBUF_C_TYPE_SFIXED32:
+    case PROTOBUF_C_TYPE_FIXED32:
+    case PROTOBUF_C_TYPE_FLOAT:
+      out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
+      return rv + fixed32_pack (*(const uint64_t *) member, out + rv);
+    case PROTOBUF_C_TYPE_SFIXED64:
+    case PROTOBUF_C_TYPE_FIXED64:
+    case PROTOBUF_C_TYPE_DOUBLE:
+      out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
+      return rv + fixed64_pack (*(const uint64_t *) member, out + rv);
+    case PROTOBUF_C_TYPE_BOOL:
+      out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+      return rv + boolean_pack (*(const protobuf_c_boolean *) member, out + rv);
+    case PROTOBUF_C_TYPE_STRING:
+      {
+        out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+        return rv + string_pack (*(char * const *) member, out + rv);
+      }
+      
+    case PROTOBUF_C_TYPE_BYTES:
+      {
+        const ProtobufCBinaryData * bd = ((const ProtobufCBinaryData*) member);
+        out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+        return rv + binary_data_pack (bd, out + rv);
+      }
+    //case PROTOBUF_C_TYPE_GROUP:          // NOT SUPPORTED
+    case PROTOBUF_C_TYPE_MESSAGE:
+      {
+        out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+        return rv + prefixed_message_pack (*(ProtobufCMessage * const *) member,
+                                           out + rv);
+      }
+    }
+  PROTOBUF_C_ASSERT_NOT_REACHED ();
+  return 0;
+}
+static size_t
+optional_field_pack (const ProtobufCFieldDescriptor *field,
+                     const protobuf_c_boolean *has,
+                     const void *member,
+                     uint8_t *out)
+{
+  if (field->type == PROTOBUF_C_TYPE_MESSAGE
+   || field->type == PROTOBUF_C_TYPE_STRING)
+    {
+      const void *ptr = * (const void * const *) member;
+      if (ptr == NULL
+       || ptr == field->default_value)
+        return 0;
+    }
+  else
+    {
+      if (!*has)
+        return 0;
+    }
+  return required_field_pack (field, member, out);
+}
+
+/* TODO: implement as a table lookup */
+static inline size_t sizeof_elt_in_repeated_array (ProtobufCType type)
+{
+  switch (type)
+    {
+    case PROTOBUF_C_TYPE_SINT32:
+    case PROTOBUF_C_TYPE_INT32:
+    case PROTOBUF_C_TYPE_UINT32:
+    case PROTOBUF_C_TYPE_SFIXED32:
+    case PROTOBUF_C_TYPE_FIXED32:
+    case PROTOBUF_C_TYPE_FLOAT:
+    case PROTOBUF_C_TYPE_ENUM:
+      return 4;
+    case PROTOBUF_C_TYPE_SINT64:
+    case PROTOBUF_C_TYPE_INT64:
+    case PROTOBUF_C_TYPE_UINT64:
+    case PROTOBUF_C_TYPE_SFIXED64:
+    case PROTOBUF_C_TYPE_FIXED64:
+    case PROTOBUF_C_TYPE_DOUBLE:
+      return 8;
+    case PROTOBUF_C_TYPE_BOOL:
+      return sizeof (protobuf_c_boolean);
+    case PROTOBUF_C_TYPE_STRING:
+    case PROTOBUF_C_TYPE_MESSAGE:
+      return sizeof (void *);
+    case PROTOBUF_C_TYPE_BYTES:
+      return sizeof (ProtobufCBinaryData);
+    }
+  PROTOBUF_C_ASSERT_NOT_REACHED ();
+  return 0;
+}
+static size_t
+repeated_field_pack (const ProtobufCFieldDescriptor *field,
+                     size_t count,
+                     const void *member,
+                     uint8_t *out)
+{
+  char *array = * (char * const *) member;
+  size_t siz;
+  unsigned i;
+  size_t rv = 0;
+  /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
+  siz = sizeof_elt_in_repeated_array (field->type);
+  for (i = 0; i < count; i++)
+    {
+      rv += required_field_pack (field, array, out + rv);
+      array += siz;
+    }
+  return rv;
+}
+static size_t
+unknown_field_pack (const ProtobufCMessageUnknownField *field, uint8_t *out)
+{
+  size_t rv = tag_pack (field->tag, out);
+  out[0] |= field->wire_type;
+  memcpy (out + rv, field->data, field->len);
+  return rv + field->len;
+}
+
+size_t    protobuf_c_message_pack           (const ProtobufCMessage *message,
+                                             uint8_t                *out)
+{
+  unsigned i;
+  size_t rv = 0;
+  ASSERT_IS_MESSAGE (message);
+  for (i = 0; i < message->descriptor->n_fields; i++)
+    {
+      const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
+      const void *member = ((const char *) message) + field->offset;
+      const void *qmember = ((const char *) message) + field->quantifier_offset;
+
+      if (field->label == PROTOBUF_C_LABEL_REQUIRED)
+        rv += required_field_pack (field, member, out + rv);
+      else if (field->label == PROTOBUF_C_LABEL_OPTIONAL)
+        rv += optional_field_pack (field, qmember, member, out + rv);
+      else
+        rv += repeated_field_pack (field, * (const size_t *) qmember, member, out + rv);
+    }
+  for (i = 0; i < message->n_unknown_fields; i++)
+    rv += unknown_field_pack (&message->unknown_fields[i], out + rv);
+  return rv;
+}
+
+/* === pack_to_buffer() === */
+static size_t
+required_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
+                               const void *member,
+                               ProtobufCBuffer *buffer)
+{
+  size_t rv;
+  uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
+  rv = tag_pack (field->id, scratch);
+  switch (field->type)
+    {
+    case PROTOBUF_C_TYPE_SINT32:
+      scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+      rv += sint32_pack (*(const int32_t *) member, scratch + rv);
+      buffer->append (buffer, rv, scratch);
+      break;
+    case PROTOBUF_C_TYPE_INT32:
+      scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+      rv += int32_pack (*(const uint32_t *) member, scratch + rv);
+      buffer->append (buffer, rv, scratch);
+      break;
+    case PROTOBUF_C_TYPE_UINT32:
+    case PROTOBUF_C_TYPE_ENUM:
+      scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+      rv += uint32_pack (*(const uint32_t *) member, scratch + rv);
+      buffer->append (buffer, rv, scratch);
+      break;
+    case PROTOBUF_C_TYPE_SINT64:
+      scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+      rv += sint64_pack (*(const int64_t *) member, scratch + rv);
+      buffer->append (buffer, rv, scratch);
+      break;
+    case PROTOBUF_C_TYPE_INT64:
+    case PROTOBUF_C_TYPE_UINT64:
+      scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+      rv += uint64_pack (*(const uint64_t *) member, scratch + rv);
+      buffer->append (buffer, rv, scratch);
+      break;
+    case PROTOBUF_C_TYPE_SFIXED32:
+    case PROTOBUF_C_TYPE_FIXED32:
+    case PROTOBUF_C_TYPE_FLOAT:
+      scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
+      rv += fixed32_pack (*(const uint64_t *) member, scratch + rv);
+      buffer->append (buffer, rv, scratch);
+      break;
+    case PROTOBUF_C_TYPE_SFIXED64:
+    case PROTOBUF_C_TYPE_FIXED64:
+    case PROTOBUF_C_TYPE_DOUBLE:
+      scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
+      rv += fixed64_pack (*(const uint64_t *) member, scratch + rv);
+      buffer->append (buffer, rv, scratch);
+      break;
+    case PROTOBUF_C_TYPE_BOOL:
+      scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+      rv += boolean_pack (*(const protobuf_c_boolean *) member, scratch + rv);
+      buffer->append (buffer, rv, scratch);
+      break;
+    case PROTOBUF_C_TYPE_STRING:
+      {
+        const char *str = *(char * const *) member;
+        size_t sublen = str ? strlen (str) : 0;
+        scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+        rv += uint32_pack (sublen, scratch + rv);
+        buffer->append (buffer, rv, scratch);
+        buffer->append (buffer, sublen, (const uint8_t *) str);
+        rv += sublen;
+        break;
+      }
+      
+    case PROTOBUF_C_TYPE_BYTES:
+      {
+        const ProtobufCBinaryData * bd = ((const ProtobufCBinaryData*) member);
+        size_t sublen = bd->len;
+        scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+        rv += uint32_pack (sublen, scratch + rv);
+        buffer->append (buffer, rv, scratch);
+        buffer->append (buffer, sublen, bd->data);
+        rv += sublen;
+        break;
+      }
+    //PROTOBUF_C_TYPE_GROUP,          // NOT SUPPORTED
+    case PROTOBUF_C_TYPE_MESSAGE:
+      {
+        uint8_t simple_buffer_scratch[256];
+        size_t sublen;
+        ProtobufCBufferSimple simple_buffer
+          = PROTOBUF_C_BUFFER_SIMPLE_INIT (simple_buffer_scratch);
+        const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
+        scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+        if (msg == NULL)
+          sublen = 0;
+        else
+          sublen = protobuf_c_message_pack_to_buffer (msg, &simple_buffer.base);
+        rv += uint32_pack (sublen, scratch + rv);
+        buffer->append (buffer, rv, scratch);
+        buffer->append (buffer, sublen, simple_buffer.data);
+        rv += sublen;
+        PROTOBUF_C_BUFFER_SIMPLE_CLEAR (&simple_buffer);
+        break;
+      }
+    default:
+      PROTOBUF_C_ASSERT_NOT_REACHED ();
+    }
+  return rv;
+}
+static size_t
+optional_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
+                               const protobuf_c_boolean *has,
+                               const void *member,
+                               ProtobufCBuffer *buffer)
+{
+  if (field->type == PROTOBUF_C_TYPE_MESSAGE
+   || field->type == PROTOBUF_C_TYPE_STRING)
+    {
+      const void *ptr = * (const void * const *) member;
+      if (ptr == NULL
+       || ptr == field->default_value)
+        return 0;
+    }
+  else
+    {
+      if (!*has)
+        return 0;
+    }
+  return required_field_pack_to_buffer (field, member, buffer);
+}
+
+static size_t
+repeated_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
+                               unsigned count,
+                               const void *member,
+                               ProtobufCBuffer *buffer)
+{
+  char *array = * (char * const *) member;
+  size_t siz;
+  unsigned i;
+  /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
+  unsigned rv = 0;
+  siz = sizeof_elt_in_repeated_array (field->type);
+  for (i = 0; i < count; i++)
+    {
+      rv += required_field_pack_to_buffer (field, array, buffer);
+      array += siz;
+    }
+  return rv;
+}
+
+static size_t
+unknown_field_pack_to_buffer (const ProtobufCMessageUnknownField *field,
+                              ProtobufCBuffer *buffer)
+{
+  uint8_t header[MAX_UINT64_ENCODED_SIZE];
+  size_t rv = tag_pack (field->tag, header);
+  header[0] |= field->wire_type;
+  buffer->append (buffer, rv, header);
+  buffer->append (buffer, field->len, field->data);
+  return rv + field->len;
+}
+
+size_t
+protobuf_c_message_pack_to_buffer (const ProtobufCMessage *message,
+                                   ProtobufCBuffer  *buffer)
+{
+  unsigned i;
+  size_t rv = 0;
+  ASSERT_IS_MESSAGE (message);
+  for (i = 0; i < message->descriptor->n_fields; i++)
+    {
+      const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
+      const void *member = ((const char *) message) + field->offset;
+      const void *qmember = ((const char *) message) + field->quantifier_offset;
+
+      if (field->label == PROTOBUF_C_LABEL_REQUIRED)
+        rv += required_field_pack_to_buffer (field, member, buffer);
+      else if (field->label == PROTOBUF_C_LABEL_OPTIONAL)
+        rv += optional_field_pack_to_buffer (field, qmember, member, buffer);
+      else
+        rv += repeated_field_pack_to_buffer (field, * (const size_t *) qmember, member, buffer);
+    }
+  for (i = 0; i < message->n_unknown_fields; i++)
+    rv += unknown_field_pack_to_buffer (&message->unknown_fields[i], buffer);
+
+  return rv;
+}
+
+/* === unpacking === */
+#if PRINT_UNPACK_ERRORS
+# define UNPACK_ERROR(args)  do { printf args;printf("\n"); }while(0)
+#else
+# define UNPACK_ERROR(args)  do { } while (0)
+#endif
+
+static inline int
+int_range_lookup (unsigned n_ranges,
+                  const ProtobufCIntRange *ranges,
+                  int value)
+{
+  unsigned start, n;
+  if (n_ranges == 0)
+    return -1;
+  start = 0;
+  n = n_ranges;
+  while (n > 1)
+    {
+      unsigned mid = start + n / 2;
+      if (value < ranges[mid].start_value)
+        {
+          n = mid - start;
+        }
+      else if (value >= ranges[mid].start_value + (int)(ranges[mid+1].orig_index-ranges[mid].orig_index))
+        {
+          unsigned new_start = mid + 1;
+          n = start + n - new_start;
+          start = new_start;
+        }
+      else
+        return (value - ranges[mid].start_value) + ranges[mid].orig_index;
+    }
+  if (n > 0)
+    {
+      unsigned start_orig_index = ranges[start].orig_index;
+      unsigned range_size = ranges[start+1].orig_index - start_orig_index;
+
+      if (ranges[start].start_value <= value
+       && value < (int)(ranges[start].start_value + range_size))
+        return (value - ranges[start].start_value) + start_orig_index;
+    }
+  return -1;
+}
+
+static size_t
+parse_tag_and_wiretype (size_t len,
+                        const uint8_t *data,
+                        uint32_t *tag_out,
+                        ProtobufCWireType *wiretype_out)
+{
+  unsigned max_rv = len > 5 ? 5 : len;
+  uint32_t tag = (data[0]&0x7f) >> 3;
+  unsigned shift = 4;
+  unsigned rv;
+  *wiretype_out = data[0] & 7;
+  if ((data[0] & 0x80) == 0)
+    {
+      *tag_out = tag;
+      return 1;
+    }
+  for (rv = 1; rv < max_rv; rv++)
+    if (data[rv] & 0x80)
+      {
+        tag |= (data[rv] & 0x7f) << shift;
+        shift += 7;
+      }
+    else
+      {
+        tag |= data[rv] << shift;
+        *tag_out = tag;
+        return rv + 1;
+      }
+  return 0;                   /* error: bad header */
+}
+
+/* sizeof(ScannedMember) must be <= (1<<BOUND_SIZEOF_SCANNED_MEMBER_LOG2) */
+#define BOUND_SIZEOF_SCANNED_MEMBER_LOG2  5
+typedef struct _ScannedMember ScannedMember;
+struct _ScannedMember
+{
+  uint32_t tag;
+  uint8_t wire_type;
+  uint8_t length_prefix_len;
+  const ProtobufCFieldDescriptor *field;
+  size_t len;
+  const uint8_t *data;
+};
+
+#define MESSAGE_GET_UNKNOWNS(message) \
+  STRUCT_MEMBER_PTR (ProtobufCMessageUnknownFieldArray, \
+                     (message), (message)->descriptor->unknown_field_array_offset)
+
+static inline uint32_t
+scan_length_prefixed_data (size_t len, const uint8_t *data, size_t *prefix_len_out)
+{
+  unsigned hdr_max = len < 5 ? len : 5;
+  unsigned hdr_len;
+  uint32_t val = 0;
+  unsigned i;
+  unsigned shift = 0;
+  for (i = 0; i < hdr_max; i++)
+    {
+      val |= (data[i] & 0x7f) << shift;
+      shift += 7;
+      if ((data[i] & 0x80) == 0)
+        break;
+    }
+  if (i == hdr_max)
+    {
+      UNPACK_ERROR (("error parsing length for length-prefixed data"));
+      return 0;
+    }
+  hdr_len = i + 1;
+  *prefix_len_out = hdr_len;
+  if (hdr_len + val > len)
+    {
+      UNPACK_ERROR (("data too short after length-prefix of %u",
+                     val));
+      return 0;
+    }
+  return hdr_len + val;
+}
+
+static inline uint32_t
+parse_uint32 (unsigned len, const uint8_t *data)
+{
+  unsigned rv = data[0] & 0x7f;
+  if (len > 1)
+    {
+      rv |= ((data[1] & 0x7f) << 7);
+      if (len > 2)
+        {
+          rv |= ((data[2] & 0x7f) << 14);
+          if (len > 3)
+            {
+              rv |= ((data[3] & 0x7f) << 21);
+              if (len > 4)
+                rv |= (data[4] << 28);
+            }
+        }
+    }
+  return rv;
+}
+static inline uint32_t
+parse_int32 (unsigned len, const uint8_t *data)
+{
+  return parse_uint32 (len, data);
+}
+static inline int32_t
+unzigzag32 (uint32_t v)
+{
+  if (v&1)
+    return -(v>>1) - 1;
+  else
+    return v>>1;
+}
+static inline uint32_t
+parse_fixed_uint32 (const uint8_t *data)
+{
+#if IS_LITTLE_ENDIAN
+  uint32_t t;
+  memcpy (&t, data, 4);
+  return t;
+#else
+  return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
+#endif
+}
+static uint64_t
+parse_uint64 (unsigned len, const uint8_t *data)
+{
+  unsigned shift, i;
+  if (len < 5)
+    return parse_uint32 (len, data);
+  uint64_t rv = ((data[0] & 0x7f))
+              | ((data[1] & 0x7f)<<7)
+              | ((data[2] & 0x7f)<<14)
+              | ((data[3] & 0x7f)<<21);
+  shift = 28;
+  for (i = 4; i < len; i++)
+    {
+      rv |= (((uint64_t)(data[i]&0x7f)) << shift);
+      shift += 7;
+    }
+  return rv;
+}
+static inline int64_t
+unzigzag64 (uint64_t v)
+{
+  if (v&1)
+    return -(v>>1) - 1;
+  else
+    return v>>1;
+}
+static inline uint64_t
+parse_fixed_uint64 (const uint8_t *data)
+{
+#if IS_LITTLE_ENDIAN
+  uint64_t t;
+  memcpy (&t, data, 8);
+  return t;
+#else
+  return (uint64_t)parse_fixed_uint32 (data)
+      | (((uint64_t)parse_fixed_uint32(data+4)) << 32);
+#endif
+}
+static protobuf_c_boolean
+parse_boolean (unsigned len, const uint8_t *data)
+{
+  unsigned i;
+  for (i = 0; i < len; i++)
+    if (data[i] & 0x7f)
+      return 1;
+  return 0;
+}
+static protobuf_c_boolean
+parse_required_member (ScannedMember *scanned_member,
+                       void *member,
+                       ProtobufCAllocator *allocator,
+                       protobuf_c_boolean maybe_clear)
+{
+  unsigned len = scanned_member->len;
+  const uint8_t *data = scanned_member->data;
+  ProtobufCWireType wire_type = scanned_member->wire_type;
+  switch (scanned_member->field->type)
+    {
+    case PROTOBUF_C_TYPE_INT32:
+      if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+        return 0;
+      *(uint32_t*)member = parse_int32 (len, data);
+      return 1;
+    case PROTOBUF_C_TYPE_UINT32:
+      if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+        return 0;
+      *(uint32_t*)member = parse_uint32 (len, data);
+      return 1;
+    case PROTOBUF_C_TYPE_SINT32:
+      if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+        return 0;
+      *(int32_t*)member = unzigzag32 (parse_uint32 (len, data));
+      return 1;
+    case PROTOBUF_C_TYPE_SFIXED32:
+    case PROTOBUF_C_TYPE_FIXED32:
+    case PROTOBUF_C_TYPE_FLOAT:
+      if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT)
+        return 0;
+      *(uint32_t*)member = parse_fixed_uint32 (data);
+      return 1;
+
+    case PROTOBUF_C_TYPE_INT64:
+    case PROTOBUF_C_TYPE_UINT64:
+      if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+        return 0;
+      *(uint64_t*)member = parse_uint64 (len, data);
+      return 1;
+    case PROTOBUF_C_TYPE_SINT64:
+      if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+        return 0;
+      *(int64_t*)member = unzigzag64 (parse_uint64 (len, data));
+      return 1;
+    case PROTOBUF_C_TYPE_SFIXED64:
+    case PROTOBUF_C_TYPE_FIXED64:
+    case PROTOBUF_C_TYPE_DOUBLE:
+      if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT)
+        return 0;
+      *(uint64_t*)member = parse_fixed_uint64 (data);
+      return 1;
+
+    case PROTOBUF_C_TYPE_BOOL:
+      *(protobuf_c_boolean*)member = parse_boolean (len, data);
+      return 1;
+
+    case PROTOBUF_C_TYPE_ENUM:
+      if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+        return 0;
+      *(uint32_t*)member = parse_uint32 (len, data);
+      return 1;
+
+    case PROTOBUF_C_TYPE_STRING:
+      if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
+        return 0;
+      {
+        char **pstr = member;
+        unsigned pref_len = scanned_member->length_prefix_len;
+        if (maybe_clear && *pstr != NULL)
+          {
+            const char *def = scanned_member->field->default_value;
+            if (*pstr != NULL && *pstr != def)
+              FREE (allocator, *pstr);
+          }
+        DO_ALLOC (*pstr, allocator, len - pref_len + 1, return 0);
+        memcpy (*pstr, data + pref_len, len - pref_len);
+        (*pstr)[len-pref_len] = 0;
+        return 1;
+      }
+    case PROTOBUF_C_TYPE_BYTES:
+      if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
+        return 0;
+      {
+        ProtobufCBinaryData *bd = member;
+        const ProtobufCBinaryData *def_bd;
+        unsigned pref_len = scanned_member->length_prefix_len;
+        def_bd = scanned_member->field->default_value;
+        if (maybe_clear && bd->data != NULL && bd->data != def_bd->data)
+          FREE (allocator, bd->data);
+        DO_ALLOC (bd->data, allocator, len - pref_len, return 0);
+        memcpy (bd->data, data + pref_len, len - pref_len);
+        bd->len = len - pref_len;
+        return 1;
+      }
+    //case PROTOBUF_C_TYPE_GROUP,          // NOT SUPPORTED
+    case PROTOBUF_C_TYPE_MESSAGE:
+      if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
+        return 0;
+      {
+        ProtobufCMessage **pmessage = member;
+        ProtobufCMessage *subm;
+        const ProtobufCMessage *def_mess;
+        unsigned pref_len = scanned_member->length_prefix_len;
+        def_mess = scanned_member->field->default_value;
+        if (maybe_clear && *pmessage != NULL && *pmessage != def_mess)
+          protobuf_c_message_free_unpacked (*pmessage, allocator);
+        subm = protobuf_c_message_unpack (scanned_member->field->descriptor,
+                                          allocator,
+                                          len - pref_len, data + pref_len);
+        *pmessage = subm;       /* since we freed the message we must clear the field, even if NULL */
+        if (subm == NULL)
+          return 0;
+        return 1;
+      }
+    }
+  return 0;
+}
+
+static protobuf_c_boolean
+parse_optional_member (ScannedMember *scanned_member,
+                       void *member,
+                       ProtobufCMessage *message,
+                       ProtobufCAllocator *allocator)
+{
+  if (!parse_required_member (scanned_member, member, allocator, TRUE))
+    return 0;
+  if (scanned_member->field->quantifier_offset != 0)
+    STRUCT_MEMBER (protobuf_c_boolean,
+                   message,
+                   scanned_member->field->quantifier_offset) = 1;
+  return 1;
+}
+
+static protobuf_c_boolean
+parse_repeated_member (ScannedMember *scanned_member,
+                       void *member,
+                       ProtobufCMessage *message,
+                       ProtobufCAllocator *allocator)
+{
+  const ProtobufCFieldDescriptor *field = scanned_member->field;
+  size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
+  size_t siz = sizeof_elt_in_repeated_array (field->type);
+  char *array = *(char**)member;
+  if (!parse_required_member (scanned_member,
+                              array + siz * (*p_n),
+                              allocator,
+                              FALSE))
+    return 0;
+  *p_n += 1;
+  return 1;
+}
+
+static protobuf_c_boolean
+parse_member (ScannedMember *scanned_member,
+              ProtobufCMessage *message,
+              ProtobufCAllocator *allocator)
+{
+  const ProtobufCFieldDescriptor *field = scanned_member->field;
+  void *member;
+  if (field == NULL)
+    {
+      ProtobufCMessageUnknownField *ufield = message->unknown_fields + (message->n_unknown_fields++);
+      ufield->tag = scanned_member->tag;
+      ufield->wire_type = scanned_member->wire_type;
+      ufield->len = scanned_member->len;
+      DO_UNALIGNED_ALLOC (ufield->data, allocator, scanned_member->len, return 0);
+      memcpy (ufield->data, scanned_member->data, ufield->len);
+      return 1;
+    }
+  member = (char*)message + field->offset;
+  switch (field->label)
+    {
+    case PROTOBUF_C_LABEL_REQUIRED:
+      return parse_required_member (scanned_member, member, allocator, TRUE);
+    case PROTOBUF_C_LABEL_OPTIONAL:
+      return parse_optional_member (scanned_member, member, message, allocator);
+    case PROTOBUF_C_LABEL_REPEATED:
+      return parse_repeated_member (scanned_member, member, message, allocator);
+    }
+  PROTOBUF_C_ASSERT_NOT_REACHED ();
+  return 0;
+}
+
+static inline void
+setup_default_values (ProtobufCMessage *message)
+{
+  const ProtobufCMessageDescriptor *desc = message->descriptor;
+  unsigned i;
+  for (i = 0; i < desc->n_fields; i++)
+    if (desc->fields[i].default_value != NULL
+     && desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED)
+      {
+        void *field = STRUCT_MEMBER_P (message, desc->fields[i].offset);
+        const void *dv = desc->fields[i].default_value;
+        switch (desc->fields[i].type)
+        {
+        case PROTOBUF_C_TYPE_INT32:
+        case PROTOBUF_C_TYPE_SINT32:
+        case PROTOBUF_C_TYPE_SFIXED32:
+        case PROTOBUF_C_TYPE_UINT32:
+        case PROTOBUF_C_TYPE_FIXED32:
+        case PROTOBUF_C_TYPE_FLOAT:
+        case PROTOBUF_C_TYPE_ENUM:
+          memcpy (field, dv, 4);
+          break;
+
+        case PROTOBUF_C_TYPE_INT64:
+        case PROTOBUF_C_TYPE_SINT64:
+        case PROTOBUF_C_TYPE_SFIXED64:
+        case PROTOBUF_C_TYPE_UINT64:
+        case PROTOBUF_C_TYPE_FIXED64:
+        case PROTOBUF_C_TYPE_DOUBLE:
+          memcpy (field, dv, 8);
+          break;
+
+        case PROTOBUF_C_TYPE_BOOL:
+          memcpy (field, dv, sizeof (protobuf_c_boolean));
+          break;
+
+        case PROTOBUF_C_TYPE_BYTES:
+          memcpy (field, dv, sizeof (ProtobufCBinaryData));
+          break;
+
+        case PROTOBUF_C_TYPE_STRING:
+        case PROTOBUF_C_TYPE_MESSAGE:
+          /* the next line essentially implements a cast from const,
+             which is totally unavoidable. */
+          *(const void**)field = dv;
+          break;
+        }
+      }
+}
+
+/* ScannedMember slabs (an unpacking implementation detail).
+   Before doing real unpacking, we first scan through the
+   elements to see how many there are (for repeated fields),
+   and which field to use (for non-repeated fields given twice).
+
+ * In order to avoid allocations for small messages,
+   we keep a stack-allocated slab of ScannedMembers of
+   size FIRST_SCANNED_MEMBER_SLAB_SIZE (16).
+   After we fill that up, we allocate each slab twice
+   as large as the previous one. */
+#define FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2             4
+
+/* The number of slabs, including the stack-allocated ones;
+   choose the number so that we would overflow if we needed
+   a slab larger than provided. */
+#define MAX_SCANNED_MEMBER_SLAB                          \
+  (sizeof(void*)*8 - 1                                   \
+   - BOUND_SIZEOF_SCANNED_MEMBER_LOG2                    \
+   - FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)
+
+ProtobufCMessage *
+protobuf_c_message_unpack         (const ProtobufCMessageDescriptor *desc,
+                                   ProtobufCAllocator  *allocator,
+                                   size_t               len,
+                                   const uint8_t       *data)
+{
+  ProtobufCMessage *rv;
+  size_t rem = len;
+  const uint8_t *at = data;
+  const ProtobufCFieldDescriptor *last_field = desc->fields + 0;
+  ScannedMember first_member_slab[1<<FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2];
+
+  /* scanned_member_slabs[i] is an array of arrays of ScannedMember.
+     The first slab (scanned_member_slabs[0] is just a pointer to
+     first_member_slab), above.  All subsequent slabs will be allocated
+     using the allocator. */
+  ScannedMember *scanned_member_slabs[MAX_SCANNED_MEMBER_SLAB+1];
+  unsigned which_slab = 0;       /* the slab we are currently populating */
+  unsigned in_slab_index = 0;    /* number of members in the slab */
+  size_t n_unknown = 0;
+  unsigned f;
+  unsigned i_slab;
+
+  ASSERT_IS_MESSAGE_DESCRIPTOR (desc);
+
+  if (allocator == NULL)
+    allocator = &protobuf_c_default_allocator;
+  DO_ALLOC (rv, allocator, desc->sizeof_message, return NULL);
+  scanned_member_slabs[0] = first_member_slab;
+
+  memset (rv, 0, desc->sizeof_message);
+  rv->descriptor = desc;
+
+  setup_default_values (rv);
+
+  while (rem > 0)
+    {
+      uint32_t tag;
+      ProtobufCWireType wire_type;
+      size_t used = parse_tag_and_wiretype (rem, at, &tag, &wire_type);
+      const ProtobufCFieldDescriptor *field;
+      ScannedMember tmp;
+      if (used == 0)
+        {
+          UNPACK_ERROR (("error parsing tag/wiretype at offset %u",
+                         (unsigned)(at-data)));
+          goto error_cleanup_during_scan;
+        }
+      /* XXX: consider optimizing for field[1].id == tag, if field[1] exists! */
+      if (last_field->id != tag)
+        {
+          /* lookup field */
+          int field_index = int_range_lookup (desc->n_field_ranges,
+                                              desc->field_ranges,
+                                              tag);
+          if (field_index < 0)
+            {
+              field = NULL;
+              n_unknown++;
+            }
+          else
+            {
+              field = desc->fields + field_index;
+              last_field = field;
+            }
+        }
+      else
+        field = last_field;
+
+      at += used;
+      rem -= used;
+      tmp.tag = tag;
+      tmp.wire_type = wire_type;
+      tmp.field = field;
+      tmp.data = at;
+      switch (wire_type)
+        {
+        case PROTOBUF_C_WIRE_TYPE_VARINT:
+          {
+            unsigned max_len = rem < 10 ? rem : 10;
+            unsigned i;
+            for (i = 0; i < max_len; i++)
+              if ((at[i] & 0x80) == 0)
+                break;
+            if (i == max_len)
+              {
+                UNPACK_ERROR (("unterminated varint at offset %u",
+                               (unsigned)(at-data)));
+                goto error_cleanup_during_scan;
+              }
+            tmp.len = i + 1;
+          }
+          break;
+        case PROTOBUF_C_WIRE_TYPE_64BIT:
+          if (rem < 8)
+            {
+              UNPACK_ERROR (("too short after 64bit wiretype at offset %u",
+                             (unsigned)(at-data)));
+              goto error_cleanup_during_scan;
+            }
+          tmp.len = 8;
+          break;
+        case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED:
+          {
+            size_t pref_len;
+            tmp.len = scan_length_prefixed_data (rem, at, &pref_len);
+            if (tmp.len == 0)
+              {
+                /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */
+                goto error_cleanup_during_scan;
+              }
+            tmp.length_prefix_len = pref_len;
+            break;
+          }
+        case PROTOBUF_C_WIRE_TYPE_32BIT:
+          if (rem < 4)
+            {
+              UNPACK_ERROR (("too short after 32bit wiretype at offset %u",
+                             (unsigned)(at-data)));
+              goto error_cleanup_during_scan;
+            }
+          tmp.len = 4;
+          break;
+        default:
+          UNPACK_ERROR (("unsupported tag %u at offset %u",
+                         wire_type, (unsigned)(at-data))); 
+          goto error_cleanup_during_scan;
+        }
+      if (in_slab_index == (1U<<(which_slab+FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)))
+        {
+          size_t size;
+          in_slab_index = 0;
+          if (which_slab == MAX_SCANNED_MEMBER_SLAB)
+            {
+              UNPACK_ERROR (("too many fields"));
+              goto error_cleanup_during_scan;
+            }
+          which_slab++;
+          size = sizeof(ScannedMember) << (which_slab+FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2);
+          /* TODO: consider using alloca() ! */
+          if (allocator->tmp_alloc != NULL)
+            scanned_member_slabs[which_slab] = TMPALLOC(allocator, size);
+          else
+            DO_ALLOC (scanned_member_slabs[which_slab], allocator, size, goto error_cleanup_during_scan);
+        }
+      scanned_member_slabs[which_slab][in_slab_index++] = tmp;
+
+      if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED)
+        {
+          STRUCT_MEMBER (size_t, rv, field->quantifier_offset) += 1;
+        }
+
+      at += tmp.len;
+      rem -= tmp.len;
+    }
+
+  /* allocate space for repeated fields */
+  for (f = 0; f < desc->n_fields; f++)
+    if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED)
+      {
+        const ProtobufCFieldDescriptor *field = desc->fields + f;
+        size_t siz = sizeof_elt_in_repeated_array (field->type);
+        size_t *n_ptr = STRUCT_MEMBER_PTR (size_t, rv, field->quantifier_offset);
+        if (*n_ptr != 0)
+          {
+            unsigned n = *n_ptr;
+            *n_ptr = 0;
+            assert(rv->descriptor != NULL);
+#define CLEAR_REMAINING_N_PTRS()                                            \
+            for(f++;f < desc->n_fields; f++)                                \
+              {                                                             \
+                field = desc->fields + f;                                   \
+                if (field->label == PROTOBUF_C_LABEL_REPEATED)              \
+                  STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \
+              }
+            DO_ALLOC (STRUCT_MEMBER (void *, rv, field->offset),
+                      allocator, siz * n,
+                      CLEAR_REMAINING_N_PTRS (); goto error_cleanup);
+#undef CLEAR_REMAINING_N_PTRS
+          }
+      }
+
+  /* allocate space for unknown fields */
+  if (n_unknown)
+    {
+      DO_ALLOC (rv->unknown_fields,
+                allocator, n_unknown * sizeof (ProtobufCMessageUnknownField),
+                goto error_cleanup);
+    }
+
+  /* do real parsing */
+  for (i_slab = 0; i_slab <= which_slab; i_slab++)
+    {
+      unsigned max = (i_slab == which_slab) ? in_slab_index : (1U<<(i_slab+4));
+      ScannedMember *slab = scanned_member_slabs[i_slab];
+      unsigned j;
+      for (j = 0; j < max; j++)
+        {
+          if (!parse_member (slab + j, rv, allocator))
+            {
+              UNPACK_ERROR (("error parsing member %s of %s",
+                             slab->field ? slab->field->name : "*unknown-field*", desc->name));
+              goto error_cleanup;
+            }
+        }
+    }
+
+  /* cleanup */
+  if (allocator->tmp_alloc == NULL)
+    {
+      unsigned j;
+      for (j = 1; j <= which_slab; j++)
+        FREE (allocator, scanned_member_slabs[j]);
+    }
+
+  return rv;
+
+error_cleanup:
+  protobuf_c_message_free_unpacked (rv, allocator);
+  if (allocator->tmp_alloc == NULL)
+    {
+      unsigned j;
+      for (j = 1; j <= which_slab; j++)
+        FREE (allocator, scanned_member_slabs[j]);
+    }
+  return NULL;
+
+error_cleanup_during_scan:
+  FREE (allocator, rv);
+  if (allocator->tmp_alloc == NULL)
+    {
+      unsigned j;
+      for (j = 1; j <= which_slab; j++)
+        FREE (allocator, scanned_member_slabs[j]);
+    }
+  return NULL;
+}
+
+/* === free_unpacked === */
+void     
+protobuf_c_message_free_unpacked  (ProtobufCMessage    *message,
+                                   ProtobufCAllocator  *allocator)
+{
+  const ProtobufCMessageDescriptor *desc = message->descriptor;
+  unsigned f;
+  ASSERT_IS_MESSAGE (message);
+  if (allocator == NULL)
+    allocator = &protobuf_c_default_allocator;
+  message->descriptor = NULL;
+  for (f = 0; f < desc->n_fields; f++)
+    {
+      if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED)
+        {
+          size_t n = STRUCT_MEMBER (size_t, message, desc->fields[f].quantifier_offset);
+          void * arr = STRUCT_MEMBER (void *, message, desc->fields[f].offset);
+          if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING)
+            {
+              unsigned i;
+              for (i = 0; i < n; i++)
+                FREE (allocator, ((char**)arr)[i]);
+            }
+          else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES)
+            {
+              unsigned i;
+              for (i = 0; i < n; i++)
+                FREE (allocator, ((ProtobufCBinaryData*)arr)[i].data);
+            }
+          else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE)
+            {
+              unsigned i;
+              for (i = 0; i < n; i++)
+                protobuf_c_message_free_unpacked (((ProtobufCMessage**)arr)[i], allocator);
+            }
+          if (arr != NULL)
+            FREE (allocator, arr);
+        }
+      else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING)
+        {
+          char *str = STRUCT_MEMBER (char *, message, desc->fields[f].offset);
+          if (str && str != desc->fields[f].default_value)
+            FREE (allocator, str);
+        }
+      else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES)
+        {
+          void *data = STRUCT_MEMBER (ProtobufCBinaryData, message, desc->fields[f].offset).data;
+          const ProtobufCBinaryData *default_bd;
+          default_bd = desc->fields[f].default_value;
+          if (data != NULL
+           && (default_bd == NULL || default_bd->data != data))
+            FREE (allocator, data);
+        }
+      else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE)
+        {
+          ProtobufCMessage *sm;
+          sm = STRUCT_MEMBER (ProtobufCMessage *, message,desc->fields[f].offset);
+          if (sm && sm != desc->fields[f].default_value)
+            protobuf_c_message_free_unpacked (sm, allocator);
+        }
+    }
+
+  for (f = 0; f < message->n_unknown_fields; f++)
+    FREE (allocator, message->unknown_fields[f].data);
+  if (message->unknown_fields != NULL)
+    FREE (allocator, message->unknown_fields);
+
+  FREE (allocator, message);
+}
+
+/* === services === */
+typedef void (*DestroyHandler)(void *service);
+typedef void (*GenericHandler)(void *service,
+                               const ProtobufCMessage *input,
+                               ProtobufCClosure  closure,
+                               void             *closure_data);
+void 
+protobuf_c_service_invoke_internal(ProtobufCService *service,
+                                  unsigned          method_index,
+                                  const ProtobufCMessage *input,
+                                  ProtobufCClosure  closure,
+                                  void             *closure_data)
+{
+  GenericHandler *handlers;
+  GenericHandler handler;
+  PROTOBUF_C_ASSERT (method_index < service->descriptor->n_methods);
+  handlers = (GenericHandler *) (service + 1);
+  handler = handlers[method_index];
+  (*handler) (service, input, closure, closure_data);
+}
+
+void
+protobuf_c_service_generated_init (ProtobufCService *service,
+                                   const ProtobufCServiceDescriptor *descriptor,
+                                   ProtobufCServiceDestroy destroy)
+{
+  ASSERT_IS_SERVICE_DESCRIPTOR(descriptor);
+  service->descriptor = descriptor;
+  service->destroy = destroy;
+  service->invoke = protobuf_c_service_invoke_internal;
+  memset (service + 1, 0, descriptor->n_methods * sizeof (GenericHandler));
+}
+
+void protobuf_c_service_destroy (ProtobufCService *service)
+{
+  service->destroy (service);
+}
+
+/* --- querying the descriptors --- */
+const ProtobufCEnumValue *
+protobuf_c_enum_descriptor_get_value_by_name 
+                         (const ProtobufCEnumDescriptor    *desc,
+                          const char                       *name)
+{
+  unsigned start = 0, count = desc->n_value_names;
+  while (count > 1)
+    {
+      unsigned mid = start + count / 2;
+      int rv = strcmp (desc->values_by_name[mid].name, name);
+      if (rv == 0)
+        return desc->values + desc->values_by_name[mid].index;
+      else if (rv < 0)
+        {
+          count = start + count - (mid - 1);
+          start = mid + 1;
+        }
+      else
+        count = mid - start;
+    }
+  if (count == 0)
+    return NULL;
+  if (strcmp (desc->values_by_name[start].name, name) == 0)
+    return desc->values + desc->values_by_name[start].index;
+  return NULL;
+}
+const ProtobufCEnumValue *
+protobuf_c_enum_descriptor_get_value        
+                         (const ProtobufCEnumDescriptor    *desc,
+                          int                               value)
+{
+  int rv = int_range_lookup (desc->n_value_ranges, desc->value_ranges, value);
+  if (rv < 0)
+    return NULL;
+  return desc->values + rv;
+}
+
+const ProtobufCFieldDescriptor *
+protobuf_c_message_descriptor_get_field_by_name
+                         (const ProtobufCMessageDescriptor *desc,
+                          const char                       *name)
+{
+  unsigned start = 0, count = desc->n_fields;
+  const ProtobufCFieldDescriptor *field;
+  while (count > 1)
+    {
+      unsigned mid = start + count / 2;
+      int rv;
+      field = desc->fields + desc->fields_sorted_by_name[mid];
+      rv = strcmp (field->name, name);
+      if (rv == 0)
+        return field;
+      else if (rv < 0)
+        {
+          count = start + count - (mid + 1);
+          start = mid + 1;
+        }
+      else
+        count = mid - start;
+    }
+  if (count == 0)
+    return NULL;
+  field = desc->fields + desc->fields_sorted_by_name[start];
+  if (strcmp (field->name, name) == 0)
+    return field;
+  return NULL;
+}
+
+const ProtobufCFieldDescriptor *
+protobuf_c_message_descriptor_get_field        
+                         (const ProtobufCMessageDescriptor *desc,
+                          unsigned                          value)
+{
+  int rv = int_range_lookup (desc->n_field_ranges,
+                             desc->field_ranges,
+                             value);
+  if (rv < 0)
+    return NULL;
+  return desc->fields + rv;
+}
+
+const ProtobufCMethodDescriptor *
+protobuf_c_service_descriptor_get_method_by_name
+                         (const ProtobufCServiceDescriptor *desc,
+                          const char                       *name)
+{
+  unsigned start = 0, count = desc->n_methods;
+  while (count > 1)
+    {
+      unsigned mid = start + count / 2;
+      int rv = strcmp (desc->methods[desc->method_indices_by_name[mid]].name, name);
+      if (rv == 0)
+        return desc->methods + desc->method_indices_by_name[mid];
+      if (rv < 0)
+        {
+          count = start + count - (mid - 1);
+          start = mid + 1;
+        }
+      else
+        {
+          count = mid - start;
+        }
+    }
+  if (count == 0)
+    return NULL;
+  if (strcmp (desc->methods[desc->method_indices_by_name[start]].name, name) == 0)
+    return desc->methods + desc->method_indices_by_name[start];
+  return NULL;
+}
diff --git a/src/google/protobuf-c/protobuf-c.h b/src/google/protobuf-c/protobuf-c.h
new file mode 100644 (file)
index 0000000..a476961
--- /dev/null
@@ -0,0 +1,413 @@
+/* --- protobuf-c.h: public protobuf c runtime api --- */
+
+/*
+ * Copyright 2008, Dave Benson.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License
+ * at http://www.apache.org/licenses/LICENSE-2.0 Unless
+ * required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef __PROTOBUF_C_RUNTIME_H_
+#define __PROTOBUF_C_RUNTIME_H_
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <assert.h>
+
+#ifdef __cplusplus
+# define PROTOBUF_C_BEGIN_DECLS    extern "C" {
+# define PROTOBUF_C_END_DECLS      }
+#else
+# define PROTOBUF_C_BEGIN_DECLS
+# define PROTOBUF_C_END_DECLS
+#endif
+
+PROTOBUF_C_BEGIN_DECLS
+
+typedef enum
+{
+  PROTOBUF_C_LABEL_REQUIRED,
+  PROTOBUF_C_LABEL_OPTIONAL,
+  PROTOBUF_C_LABEL_REPEATED
+} ProtobufCLabel;
+
+typedef enum
+{
+  PROTOBUF_C_TYPE_INT32,
+  PROTOBUF_C_TYPE_SINT32,
+  PROTOBUF_C_TYPE_SFIXED32,
+  PROTOBUF_C_TYPE_INT64,
+  PROTOBUF_C_TYPE_SINT64,
+  PROTOBUF_C_TYPE_SFIXED64,
+  PROTOBUF_C_TYPE_UINT32,
+  PROTOBUF_C_TYPE_FIXED32,
+  PROTOBUF_C_TYPE_UINT64,
+  PROTOBUF_C_TYPE_FIXED64,
+  PROTOBUF_C_TYPE_FLOAT,
+  PROTOBUF_C_TYPE_DOUBLE,
+  PROTOBUF_C_TYPE_BOOL,
+  PROTOBUF_C_TYPE_ENUM,
+  PROTOBUF_C_TYPE_STRING,
+  PROTOBUF_C_TYPE_BYTES,
+  //PROTOBUF_C_TYPE_GROUP,          // NOT SUPPORTED
+  PROTOBUF_C_TYPE_MESSAGE,
+} ProtobufCType;
+
+typedef int protobuf_c_boolean;
+#define PROTOBUF_C_OFFSETOF(struct, member) offsetof(struct, member)
+
+#define PROTOBUF_C_ASSERT(condition) assert(condition)
+#define PROTOBUF_C_ASSERT_NOT_REACHED() assert(0)
+
+typedef struct _ProtobufCBinaryData ProtobufCBinaryData;
+struct _ProtobufCBinaryData
+{
+  size_t len;
+  uint8_t *data;
+};
+
+typedef struct _ProtobufCIntRange ProtobufCIntRange; /* private */
+
+/* --- memory management --- */
+typedef struct _ProtobufCAllocator ProtobufCAllocator;
+struct _ProtobufCAllocator
+{
+  void *(*alloc)(void *allocator_data, size_t size);
+  void (*free)(void *allocator_data, void *pointer);
+  void *(*tmp_alloc)(void *allocator_data, size_t size);
+  unsigned max_alloca;
+  void *allocator_data;
+};
+
+/* This is a configurable allocator.
+ * By default, it uses the system allocator (meaning malloc() and free()).
+ * This is typically done to incorporate into frameworks that provide
+ * some nonstandard allocation functions.
+ */
+extern ProtobufCAllocator protobuf_c_default_allocator; /* settable */
+
+/* This is the system allocator, meaning it uses malloc() and free() */
+extern ProtobufCAllocator protobuf_c_system_allocator;  /* use malloc, free etc */
+
+/* This is the function that our default allocators call when they 
+   run out-of-memory.  The default behavior of this function is to
+   terminate your program. */
+extern void (*protobuf_c_out_of_memory) (void);
+
+/* --- append-only data buffer --- */
+typedef struct _ProtobufCBuffer ProtobufCBuffer;
+struct _ProtobufCBuffer
+{
+  void (*append)(ProtobufCBuffer     *buffer,
+                 size_t               len,
+                 const uint8_t       *data);
+};
+/* --- enums --- */
+typedef struct _ProtobufCEnumValue ProtobufCEnumValue;
+typedef struct _ProtobufCEnumValueIndex ProtobufCEnumValueIndex;
+typedef struct _ProtobufCEnumDescriptor ProtobufCEnumDescriptor;
+
+/* ProtobufCEnumValue:  this represents a single value of
+ * an enumeration.
+ * 'name' is the string identifying this value, as given in the .proto file.
+ * 'c_name' is the full name of the C enumeration value.
+ * 'value' is the number assigned to this value, as given in the .proto file.
+ */
+struct _ProtobufCEnumValue
+{
+  const char *name;
+  const char *c_name;
+  int value;
+};
+
+/* ProtobufCEnumDescriptor: the represents the enum as a whole,
+ * with all its values.
+ * 'magic' is a code we check to ensure that the api is used correctly.
+ * 'name' is the qualified name (e.g. "namespace.Type").
+ * 'short_name' is the unqualified name ("Type"), as given in the .proto file.
+ * 'package_name' is the '.'-separated namespace
+ * 'n_values' is the number of distinct values.
+ * 'values' is the array of distinct values.
+ * 'n_value_names' number of named values (including aliases).
+ * 'value_names' are the named values (including aliases).
+ *
+ * The rest of the values are private essentially.
+ *
+ * see also: Use protobuf_c_enum_descriptor_get_value_by_name()
+ * and protobuf_c_enum_descriptor_get_value() to efficiently
+ * lookup values in the descriptor.
+ */
+struct _ProtobufCEnumDescriptor
+{
+  uint32_t magic;
+
+  const char *name;
+  const char *short_name;
+  const char *c_name;
+  const char *package_name;
+
+  /* sorted by value */
+  unsigned n_values;
+  const ProtobufCEnumValue *values;
+
+  /* sorted by name */
+  unsigned n_value_names;
+  const ProtobufCEnumValueIndex *values_by_name;
+
+  /* value-ranges, for faster lookups by number */
+  unsigned n_value_ranges;
+  const ProtobufCIntRange *value_ranges;
+
+  void *reserved1;
+  void *reserved2;
+  void *reserved3;
+  void *reserved4;
+};
+
+/* --- messages --- */
+typedef struct _ProtobufCMessageDescriptor ProtobufCMessageDescriptor;
+typedef struct _ProtobufCFieldDescriptor ProtobufCFieldDescriptor;
+/* ProtobufCFieldDescriptor: description of a single field
+ * in a message.
+ * 'name' is the name of the field, as given in the .proto file.
+ * 'id' is the code representing the field, as given in the .proto file.
+ * 'label' is one of PROTOBUF_C_LABEL_{REQUIRED,OPTIONAL,REPEATED}
+ * 'type' is the type of field.
+ * 'quantifier_offset' is the offset in bytes into the message's C structure
+ *        for this member's "has_MEMBER" field (for optional members) or
+ *        "n_MEMBER" field (for repeated members).
+ * 'offset' is the offset in bytes into the message's C structure
+ *        for the member itself.
+ * 'descriptor' is a pointer to a ProtobufC{Enum,Message}Descriptor
+ *        if type is PROTOBUF_C_TYPE_{ENUM,MESSAGE} respectively,
+ *        otherwise NULL.
+ * 'default_value' is a pointer to a default value for this field,
+ *        where allowed.
+ */
+struct _ProtobufCFieldDescriptor
+{
+  const char *name;
+  uint32_t id;
+  ProtobufCLabel label;
+  ProtobufCType type;
+  unsigned quantifier_offset;
+  unsigned offset;
+  const void *descriptor;   /* for MESSAGE and ENUM types */
+  const void *default_value;   /* or NULL if no default-value */
+
+  void *reserved1;
+  void *reserved2;
+};
+/* ProtobufCMessageDescriptor: description of a message.
+ *
+ * 'magic' is a code we check to ensure that the api is used correctly.
+ * 'name' is the qualified name (e.g. "namespace.Type").
+ * 'short_name' is the unqualified name ("Type"), as given in the .proto file.
+ * 'c_name' is the c-formatted name of the structure
+ * 'package_name' is the '.'-separated namespace
+ * 'sizeof_message' is the size in bytes of the C structure
+ *        representing an instance of this type of message.
+ * 'n_fields' is the number of known fields in this message.
+ * 'fields' is the fields sorted by id number.
+ * 'fields_sorted_by_name', 'n_field_ranges' and 'field_ranges'
+ *       are used for looking up fields by name and id. (private)
+ */
+struct _ProtobufCMessageDescriptor
+{
+  uint32_t magic;
+
+  const char *name;
+  const char *short_name;
+  const char *c_name;
+  const char *package_name;
+
+  size_t sizeof_message;
+
+  /* sorted by field-id */
+  unsigned n_fields;
+  const ProtobufCFieldDescriptor *fields;
+  const unsigned *fields_sorted_by_name;
+
+  /* ranges, optimization for looking up fields */
+  unsigned n_field_ranges;
+  const ProtobufCIntRange *field_ranges;
+
+  void *reserved1;
+  void *reserved2;
+  void *reserved3;
+  void *reserved4;
+};
+
+
+/* ProtobufCMessage: an instance of a message.
+ *
+ * ProtobufCMessage is sort-of a lightweight
+ * base-class for all messages.
+ * 
+ * In particular, ProtobufCMessage doesn't have
+ * any allocation policy associated with it.
+ * That's because it is common to create ProtobufCMessage's
+ * on the stack.  In fact, we that's what we recommend
+ * for sending messages (because if you just allocate from the
+ * stack, then you can't really have a memory leak).
+ *
+ * This means that functions like protobuf_c_message_unpack()
+ * which return a ProtobufCMessage must be paired
+ * with a free function, like protobuf_c_message_free_unpacked().
+ *
+ * 'descriptor' gives the locations and types of the members of message
+ * 'n_unknown_fields' is the number of fields we didn't recognize.
+ * 'unknown_fields' are fields we didn't recognize.
+ */
+typedef struct _ProtobufCMessage ProtobufCMessage;
+typedef struct _ProtobufCMessageUnknownField ProtobufCMessageUnknownField;
+struct _ProtobufCMessage
+{
+  const ProtobufCMessageDescriptor *descriptor;
+  unsigned n_unknown_fields;
+  ProtobufCMessageUnknownField *unknown_fields;
+};
+#define PROTOBUF_C_MESSAGE_INIT(descriptor) { descriptor, 0, NULL }
+
+/* To pack a message: you have two options:
+   (1) you can compute the size of the message
+       using protobuf_c_message_get_packed_size() 
+       then pass protobuf_c_message_pack() a buffer of
+       that length.
+   (2) Provide a virtual buffer (a ProtobufCBuffer) to
+       accept data as we scan through it.
+ */
+size_t    protobuf_c_message_get_packed_size(const ProtobufCMessage *message);
+size_t    protobuf_c_message_pack           (const ProtobufCMessage *message,
+                                             uint8_t                *out);
+size_t    protobuf_c_message_pack_to_buffer (const ProtobufCMessage *message,
+                                             ProtobufCBuffer  *buffer);
+
+ProtobufCMessage *
+          protobuf_c_message_unpack         (const ProtobufCMessageDescriptor *,
+                                             ProtobufCAllocator  *allocator,
+                                             size_t               len,
+                                             const uint8_t       *data);
+void      protobuf_c_message_free_unpacked  (ProtobufCMessage    *message,
+                                             ProtobufCAllocator  *allocator);
+
+/* WARNING: 'to_init' must be a block of memory 
+   of size description->sizeof_message. */
+size_t    protobuf_c_message_init           (const ProtobufCMessageDescriptor *,
+                                             ProtobufCMessage       *to_init);
+
+/* --- services --- */
+typedef struct _ProtobufCMethodDescriptor ProtobufCMethodDescriptor;
+typedef struct _ProtobufCServiceDescriptor ProtobufCServiceDescriptor;
+
+struct _ProtobufCMethodDescriptor
+{
+  const char *name;
+  const ProtobufCMessageDescriptor *input;
+  const ProtobufCMessageDescriptor *output;
+};
+struct _ProtobufCServiceDescriptor
+{
+  uint32_t magic;
+
+  const char *name;
+  const char *short_name;
+  const char *c_name;
+  const char *package;
+  unsigned n_methods;
+  const ProtobufCMethodDescriptor *methods;    /* in order from .proto file */
+  const unsigned *method_indices_by_name;
+};
+
+typedef struct _ProtobufCService ProtobufCService;
+typedef void (*ProtobufCClosure)(const ProtobufCMessage *message,
+                                 void                   *closure_data);
+struct _ProtobufCService
+{
+  const ProtobufCServiceDescriptor *descriptor;
+  void (*invoke)(ProtobufCService *service,
+                 unsigned          method_index,
+                 const ProtobufCMessage *input,
+                 ProtobufCClosure  closure,
+                 void             *closure_data);
+  void (*destroy) (ProtobufCService *service);
+};
+
+
+void protobuf_c_service_destroy (ProtobufCService *);
+
+
+/* --- querying the descriptors --- */
+const ProtobufCEnumValue *
+protobuf_c_enum_descriptor_get_value_by_name 
+                         (const ProtobufCEnumDescriptor    *desc,
+                          const char                       *name);
+const ProtobufCEnumValue *
+protobuf_c_enum_descriptor_get_value        
+                         (const ProtobufCEnumDescriptor    *desc,
+                          int                               value);
+const ProtobufCFieldDescriptor *
+protobuf_c_message_descriptor_get_field_by_name
+                         (const ProtobufCMessageDescriptor *desc,
+                          const char                       *name);
+const ProtobufCFieldDescriptor *
+protobuf_c_message_descriptor_get_field        
+                         (const ProtobufCMessageDescriptor *desc,
+                          unsigned                          value);
+const ProtobufCMethodDescriptor *
+protobuf_c_service_descriptor_get_method_by_name
+                         (const ProtobufCServiceDescriptor *desc,
+                          const char                       *name);
+
+/* --- wire format enums --- */
+typedef enum
+{
+  PROTOBUF_C_WIRE_TYPE_VARINT,
+  PROTOBUF_C_WIRE_TYPE_64BIT,
+  PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED,
+  PROTOBUF_C_WIRE_TYPE_START_GROUP,     /* unsupported */
+  PROTOBUF_C_WIRE_TYPE_END_GROUP,       /* unsupported */
+  PROTOBUF_C_WIRE_TYPE_32BIT
+} ProtobufCWireType;
+
+/* --- unknown message fields --- */
+struct _ProtobufCMessageUnknownField
+{
+  uint32_t tag;
+  ProtobufCWireType wire_type;
+  size_t len;
+  uint8_t *data;
+};
+
+/* --- extra (superfluous) api:  trivial buffer --- */
+typedef struct _ProtobufCBufferSimple ProtobufCBufferSimple;
+struct _ProtobufCBufferSimple
+{
+  ProtobufCBuffer base;
+  size_t alloced;
+  size_t len;
+  uint8_t *data;
+  protobuf_c_boolean must_free_data;
+};
+#define PROTOBUF_C_BUFFER_SIMPLE_INIT(array_of_bytes) \
+{ { protobuf_c_buffer_simple_append }, \
+  sizeof(array_of_bytes), 0, (array_of_bytes), 0 }
+#define PROTOBUF_C_BUFFER_SIMPLE_CLEAR(simp_buf) \
+  do { if ((simp_buf)->must_free_data) \
+         protobuf_c_default_allocator.free (&protobuf_c_default_allocator.allocator_data, (simp_buf)->data); } while (0)
+
+/* ====== private ====== */
+#include "protobuf-c-private.h"
+
+
+PROTOBUF_C_END_DECLS
+
+#endif /* __PROTOBUF_C_RUNTIME_H_ */
index 8cca053e55a281f0b5326398ff7bac7e431dfef5..a962cac477fb7484facd041d0433df6c72f153ed 100644 (file)
 
 extern channel_t *defaultChan;
 
-static void sendServerReject(client_t *client, const char *reason, rejectType_t type)
+static void sendServerReject(client_t *client, const char *reason, MumbleProto__Reject__RejectType type)
 {
-       message_t *msg = Msg_create(ServerReject);
-       msg->sessionId = client->sessionId;
-       strcpy(msg->payload.serverReject.reason, reason);
-       msg->payload.serverReject.type = type;
+       message_t *msg = Msg_create(Reject);
+       msg->payload.reject->reason = strdup(reason);
+       msg->payload.reject->type = type;
+       msg->payload.reject->has_type = true;
        Client_send_message(client, msg);
 }
 
 static void sendPermissionDenied(client_t *client, const char *reason)
 {
        message_t *msg = Msg_create(PermissionDenied);
-       msg->sessionId = client->sessionId;
-       strncpy(msg->payload.permissionDenied.reason, reason, MAX_TEXT);
+       msg->payload.permissionDenied->has_type = true;
+       msg->payload.permissionDenied->type = MUMBLE_PROTO__PERMISSION_DENIED__DENY_TYPE__Text;
+       msg->payload.permissionDenied->reason = strdup(reason);
        Client_send_message(client, msg);
 }
 
@@ -65,7 +66,7 @@ void Mh_handle_message(client_t *client, message_t *msg)
        client_t *client_itr;
        
        switch (msg->messageType) {
-       case ServerAuthenticate:
+       case Authenticate:
                /*
                 * 1. Check stuff, Serverreject if not ok
                 * 2. Setup UDP encryption -> MessageCryptSetup
@@ -78,63 +79,67 @@ void Mh_handle_message(client_t *client, message_t *msg)
                 * 9. PlayerDeaf/PlayerMute/PlayerSelfMuteDeaf for all users it applies to
                 * 10. MessageServerSync
                 */
-               if (msg->payload.serverAuthenticate.version != MESSAGE_STREAM_VERSION) {
-                       char buf[64];
-                       sprintf(buf, "Wrong version of mumble protocol (client: %d, server: %d)",
-                                       msg->payload.serverAuthenticate.version, MESSAGE_STREAM_VERSION);
-                       sendServerReject(client, buf, WrongVersion);
-                       goto disconnect;
-               }
                                
+               Log_debug("Authenticate message received");
+               Log_debug("Username: %s", msg->payload.authenticate->username);
+               
+               client->authenticated = true;
+               
                client_itr = NULL;
                while (Client_iterate(&client_itr) != NULL) {
                        if (!IS_AUTH(client_itr))
                                continue;
-                       if (strncmp(client_itr->playerName, msg->payload.serverAuthenticate.userName, MAX_TEXT) == 0) {
+                       if (strncmp(client_itr->playerName, msg->payload.authenticate->username, MAX_TEXT) == 0) {
                                char buf[64];
                                sprintf(buf, "Username already in use");
-                               sendServerReject(client, buf, UsernameInUse);
+                               Log_debug("Username already in use");
+                               sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
                                goto disconnect;
                        }                               
                }
-               
-               if (strncmp(getStrConf(PASSPHRASE), msg->payload.serverAuthenticate.password, MAX_TEXT) != 0) {
+               if (msg->payload.authenticate->password && strncmp(getStrConf(PASSPHRASE), msg->payload.authenticate->password, MAX_TEXT) != 0) {
                        char buf[64];
                        sprintf(buf, "Wrong server password");
-                       sendServerReject(client, buf, WrongServerPW);
+                       Log_debug("Wrong server password: %s", msg->payload.authenticate->password);
+                       sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__WrongServerPW);
                        goto disconnect;
                }                               
-
-               if (strlen(msg->payload.serverAuthenticate.userName) == 0) { /* XXX - other invalid names? */
+               if (strlen(msg->payload.authenticate->username) == 0 ||
+                       strlen(msg->payload.authenticate->username) >= MAX_TEXT) { /* XXX - other invalid names? */
                        char buf[64];
                        sprintf(buf, "Invalid username");
-                       sendServerReject(client, buf, InvalidUsername);
+                       Log_debug("Invalid username");
+                       sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
                        goto disconnect;
                }                               
 
                if (Client_count() >= getIntConf(MAX_CLIENTS)) {
                        char buf[64];
                        sprintf(buf, "Server is full (max %d users)", getIntConf(MAX_CLIENTS));
-                       sendServerReject(client, buf, ServerFull);
+                       sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
                        goto disconnect;
                }
                
                /* Name & password */
-               strncpy(client->playerName, msg->payload.serverAuthenticate.userName, MAX_TEXT);
+               strncpy(client->playerName, msg->payload.authenticate->username, MAX_TEXT);
                client->playerId = client->sessionId;
-
-               client->authenticated = true;
                
-               /* XXX - Kick ghost */
+               
+               /* XXX - Kick ghost? */
                
                /* Setup UDP encryption */
                CryptState_init(&client->cryptState);
                CryptState_genKey(&client->cryptState);
                sendmsg = Msg_create(CryptSetup);
-               sendmsg->sessionId = client->sessionId;
-               memcpy(sendmsg->payload.cryptSetup.key, client->cryptState.raw_key, AES_BLOCK_SIZE);
-               memcpy(sendmsg->payload.cryptSetup.serverNonce, client->cryptState.encrypt_iv, AES_BLOCK_SIZE);
-               memcpy(sendmsg->payload.cryptSetup.clientNonce, client->cryptState.decrypt_iv, AES_BLOCK_SIZE);
+               sendmsg->payload.cryptSetup->has_key = true;
+               sendmsg->payload.cryptSetup->key.data = client->cryptState.raw_key;
+               sendmsg->payload.cryptSetup->key.len = AES_BLOCK_SIZE;
+               sendmsg->payload.cryptSetup->has_server_nonce = true;
+               sendmsg->payload.cryptSetup->server_nonce.data = client->cryptState.encrypt_iv;
+               sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
+               sendmsg->payload.cryptSetup->has_client_nonce = true;
+               sendmsg->payload.cryptSetup->client_nonce.data = client->cryptState.decrypt_iv;
+               sendmsg->payload.cryptSetup->client_nonce.len = AES_BLOCK_SIZE;
                Client_send_message(client, sendmsg);
 
                /* Channel stuff */
@@ -144,131 +149,159 @@ void Mh_handle_message(client_t *client, message_t *msg)
                ch_itr = NULL;
                Chan_iterate(&ch_itr);
                do {
-                       sendmsg = Msg_create(ChannelAdd);
-                       sendmsg->sessionId = 0;
-                       sendmsg->payload.channelAdd.id = ch_itr->id;
-                       if (ch_itr->id == 0)
-                               sendmsg->payload.channelAdd.parentId = -1;
-                       else
-                               sendmsg->payload.channelAdd.parentId = ch_itr->parent->id;
-                       strcpy(sendmsg->payload.channelAdd.name, ch_itr->name);
-                       Client_send_message(client, sendmsg);
-                       
-                       sendmsg = Msg_create(ChannelDescUpdate);
-                       sendmsg->sessionId = 0;
-                       sendmsg->payload.channelDescUpdate.id = ch_itr->id;
-                       strcpy(sendmsg->payload.channelDescUpdate.desc, ch_itr->desc);
+                       sendmsg = Msg_create(ChannelState);
+                       sendmsg->payload.channelState->has_channel_id = true;
+                       sendmsg->payload.channelState->channel_id = ch_itr->id;
+                       if (ch_itr->id != 0) {
+                               sendmsg->payload.channelState->has_parent = true;
+                               sendmsg->payload.channelState->parent = ch_itr->parent->id;
+                       }
+                       sendmsg->payload.channelState->name = strdup(ch_itr->name);
+                       if (strlen(ch_itr->desc) > 0) {
+                               sendmsg->payload.channelState->description = strdup(ch_itr->desc);
+                       }
+                       Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
                        Client_send_message(client, sendmsg);
                        
                        Chan_iterate(&ch_itr);
                } while (ch_itr != NULL);
 
-               /* Not supporting channel link for now */
-
-               /* Server join for connecting user */
-               sendmsg = Msg_create(ServerJoin);
-               sendmsg->sessionId = client->sessionId;
-               sendmsg->payload.serverJoin.id = client->playerId;
-               strcpy(sendmsg->payload.serverJoin.playerName, client->playerName);
+               /* Not supporting channel links yet */
+               
+               /* Send user state for connecting user to other users */
+               sendmsg = Msg_create(UserState);
+               sendmsg->payload.userState->has_session = true;
+               sendmsg->payload.userState->session = client->sessionId;
+               sendmsg->payload.userState->has_user_id = true;
+               sendmsg->payload.userState->user_id = client->playerId;
+               sendmsg->payload.userState->name = strdup(client->playerName);
+               sendmsg->payload.userState->has_channel_id = true;
+               sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
+               
                Client_send_message_except(client, sendmsg);
 
-               /* Player move for connecting user */
-               if (((channel_t *)client->channel)->id != 0) {
-                       sendmsg = Msg_create(PlayerMove);
-                       sendmsg->sessionId = client->sessionId;
-                       sendmsg->payload.playerMove.victim = client->playerId;
-                       sendmsg->payload.playerMove.channel = ((channel_t *)client->channel)->id;
-                       Client_send_message_except(client, sendmsg);
-               }
                client_itr = NULL;
                while (Client_iterate(&client_itr) != NULL) {
                        if (!IS_AUTH(client_itr))
                                continue;
-                       sendmsg = Msg_create(ServerJoin);
-                       sendmsg->sessionId = client_itr->sessionId;
-                       sendmsg->payload.serverJoin.id = client_itr->playerId;
-                       strncpy(sendmsg->payload.serverJoin.playerName, client_itr->playerName, MAX_TEXT);
-                       Client_send_message(client, sendmsg);
-                       
-                       sendmsg = Msg_create(PlayerMove);
-                       sendmsg->sessionId = client_itr->sessionId;
-                       sendmsg->payload.playerMove.victim = client_itr->playerId;
-                       sendmsg->payload.playerMove.channel = ((channel_t *)client_itr->channel)->id;
+                       sendmsg = Msg_create(UserState);
+                       sendmsg->payload.userState->has_session = true;
+                       sendmsg->payload.userState->session = client->sessionId;
+                       sendmsg->payload.userState->name = strdup(client->playerName);
+                       sendmsg->payload.userState->has_channel_id = true;
+                       sendmsg->payload.userState->channel_id = ((channel_t *)client->channel)->id;
+
+                       /* XXX - check if self_* is correct */
+                       if (client->deaf) {
+                               sendmsg->payload.userState->has_self_deaf = true;
+                               sendmsg->payload.userState->self_deaf = true;
+                       }
+                       if (client->mute) {
+                               sendmsg->payload.userState->has_self_mute = true;
+                               sendmsg->payload.userState->self_mute = true;
+                       }
                        Client_send_message(client, sendmsg);
                }
-               
+
+               /* Sync message */
                sendmsg = Msg_create(ServerSync);
-               sendmsg->sessionId = client->sessionId;
-               strcpy(sendmsg->payload.serverSync.welcomeText, getStrConf(WELCOMETEXT));
-               sendmsg->payload.serverSync.maxBandwidth = getIntConf(MAX_BANDWIDTH);
+               sendmsg->payload.serverSync->has_session = true;
+               sendmsg->payload.serverSync->session = client->sessionId;
+               sendmsg->payload.serverSync->welcome_text = strdup(getStrConf(WELCOMETEXT));
+               sendmsg->payload.serverSync->has_max_bandwidth = true;
+               sendmsg->payload.serverSync->max_bandwidth = getIntConf(MAX_BANDWIDTH);
+               sendmsg->payload.serverSync->has_allow_html = true;
+               sendmsg->payload.serverSync->allow_html = false; /* Support this? */
                Client_send_message(client, sendmsg);
                
-               Log_info("Player %s authenticated", client->playerName);
-               
+               Log_info("User %s authenticated", client->playerName);
                break;
                
-       case PingStats:
-               client->cryptState.uiRemoteGood = msg->payload.pingStats.good;
-               client->cryptState.uiRemoteLate = msg->payload.pingStats.late;
-               client->cryptState.uiRemoteLost = msg->payload.pingStats.lost;
-               client->cryptState.uiRemoteResync = msg->payload.pingStats.resync;
+       case Ping:
+       {
+               uint64_t timestamp;
+               if (msg->payload.ping->has_good)
+                       client->cryptState.uiRemoteGood = msg->payload.ping->good;
+               if (msg->payload.ping->has_late)
+                       client->cryptState.uiRemoteLate = msg->payload.ping->late;
+               if (msg->payload.ping->has_lost)
+                       client->cryptState.uiRemoteLost = msg->payload.ping->lost;
+               if (msg->payload.ping->has_resync)
+                       client->cryptState.uiRemoteResync = msg->payload.ping->resync;
 
-               Log_debug("Pingstats <-: %d %d %d %d",
+               Log_debug("Ping <-: %d %d %d %d",
                                  client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
-                                 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync);
+                                 client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
+                       );
                
                /* Ignoring the double values since they don't seem to be used */
-               sendmsg = Msg_create(PingStats);
-               sendmsg->sessionId = client->sessionId;
-               sendmsg->payload.pingStats.timestamp = msg->payload.pingStats.timestamp;
                
-               sendmsg->payload.pingStats.good = client->cryptState.uiGood;
-               sendmsg->payload.pingStats.late = client->cryptState.uiLate;
-               sendmsg->payload.pingStats.lost = client->cryptState.uiLost;
-               sendmsg->payload.pingStats.resync = client->cryptState.uiResync;
+               sendmsg = Msg_create(Ping);
+               timestamp = msg->payload.ping->timestamp;
+
+               sendmsg->payload.ping->timestamp = timestamp;
                
+               sendmsg->payload.ping->good = client->cryptState.uiGood;
+               sendmsg->payload.ping->has_good = true;
+               sendmsg->payload.ping->late = client->cryptState.uiLate;
+               sendmsg->payload.ping->has_late = true;
+               sendmsg->payload.ping->lost = client->cryptState.uiLost;
+               sendmsg->payload.ping->has_lost = true;
+               sendmsg->payload.ping->resync = client->cryptState.uiResync;
+               sendmsg->payload.ping->has_resync = true;
+
                Client_send_message(client, sendmsg);
-               Log_debug("Pingstats ->: %d %d %d %d",
+               Log_debug("Ping ->: %d %d %d %d",
                                  client->cryptState.uiGood, client->cryptState.uiLate,
                                  client->cryptState.uiLost, client->cryptState.uiResync);
 
                break;
-       case Ping:
-               sendmsg = Msg_create(Ping);
-               sendmsg->sessionId = client->sessionId;
-               sendmsg->payload.ping.timestamp = msg->payload.ping.timestamp;
-               Client_send_message(client, sendmsg);
-               break;
-       case CryptSync:
+       }
+       case CryptSetup:
                Log_debug("Voice channel crypt resync requested");
-               if (msg->payload.cryptSync.empty) {
-                       sendmsg = Msg_create(CryptSync);
-                       sendmsg->sessionId = msg->sessionId;
-                       sendmsg->payload.cryptSync.empty = false;
-                       memcpy(sendmsg->payload.cryptSync.nonce, client->cryptState.decrypt_iv, AES_BLOCK_SIZE);
+               if (!msg->payload.cryptSetup->has_client_nonce) {
+                       sendmsg = Msg_create(CryptSetup);
+                       sendmsg->payload.cryptSetup->has_server_nonce = true;
+                       memcpy(sendmsg->payload.cryptSetup->server_nonce.data, client->cryptState.decrypt_iv, AES_BLOCK_SIZE);
+                       sendmsg->payload.cryptSetup->server_nonce.len = AES_BLOCK_SIZE;
                        Client_send_message(client, sendmsg);
                } else {
-                       memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSync.nonce, AES_BLOCK_SIZE);
+                       memcpy(client->cryptState.decrypt_iv, msg->payload.cryptSetup->client_nonce.data, AES_BLOCK_SIZE);
                        client->cryptState.uiResync++;
                }
                break;
-       case PlayerMute:
-               if (msg->payload.playerMute.victim != client->playerId) {
+       case UserState:
+               /* Only allow state changes for for the self user */
+               if (msg->payload.userState->has_session &&
+                       msg->payload.userState->session != client->sessionId) {
                        sendPermissionDenied(client, "Permission denied");
-               } else {
-                       Log_debug("Player ID %d muted", msg->payload.playerMute.victim);
-                       client->mute = msg->payload.playerMute.bMute;                   
+                       break;
                }
-               break;
-       case PlayerDeaf:
-               if (msg->payload.playerDeaf.victim != client->playerId) {
-                       sendPermissionDenied(client, "Permission denied");
-               } else {
-                       Log_debug("Player ID %d deaf", msg->payload.playerDeaf.victim);
-                       client->deaf = msg->payload.playerDeaf.bDeaf;
+               if (msg->payload.userState->has_user_id || msg->payload.userState->has_mute ||
+                       msg->payload.userState->has_deaf || msg->payload.userState->has_suppress ||
+                       msg->payload.userState->has_texture) {
+                       
+                       sendPermissionDenied(client, "Not supported by uMurmur");
+                       break;
+               }
+               if (msg->payload.userState->has_self_deaf) {
+                       client->deaf = msg->payload.userState->self_deaf;
+               }
+               if (msg->payload.userState->has_self_mute) {
+                       client->mute = msg->payload.userState->self_mute;                       
                }
+               if (msg->payload.userState->has_channel_id) {
+                       Chan_playerJoin_id(msg->payload.userState->channel_id, client);
+               }
+               /* Re-use message */
+               Msg_inc_ref(msg);
+               msg->payload.userState->has_actor = true;
+               msg->payload.userState->actor = client->sessionId;
+               Client_send_message_except(NULL, msg);
                break;
+               
        case TextMessage:
+#if 0
                if (msg->payload.textMessage.bTree)
                        sendPermissionDenied(client, "Tree message not supported");
                else if (msg->payload.textMessage.channel != -1) { /* To channel */
@@ -307,38 +340,42 @@ void Mh_handle_message(client_t *client, message_t *msg)
                                Log_warn("TextMessage: Player ID %d not found", msg->payload.textMessage.victim);
                }
                break;
-       case PlayerSelfMuteDeaf:
-               client->deaf = msg->payload.playerSelfMuteDeaf.bDeaf;
-               client->mute = msg->payload.playerSelfMuteDeaf.bMute;
-               Log_debug("Player ID %d %s and %s", client->playerId, client->deaf ? "deaf": "not deaf",
-                                 client->mute ? "mute" : "not mute");
+#endif
+
+       case VoiceTarget:
+               /* XXX -TODO */
                break;
-       case PlayerMove:
-               Msg_inc_ref(msg); /* Re-use message */
-               Client_send_message_except(NULL, msg);
-               Chan_playerJoin_id(msg->payload.playerMove.channel, client);            
+
+       case Version:
+               sendmsg = Msg_create(Version); /* Re-use message */
+               Log_debug("Version message received");
+               sendmsg->payload.version->has_version = true;
+               sendmsg->payload.version->version = (1 << 16) | (2 << 8) | 0; /* XXX fix */
+               sendmsg->payload.version->release = "Phony donkey";
+               sendmsg->payload.version->os = "OpenWRT";
+               
+               Client_send_message(client, sendmsg);
                break;
+       case CodecVersion:
+               Msg_inc_ref(msg); /* Re-use message */
 
+               /* XXX - fill in version */
+               
+               Client_send_message(client, msg);
+               break;
+       case UDPTunnel:
+               Client_voiceMsg(client, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
+           break;
                /* Permission denied for all these messages. Not implemented. */
-       case PlayerRename:
-       case ChannelAdd:
-       case ChannelDescUpdate:
-       case ContextAction:
-       case ContextAddAction:
-       case ServerBanList:
-       case PlayerKick:
-       case PlayerBan:
        case ChannelRemove:
-       case ChannelMove:
-       case ChannelLink:
-       case ChannelRename:
-       case EditACL:
+       case ChannelState:
+       case ContextAction:
+       case ContextActionAdd:
+       case ACL:
+       case BanList:
                sendPermissionDenied(client, "Not supported by uMurmur");
                break;
-               
-       case PlayerTexture: /* Ignore */
-               break;
-               
+                               
        default:
                Log_warn("Message %d not handled", msg->messageType);
                break;
index 42f1fa9a34fa5337ab0f1e4c68fce7da1164365f..3014f88ca34f19b882f1776b080cf891ec95803e 100644 (file)
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <arpa/inet.h>
 
 #include "messages.h"
+#include "client.h"
 #include "pds.h"
 #include "log.h"
 
 
 void dumpmsg(uint8_t *data, int size);
 
-int Msg_messageToNetwork(message_t *msg, uint8_t *buffer, int bufsize)
+void Msg_addPreamble(uint8_t *buffer, uint16_t type, uint32_t len)
 {
-       pds_t *pds = Pds_create(buffer, bufsize);
-       int len;
+       uint16_t *msgType = (uint16_t *) &buffer[0];
+       uint32_t *msgLen = (uint32_t *) &buffer[2];
        
-       Pds_add_numval(pds, msg->messageType);
-       Pds_add_numval(pds, msg->sessionId);
+       *msgType = htons(type);
+       *msgLen = htonl(len);
+}
+
+static void Msg_getPreamble(uint8_t *buffer, int *type, int *len)
+{
+       uint16_t *msgType = (uint16_t *) &buffer[0];
+       uint32_t *msgLen = (uint32_t *) &buffer[2];
        
+       *type = (int)ntohs(*msgType);
+       *len = (int)ntohl(*msgLen);
+}
+
+#define MAX_MSGSIZE (BUFSIZE - 6)
+int Msg_messageToNetwork(message_t *msg, uint8_t *buffer)
+{
+       int len;
+       uint8_t *bufptr = buffer + 6;
+               
+       Log_debug("To net: msg type %d", msg->messageType);
        switch (msg->messageType) {
-               case Speex:
-                       Pds_add_numval(pds, msg->payload.speex.seq);
-                       Pds_append_data_nosize(pds, msg->payload.speex.data, msg->payload.speex.size);
-                       break;
-               case ServerReject:
-                       Pds_add_string(pds, msg->payload.serverReject.reason);
-                       Pds_add_numval(pds, msg->payload.serverReject.type);
-                       break;
-               case ServerSync:
-                       Pds_add_numval(pds, msg->payload.serverSync.maxBandwidth);
-                       Pds_add_string(pds, msg->payload.serverSync.welcomeText);
-                       break;
-               case ServerJoin:
-                       Pds_add_string(pds, msg->payload.serverJoin.playerName);                        
-                       Pds_add_numval(pds, msg->payload.serverJoin.id);
-                       break;
-               case ChannelDescUpdate:
-                       Pds_add_numval(pds, msg->payload.channelDescUpdate.id);
-                       Pds_add_string(pds, msg->payload.channelDescUpdate.desc);                       
-                       break;
-               case ChannelAdd:
-                       Pds_add_numval(pds, msg->payload.channelAdd.id);
-                       Pds_add_numval(pds, msg->payload.channelAdd.parentId);
-                       Pds_add_string(pds, msg->payload.channelAdd.name);
-                       break;
-               case PlayerMove:
-                       Pds_add_numval(pds, msg->payload.playerMove.victim);
-                       Pds_add_numval(pds, msg->payload.playerMove.channel);
-                       break;
-               case QueryUsers:
-                       break;
-               case Ping:
-                       Pds_add_numval(pds, msg->payload.ping.timestamp);
-                       break;
-               case PingStats:
-                       Pds_add_numval(pds, msg->payload.pingStats.timestamp);
-                       Pds_add_numval(pds, msg->payload.pingStats.good);
-                       Pds_add_numval(pds, msg->payload.pingStats.late);
-                       Pds_add_numval(pds, msg->payload.pingStats.lost);
-                       Pds_add_numval(pds, msg->payload.pingStats.resync);
-                       Pds_add_double(pds, msg->payload.pingStats.dUDPPingAvg);
-                       Pds_add_double(pds, msg->payload.pingStats.dUDPPingVar);
-                       Pds_add_numval(pds, msg->payload.pingStats.UDPPackets);
-                       Pds_add_double(pds, msg->payload.pingStats.dTCPPingAvg);
-                       Pds_add_double(pds, msg->payload.pingStats.dTCPPingVar);
-                       Pds_add_numval(pds, msg->payload.pingStats.TCPPackets);                 
-                       break;
-               case PlayerMute:
-                       break;
-               case PlayerDeaf:
-                       break;
-               case PlayerSelfMuteDeaf:
+       case Version:
+               len = mumble_proto__version__get_packed_size(msg->payload.version);
+               if (len > MAX_MSGSIZE) {
+                       Log_warn("Too big tx message. Discarding");
                        break;
-               case TextMessage:
-                       Pds_add_numval(pds, msg->payload.textMessage.victim);                   
-                       Pds_add_numval(pds, msg->payload.textMessage.channel);                  
-                       Pds_add_numval(pds, msg->payload.textMessage.bTree);                    
-                       Pds_add_string(pds, msg->payload.textMessage.message);
-                       break;
-               case PermissionDenied:
-                       Pds_add_string(pds, msg->payload.permissionDenied.reason);
-                       break;
-               case CryptSetup:
-                       Pds_append_data(pds, msg->payload.cryptSetup.key, AES_BLOCK_SIZE);
-                       Pds_append_data(pds, msg->payload.cryptSetup.serverNonce, AES_BLOCK_SIZE);
-                       Pds_append_data(pds, msg->payload.cryptSetup.clientNonce, AES_BLOCK_SIZE);
-                       break;
-               case CryptSync:
-                       if (!msg->payload.cryptSync.empty)
-                               Pds_append_data(pds, msg->payload.cryptSync.nonce, AES_BLOCK_SIZE);                     
-                       break;
-               case ServerLeave:
-                       /* No info to add */
+               }
+               Msg_addPreamble(buffer, msg->messageType, len);
+               mumble_proto__version__pack(msg->payload.version, bufptr);
+               break;
+       case UDPTunnel:
+               len = mumble_proto__udptunnel__get_packed_size(msg->payload.UDPTunnel);
+               if (len > MAX_MSGSIZE) {
+                       Log_warn("Too big tx message. Discarding");
                        break;
+               }
+               Msg_addPreamble(buffer, msg->messageType, len);
+               mumble_proto__udptunnel__pack(msg->payload.UDPTunnel, bufptr);          
+               break;
+       case Authenticate:
+               len = mumble_proto__authenticate__get_packed_size(msg->payload.authenticate);
+               if (len > MAX_MSGSIZE) {
+                       Log_warn("Too big tx message. Discarding");
+                       break;
+                       }
+               Msg_addPreamble(buffer, msg->messageType, len);
+               mumble_proto__authenticate__pack(msg->payload.authenticate, bufptr);
+               break;
+       case Ping:
+               len = mumble_proto__ping__get_packed_size(msg->payload.ping);
+               if (len > MAX_MSGSIZE) {
+                       Log_warn("Too big tx message. Discarding");
+                       break;
+                       }
+               Msg_addPreamble(buffer, msg->messageType, len);
+               mumble_proto__ping__pack(msg->payload.ping, bufptr);
+               break;
+       case Reject:
+               len = mumble_proto__reject__get_packed_size(msg->payload.reject);
+               if (len > MAX_MSGSIZE) {
+                       Log_warn("Too big tx message. Discarding");
+                       break;
+                       }
+               Msg_addPreamble(buffer, msg->messageType, len);
+               mumble_proto__reject__pack(msg->payload.reject, bufptr);
+               break;
+       case ServerSync:
+               len = mumble_proto__server_sync__get_packed_size(msg->payload.serverSync);
+               if (len > MAX_MSGSIZE) {
+                       Log_warn("Too big tx message. Discarding");
+                       break;
+                       }
+               Msg_addPreamble(buffer, msg->messageType, len);
+               mumble_proto__server_sync__pack(msg->payload.serverSync, bufptr);
+               break;
+       case TextMessage:
+               len = mumble_proto__text_message__get_packed_size(msg->payload.textMessage);
+               if (len > MAX_MSGSIZE) {
+                       Log_warn("Too big tx message. Discarding");
+                       break;
+                       }
+               Msg_addPreamble(buffer, msg->messageType, len);
+               mumble_proto__text_message__pack(msg->payload.textMessage, bufptr);
+               break;
+       case PermissionDenied:
+               len = mumble_proto__permission_denied__get_packed_size(msg->payload.permissionDenied);
+               if (len > MAX_MSGSIZE) {
+                       Log_warn("Too big tx message. Discarding");
+                       break;
+                       }
+               Msg_addPreamble(buffer, msg->messageType, len);
+               mumble_proto__permission_denied__pack(msg->payload.permissionDenied, bufptr);
+               break;
+       case CryptSetup:
+               len = mumble_proto__crypt_setup__get_packed_size(msg->payload.cryptSetup);
+               if (len > MAX_MSGSIZE) {
+                       Log_warn("Too big tx message. Discarding");
+                       break;
+                       }
+               Msg_addPreamble(buffer, msg->messageType, len);
+               mumble_proto__crypt_setup__pack(msg->payload.cryptSetup, bufptr);
+               break;
+       case UserList:
+               len = mumble_proto__user_list__get_packed_size(msg->payload.userList);
+               if (len > MAX_MSGSIZE) {
+                       Log_warn("Too big tx message. Discarding");
+                       break;
+                       }
+               Msg_addPreamble(buffer, msg->messageType, len);
+               mumble_proto__user_list__pack(msg->payload.userList, bufptr);
+               break;
+       case UserState:
+               len = mumble_proto__user_state__get_packed_size(msg->payload.userState);
+               if (len > MAX_MSGSIZE) {
+                       Log_warn("Too big tx message. Discarding");
+                       break;
+                       }
+               Msg_addPreamble(buffer, msg->messageType, len);
+               mumble_proto__user_state__pack(msg->payload.userState, bufptr);
+               break;
+       case ChannelState:
+               len = mumble_proto__channel_state__get_packed_size(msg->payload.channelState);
+               if (len > MAX_MSGSIZE) {
+                       Log_warn("Too big tx message. Discarding");
+                       break;
+                       }
+               Msg_addPreamble(buffer, msg->messageType, len);
+               mumble_proto__channel_state__pack(msg->payload.channelState, bufptr);
+               break;
+       case VoiceTarget:
+               len = mumble_proto__voice_target__get_packed_size(msg->payload.voiceTarget);
+               if (len > MAX_MSGSIZE) {
+                       Log_warn("Too big tx message. Discarding");
+                       break;
+                       }
+               Msg_addPreamble(buffer, msg->messageType, len);
+               mumble_proto__voice_target__pack(msg->payload.voiceTarget, bufptr);
+               break;
+       case CodecVersion:
+               len = mumble_proto__codec_version__get_packed_size(msg->payload.codecVersion);
+               if (len > MAX_MSGSIZE) {
+                       Log_warn("Too big tx message. Discarding");
+                       break;
+                       }
+               Msg_addPreamble(buffer, msg->messageType, len);
+               mumble_proto__codec_version__pack(msg->payload.codecVersion, bufptr);
+               break;
 
        default:
                Log_warn("Unsupported message %d", msg->messageType);
-               break;
+               return 0;
        }
-       len = pds->offset;
-       Pds_free(pds);
-       return len;
+       return len + 6;
 }
 
 message_t *Msg_create(messageType_t messageType)
@@ -144,11 +213,73 @@ message_t *Msg_create(messageType_t messageType)
        msg->messageType = messageType;
        init_list_entry(&msg->node);
        
-       if (msg->messageType == Speex) {
-               msg->payload.speex.data = malloc(SPEEX_DATA_SIZE);
-               if (msg->payload.speex.data == NULL)
-                       Log_fatal("Out of memory");
+       switch (messageType) {
+       case Version:
+               msg->payload.version = malloc(sizeof(MumbleProto__Version));
+               mumble_proto__version__init(msg->payload.version);
+               break;
+       case UDPTunnel:
+               msg->payload.UDPTunnel = malloc(sizeof(MumbleProto__UDPTunnel));
+               mumble_proto__udptunnel__init(msg->payload.UDPTunnel);
+               break;
+       case Authenticate:
+               msg->payload.authenticate = malloc(sizeof(MumbleProto__Authenticate));
+               mumble_proto__authenticate__init(msg->payload.authenticate);
+               break;
+       case Ping:
+               msg->payload.ping = malloc(sizeof(MumbleProto__Ping));
+               mumble_proto__ping__init(msg->payload.ping);
+               break;
+       case Reject:
+               msg->payload.reject = malloc(sizeof(MumbleProto__Reject));
+               mumble_proto__reject__init(msg->payload.reject);
+               break;
+       case ServerSync:
+               msg->payload.serverSync = malloc(sizeof(MumbleProto__ServerSync));
+               mumble_proto__server_sync__init(msg->payload.serverSync);
+               break;
+       case TextMessage:
+               msg->payload.textMessage = malloc(sizeof(MumbleProto__TextMessage));
+               mumble_proto__text_message__init(msg->payload.textMessage);
+               break;
+       case PermissionDenied:
+               msg->payload.permissionDenied = malloc(sizeof(MumbleProto__PermissionDenied));
+               mumble_proto__permission_denied__init(msg->payload.permissionDenied);
+               break;
+       case CryptSetup:
+               msg->payload.cryptSetup = malloc(sizeof(MumbleProto__CryptSetup));
+               mumble_proto__crypt_setup__init(msg->payload.cryptSetup);
+               break;
+       case UserList:
+               msg->payload.userList = malloc(sizeof(MumbleProto__UserList));
+               mumble_proto__user_list__init(msg->payload.userList);
+               break;
+       case UserState:
+               msg->payload.userState = malloc(sizeof(MumbleProto__UserState));
+               mumble_proto__user_state__init(msg->payload.userState);
+               break;
+       case UserRemove:
+               msg->payload.userRemove = malloc(sizeof(MumbleProto__UserRemove));
+               mumble_proto__user_remove__init(msg->payload.userRemove);
+               break;
+       case VoiceTarget:
+               msg->payload.voiceTarget = malloc(sizeof(MumbleProto__VoiceTarget));
+               mumble_proto__voice_target__init(msg->payload.voiceTarget);
+               break;
+       case CodecVersion:
+               msg->payload.codecVersion = malloc(sizeof(MumbleProto__CodecVersion));
+               mumble_proto__codec_version__init(msg->payload.codecVersion);
+               break;
+       case ChannelState:
+               msg->payload.channelState = malloc(sizeof(MumbleProto__ChannelState));
+               mumble_proto__channel_state__init(msg->payload.channelState);
+               break;
+
+       default:
+               Log_warn("Msg_create: Unsupported message %d", msg->messageType);
+               break;
        }
+
        return msg;
 }
 
@@ -162,8 +293,124 @@ void Msg_free(message_t *msg)
        if (msg->refcount) msg->refcount--;
        if (msg->refcount > 0)
                return;
-       if (msg->messageType == Speex)
-               free(msg->payload.speex.data);
+
+       /* XXX - add free for locally generated messages too */
+       switch (msg->messageType) {
+       case Version:
+               if (msg->unpacked)
+                       mumble_proto__version__free_unpacked(msg->payload.version, NULL);
+               else {
+                       free(msg->payload.version);
+               }
+               break;
+       case UDPTunnel:
+               if (msg->unpacked)
+                       mumble_proto__udptunnel__free_unpacked(msg->payload.UDPTunnel, NULL);
+               else {
+                       free(msg->payload.UDPTunnel->packet.data);
+                       free(msg->payload.UDPTunnel);
+               }
+               break;
+       case Authenticate:
+               if (msg->unpacked)
+                       mumble_proto__authenticate__free_unpacked(msg->payload.authenticate, NULL);
+               break;
+       case Ping:
+               if (msg->unpacked)
+                       mumble_proto__ping__free_unpacked(msg->payload.ping, NULL);
+               else {
+                       free(msg->payload.ping);
+               }
+               break;
+       case Reject:
+               if (msg->unpacked)
+                       mumble_proto__reject__free_unpacked(msg->payload.reject, NULL);
+               else {
+                       free(msg->payload.reject->reason);
+                       free(msg->payload.reject);
+               }
+               break;
+       case ServerSync:
+               if (msg->unpacked)
+                       mumble_proto__server_sync__free_unpacked(msg->payload.serverSync, NULL);
+               else {
+                       free(msg->payload.serverSync->welcome_text);
+                       free(msg->payload.serverSync);
+               }
+               break;
+       case TextMessage:
+               if (msg->unpacked)
+                       mumble_proto__text_message__free_unpacked(msg->payload.textMessage, NULL);
+               else {
+                       free(msg->payload.textMessage);
+               }
+               break;
+       case PermissionDenied:
+               if (msg->unpacked)
+                       mumble_proto__permission_denied__free_unpacked(msg->payload.permissionDenied, NULL);
+               else {
+                       free(msg->payload.permissionDenied->reason);
+                       free(msg->payload.permissionDenied);
+               }
+               break;
+       case CryptSetup:
+               if (msg->unpacked)
+                       mumble_proto__crypt_setup__free_unpacked(msg->payload.cryptSetup, NULL);
+               else {
+                       free(msg->payload.cryptSetup);
+               }
+               break;
+       case UserList:
+               if (msg->unpacked)
+                       mumble_proto__user_list__free_unpacked(msg->payload.userList, NULL);
+               else {
+                       free(msg->payload.userList);
+               }
+               break;
+       case UserState:
+               if (msg->unpacked)
+                       mumble_proto__user_state__free_unpacked(msg->payload.userState, NULL);
+               else {
+                       free(msg->payload.userState->name);
+                       free(msg->payload.userState);
+               }
+               break;
+       case UserRemove:
+               if (msg->unpacked)
+                       mumble_proto__user_remove__free_unpacked(msg->payload.userRemove, NULL);
+               else {
+                       free(msg->payload.userRemove);
+               }
+               break;
+       case VoiceTarget:
+               if (msg->unpacked)
+                       mumble_proto__voice_target__free_unpacked(msg->payload.voiceTarget, NULL);
+               else {
+                       free(msg->payload.voiceTarget);
+               }
+               break;
+       case CodecVersion:
+               if (msg->unpacked)
+                       mumble_proto__codec_version__free_unpacked(msg->payload.codecVersion, NULL);
+               else {
+                       free(msg->payload.codecVersion);
+               }
+               break;
+       case ChannelState:
+               if (msg->unpacked)
+                       mumble_proto__channel_state__free_unpacked(msg->payload.channelState, NULL);
+               else {
+                       if (msg->payload.channelState->description)
+                               free(msg->payload.channelState->description);
+                       free(msg->payload.channelState->name);
+                       free(msg->payload.channelState);
+               }
+               break;
+
+       default:
+               Log_warn("Msg_free: Unsupported message %d", msg->messageType);
+               break;
+       }
        free(msg);
 }
 
@@ -187,167 +434,110 @@ void dumpmsg(uint8_t *data, int size)
 message_t *Msg_networkToMessage(uint8_t *data, int size)
 {
        message_t *msg = NULL;
-       int messageType;
-       int sessionId;
-       pds_t *pds;
+       uint8_t *msgData = &data[6];
+       int messageType, msgLen;
 
-       pds = Pds_create(data, size);
-       messageType = Pds_get_numval(pds);
-       sessionId = Pds_get_numval(pds);
+       Msg_getPreamble(data, &messageType, &msgLen);
+
+       Log_debug("Message type %d size %d", messageType, msgLen);
+       dumpmsg(data, size);
        
        switch (messageType) {
-               case Speex:
-                       msg = Msg_create(Speex);
-                       msg->payload.speex.seq = Pds_get_numval(pds);
-                       msg->payload.speex.size = pds->maxsize - pds->offset;
-                       memcpy(msg->payload.speex.data, &pds->data[pds->offset], pds->maxsize - pds->offset);
-                       break;
-               case ServerAuthenticate:
-                       msg = Msg_create(ServerAuthenticate);
-                       msg->payload.serverAuthenticate.version = Pds_get_numval(pds);
-                       Pds_get_string(pds, msg->payload.serverAuthenticate.userName, MAX_TEXT);
-                       Pds_get_string(pds, msg->payload.serverAuthenticate.password, MAX_TEXT);
-                       break;
-               case ServerReject:
-                       msg = Msg_create(ServerReject);
-                       break;
-               case ServerSync:
-                       msg = Msg_create(ServerSync);
-                       break;
-               case ServerJoin:
-                       msg = Msg_create(ServerJoin);
-                       break;
-               case ServerLeave:
-                       msg = Msg_create(ServerLeave);
-                       break;
-               case QueryUsers:
-                       msg = Msg_create(QueryUsers);
-                       break;
-               case Ping:
-                       msg = Msg_create(Ping);
-                       msg->payload.ping.timestamp = Pds_get_numval(pds);
-                       break;
-               case PingStats:
-                       msg = Msg_create(PingStats);
-                       msg->payload.pingStats.timestamp = Pds_get_numval(pds);
-                       msg->payload.pingStats.good = Pds_get_numval(pds);
-                       msg->payload.pingStats.late = Pds_get_numval(pds);
-                       msg->payload.pingStats.lost = Pds_get_numval(pds);
-                       msg->payload.pingStats.resync = Pds_get_numval(pds);
-                       msg->payload.pingStats.dUDPPingAvg = Pds_get_double(pds);
-                       msg->payload.pingStats.dUDPPingVar = Pds_get_double(pds);
-                       msg->payload.pingStats.UDPPackets = Pds_get_numval(pds);
-                       msg->payload.pingStats.dTCPPingAvg = Pds_get_double(pds);
-                       msg->payload.pingStats.dTCPPingVar = Pds_get_double(pds);
-                       msg->payload.pingStats.TCPPackets = Pds_get_numval(pds);
-                       break;
-               case PlayerMute:
-                       msg = Msg_create(PlayerMute);
-                       msg->payload.playerMute.victim = Pds_get_numval(pds);
-                       msg->payload.playerMute.bMute = Pds_get_numval(pds);
-                       break;
-               case PlayerDeaf:
-                       msg = Msg_create(PlayerDeaf);
-                       msg->payload.playerDeaf.victim = Pds_get_numval(pds);
-                       msg->payload.playerDeaf.bDeaf = Pds_get_numval(pds);
-                       break;
-               case PlayerSelfMuteDeaf:
-                       msg = Msg_create(PlayerSelfMuteDeaf);
-                       msg->payload.playerSelfMuteDeaf.bMute = Pds_get_numval(pds);
-                       msg->payload.playerSelfMuteDeaf.bDeaf = Pds_get_numval(pds);
-                       break;
-               case TextMessage:
-                       msg = Msg_create(TextMessage);
-                       msg->payload.textMessage.victim = Pds_get_numval(pds);
-                       msg->payload.textMessage.channel = Pds_get_numval(pds);
-                       msg->payload.textMessage.bTree = Pds_get_numval(pds);
-                       Pds_get_string(pds, msg->payload.textMessage.message, MAX_TEXT);
-                       break;
-               case PermissionDenied:
-                       Log_warn("Ignoring message PermissionDenied - not supported");
-                       break;
-               case CryptSetup:
-                       Log_warn("Ignoring message CryptSetup - not supported");
-                       break;
-               case CryptSync:
-                       msg = Msg_create(CryptSync);
-                       if (Pds_get_data(pds, msg->payload.cryptSync.nonce, AES_BLOCK_SIZE) == 0)
-                               msg->payload.cryptSync.empty = true;
-                       else
-                               msg->payload.cryptSync.empty = false;                           
-                       break;
-               case PlayerMove:
-                       msg = Msg_create(PlayerMove);
-                       msg->payload.playerMove.victim = Pds_get_numval(pds);
-                       msg->payload.playerMove.channel = Pds_get_numval(pds);
-                       break;
-                       
-                       /* The commands below are not supported -> no need to read the parameters */
-               case PlayerRename:
-                       msg = Msg_create(PlayerRename);
-                       break;                  
-               case ChannelAdd:
-                       msg = Msg_create(ChannelAdd);
-                       break;
-               case ChannelDescUpdate:
-                       msg = Msg_create(ChannelDescUpdate);
-                       break;
-               case ContextAction:
-                       msg = Msg_create(ContextAction);
-                       break;
-               case ContextAddAction:
-                       msg = Msg_create(ContextAddAction);
-                       break;
-               case ServerBanList:
-                       msg = Msg_create(ServerBanList);
-                       break;
-               case PlayerKick:
-                       msg = Msg_create(PlayerKick);
-                       break;
-               case PlayerBan:
-                       msg = Msg_create(PlayerBan);
-                       break;
-               case ChannelRemove:
-                       msg = Msg_create(ChannelRemove);
-                       break;
-               case ChannelMove:
-                       msg = Msg_create(ChannelMove);
-                       break;
-               case ChannelLink:
-                       msg = Msg_create(ChannelLink);
-                       break;
-               case ChannelRename:
-                       msg = Msg_create(ChannelRename);
-                       break;
-               case EditACL:
-                       msg = Msg_create(EditACL);
-                       break;
-               case PlayerTexture:
-                       msg = Msg_create(PlayerTexture);
-                       break;
-               default:
-                       Log_warn("Message: Type %d (session %d) is unknown type", messageType, sessionId);
+       case Version:
+       {
+               msg = Msg_create(Version);
+               msg->unpacked = true;
+               msg->payload.version = mumble_proto__version__unpack(NULL, msgLen, msgData);
+               break;
        }
-       if (msg) {
-               msg->sessionId = sessionId;
-#if 0
-               if (!pds->bOk) {
-                       Msg_free(msg);
-                       msg = NULL;
-                       Log_warn("Message: Type %d (session %d, size %d) corrupt or short packet",
-                                        messageType, sessionId, pds->offset);
-               } else if (pds->maxsize - pds->offset != 0) {
-                       Msg_free(msg);
-                       msg = NULL;
-                       Log_warn("Message: Type %d (session %d) Long packet: %d/%d leftover bytes",
-                                        messageType, sessionId, pds->overshoot, pds->offset);
-               } else if (!pds->bOk) {
-                       Msg_free(msg);
-                       msg = NULL;
-                       Log_warn("Message: Type %d (session %d, size %d) failed to validate", messageType, sessionId, pds->maxsize);
-               }
-#endif
+       case UDPTunnel:
+       {
+               msg = Msg_create(UDPTunnel);
+               msg->unpacked = true;
+               msg->payload.UDPTunnel = mumble_proto__udptunnel__unpack(NULL, msgLen, msgData);
+               break;
+       }
+       case Authenticate:
+       {
+               msg = Msg_create(Authenticate);
+               msg->unpacked = true;
+               msg->payload.authenticate = mumble_proto__authenticate__unpack(NULL, msgLen, msgData);
+               break;
+       }
+       case Ping:
+       {
+               msg = Msg_create(Ping);
+               msg->unpacked = true;
+               msg->payload.ping = mumble_proto__ping__unpack(NULL, msgLen, msgData);
+               break;
+       }
+       case Reject:
+       {
+               msg = Msg_create(Reject);
+               msg->unpacked = true;
+               msg->payload.reject = mumble_proto__reject__unpack(NULL, msgLen, msgData);
+               break;
+       }
+       case ServerSync:
+       {
+               msg = Msg_create(ServerSync);
+               msg->unpacked = true;
+               msg->payload.serverSync = mumble_proto__server_sync__unpack(NULL, msgLen, msgData);
+               break;
+       }
+       case TextMessage:
+       {
+               msg = Msg_create(TextMessage);
+               msg->unpacked = true;
+               msg->payload.textMessage = mumble_proto__text_message__unpack(NULL, msgLen, msgData);
+               break;
+       }
+       case PermissionDenied:
+       {
+               msg = Msg_create(PermissionDenied);
+               msg->unpacked = true;
+               msg->payload.permissionDenied = mumble_proto__permission_denied__unpack(NULL, msgLen, msgData);
+               break;
+       }
+       case CryptSetup:
+       {
+               msg = Msg_create(CryptSetup);
+               msg->unpacked = true;
+               msg->payload.cryptSetup = mumble_proto__crypt_setup__unpack(NULL, msgLen, msgData);
+               break;
+       }
+       case UserList:
+       {
+               msg = Msg_create(UserList);
+               msg->unpacked = true;
+               msg->payload.userList = mumble_proto__user_list__unpack(NULL, msgLen, msgData);
+               break;
+       }
+       case UserState:
+       {
+               msg = Msg_create(UserState);
+               msg->unpacked = true;
+               msg->payload.userState = mumble_proto__user_state__unpack(NULL, msgLen, msgData);
+               break;
+       }
+       case VoiceTarget:
+       {
+               msg = Msg_create(VoiceTarget);
+               msg->unpacked = true;
+               msg->payload.voiceTarget = mumble_proto__voice_target__unpack(NULL, msgLen, msgData);
+               break;
+       }
+       case CodecVersion:
+       {
+               msg = Msg_create(CodecVersion);
+               msg->unpacked = true;
+               msg->payload.codecVersion = mumble_proto__codec_version__unpack(NULL, msgLen, msgData);
+               break;
+       }
+
+       default:
+               Log_warn("Unsupported message %d", messageType);
+               break;
        }
-       Pds_free(pds);
        return msg;
 }
index 7bc5af69da31977f48a66f66547de7906fd97e39..4582d6cc56fd9df51de4fea234bb14a2eff32706 100644 (file)
 #define MESSAGES_H_89768
 
 #include <stdint.h>
-#include <openssl/aes.h>
+#include "Mumble.pb-c.h"
 #include "list.h"
 #include "types.h"
 
 #define MAX_TEXT 256
-#define SPEEX_DATA_SIZE 1024
 #define MESSAGE_STREAM_VERSION 4
 
 typedef enum {
-       ServerReject,
-       ServerAuthenticate,
-       Speex,
+       Version,
+       UDPTunnel,
+       Authenticate,
+       Ping,
+       Reject,
        ServerSync,
-       ServerJoin,
-       ServerLeave,
-       ServerBanList,
-       PlayerMute,
-       PlayerDeaf,
-       PlayerKick,
-       PlayerRename, /*10 */
-       PlayerBan,
-       PlayerMove,
-       PlayerSelfMuteDeaf,
-       ChannelAdd,
        ChannelRemove,
-       ChannelMove,
-       ChannelLink,
-       ChannelRename,
+       ChannelState,
+       UserRemove,
+       UserState,
+       BanList,
+       TextMessage,
        PermissionDenied,
-       EditACL, /* 20 */
+       ACL,
        QueryUsers,
-       Ping,
-       TextMessage,
-       PlayerTexture,
        CryptSetup,
-       CryptSync,
-       PingStats,
+       ContextActionAdd,
        ContextAction,
-       ContextAddAction,
-       ChannelDescUpdate,
+       UserList,
+       VoiceTarget,
+       PermissionQuery,
+       CodecVersion,
 } messageType_t;
 
-
 typedef enum {
-       AltSpeak = 0x01,
-       LoopBack = 0x02,
-       EndSpeech = 0x04,
-       FrameCountMask = 0x30
-} speexflag_t;
-
-typedef struct {
-       int speexflag;
-       int seq;
-       uint8_t *data;
-       int size;
-} speex_t;
-
-typedef struct {
-       int maxBandwidth;
-       char welcomeText[MAX_TEXT];
-} serverSync_t;
-
-typedef struct {
-       char playerName[MAX_TEXT];
-       int id;
-} serverLeave_t;
+       UDPVoiceCELTAlpha,
+       UDPPing,
+       UDPVoiceSpeex,
+       UDPVoiceCELTBeta,
+} UDPMessageType_t;
 
-typedef enum {
-       None,
-       WrongVersion,
-       InvalidUsername,
-       WrongUserPW,
-       WrongServerPW,
-       UsernameInUse,
-       ServerFull
-} rejectType_t;
-
-typedef struct {
-       char reason[MAX_TEXT];
-       rejectType_t type;
-} serverReject_t;
-
-typedef struct {
-       int version;
-       char userName[MAX_TEXT];
-       char password[MAX_TEXT];
-} serverAuthenticate_t;
-
-typedef struct {
-       int id;
-       int parentId;
-       char name[MAX_TEXT];
-} channelAdd_t;
-
-typedef struct {
-       int id;
-       char desc[MAX_TEXT];
-} channelDescUpdate_t;
-
-typedef struct {
-       char playerName[MAX_TEXT];
-       int id;
-} serverJoin_t;
-
-typedef struct {
-       int victim;
-       int channel;
-} playerMove_t;
-
-typedef struct {
-       uint8_t key[AES_BLOCK_SIZE];
-       uint8_t clientNonce[AES_BLOCK_SIZE];
-       uint8_t serverNonce[AES_BLOCK_SIZE];
-} cryptSetup_t;
-
-typedef struct {
-       bool_t empty;
-       uint8_t nonce[AES_BLOCK_SIZE];
-} cryptSync_t;
-
-typedef struct {
-       uint64_t timestamp;
-} ping_t;
-
-typedef struct {
-       uint64_t timestamp;
-       uint32_t good;
-       uint32_t late;
-       uint32_t lost;
-       uint32_t resync;
-       double dUDPPingAvg;
-       double dUDPPingVar;
-       uint32_t UDPPackets;
-       double dTCPPingAvg;
-       double dTCPPingVar;
-       uint32_t TCPPackets;
-} pingStats_t;
-
-typedef struct {
-       char reason[MAX_TEXT];
-} permissionDenied_t;
-
-typedef struct {
-       uint32_t victim;
-       bool_t bMute;
-} playerMute_t;
-
-typedef struct {
-       uint32_t victim;
-       bool_t bDeaf;
-} playerDeaf_t;
-
-typedef struct {
-       bool_t bMute;
-       bool_t bDeaf;
-} playerSelfMuteDeaf_t;
-
-typedef struct {
-       int32_t victim;
-       int32_t channel;
-       bool_t bTree;
-       char message[MAX_TEXT];
-} textMessage_t;
 
 typedef union payload {
-       speex_t speex;
-       serverSync_t serverSync;
-       serverJoin_t serverJoin;
-       serverLeave_t serverLeave;
-       serverReject_t serverReject;
-       serverAuthenticate_t serverAuthenticate;
-       cryptSetup_t cryptSetup;
-       cryptSync_t cryptSync;
-       pingStats_t pingStats;
-       ping_t ping;
-       channelAdd_t channelAdd;
-       channelDescUpdate_t channelDescUpdate;
-       playerMove_t playerMove;
-       permissionDenied_t permissinDenied;
-       playerMute_t playerMute;
-       playerDeaf_t playerDeaf;
-       playerSelfMuteDeaf_t playerSelfMuteDeaf;
-       permissionDenied_t permissionDenied;
-       textMessage_t textMessage;
+       struct  _MumbleProto__Version *version;
+       struct  _MumbleProto__UDPTunnel *UDPTunnel;
+       struct  _MumbleProto__Authenticate *authenticate;
+       struct  _MumbleProto__Ping *ping;
+       struct  _MumbleProto__Reject *reject;
+       struct  _MumbleProto__ServerSync *serverSync;
+       struct  _MumbleProto__ChannelRemove *channelRemove;
+       struct  _MumbleProto__ChannelState *channelState;
+       struct  _MumbleProto__UserRemove *userRemove;
+       struct  _MumbleProto__UserState *userState;
+       /* BanEntry not supported */
+       /* BanList not supported */
+       struct  _MumbleProto__TextMessage *textMessage;
+       struct  _MumbleProto__PermissionDenied *permissionDenied;
+       /* ChanACL not supported */
+       /* ACL not supported */
+       struct  _MumbleProto__QueryUsers *queryUsers;
+       struct  _MumbleProto__CryptSetup *cryptSetup;
+       /* ContextActionAdd not supported */
+       /* ContextAction not supported */
+       struct  _MumbleProto__UserList__User *userList_user;
+       struct  _MumbleProto__UserList *userList;
+       struct  _MumbleProto__VoiceTarget__Target *voiceTarget_target;
+       struct  _MumbleProto__VoiceTarget *voiceTarget;
+       /* PermissionQuery not supported */
+       struct  _MumbleProto__CodecVersion *codecVersion;
 } payload_t;
 
 typedef struct message {
        messageType_t messageType;
-       uint32_t sessionId;
        int refcount;
        struct dlist node;
+       bool_t unpacked;
        payload_t payload;
 } message_t;
 
 
 
-int Msg_messageToNetwork(message_t *msg, uint8_t *buffer, int bufsize);
+int Msg_messageToNetwork(message_t *msg, uint8_t *buffer);
 message_t *Msg_networkToMessage(uint8_t *data, int size);
 void Msg_free(message_t *msg);
 void Msg_inc_ref(message_t *msg);
index 7db1e7a5090cfee291f0184908ee6c52de88ece5..5c00abf6ebd1e5f85d538a0244b8338a19060a76 100644 (file)
--- a/src/pds.c
+++ b/src/pds.c
@@ -83,6 +83,28 @@ void Pds_append_data_nosize(pds_t *pds, const uint8_t *data, uint32_t len)
        }
 }
 
+uint8_t Pds_next8(pds_t *pds)
+{
+       if (pds->offset < pds->maxsize)
+               return pds->data[pds->offset++];
+       else {
+               pds->bOk = false;
+               return 0;
+       }
+}
+
+int Pds_skip(pds_t *pds, int offset)
+{
+       if (pds->offset + offset < pds->maxsize) {
+               pds->offset += offset;
+               return offset;
+       } else {
+               pds->bOk = false;
+               return 0;
+       }
+       
+}
+
 static inline uint64_t next(pds_t *pds)
 {
        if (pds->offset < pds->maxsize)
index e5be19bb0f2d1edb3d0ee0828096ea15e88a9b10..89856030864e7f1dfdf15cc4075a7588f33bffd2 100644 (file)
--- a/src/pds.h
+++ b/src/pds.h
@@ -53,6 +53,8 @@ void Pds_get_string(pds_t *pds, char *str, int maxlen);
 void Pds_add_double(pds_t *pds, double value);
 double Pds_get_double(pds_t *pds);
 int Pds_get_data(pds_t *pds, uint8_t *data, int maxlen);
+uint8_t Pds_next8(pds_t *pds);
+int Pds_skip(pds_t *pds, int offset);
 
 
 #endif