-/* Copyright (C) 2009, Martin Johansson <martin@fatbob.nu>
- Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com>
+/* Copyright (C) 2009-2010, Martin Johansson <martin@fatbob.nu>
+ Copyright (C) 2005-2010, Thorvald Natvig <thorvald@natvig.com>
All rights reserved.
#include "pds.h"
#include "log.h"
+#define PREAMBLE_SIZE 6
-void dumpmsg(uint8_t *data, int size);
static message_t *Msg_create_nopayload(messageType_t messageType);
-void Msg_addPreamble(uint8_t *buffer, uint16_t type, uint32_t len)
+static void Msg_addPreamble(uint8_t *buffer, uint16_t type, uint32_t len)
{
- uint16_t *msgType = (uint16_t *) &buffer[0];
- uint32_t *msgLen = (uint32_t *) &buffer[2];
+ type = htons(type);
+ len = htonl(len);
- *msgType = htons(type);
- *msgLen = htonl(len);
+ buffer[0] = (type) & 0xff;
+ buffer[1] = (type >> 8) & 0xff;
+
+ buffer[2] = (len) & 0xff;
+ buffer[3] = (len >> 8) & 0xff;
+ buffer[4] = (len >> 16) & 0xff;
+ buffer[5] = (len >> 24) & 0xff;
}
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];
+ uint16_t msgType;
+ uint32_t msgLen;
- *type = (int)ntohs(*msgType);
- *len = (int)ntohl(*msgLen);
+ msgType = buffer[0] | (buffer[1] << 8);
+ msgLen = buffer[2] | (buffer[3] << 8) | (buffer[4] << 16) | (buffer[5] << 24);
+ *type = (int)ntohs(msgType);
+ *len = (int)ntohl(msgLen);
}
-#define MAX_MSGSIZE (BUFSIZE - 6)
+#define MAX_MSGSIZE (BUFSIZE - PREAMBLE_SIZE)
int Msg_messageToNetwork(message_t *msg, uint8_t *buffer)
{
int len;
- uint8_t *bufptr = buffer + 6;
+ uint8_t *bufptr = buffer + PREAMBLE_SIZE;
Log_debug("To net: msg type %d", msg->messageType);
switch (msg->messageType) {
break;
}
Msg_addPreamble(buffer, msg->messageType, len);
- Log_debug("To net: Version->release: %s Version->os: %s",
- msg->payload.version->release, msg->payload.version->os);
mumble_proto__version__pack(msg->payload.version, bufptr);
break;
case UDPTunnel: /* Non-standard handling of tunneled voice traffic. */
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;
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) {
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;
default:
- Log_warn("Unsupported message %d", msg->messageType);
+ Log_warn("Msg_MessageToNetwork: Unsupported message %d", msg->messageType);
return 0;
}
- return len + 6;
+ return len + PREAMBLE_SIZE;
}
-message_t *Msg_create_nopayload(messageType_t messageType)
+static message_t *Msg_create_nopayload(messageType_t messageType)
{
message_t *msg = malloc(sizeof(message_t));
msg->payload.userState = malloc(sizeof(MumbleProto__UserState));
mumble_proto__user_state__init(msg->payload.userState);
break;
+ case ChannelState:
+ msg->payload.channelState = malloc(sizeof(MumbleProto__ChannelState));
+ mumble_proto__channel_state__init(msg->payload.channelState);
+ break;
case UserRemove:
msg->payload.userRemove = malloc(sizeof(MumbleProto__UserRemove));
mumble_proto__user_remove__init(msg->payload.userRemove);
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;
case PermissionQuery:
msg->payload.permissionQuery = malloc(sizeof(MumbleProto__PermissionQuery));
mumble_proto__permission_query__init(msg->payload.permissionQuery);
break;
+ case ChannelRemove:
+ msg->payload.channelRemove = malloc(sizeof(MumbleProto__ChannelRemove));
+ mumble_proto__channel_remove__init(msg->payload.channelRemove);
+ break;
default:
Log_warn("Msg_create: Unsupported message %d", msg->messageType);
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);
free(msg->payload.codecVersion);
}
break;
- case ChannelState:
+ case PermissionQuery:
if (msg->unpacked)
- mumble_proto__channel_state__free_unpacked(msg->payload.channelState, NULL);
+ mumble_proto__permission_query__free_unpacked(msg->payload.permissionQuery, NULL);
else {
- if (msg->payload.channelState->description)
- free(msg->payload.channelState->description);
- free(msg->payload.channelState->name);
- free(msg->payload.channelState);
+ free(msg->payload.permissionQuery);
}
break;
- case PermissionQuery:
+ case ChannelRemove:
if (msg->unpacked)
- mumble_proto__permission_query__free_unpacked(msg->payload.permissionQuery, NULL);
+ mumble_proto__channel_remove__free_unpacked(msg->payload.channelRemove, NULL);
else {
- free(msg->payload.permissionQuery);
+ free(msg->payload.channelRemove);
}
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];
+ message_t *msg = NULL;
- 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;
- }
+ msg = Msg_create_nopayload(UDPTunnel);
+ msg->unpacked = false;
+ msg->payload.UDPTunnel = malloc(sizeof(struct _MumbleProto__UDPTunnel));
+ if (msg->payload.UDPTunnel == NULL)
+ Log_fatal("Out of memory");
+ msg->payload.UDPTunnel->packet.data = malloc(size);
+ if (msg->payload.UDPTunnel->packet.data == NULL)
+ Log_fatal("Out of memory");
+ 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)
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;
}
case UDPTunnel: /* Non-standard handling of tunneled voice data */
{
- msg = Msg_create_nopayload(UDPTunnel);
- msg->unpacked = false;
- msg->payload.UDPTunnel = malloc(sizeof(struct _MumbleProto__UDPTunnel));
- if (msg->payload.UDPTunnel == NULL)
- Log_fatal("Out of memory");
- msg->payload.UDPTunnel->packet.data = malloc(msgLen);
- if (msg->payload.UDPTunnel->packet.data == NULL)
- Log_fatal("Out of memory");
- memcpy(msg->payload.UDPTunnel->packet.data, msgData, msgLen);
- msg->payload.UDPTunnel->packet.len = msgLen;
+ 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;
}
break;
}
return msg;
+
+err_out:
+ free(msg);
+ return NULL;
}