/*
This file is part of cpp - ethereum .
cpp - ethereum is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
cpp - ethereum is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with cpp - ethereum . If not , see < http : //www.gnu.org/licenses/>.
*/
/** @file Session.h
* @ author Gav Wood < i @ gavwood . com >
* @ date 2014
*/
# pragma once
# include <mutex>
# include <array>
# include <deque>
# include <set>
# include <memory>
# include <utility>
# include <libdevcore/Common.h>
# include <libdevcore/RLP.h>
# include <libdevcore/RangeMask.h>
# include <libdevcore/Guards.h>
# include "Common.h"
namespace dev
{
namespace p2p
{
struct Node ;
/**
* @ brief The Session class
* @ todo Document fully .
*/
class Session : public std : : enable_shared_from_this < Session >
{
friend class Host ;
friend class HostCapabilityFace ;
public :
Session ( Host * _server , bi : : tcp : : socket _socket , std : : shared_ptr < Node > const & _n , bool _force = false ) ;
Session ( Host * _server , bi : : tcp : : socket _socket , bi : : tcp : : endpoint const & _manual ) ;
virtual ~ Session ( ) ;
void start ( ) ;
void disconnect ( DisconnectReason _reason ) ;
void ping ( ) ;
bool isOpen ( ) const { return m_socket . is_open ( ) ; }
NodeId id ( ) const ;
unsigned socketId ( ) const { return m_socket . native_handle ( ) ; }
bi : : tcp : : endpoint endpoint ( ) const ; ///< for other peers to connect to.
template < class PeerCap >
std : : shared_ptr < PeerCap > cap ( ) const { try { return std : : static_pointer_cast < PeerCap > ( m_capabilities . at ( std : : make_pair ( PeerCap : : name ( ) , PeerCap : : version ( ) ) ) ) ; } catch ( . . . ) { return nullptr ; } }
static RLPStream & prep ( RLPStream & _s , PacketType _t , unsigned _args = 0 ) ;
static RLPStream & prep ( RLPStream & _s ) ;
void sealAndSend ( RLPStream & _s ) ;
void send ( bytes & & _msg ) ;
void send ( bytesConstRef _msg ) ;
int rating ( ) const ;
void addRating ( unsigned _r ) ;
void addNote ( std : : string const & _k , std : : string const & _v ) { m_info . notes [ _k ] = _v ; }
PeerInfo const & info ( ) const { return m_info ; }
void ensureNodesRequested ( ) ;
void serviceNodesRequest ( ) ;
private :
/// Drop the connection for the reason @a _r.
void drop ( DisconnectReason _r ) ;
/// Perform a read on the socket.
void doRead ( ) ;
/// Perform a single round of the write operation. This could end up calling itself asynchronously.
void write ( ) ;
/// Interpret an incoming message.
bool interpret ( RLP const & _r ) ;
/// @returns true iff the _msg forms a valid message for sending or receiving on the network.
static bool checkPacket ( bytesConstRef _msg ) ;
Host * m_server ; ///< The host that owns us. Never null.
mutable bi : : tcp : : socket m_socket ; ///< Socket for the peer's connection. Mutable to ask for native_handle().
Mutex x_writeQueue ; ///< Mutex for the write queue.
std : : deque < bytes > m_writeQueue ; ///< The write queue.
std : : array < byte , 65536 > m_data ; ///< Buffer for ingress packet data.
bytes m_incoming ; ///< Read buffer for ingress bytes.
PeerInfo m_info ; ///< Dynamic information about this peer.
unsigned m_protocolVersion = 0 ; ///< The protocol version of the peer.
std : : shared_ptr < Node > m_node ; ///< The Node object. Might be null if we constructed using a bare address/port.
bi : : tcp : : endpoint m_manualEndpoint ; ///< The endpoint as specified by the constructor.
bool m_force = false ; ///< If true, ignore IDs being different. This could open you up to MitM attacks.
bool m_dropped = false ; ///< If true, we've already divested ourselves of this peer. We're just waiting for the reads & writes to fail before the shared_ptr goes OOS and the destructor kicks in.
bool m_theyRequestedNodes = false ; ///< Has the peer requested nodes from us without receiveing an answer from us?
bool m_weRequestedNodes = false ; ///< Have we requested nodes from the peer and not received an answer yet?
std : : chrono : : steady_clock : : time_point m_connect ; ///< Time point of connection.
std : : chrono : : steady_clock : : time_point m_ping ; ///< Time point of last ping.
std : : chrono : : steady_clock : : time_point m_lastReceived ; ///< Time point of last message.
std : : map < CapDesc , std : : shared_ptr < Capability > > m_capabilities ; ///< The peer's capability set.
RangeMask < unsigned > m_knownNodes ; ///< Nodes we already know about as indices into Host's nodesList. These shouldn't be resent to peer.
} ;
}
}