mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
d4be41a3ad
The new encoding is `0` for `Nothing` and `[1, x]` for `Just x`.
275 lines
6.7 KiB
C
275 lines
6.7 KiB
C
#define _BSD_SOURCE
|
|
#include "methods.h"
|
|
|
|
#include "byteswap.h"
|
|
#include "packet_kinds.h"
|
|
|
|
#include "../../toxcore/DHT.h"
|
|
|
|
|
|
static void decode_bytestring(msgpack_object_bin args, msgpack_packer *res,
|
|
int64_t min_length)
|
|
{
|
|
SUCCESS {
|
|
if (args.size < sizeof(uint64_t))
|
|
{
|
|
// Not enough space to even fit the size.
|
|
msgpack_pack_uint8(res, 0);
|
|
return;
|
|
}
|
|
|
|
uint64_t tmp;
|
|
memcpy(&tmp, args.ptr, sizeof(uint64_t));
|
|
int64_t length = be64toh(tmp);
|
|
|
|
// TODO(iphydf): Get rid of this case if/when
|
|
// https://github.com/kolmodin/binary/issues/127 is fixed. This is a
|
|
// workaround for a Haskell library bug. Our implementation here without
|
|
// the special case for negative length, and instead interpreting the
|
|
// length as unsigned integer, was correct.
|
|
if (length < 0)
|
|
{
|
|
length = 0;
|
|
}
|
|
|
|
if (args.size >= sizeof(uint64_t) && args.size == length + sizeof(uint64_t))
|
|
{
|
|
if (length < min_length) {
|
|
// CipherTexts need at least a MAC.
|
|
msgpack_pack_uint8(res, 0);
|
|
return;
|
|
}
|
|
|
|
msgpack_pack_array(res, 2);
|
|
msgpack_pack_uint8(res, 1);
|
|
|
|
msgpack_pack_bin(res, args.size - sizeof(uint64_t));
|
|
msgpack_pack_bin_body(res, args.ptr + sizeof(uint64_t), args.size - sizeof(uint64_t));
|
|
} else {
|
|
msgpack_pack_uint8(res, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
METHOD(bin, Binary_decode, CipherText)
|
|
{
|
|
decode_bytestring(args, res, CRYPTO_MAC_SIZE);
|
|
return 0;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, DhtPacket)
|
|
{
|
|
return pending;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, DhtRequestPacket)
|
|
{
|
|
return pending;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, HostAddress)
|
|
{
|
|
return pending;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, Word64)
|
|
{
|
|
return pending;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, Key_PublicKey)
|
|
{
|
|
return pending;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, KeyPair)
|
|
{
|
|
SUCCESS {
|
|
if (args.size != 64)
|
|
{
|
|
msgpack_pack_uint8(res, 0);
|
|
} else {
|
|
msgpack_pack_array(res, 2);
|
|
msgpack_pack_uint8(res, 1);
|
|
|
|
msgpack_pack_array(res, 2);
|
|
msgpack_pack_bin(res, 32);
|
|
msgpack_pack_bin_body(res, args.ptr, 32);
|
|
msgpack_pack_bin(res, 32);
|
|
msgpack_pack_bin_body(res, args.ptr + 32, 32);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, NodeInfo)
|
|
{
|
|
uint16_t data_processed;
|
|
Node_format node;
|
|
int len = unpack_nodes(&node, 1, &data_processed, (uint8_t const *)args.ptr, args.size, 1);
|
|
|
|
bool ip6_node = node.ip_port.ip.family == AF_INET6 || node.ip_port.ip.family == TCP_INET6;
|
|
bool tcp = node.ip_port.ip.family == TCP_INET || node.ip_port.ip.family == TCP_INET6;
|
|
|
|
uint16_t port = ntohs(node.ip_port.port);
|
|
uint32_t ip4 = ntohl(node.ip_port.ip.ip4.uint32);
|
|
uint32_t ip6_0 = ntohl(node.ip_port.ip.ip6.uint32[0]);
|
|
uint32_t ip6_1 = ntohl(node.ip_port.ip.ip6.uint32[1]);
|
|
uint32_t ip6_2 = ntohl(node.ip_port.ip.ip6.uint32[2]);
|
|
uint32_t ip6_3 = ntohl(node.ip_port.ip.ip6.uint32[3]);
|
|
|
|
SUCCESS {
|
|
if (len > 0 && data_processed > 0 && data_processed == args.size)
|
|
{
|
|
msgpack_pack_array(res, 2);
|
|
msgpack_pack_uint8(res, 1);
|
|
|
|
msgpack_pack_array(res, 3);
|
|
msgpack_pack_uint8(res, tcp);
|
|
msgpack_pack_array(res, 2);
|
|
msgpack_pack_array(res, 2);
|
|
msgpack_pack_uint8(res, ip6_node);
|
|
|
|
if (ip6_node) {
|
|
msgpack_pack_array(res, 4);
|
|
msgpack_pack_uint32(res, ip6_0);
|
|
msgpack_pack_uint32(res, ip6_1);
|
|
msgpack_pack_uint32(res, ip6_2);
|
|
msgpack_pack_uint32(res, ip6_3);
|
|
} else {
|
|
msgpack_pack_uint32(res, ip4);
|
|
}
|
|
|
|
msgpack_pack_uint16(res, port);
|
|
msgpack_pack_bin(res, CRYPTO_PUBLIC_KEY_SIZE);
|
|
msgpack_pack_bin_body(res, &node.public_key, CRYPTO_PUBLIC_KEY_SIZE);
|
|
} else {
|
|
msgpack_pack_uint8(res, 0);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, NodesRequest)
|
|
{
|
|
return pending;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, NodesResponse)
|
|
{
|
|
return pending;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, Packet_Word64)
|
|
{
|
|
return pending;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, PacketKind)
|
|
{
|
|
SUCCESS {
|
|
if (args.size != 1)
|
|
{
|
|
msgpack_pack_uint8(res, 0);
|
|
} else {
|
|
uint8_t kind = args.ptr[0];
|
|
size_t i;
|
|
|
|
for (i = 0; i < sizeof packet_kinds / sizeof *packet_kinds; i++)
|
|
{
|
|
if (packet_kinds[i] == kind) {
|
|
msgpack_pack_array(res, 2);
|
|
msgpack_pack_uint8(res, 1);
|
|
msgpack_pack_fix_uint8(res, i);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// Packet kind not found => error.
|
|
msgpack_pack_uint8(res, 0);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, PingPacket)
|
|
{
|
|
return pending;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, PlainText)
|
|
{
|
|
decode_bytestring(args, res, 0);
|
|
return 0;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, PortNumber)
|
|
{
|
|
SUCCESS {
|
|
if (args.size == 2)
|
|
{
|
|
uint16_t tmp;
|
|
memcpy(&tmp, args.ptr, 2);
|
|
uint16_t port = ntohs(tmp);
|
|
msgpack_pack_array(res, 2);
|
|
msgpack_pack_uint8(res, 1);
|
|
msgpack_pack_uint16(res, port);
|
|
} else {
|
|
msgpack_pack_uint8(res, 0);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, RpcPacket_Word64)
|
|
{
|
|
return pending;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, SocketAddress)
|
|
{
|
|
return pending;
|
|
}
|
|
|
|
METHOD(bin, Binary_decode, TransportProtocol)
|
|
{
|
|
return pending;
|
|
}
|
|
|
|
METHOD(array, Binary, decode)
|
|
{
|
|
CHECK_SIZE(args, 2);
|
|
CHECK_TYPE(args.ptr[0], MSGPACK_OBJECT_STR);
|
|
CHECK_TYPE(args.ptr[1], MSGPACK_OBJECT_BIN);
|
|
|
|
msgpack_object_str type = args.ptr[0].via.str;
|
|
#define DISPATCH(TYPE) \
|
|
if (type.size == sizeof #TYPE - 1 && method_cmp(type.ptr, #TYPE, type.size) == 0) \
|
|
return Binary_decode_##TYPE(args.ptr[1].via.bin, res)
|
|
DISPATCH(CipherText);
|
|
DISPATCH(DhtPacket);
|
|
DISPATCH(DhtRequestPacket);
|
|
DISPATCH(HostAddress);
|
|
DISPATCH(Word64);
|
|
DISPATCH(Key_PublicKey);
|
|
DISPATCH(KeyPair);
|
|
DISPATCH(NodeInfo);
|
|
DISPATCH(NodesRequest);
|
|
DISPATCH(NodesResponse);
|
|
DISPATCH(Packet_Word64);
|
|
DISPATCH(PacketKind);
|
|
DISPATCH(PingPacket);
|
|
DISPATCH(PlainText);
|
|
DISPATCH(PortNumber);
|
|
DISPATCH(RpcPacket_Word64);
|
|
DISPATCH(SocketAddress);
|
|
DISPATCH(TransportProtocol);
|
|
#undef DISPATCH
|
|
|
|
return unimplemented;
|
|
}
|