-/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
- Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+/* Copyright (C) 2009-2014, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2014, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
#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"
+#include "memory.h"
+#define PREAMBLE_SIZE 6
-void dumpmsg(uint8_t *data, int size);
+static message_t *Msg_create_nopayload(messageType_t messageType);
-int Msg_messageToNetwork(message_t *msg, uint8_t *buffer, int bufsize)
+static void Msg_addPreamble(uint8_t *buffer, uint16_t type, uint32_t len)
+{
+ buffer[1] = (type) & 0xff;
+ buffer[0] = (type >> 8) & 0xff;
+
+ buffer[5] = (len) & 0xff;
+ buffer[4] = (len >> 8) & 0xff;
+ buffer[3] = (len >> 16) & 0xff;
+ buffer[2] = (len >> 24) & 0xff;
+}
+
+static void Msg_getPreamble(uint8_t *buffer, int *type, int *len)
+{
+ uint16_t msgType;
+ uint32_t msgLen;
+
+ msgType = buffer[1] | (buffer[0] << 8);
+ msgLen = buffer[5] | (buffer[4] << 8) | (buffer[3] << 16) | (buffer[2] << 24);
+ *type = (int)msgType;
+ *len = (int)msgLen;
+}
+
+#define MAX_MSGSIZE (BUFSIZE - PREAMBLE_SIZE)
+int Msg_messageToNetwork(message_t *msg, uint8_t *buffer)
{
- pds_t *pds = Pds_create(buffer, bufsize);
int len;
-
- Pds_add_numval(pds, msg->messageType);
- Pds_add_numval(pds, msg->sessionId);
-
+ uint8_t *bufptr = buffer + PREAMBLE_SIZE;
+
+ 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);
+ 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 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:
- 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: /* Non-standard handling of tunneled voice traffic. */
+ if (msg->payload.UDPTunnel->packet.len > MAX_MSGSIZE) {
+ Log_warn("Too big tx message. Discarding");
break;
+ }
+ len = msg->payload.UDPTunnel->packet.len;
+ Msg_addPreamble(buffer, msg->messageType, msg->payload.UDPTunnel->packet.len);
+ memcpy(bufptr, msg->payload.UDPTunnel->packet.data, msg->payload.UDPTunnel->packet.len);
+ 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 UserRemove:
+ len = mumble_proto__user_remove__get_packed_size(msg->payload.userRemove);
+ if (len > MAX_MSGSIZE) {
+ Log_warn("Too big tx message. Discarding");
+ break;
+ }
+ Msg_addPreamble(buffer, msg->messageType, len);
+ mumble_proto__user_remove__pack(msg->payload.userRemove, 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;
+ case PermissionQuery:
+ len = mumble_proto__permission_query__get_packed_size(msg->payload.permissionQuery);
+ if (len > MAX_MSGSIZE) {
+ Log_warn("Too big tx message. Discarding");
+ break;
+ }
+ Msg_addPreamble(buffer, msg->messageType, len);
+ mumble_proto__permission_query__pack(msg->payload.permissionQuery, bufptr);
+ break;
+ case ChannelRemove:
+ len = mumble_proto__channel_remove__get_packed_size(msg->payload.channelRemove);
+ if (len > MAX_MSGSIZE) {
+ Log_warn("Too big tx message. Discarding");
+ break;
+ }
+ Msg_addPreamble(buffer, msg->messageType, len);
+ mumble_proto__channel_remove__pack(msg->payload.channelRemove, bufptr);
+ break;
+ case UserStats:
+ {
+ len = mumble_proto__user_stats__get_packed_size(msg->payload.userStats);
+ if (len > MAX_MSGSIZE) {
+ Log_warn("Too big tx message. Discarding");
+ break;
+ }
+ Msg_addPreamble(buffer, msg->messageType, len);
+ mumble_proto__user_stats__pack(msg->payload.userStats, bufptr);
+ break;
+ }
+ case ServerConfig:
+ len = mumble_proto__server_config__get_packed_size(msg->payload.serverConfig);
+ if (len > MAX_MSGSIZE) {
+ Log_warn("Too big tx message. Discarding");
+ break;
+ }
+ Msg_addPreamble(buffer, msg->messageType, len);
+ mumble_proto__server_config__pack(msg->payload.serverConfig, bufptr);
+ break;
- default:
- Log_warn("Unsupported message %d", msg->messageType);
+ case BanList:
+ len = mumble_proto__ban_list__get_packed_size(msg->payload.banList);
+ if (len > MAX_MSGSIZE) {
+ Log_warn("Too big tx message. Discarding");
+ break;
+ }
+ Msg_addPreamble(buffer, msg->messageType, len);
+ Log_debug("Msg_MessageToNetwork: BanList size %d", len);
+ mumble_proto__ban_list__pack(msg->payload.banList, bufptr);
break;
+ default:
+ Log_warn("Msg_MessageToNetwork: Unsupported message %d", msg->messageType);
+ return 0;
}
- len = pds->offset;
- Pds_free(pds);
- return len;
+ return len + PREAMBLE_SIZE;
}
-message_t *Msg_create(messageType_t messageType)
+static message_t *Msg_create_nopayload(messageType_t messageType)
{
- message_t *msg = malloc(sizeof(message_t));
+ message_t *msg = Memory_safeMalloc(1, sizeof(message_t));
- if (msg == NULL)
- Log_fatal("Out of memory");
memset(msg, 0, sizeof(message_t));
msg->refcount = 1;
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");
+ return msg;
+}
+
+message_t *Msg_create(messageType_t messageType)
+{
+ message_t *msg = Msg_create_nopayload(messageType);
+ int i;
+
+ switch (messageType) {
+ case Version:
+ msg->payload.version = Memory_safeMalloc(1, sizeof(MumbleProto__Version));
+ mumble_proto__version__init(msg->payload.version);
+ break;
+ case UDPTunnel:
+ msg->payload.UDPTunnel = Memory_safeMalloc(1, sizeof(MumbleProto__UDPTunnel));
+ mumble_proto__udptunnel__init(msg->payload.UDPTunnel);
+ break;
+ case Authenticate:
+ msg->payload.authenticate = Memory_safeMalloc(1, sizeof(MumbleProto__Authenticate));
+ mumble_proto__authenticate__init(msg->payload.authenticate);
+ break;
+ case Ping:
+ msg->payload.ping = Memory_safeMalloc(1, sizeof(MumbleProto__Ping));
+ mumble_proto__ping__init(msg->payload.ping);
+ break;
+ case Reject:
+ msg->payload.reject = Memory_safeMalloc(1, sizeof(MumbleProto__Reject));
+ mumble_proto__reject__init(msg->payload.reject);
+ break;
+ case ServerSync:
+ msg->payload.serverSync = Memory_safeMalloc(1, sizeof(MumbleProto__ServerSync));
+ mumble_proto__server_sync__init(msg->payload.serverSync);
+ break;
+ case TextMessage:
+ msg->payload.textMessage = Memory_safeMalloc(1, sizeof(MumbleProto__TextMessage));
+ mumble_proto__text_message__init(msg->payload.textMessage);
+ break;
+ case PermissionDenied:
+ msg->payload.permissionDenied = Memory_safeMalloc(1, sizeof(MumbleProto__PermissionDenied));
+ mumble_proto__permission_denied__init(msg->payload.permissionDenied);
+ break;
+ case CryptSetup:
+ msg->payload.cryptSetup = Memory_safeMalloc(1, sizeof(MumbleProto__CryptSetup));
+ mumble_proto__crypt_setup__init(msg->payload.cryptSetup);
+ break;
+ case UserList:
+ msg->payload.userList = Memory_safeMalloc(1, sizeof(MumbleProto__UserList));
+ mumble_proto__user_list__init(msg->payload.userList);
+ break;
+ case UserState:
+ msg->payload.userState = Memory_safeMalloc(1, sizeof(MumbleProto__UserState));
+ mumble_proto__user_state__init(msg->payload.userState);
+ break;
+ case ChannelState:
+ msg->payload.channelState = Memory_safeMalloc(1, sizeof(MumbleProto__ChannelState));
+ mumble_proto__channel_state__init(msg->payload.channelState);
+ break;
+ case UserRemove:
+ msg->payload.userRemove = Memory_safeMalloc(1, sizeof(MumbleProto__UserRemove));
+ mumble_proto__user_remove__init(msg->payload.userRemove);
+ break;
+ case VoiceTarget:
+ msg->payload.voiceTarget = Memory_safeMalloc(1, sizeof(MumbleProto__VoiceTarget));
+ mumble_proto__voice_target__init(msg->payload.voiceTarget);
+ break;
+ case CodecVersion:
+ msg->payload.codecVersion = Memory_safeMalloc(1, sizeof(MumbleProto__CodecVersion));
+ mumble_proto__codec_version__init(msg->payload.codecVersion);
+ break;
+ case PermissionQuery:
+ msg->payload.permissionQuery = Memory_safeMalloc(1, sizeof(MumbleProto__PermissionQuery));
+ mumble_proto__permission_query__init(msg->payload.permissionQuery);
+ break;
+ case ChannelRemove:
+ msg->payload.channelRemove = Memory_safeMalloc(1, sizeof(MumbleProto__ChannelRemove));
+ mumble_proto__channel_remove__init(msg->payload.channelRemove);
+ break;
+ case UserStats:
+ msg->payload.userStats = Memory_safeMalloc(1, sizeof(MumbleProto__UserStats));
+ mumble_proto__user_stats__init(msg->payload.userStats);
+
+ msg->payload.userStats->from_client = Memory_safeMalloc(1, sizeof(MumbleProto__UserStats__Stats));
+ mumble_proto__user_stats__stats__init(msg->payload.userStats->from_client);
+
+ msg->payload.userStats->from_server = Memory_safeMalloc(1, sizeof(MumbleProto__UserStats__Stats));
+ mumble_proto__user_stats__stats__init(msg->payload.userStats->from_server);
+
+ msg->payload.userStats->version = Memory_safeMalloc(1, sizeof(MumbleProto__Version));
+ mumble_proto__version__init(msg->payload.userStats->version);
+
+ break;
+ case ServerConfig:
+ msg->payload.serverConfig = Memory_safeMalloc(1, sizeof(MumbleProto__ServerConfig));
+ mumble_proto__server_config__init(msg->payload.serverConfig);
+ break;
+
+ default:
+ Log_warn("Msg_create: Unsupported message %d", msg->messageType);
+ break;
+ }
+
+ return msg;
+}
+
+message_t *Msg_banList_create(int n_bans)
+{
+ message_t *msg = Msg_create_nopayload(BanList);
+ int i;
+
+ msg->payload.banList = Memory_safeMalloc(1, sizeof(MumbleProto__BanList));
+ memset(msg->payload.banList, 0, sizeof(MumbleProto__BanList));
+ mumble_proto__ban_list__init(msg->payload.banList);
+ msg->payload.banList->n_bans = n_bans;
+ msg->payload.banList->bans = Memory_safeMalloc(1, sizeof(MumbleProto__BanList__BanEntry *) * n_bans);
+ for (i = 0; i < n_bans; i++) {
+ msg->payload.banList->bans[i] = Memory_safeMalloc(1, sizeof(MumbleProto__BanList__BanEntry));
+ memset(msg->payload.banList->bans[i], 0, sizeof(MumbleProto__BanList__BanEntry));
+ mumble_proto__ban_list__ban_entry__init(msg->payload.banList->bans[i]);
}
return msg;
}
+void Msg_banList_addEntry(message_t *msg, int index, uint8_t *address, uint32_t mask,
+ char *name, char *hash, char *reason, char *start, uint32_t duration)
+{
+ MumbleProto__BanList__BanEntry *entry = msg->payload.banList->bans[index];
+
+ entry->address.data = Memory_safeMalloc(1, 16);
+ memcpy(entry->address.data, address, 16);
+ entry->address.len = 16;
+ entry->mask = mask;
+ entry->name = strdup(name);
+ entry->hash = strdup(hash);
+ entry->reason = strdup(reason);
+ entry->start = strdup(start);
+ if (!entry->name || !entry->hash || !entry->reason || !entry->start)
+ Log_fatal("Out of memory");
+
+ if (duration > 0) {
+ entry->duration = duration;
+ entry->has_duration = true;
+ }
+ Log_debug("Msg_banList_addEntry: %s %s %s %s %s",
+ entry->name, entry->hash, entry->address.data, entry->reason, entry->start);
+}
+
+void Msg_banList_getEntry(message_t *msg, int index, uint8_t **address, uint32_t *mask,
+ char **name, char **hash, char **reason, char **start, uint32_t *duration)
+{
+ MumbleProto__BanList__BanEntry *entry = msg->payload.banList->bans[index];
+
+ *address = entry->address.data;
+ *mask = entry->mask;
+ *name = entry->name;
+ *hash = entry->hash;
+ *reason = entry->reason;
+ *start = entry->start;
+ if (entry->has_duration)
+ *duration = entry->duration;
+ else
+ *duration = 0;
+}
+
+
void Msg_inc_ref(message_t *msg)
{
msg->refcount++;
void Msg_free(message_t *msg)
{
+ int i;
+
if (msg->refcount) msg->refcount--;
if (msg->refcount > 0)
return;
- if (msg->messageType == Speex)
- free(msg->payload.speex.data);
+
+ switch (msg->messageType) {
+ case Version:
+ if (msg->unpacked)
+ mumble_proto__version__free_unpacked(msg->payload.version, NULL);
+ else {
+ if (msg->payload.version->release)
+ free(msg->payload.version->release);
+ if (msg->payload.version->os)
+ free(msg->payload.version->os);
+ if (msg->payload.version->os_version)
+ free(msg->payload.version->os_version);
+ 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);
+ else
+ free(msg->payload.authenticate);
+ 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 {
+ if (msg->payload.textMessage->message)
+ free(msg->payload.textMessage->message);
+ if (msg->payload.textMessage->session)
+ free(msg->payload.textMessage->session);
+ if (msg->payload.textMessage->channel_id)
+ free(msg->payload.textMessage->channel_id);
+ if (msg->payload.textMessage->tree_id)
+ free(msg->payload.textMessage->tree_id);
+ 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 ChannelState:
+ if (msg->unpacked)
+ mumble_proto__channel_state__free_unpacked(msg->payload.channelState, NULL);
+ else {
+ if (msg->payload.channelState->name)
+ free(msg->payload.channelState->name);
+ if (msg->payload.channelState->description)
+ free(msg->payload.channelState->description);
+ if (msg->payload.channelState->links)
+ free(msg->payload.channelState->links);
+ free(msg->payload.channelState);
+ }
+ 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 PermissionQuery:
+ if (msg->unpacked)
+ mumble_proto__permission_query__free_unpacked(msg->payload.permissionQuery, NULL);
+ else {
+ free(msg->payload.permissionQuery);
+ }
+ break;
+ case ChannelRemove:
+ if (msg->unpacked)
+ mumble_proto__channel_remove__free_unpacked(msg->payload.channelRemove, NULL);
+ else {
+ free(msg->payload.channelRemove);
+ }
+ break;
+ case UserStats:
+ if (msg->unpacked)
+ mumble_proto__user_stats__free_unpacked(msg->payload.userStats, NULL);
+ else {
+ if (msg->payload.userStats->from_client)
+ free(msg->payload.userStats->from_client);
+ if (msg->payload.userStats->from_server)
+ free(msg->payload.userStats->from_server);
+ if (msg->payload.userStats->version) {
+ if (msg->payload.userStats->version->release)
+ free(msg->payload.userStats->version->release);
+ if (msg->payload.userStats->version->os)
+ free(msg->payload.userStats->version->os);
+ if (msg->payload.userStats->version->os_version)
+ free(msg->payload.userStats->version->os_version);
+
+ free(msg->payload.userStats->version);
+ }
+ if (msg->payload.userStats->celt_versions)
+ free(msg->payload.userStats->celt_versions);
+ if (msg->payload.userStats->certificates) {
+ if (msg->payload.userStats->certificates->data)
+ free(msg->payload.userStats->certificates->data);
+ free(msg->payload.userStats->certificates);
+ }
+ if (msg->payload.userStats->address.data)
+ free(msg->payload.userStats->address.data);
+
+ free(msg->payload.userStats);
+ }
+ break;
+ case ServerConfig:
+ if (msg->unpacked)
+ mumble_proto__server_config__free_unpacked(msg->payload.serverConfig, NULL);
+ else {
+ free(msg->payload.serverConfig);
+ }
+ break;
+ case BanList:
+ if (msg->unpacked)
+ mumble_proto__ban_list__free_unpacked(msg->payload.banList, NULL);
+ else {
+ for (i = 0; i < msg->payload.banList->n_bans; i++) {
+ free(msg->payload.banList->bans[i]->address.data);
+ free(msg->payload.banList->bans[i]->name);
+ free(msg->payload.banList->bans[i]->hash);
+ free(msg->payload.banList->bans[i]->reason);
+ free(msg->payload.banList->bans[i]->start);
+ free(msg->payload.banList->bans[i]);
+ }
+ free(msg->payload.banList->bans);
+ free(msg->payload.banList);
+ }
+ break;
+
+ default:
+ Log_warn("Msg_free: Unsupported message %d", msg->messageType);
+ break;
+ }
free(msg);
}
-void dumpmsg(uint8_t *data, int size)
+message_t *Msg_CreateVoiceMsg(uint8_t *data, int size)
{
- int i, r = 0, offset = 0;
- char buf[512];
-
- while (r * 8 + i < size) {
- for (i = 0; i < 8 && r * 8 + i < size; i++) {
- offset += sprintf(buf + offset, "%x ", data[r * 8 + i]);
- }
- sprintf(buf + offset, "\n");
- printf(buf);
- offset = 0;
- r++;
- i = 0;
- }
+ message_t *msg = NULL;
+
+ msg = Msg_create_nopayload(UDPTunnel);
+ msg->unpacked = false;
+ msg->payload.UDPTunnel = Memory_safeMalloc(1, sizeof(struct _MumbleProto__UDPTunnel));
+ msg->payload.UDPTunnel->packet.data = Memory_safeMalloc(1, size);
+ memcpy(msg->payload.UDPTunnel->packet.data, data, size);
+ msg->payload.UDPTunnel->packet.len = size;
+ return msg;
}
message_t *Msg_networkToMessage(uint8_t *data, int size)
{
message_t *msg = NULL;
- int messageType;
- int sessionId;
- pds_t *pds;
-
- pds = Pds_create(data, size);
- messageType = Pds_get_numval(pds);
- sessionId = Pds_get_numval(pds);
-
+ uint8_t *msgData = &data[6];
+ int messageType, msgLen;
+
+ 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_nopayload(Version);
+ msg->unpacked = true;
+ msg->payload.version = mumble_proto__version__unpack(NULL, msgLen, msgData);
+ if (msg->payload.version == NULL)
+ goto err_out;
+ 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: /* Non-standard handling of tunneled voice data */
+ {
+ msg = Msg_CreateVoiceMsg(msgData, msgLen);
+ break;
+ }
+ case Authenticate:
+ {
+ msg = Msg_create_nopayload(Authenticate);
+ msg->unpacked = true;
+ msg->payload.authenticate = mumble_proto__authenticate__unpack(NULL, msgLen, msgData);
+ if (msg->payload.authenticate == NULL)
+ goto err_out;
+ break;
+ }
+ case Ping:
+ {
+ msg = Msg_create_nopayload(Ping);
+ msg->unpacked = true;
+ msg->payload.ping = mumble_proto__ping__unpack(NULL, msgLen, msgData);
+ if (msg->payload.ping == NULL)
+ goto err_out;
+ break;
+ }
+ case Reject:
+ {
+ msg = Msg_create_nopayload(Reject);
+ msg->unpacked = true;
+ msg->payload.reject = mumble_proto__reject__unpack(NULL, msgLen, msgData);
+ if (msg->payload.reject == NULL)
+ goto err_out;
+ break;
+ }
+ case ServerSync:
+ {
+ msg = Msg_create_nopayload(ServerSync);
+ msg->unpacked = true;
+ msg->payload.serverSync = mumble_proto__server_sync__unpack(NULL, msgLen, msgData);
+ if (msg->payload.serverSync == NULL)
+ goto err_out;
+ break;
+ }
+ case TextMessage:
+ {
+ msg = Msg_create_nopayload(TextMessage);
+ msg->unpacked = true;
+ msg->payload.textMessage = mumble_proto__text_message__unpack(NULL, msgLen, msgData);
+ if (msg->payload.textMessage == NULL)
+ goto err_out;
+ break;
+ }
+ case PermissionDenied:
+ {
+ msg = Msg_create_nopayload(PermissionDenied);
+ msg->unpacked = true;
+ msg->payload.permissionDenied = mumble_proto__permission_denied__unpack(NULL, msgLen, msgData);
+ if (msg->payload.permissionDenied == NULL)
+ goto err_out;
+ break;
+ }
+ case CryptSetup:
+ {
+ msg = Msg_create_nopayload(CryptSetup);
+ msg->unpacked = true;
+ msg->payload.cryptSetup = mumble_proto__crypt_setup__unpack(NULL, msgLen, msgData);
+ if (msg->payload.cryptSetup == NULL)
+ goto err_out;
+ break;
+ }
+ case UserList:
+ {
+ msg = Msg_create_nopayload(UserList);
+ msg->unpacked = true;
+ msg->payload.userList = mumble_proto__user_list__unpack(NULL, msgLen, msgData);
+ if (msg->payload.userList == NULL)
+ goto err_out;
+ break;
+ }
+ case UserState:
+ {
+ msg = Msg_create_nopayload(UserState);
+ msg->unpacked = true;
+ msg->payload.userState = mumble_proto__user_state__unpack(NULL, msgLen, msgData);
+ if (msg->payload.userState == NULL)
+ goto err_out;
+ break;
+ }
+ case ChannelState:
+ {
+ msg = Msg_create_nopayload(ChannelState);
+ msg->unpacked = true;
+ msg->payload.channelState = mumble_proto__channel_state__unpack(NULL, msgLen, msgData);
+ if (msg->payload.channelState == NULL)
+ goto err_out;
+ break;
+ }
+ case VoiceTarget:
+ {
+ msg = Msg_create_nopayload(VoiceTarget);
+ msg->unpacked = true;
+ msg->payload.voiceTarget = mumble_proto__voice_target__unpack(NULL, msgLen, msgData);
+ if (msg->payload.voiceTarget == NULL)
+ goto err_out;
+ break;
+ }
+ case CodecVersion:
+ {
+ msg = Msg_create_nopayload(CodecVersion);
+ msg->unpacked = true;
+ msg->payload.codecVersion = mumble_proto__codec_version__unpack(NULL, msgLen, msgData);
+ if (msg->payload.codecVersion == NULL)
+ goto err_out;
+ break;
+ }
+ case PermissionQuery:
+ {
+ msg = Msg_create_nopayload(PermissionQuery);
+ msg->unpacked = true;
+ msg->payload.permissionQuery = mumble_proto__permission_query__unpack(NULL, msgLen, msgData);
+ if (msg->payload.permissionQuery == NULL)
+ goto err_out;
+ break;
+ }
+ case ChannelRemove:
+ {
+ msg = Msg_create_nopayload(ChannelRemove);
+ msg->unpacked = true;
+ msg->payload.channelRemove = mumble_proto__channel_remove__unpack(NULL, msgLen, msgData);
+ if (msg->payload.channelRemove == NULL)
+ goto err_out;
+ break;
+ }
+ case UserStats:
+ {
+ msg = Msg_create_nopayload(UserStats);
+ msg->unpacked = true;
+ msg->payload.userStats = mumble_proto__user_stats__unpack(NULL, msgLen, msgData);
+ if (msg->payload.userStats == NULL)
+ goto err_out;
+ break;
+ }
+ case UserRemove:
+ {
+ msg = Msg_create_nopayload(UserRemove);
+ msg->unpacked = true;
+ msg->payload.userRemove = mumble_proto__user_remove__unpack(NULL, msgLen, msgData);
+ if (msg->payload.userRemove == NULL)
+ goto err_out;
+ break;
+ }
+ case BanList:
+ {
+ msg = Msg_create_nopayload(BanList);
+ msg->unpacked = true;
+ msg->payload.banList = mumble_proto__ban_list__unpack(NULL, msgLen, msgData);
+ if (msg->payload.banList == NULL)
+ goto err_out;
+ break;
+ }
+
+ default:
+ Log_warn("Msg_networkToMessage: Unsupported message %d", messageType);
+ break;
}
- Pds_free(pds);
return msg;
+
+err_out:
+ free(msg);
+ return NULL;
}