/* * Copyright (c) 2015, Cryptonomex, Inc. * All rights reserved. * * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification, * are permitted until September 8, 2015, provided that the following conditions are met: * * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include #include #include #include #include #include namespace graphene { namespace net { /** * Defines an 8 byte header that is always present because the minimum encrypted packet * size is 8 bytes (blowfish). The maximum message size is defined in config.hpp. The channel, * and message type is also included because almost every channel will have a message type * field and we might as well include it in the 8 byte header to save space. */ struct message_header { uint32_t size; // number of bytes in message, capped at MAX_MESSAGE_SIZE uint32_t msg_type; // every channel gets a 16 bit message type specifier }; typedef fc::uint160_t message_hash_type; /** * Abstracts the process of packing/unpacking a message for a * particular channel. */ struct message : public message_header { std::vector data; message(){} message( message&& m ) :message_header(m),data( std::move(m.data) ){} message( const message& m ) :message_header(m),data( m.data ){} /** * Assumes that T::type specifies the message type */ template message( const T& m ) { msg_type = T::type; data = fc::raw::pack(m); size = (uint32_t)data.size(); } fc::uint160_t id()const { return fc::ripemd160::hash( data.data(), (uint32_t)data.size() ); } /** * Automatically checks the type and deserializes T in the * opposite process from the constructor. */ template T as()const { try { FC_ASSERT( msg_type == T::type ); T tmp; if( data.size() ) { fc::datastream ds( data.data(), data.size() ); fc::raw::unpack( ds, tmp ); } else { // just to make sure that tmp shouldn't have any data fc::datastream ds( nullptr, 0 ); fc::raw::unpack( ds, tmp ); } return tmp; } FC_RETHROW_EXCEPTIONS( warn, "error unpacking network message as a '${type}' ${x} !=? ${msg_type}", ("type", fc::get_typename::name() ) ("x", T::type) ("msg_type", msg_type) ); } }; } } // graphene::net FC_REFLECT( graphene::net::message_header, (size)(msg_type) ) FC_REFLECT_DERIVED( graphene::net::message, (graphene::net::message_header), (data) )