diff options
Diffstat (limited to 'src/network/network.h')
-rw-r--r-- | src/network/network.h | 318 |
1 files changed, 162 insertions, 156 deletions
diff --git a/src/network/network.h b/src/network/network.h index 56c37fb..00125f5 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -42,198 +42,204 @@ #include <string> #include <vector> -#include <sys/socket.h> #include <netinet/in.h> +#include <sys/socket.h> #include "src/crypto/crypto.h" using namespace Crypto; namespace Network { - static const unsigned int MOSH_PROTOCOL_VERSION = 2; /* bumped for echo-ack */ - - uint64_t timestamp( void ); - uint16_t timestamp16( void ); - uint16_t timestamp_diff( uint16_t tsnew, uint16_t tsold ); - - class NetworkException : public std::exception { - public: - std::string function; - int the_errno; +static const unsigned int MOSH_PROTOCOL_VERSION = 2; /* bumped for echo-ack */ + +uint64_t timestamp( void ); +uint16_t timestamp16( void ); +uint16_t timestamp_diff( uint16_t tsnew, uint16_t tsold ); + +class NetworkException : public std::exception +{ +public: + std::string function; + int the_errno; + +private: + std::string my_what; + +public: + NetworkException( std::string s_function = "<none>", int s_errno = 0 ) + : function( s_function ), the_errno( s_errno ), my_what( function + ": " + strerror( the_errno ) ) + {} + const char* what() const throw() { return my_what.c_str(); } + ~NetworkException() throw() {} +}; + +enum Direction +{ + TO_SERVER = 0, + TO_CLIENT = 1 +}; + +class Packet +{ +public: + const uint64_t seq; + Direction direction; + uint16_t timestamp, timestamp_reply; + std::string payload; + + Packet( Direction s_direction, uint16_t s_timestamp, uint16_t s_timestamp_reply, const std::string& s_payload ) + : seq( Crypto::unique() ), direction( s_direction ), timestamp( s_timestamp ), + timestamp_reply( s_timestamp_reply ), payload( s_payload ) + {} + + Packet( const Message& message ); + + Message toMessage( void ); +}; + +union Addr { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr_storage ss; +}; + +class Connection +{ +private: + /* + * For IPv4, guess the typical (minimum) header length; + * fragmentation is not dangerous, just inefficient. + */ + static const int IPV4_HEADER_LEN = 20 /* base IP header */ + + 8 /* UDP */; + /* + * For IPv6, we don't want to ever have MTU issues, so make a + * conservative guess about header size. + */ + static const int IPV6_HEADER_LEN = 40 /* base IPv6 header */ + + 16 /* 2 minimum-sized extension headers */ + + 8 /* UDP */; + /* Application datagram MTU. For constructors and fallback. */ + static const int DEFAULT_SEND_MTU = 500; + /* + * IPv4 MTU. Don't use full Ethernet-derived MTU, + * mobile networks have high tunneling overhead. + * + * As of July 2016, VPN traffic over Amtrak Acela wifi seems to be + * dropped if tunnelled packets are 1320 bytes or larger. Use a + * 1280-byte IPv4 MTU for now. + * + * We may have to implement ICMP-less PMTUD (RFC 4821) eventually. + */ + static const int DEFAULT_IPV4_MTU = 1280; + /* IPv6 MTU. Use the guaranteed minimum to avoid fragmentation. */ + static const int DEFAULT_IPV6_MTU = 1280; + + static const uint64_t MIN_RTO = 50; /* ms */ + static const uint64_t MAX_RTO = 1000; /* ms */ + + static const int PORT_RANGE_LOW = 60001; + static const int PORT_RANGE_HIGH = 60999; + + static const unsigned int SERVER_ASSOCIATION_TIMEOUT = 40000; + static const unsigned int PORT_HOP_INTERVAL = 10000; + + static const unsigned int MAX_PORTS_OPEN = 10; + static const unsigned int MAX_OLD_SOCKET_AGE = 60000; + + static const int CONGESTION_TIMESTAMP_PENALTY = 500; /* ms */ + + bool try_bind( const char* addr, int port_low, int port_high ); + + class Socket + { private: - std::string my_what; - public: - NetworkException( std::string s_function="<none>", int s_errno=0) - : function( s_function ), the_errno( s_errno ), - my_what(function + ": " + strerror(the_errno)) {} - const char *what() const throw () { return my_what.c_str(); } - ~NetworkException() throw () {} - }; - - enum Direction { - TO_SERVER = 0, - TO_CLIENT = 1 - }; + int _fd; - class Packet { public: - const uint64_t seq; - Direction direction; - uint16_t timestamp, timestamp_reply; - std::string payload; - - Packet( Direction s_direction, - uint16_t s_timestamp, uint16_t s_timestamp_reply, const std::string & s_payload ) - : seq( Crypto::unique() ), direction( s_direction ), - timestamp( s_timestamp ), timestamp_reply( s_timestamp_reply ), payload( s_payload ) - {} - - Packet( const Message & message ); - - Message toMessage( void ); - }; + int fd( void ) const { return _fd; } + Socket( int family ); + ~Socket(); - union Addr { - struct sockaddr sa; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; - struct sockaddr_storage ss; + Socket( const Socket& other ); + Socket& operator=( const Socket& other ); }; - class Connection { - private: - /* - * For IPv4, guess the typical (minimum) header length; - * fragmentation is not dangerous, just inefficient. - */ - static const int IPV4_HEADER_LEN = 20 /* base IP header */ - + 8 /* UDP */; - /* - * For IPv6, we don't want to ever have MTU issues, so make a - * conservative guess about header size. - */ - static const int IPV6_HEADER_LEN = 40 /* base IPv6 header */ - + 16 /* 2 minimum-sized extension headers */ - + 8 /* UDP */; - /* Application datagram MTU. For constructors and fallback. */ - static const int DEFAULT_SEND_MTU = 500; - /* - * IPv4 MTU. Don't use full Ethernet-derived MTU, - * mobile networks have high tunneling overhead. - * - * As of July 2016, VPN traffic over Amtrak Acela wifi seems to be - * dropped if tunnelled packets are 1320 bytes or larger. Use a - * 1280-byte IPv4 MTU for now. - * - * We may have to implement ICMP-less PMTUD (RFC 4821) eventually. - */ - static const int DEFAULT_IPV4_MTU = 1280; - /* IPv6 MTU. Use the guaranteed minimum to avoid fragmentation. */ - static const int DEFAULT_IPV6_MTU = 1280; - - static const uint64_t MIN_RTO = 50; /* ms */ - static const uint64_t MAX_RTO = 1000; /* ms */ + std::deque<Socket> socks; + bool has_remote_addr; + Addr remote_addr; + socklen_t remote_addr_len; - static const int PORT_RANGE_LOW = 60001; - static const int PORT_RANGE_HIGH = 60999; + bool server; - static const unsigned int SERVER_ASSOCIATION_TIMEOUT = 40000; - static const unsigned int PORT_HOP_INTERVAL = 10000; + int MTU; /* application datagram MTU */ - static const unsigned int MAX_PORTS_OPEN = 10; - static const unsigned int MAX_OLD_SOCKET_AGE = 60000; + Base64Key key; + Session session; - static const int CONGESTION_TIMESTAMP_PENALTY = 500; /* ms */ + void setup( void ); - bool try_bind( const char *addr, int port_low, int port_high ); + Direction direction; + uint16_t saved_timestamp; + uint64_t saved_timestamp_received_at; + uint64_t expected_receiver_seq; - class Socket - { - private: - int _fd; + uint64_t last_heard; + uint64_t last_port_choice; + uint64_t last_roundtrip_success; /* transport layer needs to tell us this */ - public: - int fd( void ) const { return _fd; } - Socket( int family ); - ~Socket(); + bool RTT_hit; + double SRTT; + double RTTVAR; - Socket( const Socket & other ); - Socket & operator=( const Socket & other ); - }; + /* Error from send()/sendto(). */ + std::string send_error; - std::deque< Socket > socks; - bool has_remote_addr; - Addr remote_addr; - socklen_t remote_addr_len; + Packet new_packet( const std::string& s_payload ); - bool server; + void hop_port( void ); - int MTU; /* application datagram MTU */ + int sock( void ) const + { + assert( !socks.empty() ); + return socks.back().fd(); + } - Base64Key key; - Session session; + void prune_sockets( void ); - void setup( void ); + std::string recv_one( int sock_to_recv ); - Direction direction; - uint16_t saved_timestamp; - uint64_t saved_timestamp_received_at; - uint64_t expected_receiver_seq; + void set_MTU( int family ); - uint64_t last_heard; - uint64_t last_port_choice; - uint64_t last_roundtrip_success; /* transport layer needs to tell us this */ +public: + /* Network transport overhead. */ + static const int ADDED_BYTES = 8 /* seqno/nonce */ + 4 /* timestamps */; - bool RTT_hit; - double SRTT; - double RTTVAR; + Connection( const char* desired_ip, const char* desired_port ); /* server */ + Connection( const char* key_str, const char* ip, const char* port ); /* client */ - /* Error from send()/sendto(). */ - std::string send_error; + void send( const std::string& s ); + std::string recv( void ); + const std::vector<int> fds( void ) const; + int get_MTU( void ) const { return MTU; } - Packet new_packet( const std::string &s_payload ); + std::string port( void ) const; + std::string get_key( void ) const { return key.printable_key(); } + bool get_has_remote_addr( void ) const { return has_remote_addr; } - void hop_port( void ); + uint64_t timeout( void ) const; + double get_SRTT( void ) const { return SRTT; } - int sock( void ) const { assert( !socks.empty() ); return socks.back().fd(); } + const Addr& get_remote_addr( void ) const { return remote_addr; } + socklen_t get_remote_addr_len( void ) const { return remote_addr_len; } - void prune_sockets( void ); + std::string& get_send_error( void ) { return send_error; } - std::string recv_one( int sock_to_recv ); + void set_last_roundtrip_success( uint64_t s_success ) { last_roundtrip_success = s_success; } - void set_MTU( int family ); - - public: - /* Network transport overhead. */ - static const int ADDED_BYTES = 8 /* seqno/nonce */ + 4 /* timestamps */; - - Connection( const char *desired_ip, const char *desired_port ); /* server */ - Connection( const char *key_str, const char *ip, const char *port ); /* client */ - - void send( const std::string & s ); - std::string recv( void ); - const std::vector< int > fds( void ) const; - int get_MTU( void ) const { return MTU; } - - std::string port( void ) const; - std::string get_key( void ) const { return key.printable_key(); } - bool get_has_remote_addr( void ) const { return has_remote_addr; } - - uint64_t timeout( void ) const; - double get_SRTT( void ) const { return SRTT; } - - const Addr &get_remote_addr( void ) const { return remote_addr; } - socklen_t get_remote_addr_len( void ) const { return remote_addr_len; } - - std::string &get_send_error( void ) - { - return send_error; - } - - void set_last_roundtrip_success( uint64_t s_success ) { last_roundtrip_success = s_success; } - - static bool parse_portrange( const char * desired_port_range, int & desired_port_low, int & desired_port_high ); - }; + static bool parse_portrange( const char* desired_port_range, int& desired_port_low, int& desired_port_high ); +}; } #endif |